@@ -1,55 +1,32 @@ | |||
AUTOMAKE_OPTIONS = foreign no-dependencies | |||
bin_SCRIPTS = event_rpcgen.py | |||
EXTRA_DIST = acconfig.h event.h event-internal.h log.h evsignal.h evdns.3 \ | |||
event.3 \ | |||
EXTRA_DIST = acconfig.h event.h event-internal.h log.h evsignal.h \ | |||
kqueue.c epoll_sub.c epoll.c select.c rtsig.c poll.c signal.c \ | |||
evport.c devpoll.c event_rpcgen.py \ | |||
sample/Makefile.am sample/Makefile.in sample/event-test.c \ | |||
sample/signal-test.c sample/time-test.c \ | |||
test/Makefile.am test/Makefile.in test/bench.c test/regress.c \ | |||
test/test-eof.c test/test-weof.c test/test-time.c \ | |||
test/test-init.c test/test.sh \ | |||
evport.c devpoll.c buffer.c \ | |||
compat/sys/queue.h compat/sys/tree.h compat/sys/_time.h \ | |||
WIN32-Code/config.h WIN32-Code/misc.c \ | |||
WIN32-Code/win32.c WIN32-Code/misc.h \ | |||
WIN32-Prj/event_test/event_test.dsp \ | |||
WIN32-Prj/event_test/test.txt WIN32-Prj/libevent.dsp \ | |||
WIN32-Prj/libevent.dsw WIN32-Prj/signal_test/signal_test.dsp \ | |||
WIN32-Prj/time_test/time_test.dsp | |||
WIN32-Code/win32.c WIN32-Code/misc.h | |||
lib_LTLIBRARIES = libevent.la | |||
noinst_LIBRARIES = libevent.a | |||
if BUILD_WIN32 | |||
SUBDIRS = . sample | |||
SYS_LIBS = -lws2_32 | |||
SYS_SRC = WIN32-Code/misc.c WIN32-Code/win32.c | |||
SYS_INCLUDES = -IWIN32-Code | |||
SYS_INCLUDES = -I$(top_srcdir)/WIN32-Code | |||
else | |||
SUBDIRS = . sample test | |||
SYS_LIBS = | |||
SYS_SRC = | |||
SYS_INCLUDES = | |||
endif | |||
libevent_la_SOURCES = event.c buffer.c evbuffer.c log.c event_tagging.c \ | |||
http.c evhttp.h http-internal.h evdns.c evdns.h $(SYS_SRC) | |||
libevent_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS) | |||
libevent_la_LDFLAGS = -release @VERSION@ -version-info 1:3:0 | |||
include_HEADERS = event.h evhttp.h evdns.h | |||
INCLUDES = -Icompat $(SYS_INCLUDES) | |||
man_MANS = event.3 evdns.3 | |||
libevent_a_SOURCES = event.c buffer.c event.h log.c evdns.c evdns.h $(SYS_SRC) | |||
libevent_a_LIBADD = @LIBOBJS@ $(SYS_LIBS) | |||
verify: libevent.la | |||
cd $(srcdir)/test && make verify | |||
INCLUDES = -I$(top_srcdir)/compat $(SYS_INCLUDES) | |||
DISTCLEANFILES = *~ |
@@ -1,35 +0,0 @@ | |||
To build libevent, type | |||
$ ./configure && make | |||
Install as root via | |||
# make install | |||
You can run the regression tests by | |||
$ make verify | |||
Before, reporting any problems, please run the regression tests. | |||
To enable the low-level tracing build the library as: | |||
CFLAGS=-DUSE_DEBUG ./configure [...] | |||
Acknowledgements: | |||
----------------- | |||
The following people have helped with suggestions, ideas, code or | |||
fixing bugs: | |||
Nick Mathewson | |||
Andrew Danforth | |||
Shie Erlich | |||
Mike Davis | |||
William Ahern | |||
Alexander von Gernler | |||
Artur Grabowski | |||
Stas Bekman | |||
Tassilo von Parseval | |||
If I have forgotten your name, please contact me. |
@@ -1,100 +0,0 @@ | |||
# Microsoft Developer Studio Project File - Name="event_test" - Package Owner=<4> | |||
# Microsoft Developer Studio Generated Build File, Format Version 6.00 | |||
# ** DO NOT EDIT ** | |||
# TARGTYPE "Win32 (x86) Console Application" 0x0103 | |||
CFG=event_test - Win32 Debug | |||
!MESSAGE This is not a valid makefile. To build this project using NMAKE, | |||
!MESSAGE use the Export Makefile command and run | |||
!MESSAGE | |||
!MESSAGE NMAKE /f "event_test.mak". | |||
!MESSAGE | |||
!MESSAGE You can specify a configuration when running NMAKE | |||
!MESSAGE by defining the macro CFG on the command line. For example: | |||
!MESSAGE | |||
!MESSAGE NMAKE /f "event_test.mak" CFG="event_test - Win32 Debug" | |||
!MESSAGE | |||
!MESSAGE Possible choices for configuration are: | |||
!MESSAGE | |||
!MESSAGE "event_test - Win32 Release" (based on "Win32 (x86) Console Application") | |||
!MESSAGE "event_test - Win32 Debug" (based on "Win32 (x86) Console Application") | |||
!MESSAGE | |||
# Begin Project | |||
# PROP AllowPerConfigDependencies 0 | |||
# PROP Scc_ProjName "" | |||
# PROP Scc_LocalPath "" | |||
CPP=cl.exe | |||
RSC=rc.exe | |||
!IF "$(CFG)" == "event_test - Win32 Release" | |||
# PROP BASE Use_MFC 0 | |||
# PROP BASE Use_Debug_Libraries 0 | |||
# PROP BASE Output_Dir "Release" | |||
# PROP BASE Intermediate_Dir "Release" | |||
# PROP BASE Target_Dir "" | |||
# PROP Use_MFC 0 | |||
# PROP Use_Debug_Libraries 0 | |||
# PROP Output_Dir "Release" | |||
# PROP Intermediate_Dir "Release" | |||
# PROP Target_Dir "" | |||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c | |||
# ADD CPP /nologo /W3 /GX /O2 /I "..\..\\" /I "..\..\WIN32-Code" /I "..\..\compat" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c | |||
# ADD BASE RSC /l 0x409 /d "NDEBUG" | |||
# ADD RSC /l 0x409 /d "NDEBUG" | |||
BSC32=bscmake.exe | |||
# ADD BASE BSC32 /nologo | |||
# ADD BSC32 /nologo | |||
LINK32=link.exe | |||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 | |||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 | |||
!ELSEIF "$(CFG)" == "event_test - Win32 Debug" | |||
# PROP BASE Use_MFC 0 | |||
# PROP BASE Use_Debug_Libraries 1 | |||
# PROP BASE Output_Dir "Debug" | |||
# PROP BASE Intermediate_Dir "Debug" | |||
# PROP BASE Target_Dir "" | |||
# PROP Use_MFC 0 | |||
# PROP Use_Debug_Libraries 1 | |||
# PROP Output_Dir "Debug" | |||
# PROP Intermediate_Dir "Debug" | |||
# PROP Target_Dir "" | |||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c | |||
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\\" /I "..\..\WIN32-Code" /I "..\..\compat" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c | |||
# ADD BASE RSC /l 0x409 /d "_DEBUG" | |||
# ADD RSC /l 0x409 /d "_DEBUG" | |||
BSC32=bscmake.exe | |||
# ADD BASE BSC32 /nologo | |||
# ADD BSC32 /nologo | |||
LINK32=link.exe | |||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept | |||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept | |||
!ENDIF | |||
# Begin Target | |||
# Name "event_test - Win32 Release" | |||
# Name "event_test - Win32 Debug" | |||
# Begin Group "Source Files" | |||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" | |||
# Begin Source File | |||
SOURCE="..\..\sample\event-test.c" | |||
# End Source File | |||
# End Group | |||
# Begin Group "Header Files" | |||
# PROP Default_Filter "h;hpp;hxx;hm;inl" | |||
# End Group | |||
# Begin Group "Resource Files" | |||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" | |||
# End Group | |||
# End Target | |||
# End Project |
@@ -1,180 +0,0 @@ | |||
Platform SDK: File Storage | |||
ReadFile | |||
The ReadFile function reads data from a file, starting at the position indicated by the file pointer. After the read operation has been completed, the file pointer is adjusted by the number of bytes actually read, unless the file handle is created with the overlapped attribute. If the file handle is created for overlapped input and output (I/O), the application must adjust the position of the file pointer after the read operation. | |||
This function is designed for both synchronous and asynchronous operation. The ReadFileEx function is designed solely for asynchronous operation. It lets an application perform other processing during a file read operation. | |||
BOOL ReadFile( | |||
HANDLE hFile, // handle to file | |||
LPVOID lpBuffer, // data buffer | |||
DWORD nNumberOfBytesToRead, // number of bytes to read | |||
LPDWORD lpNumberOfBytesRead, // number of bytes read | |||
LPOVERLAPPED lpOverlapped // overlapped buffer | |||
); | |||
Parameters | |||
hFile | |||
[in] Handle to the file to be read. The file handle must have been created with GENERIC_READ access to the file. | |||
Windows NT/2000/XP: For asynchronous read operations, hFile can be any handle opened with the FILE_FLAG_OVERLAPPED flag by the CreateFile function, or a socket handle returned by the socket or accept function. | |||
Windows 95/98/Me: For asynchronous read operations, hFile can be a communications resource opened with the FILE_FLAG_OVERLAPPED flag by CreateFile, or a socket handle returned by socket or accept. You cannot perform asynchronous read operations on mailslots, named pipes, or disk files. | |||
lpBuffer | |||
[out] Pointer to the buffer that receives the data read from the file. | |||
nNumberOfBytesToRead | |||
[in] Specifies the number of bytes to be read from the file. | |||
lpNumberOfBytesRead | |||
[out] Pointer to the variable that receives the number of bytes read. ReadFile sets this value to zero before doing any work or error checking. If this parameter is zero when ReadFile returns TRUE on a named pipe, the other end of the message-mode pipe called the WriteFile function with nNumberOfBytesToWrite set to zero. | |||
Windows NT/2000/XP: If lpOverlapped is NULL, lpNumberOfBytesRead cannot be NULL. If lpOverlapped is not NULL, lpNumberOfBytesRead can be NULL. If this is an overlapped read operation, you can get the number of bytes read by calling GetOverlappedResult. If hFile is associated with an I/O completion port, you can get the number of bytes read by calling GetQueuedCompletionStatus. | |||
If I/O completion ports are used and you are using a callback routine to free the memory allocated to the OVERLAPPED structure pointed to by the lpOverlapped parameter, specify NULL as the value of this parameter to avoid a memory corruption problem during the deallocation. This memory corruption problem will cause an invalid number of bytes to be returned in this parameter. | |||
Windows 95/98/Me: This parameter cannot be NULL. | |||
lpOverlapped | |||
[in] Pointer to an OVERLAPPED structure. This structure is required if hFile was created with FILE_FLAG_OVERLAPPED. | |||
If hFile was opened with FILE_FLAG_OVERLAPPED, the lpOverlapped parameter must not be NULL. It must point to a valid OVERLAPPED structure. If hFile was created with FILE_FLAG_OVERLAPPED and lpOverlapped is NULL, the function can incorrectly report that the read operation is complete. | |||
If hFile was opened with FILE_FLAG_OVERLAPPED and lpOverlapped is not NULL, the read operation starts at the offset specified in the OVERLAPPED structure and ReadFile may return before the read operation has been completed. In this case, ReadFile returns FALSE and the GetLastError function returns ERROR_IO_PENDING. This allows the calling process to continue while the read operation finishes. The event specified in the OVERLAPPED structure is set to the signaled state upon completion of the read operation. | |||
If hFile was not opened with FILE_FLAG_OVERLAPPED and lpOverlapped is NULL, the read operation starts at the current file position and ReadFile does not return until the operation has been completed. | |||
Windows NT/2000/XP: If hFile is not opened with FILE_FLAG_OVERLAPPED and lpOverlapped is not NULL, the read operation starts at the offset specified in the OVERLAPPED structure. ReadFile does not return until the read operation has been completed. | |||
Windows 95/98/Me: For operations on files, disks, pipes, or mailslots, this parameter must be NULL; a pointer to an OVERLAPPED structure causes the call to fail. However, Windows 95/98/Me supports overlapped I/O on serial and parallel ports. | |||
Return Values | |||
The ReadFile function returns when one of the following is true: a write operation completes on the write end of the pipe, the number of bytes requested has been read, or an error occurs. | |||
If the function succeeds, the return value is nonzero. | |||
If the return value is nonzero and the number of bytes read is zero, the file pointer was beyond the current end of the file at the time of the read operation. However, if the file was opened with FILE_FLAG_OVERLAPPED and lpOverlapped is not NULL, the return value is FALSE and GetLastError returns ERROR_HANDLE_EOF when the file pointer goes beyond the current end of file. | |||
If the function fails, the return value is zero. To get extended error information, call GetLastError. | |||
Remarks | |||
If part of the file is locked by another process and the read operation overlaps the locked portion, this function fails. | |||
An application must meet certain requirements when working with files opened with FILE_FLAG_NO_BUFFERING: | |||
File access must begin at byte offsets within the file that are integer multiples of the volume's sector size. To determine a volume's sector size, call the GetDiskFreeSpace function. | |||
File access must be for numbers of bytes that are integer multiples of the volume's sector size. For example, if the sector size is 512 bytes, an application can request reads and writes of 512, 1024, or 2048 bytes, but not of 335, 981, or 7171 bytes. | |||
Buffer addresses for read and write operations must be sector aligned (aligned on addresses in memory that are integer multiples of the volume's sector size). One way to sector align buffers is to use the VirtualAlloc function to allocate the buffers. This function allocates memory that is aligned on addresses that are integer multiples of the system's page size. Because both page and volume sector sizes are powers of 2, memory aligned by multiples of the system's page size is also aligned by multiples of the volume's sector size. | |||
Accessing the input buffer while a read operation is using the buffer may lead to corruption of the data read into that buffer. Applications must not read from, write to, reallocate, or free the input buffer that a read operation is using until the read operation completes. | |||
Characters can be read from the console input buffer by using ReadFile with a handle to console input. The console mode determines the exact behavior of the ReadFile function. | |||
If a named pipe is being read in message mode and the next message is longer than the nNumberOfBytesToRead parameter specifies, ReadFile returns FALSE and GetLastError returns ERROR_MORE_DATA. The remainder of the message may be read by a subsequent call to the ReadFile or PeekNamedPipe function. | |||
When reading from a communications device, the behavior of ReadFile is governed by the current communication time-outs as set and retrieved using the SetCommTimeouts and GetCommTimeouts functions. Unpredictable results can occur if you fail to set the time-out values. For more information about communication time-outs, see COMMTIMEOUTS. | |||
If ReadFile attempts to read from a mailslot whose buffer is too small, the function returns FALSE and GetLastError returns ERROR_INSUFFICIENT_BUFFER. | |||
If the anonymous write pipe handle has been closed and ReadFile attempts to read using the corresponding anonymous read pipe handle, the function returns FALSE and GetLastError returns ERROR_BROKEN_PIPE. | |||
The ReadFile function may fail and return ERROR_INVALID_USER_BUFFER or ERROR_NOT_ENOUGH_MEMORY whenever there are too many outstanding asynchronous I/O requests. | |||
The ReadFile code to check for the end-of-file condition (eof) differs for synchronous and asynchronous read operations. | |||
When a synchronous read operation reaches the end of a file, ReadFile returns TRUE and sets *lpNumberOfBytesRead to zero. The following sample code tests for end-of-file for a synchronous read operation: | |||
// Attempt a synchronous read operation. | |||
bResult = ReadFile(hFile, &inBuffer, nBytesToRead, &nBytesRead, NULL) ; | |||
// Check for end of file. | |||
if (bResult && nBytesRead == 0, ) | |||
{ | |||
// we're at the end of the file | |||
} | |||
An asynchronous read operation can encounter the end of a file during the initiating call to ReadFile, or during subsequent asynchronous operation. | |||
If EOF is detected at ReadFile time for an asynchronous read operation, ReadFile returns FALSE and GetLastError returns ERROR_HANDLE_EOF. | |||
If EOF is detected during subsequent asynchronous operation, the call to GetOverlappedResult to obtain the results of that operation returns FALSE and GetLastError returns ERROR_HANDLE_EOF. | |||
To cancel all pending asynchronous I/O operations, use the CancelIo function. This function only cancels operations issued by the calling thread for the specified file handle. I/O operations that are canceled complete with the error ERROR_OPERATION_ABORTED. | |||
If you are attempting to read from a floppy drive that does not have a floppy disk, the system displays a message box prompting the user to retry the operation. To prevent the system from displaying this message box, call the SetErrorMode function with SEM_NOOPENFILEERRORBOX. | |||
The following sample code illustrates testing for end-of-file for an asynchronous read operation: | |||
// set up overlapped structure fields | |||
gOverLapped.Offset = 0; | |||
gOverLapped.OffsetHigh = 0; | |||
gOverLapped.hEvent = hEvent; | |||
// attempt an asynchronous read operation | |||
bResult = ReadFile(hFile, &inBuffer, nBytesToRead, &nBytesRead, | |||
&gOverlapped) ; | |||
// if there was a problem, or the async. operation's still pending ... | |||
if (!bResult) | |||
{ | |||
// deal with the error code | |||
switch (dwError = GetLastError()) | |||
{ | |||
case ERROR_HANDLE_EOF: | |||
{ | |||
// we have reached the end of the file | |||
// during the call to ReadFile | |||
// code to handle that | |||
} | |||
case ERROR_IO_PENDING: | |||
{ | |||
// asynchronous i/o is still in progress | |||
// do something else for a while | |||
GoDoSomethingElse() ; | |||
// check on the results of the asynchronous read | |||
bResult = GetOverlappedResult(hFile, &gOverlapped, | |||
&nBytesRead, FALSE) ; | |||
// if there was a problem ... | |||
if (!bResult) | |||
{ | |||
// deal with the error code | |||
switch (dwError = GetLastError()) | |||
{ | |||
case ERROR_HANDLE_EOF: | |||
{ | |||
// we have reached the end of | |||
// the file during asynchronous | |||
// operation | |||
} | |||
// deal with other error cases | |||
} | |||
} | |||
} // end case | |||
// deal with other error cases | |||
} // end switch | |||
} // end if | |||
Example Code | |||
For an example, see Reading, Writing, and Locking Files. | |||
Requirements | |||
Windows NT/2000/XP: Included in Windows NT 3.1 and later. | |||
Windows 95/98/Me: Included in Windows 95 and later. | |||
Header: Declared in Winbase.h; include Windows.h. | |||
Library: Use Kernel32.lib. | |||
See Also | |||
File I/O Overview, File I/O Functions, CancelIo, CreateFile, GetCommTimeouts, GetOverlappedResult, GetQueuedCompletionStatus, OVERLAPPED, PeekNamedPipe, ReadFileEx, SetCommTimeouts, SetErrorMode, WriteFile | |||
Platform SDK Release: November 2001 What did you think of this topic? | |||
Let us know. Order a Platform SDK CD Online | |||
(U.S/Canada) (International) | |||
Requirements | |||
Windows NT/2000/XP: Included in Windows NT 3.1 and later. | |||
Windows 95/98/Me: Included in Windows 95 and later. | |||
Header: Declared in Winbase.h; include Windows.h. | |||
Library: Use Kernel32.lib. | |||
See Also | |||
File I/O Overview, File I/O Functions, CancelIo, CreateFile, GetCommTimeouts, GetOverlappedResult, GetQueuedCompletionStatus, OVERLAPPED, PeekNamedPipe, ReadFileEx, SetCommTimeouts, SetErrorMode, WriteFile |
@@ -1,128 +0,0 @@ | |||
# Microsoft Developer Studio Project File - Name="libevent" - Package Owner=<4> | |||
# Microsoft Developer Studio Generated Build File, Format Version 6.00 | |||
# ** DO NOT EDIT ** | |||
# TARGTYPE "Win32 (x86) Static Library" 0x0104 | |||
CFG=libevent - Win32 Debug | |||
!MESSAGE This is not a valid makefile. To build this project using NMAKE, | |||
!MESSAGE use the Export Makefile command and run | |||
!MESSAGE | |||
!MESSAGE NMAKE /f "libevent.mak". | |||
!MESSAGE | |||
!MESSAGE You can specify a configuration when running NMAKE | |||
!MESSAGE by defining the macro CFG on the command line. For example: | |||
!MESSAGE | |||
!MESSAGE NMAKE /f "libevent.mak" CFG="libevent - Win32 Debug" | |||
!MESSAGE | |||
!MESSAGE Possible choices for configuration are: | |||
!MESSAGE | |||
!MESSAGE "libevent - Win32 Release" (based on "Win32 (x86) Static Library") | |||
!MESSAGE "libevent - Win32 Debug" (based on "Win32 (x86) Static Library") | |||
!MESSAGE | |||
# Begin Project | |||
# PROP AllowPerConfigDependencies 0 | |||
# PROP Scc_ProjName "" | |||
# PROP Scc_LocalPath "" | |||
CPP=cl.exe | |||
RSC=rc.exe | |||
!IF "$(CFG)" == "libevent - Win32 Release" | |||
# PROP BASE Use_MFC 0 | |||
# PROP BASE Use_Debug_Libraries 0 | |||
# PROP BASE Output_Dir "Release" | |||
# PROP BASE Intermediate_Dir "Release" | |||
# PROP BASE Target_Dir "" | |||
# PROP Use_MFC 0 | |||
# PROP Use_Debug_Libraries 0 | |||
# PROP Output_Dir "Release" | |||
# PROP Intermediate_Dir "Release" | |||
# PROP Target_Dir "" | |||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c | |||
# ADD CPP /nologo /W3 /GX /O2 /I "..\\" /I "..\WIN32-Code" /I "..\compat" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c | |||
# ADD BASE RSC /l 0x409 /d "NDEBUG" | |||
# ADD RSC /l 0x409 /d "NDEBUG" | |||
BSC32=bscmake.exe | |||
# ADD BASE BSC32 /nologo | |||
# ADD BSC32 /nologo | |||
LIB32=link.exe -lib | |||
# ADD BASE LIB32 /nologo | |||
# ADD LIB32 /nologo | |||
!ELSEIF "$(CFG)" == "libevent - Win32 Debug" | |||
# PROP BASE Use_MFC 0 | |||
# PROP BASE Use_Debug_Libraries 1 | |||
# PROP BASE Output_Dir "Debug" | |||
# PROP BASE Intermediate_Dir "Debug" | |||
# PROP BASE Target_Dir "" | |||
# PROP Use_MFC 0 | |||
# PROP Use_Debug_Libraries 1 | |||
# PROP Output_Dir "Debug" | |||
# PROP Intermediate_Dir "Debug" | |||
# PROP Target_Dir "" | |||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c | |||
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\\" /I "..\WIN32-Code" /I "..\compat" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c | |||
# ADD BASE RSC /l 0x409 /d "_DEBUG" | |||
# ADD RSC /l 0x409 /d "_DEBUG" | |||
BSC32=bscmake.exe | |||
# ADD BASE BSC32 /nologo | |||
# ADD BSC32 /nologo | |||
LIB32=link.exe -lib | |||
# ADD BASE LIB32 /nologo | |||
# ADD LIB32 /nologo | |||
!ENDIF | |||
# Begin Target | |||
# Name "libevent - Win32 Release" | |||
# Name "libevent - Win32 Debug" | |||
# Begin Group "Source Files" | |||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" | |||
# Begin Source File | |||
SOURCE=..\log.c | |||
# End Source File | |||
# Begin Source File | |||
SOURCE=..\event.c | |||
# End Source File | |||
# Begin Source File | |||
SOURCE="..\WIN32-Code\misc.c" | |||
# End Source File | |||
# Begin Source File | |||
SOURCE="..\WIN32-Code\win32.c" | |||
# End Source File | |||
# End Group | |||
# Begin Group "Header Files" | |||
# PROP Default_Filter "h;hpp;hxx;hm;inl" | |||
# Begin Source File | |||
SOURCE=..\acconfig.h | |||
# End Source File | |||
# Begin Source File | |||
SOURCE="..\WIN32-Code\config.h" | |||
# End Source File | |||
# Begin Source File | |||
SOURCE=..\compat\err.h | |||
# End Source File | |||
# Begin Source File | |||
SOURCE=..\event.h | |||
# End Source File | |||
# Begin Source File | |||
SOURCE="..\WIN32-Code\misc.h" | |||
# End Source File | |||
# End Group | |||
# End Target | |||
# End Project |
@@ -1,74 +0,0 @@ | |||
Microsoft Developer Studio Workspace File, Format Version 6.00 | |||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! | |||
############################################################################### | |||
Project: "event_test"=".\event_test\event_test.dsp" - Package Owner=<4> | |||
Package=<5> | |||
{{{ | |||
}}} | |||
Package=<4> | |||
{{{ | |||
Begin Project Dependency | |||
Project_Dep_Name libevent | |||
End Project Dependency | |||
}}} | |||
############################################################################### | |||
Project: "libevent"=".\libevent.dsp" - Package Owner=<4> | |||
Package=<5> | |||
{{{ | |||
}}} | |||
Package=<4> | |||
{{{ | |||
}}} | |||
############################################################################### | |||
Project: "signal_test"=".\signal_test\signal_test.dsp" - Package Owner=<4> | |||
Package=<5> | |||
{{{ | |||
}}} | |||
Package=<4> | |||
{{{ | |||
Begin Project Dependency | |||
Project_Dep_Name libevent | |||
End Project Dependency | |||
}}} | |||
############################################################################### | |||
Project: "time_test"=".\time_test\time_test.dsp" - Package Owner=<4> | |||
Package=<5> | |||
{{{ | |||
}}} | |||
Package=<4> | |||
{{{ | |||
Begin Project Dependency | |||
Project_Dep_Name libevent | |||
End Project Dependency | |||
}}} | |||
############################################################################### | |||
Global: | |||
Package=<5> | |||
{{{ | |||
}}} | |||
Package=<3> | |||
{{{ | |||
}}} | |||
############################################################################### | |||
@@ -1,100 +0,0 @@ | |||
# Microsoft Developer Studio Project File - Name="signal_test" - Package Owner=<4> | |||
# Microsoft Developer Studio Generated Build File, Format Version 6.00 | |||
# ** DO NOT EDIT ** | |||
# TARGTYPE "Win32 (x86) Console Application" 0x0103 | |||
CFG=signal_test - Win32 Debug | |||
!MESSAGE This is not a valid makefile. To build this project using NMAKE, | |||
!MESSAGE use the Export Makefile command and run | |||
!MESSAGE | |||
!MESSAGE NMAKE /f "signal_test.mak". | |||
!MESSAGE | |||
!MESSAGE You can specify a configuration when running NMAKE | |||
!MESSAGE by defining the macro CFG on the command line. For example: | |||
!MESSAGE | |||
!MESSAGE NMAKE /f "signal_test.mak" CFG="signal_test - Win32 Debug" | |||
!MESSAGE | |||
!MESSAGE Possible choices for configuration are: | |||
!MESSAGE | |||
!MESSAGE "signal_test - Win32 Release" (based on "Win32 (x86) Console Application") | |||
!MESSAGE "signal_test - Win32 Debug" (based on "Win32 (x86) Console Application") | |||
!MESSAGE | |||
# Begin Project | |||
# PROP AllowPerConfigDependencies 0 | |||
# PROP Scc_ProjName "" | |||
# PROP Scc_LocalPath "" | |||
CPP=cl.exe | |||
RSC=rc.exe | |||
!IF "$(CFG)" == "signal_test - Win32 Release" | |||
# PROP BASE Use_MFC 0 | |||
# PROP BASE Use_Debug_Libraries 0 | |||
# PROP BASE Output_Dir "Release" | |||
# PROP BASE Intermediate_Dir "Release" | |||
# PROP BASE Target_Dir "" | |||
# PROP Use_MFC 0 | |||
# PROP Use_Debug_Libraries 0 | |||
# PROP Output_Dir "Release" | |||
# PROP Intermediate_Dir "Release" | |||
# PROP Target_Dir "" | |||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c | |||
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c | |||
# ADD BASE RSC /l 0x409 /d "NDEBUG" | |||
# ADD RSC /l 0x409 /d "NDEBUG" | |||
BSC32=bscmake.exe | |||
# ADD BASE BSC32 /nologo | |||
# ADD BSC32 /nologo | |||
LINK32=link.exe | |||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 | |||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 | |||
!ELSEIF "$(CFG)" == "signal_test - Win32 Debug" | |||
# PROP BASE Use_MFC 0 | |||
# PROP BASE Use_Debug_Libraries 1 | |||
# PROP BASE Output_Dir "Debug" | |||
# PROP BASE Intermediate_Dir "Debug" | |||
# PROP BASE Target_Dir "" | |||
# PROP Use_MFC 0 | |||
# PROP Use_Debug_Libraries 1 | |||
# PROP Output_Dir "Debug" | |||
# PROP Intermediate_Dir "Debug" | |||
# PROP Target_Dir "" | |||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c | |||
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\\" /I "..\..\WIN32-Code" /I "..\..\compat" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c | |||
# ADD BASE RSC /l 0x409 /d "_DEBUG" | |||
# ADD RSC /l 0x409 /d "_DEBUG" | |||
BSC32=bscmake.exe | |||
# ADD BASE BSC32 /nologo | |||
# ADD BSC32 /nologo | |||
LINK32=link.exe | |||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept | |||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept | |||
!ENDIF | |||
# Begin Target | |||
# Name "signal_test - Win32 Release" | |||
# Name "signal_test - Win32 Debug" | |||
# Begin Group "Source Files" | |||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" | |||
# Begin Source File | |||
SOURCE="..\..\sample\signal-test.c" | |||
# End Source File | |||
# End Group | |||
# Begin Group "Header Files" | |||
# PROP Default_Filter "h;hpp;hxx;hm;inl" | |||
# End Group | |||
# Begin Group "Resource Files" | |||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" | |||
# End Group | |||
# End Target | |||
# End Project |
@@ -1,100 +0,0 @@ | |||
# Microsoft Developer Studio Project File - Name="time_test" - Package Owner=<4> | |||
# Microsoft Developer Studio Generated Build File, Format Version 6.00 | |||
# ** DO NOT EDIT ** | |||
# TARGTYPE "Win32 (x86) Console Application" 0x0103 | |||
CFG=time_test - Win32 Debug | |||
!MESSAGE This is not a valid makefile. To build this project using NMAKE, | |||
!MESSAGE use the Export Makefile command and run | |||
!MESSAGE | |||
!MESSAGE NMAKE /f "time_test.mak". | |||
!MESSAGE | |||
!MESSAGE You can specify a configuration when running NMAKE | |||
!MESSAGE by defining the macro CFG on the command line. For example: | |||
!MESSAGE | |||
!MESSAGE NMAKE /f "time_test.mak" CFG="time_test - Win32 Debug" | |||
!MESSAGE | |||
!MESSAGE Possible choices for configuration are: | |||
!MESSAGE | |||
!MESSAGE "time_test - Win32 Release" (based on "Win32 (x86) Console Application") | |||
!MESSAGE "time_test - Win32 Debug" (based on "Win32 (x86) Console Application") | |||
!MESSAGE | |||
# Begin Project | |||
# PROP AllowPerConfigDependencies 0 | |||
# PROP Scc_ProjName "" | |||
# PROP Scc_LocalPath "" | |||
CPP=cl.exe | |||
RSC=rc.exe | |||
!IF "$(CFG)" == "time_test - Win32 Release" | |||
# PROP BASE Use_MFC 0 | |||
# PROP BASE Use_Debug_Libraries 0 | |||
# PROP BASE Output_Dir "Release" | |||
# PROP BASE Intermediate_Dir "Release" | |||
# PROP BASE Target_Dir "" | |||
# PROP Use_MFC 0 | |||
# PROP Use_Debug_Libraries 0 | |||
# PROP Output_Dir "Release" | |||
# PROP Intermediate_Dir "Release" | |||
# PROP Target_Dir "" | |||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c | |||
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c | |||
# ADD BASE RSC /l 0x409 /d "NDEBUG" | |||
# ADD RSC /l 0x409 /d "NDEBUG" | |||
BSC32=bscmake.exe | |||
# ADD BASE BSC32 /nologo | |||
# ADD BSC32 /nologo | |||
LINK32=link.exe | |||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 | |||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 | |||
!ELSEIF "$(CFG)" == "time_test - Win32 Debug" | |||
# PROP BASE Use_MFC 0 | |||
# PROP BASE Use_Debug_Libraries 1 | |||
# PROP BASE Output_Dir "Debug" | |||
# PROP BASE Intermediate_Dir "Debug" | |||
# PROP BASE Target_Dir "" | |||
# PROP Use_MFC 0 | |||
# PROP Use_Debug_Libraries 1 | |||
# PROP Output_Dir "Debug" | |||
# PROP Intermediate_Dir "Debug" | |||
# PROP Target_Dir "" | |||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c | |||
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\\" /I "..\..\WIN32-Code" /I "..\..\compat" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c | |||
# ADD BASE RSC /l 0x409 /d "_DEBUG" | |||
# ADD RSC /l 0x409 /d "_DEBUG" | |||
BSC32=bscmake.exe | |||
# ADD BASE BSC32 /nologo | |||
# ADD BSC32 /nologo | |||
LINK32=link.exe | |||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept | |||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept | |||
!ENDIF | |||
# Begin Target | |||
# Name "time_test - Win32 Release" | |||
# Name "time_test - Win32 Debug" | |||
# Begin Group "Source Files" | |||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" | |||
# Begin Source File | |||
SOURCE="..\..\sample\time-test.c" | |||
# End Source File | |||
# End Group | |||
# Begin Group "Header Files" | |||
# PROP Default_Filter "h;hpp;hxx;hm;inl" | |||
# End Group | |||
# Begin Group "Resource Files" | |||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" | |||
# End Group | |||
# End Target | |||
# End Project |
@@ -21,13 +21,13 @@ if test "$GCC" = yes ; then | |||
CFLAGS="$CFLAGS -Wall" | |||
fi | |||
AC_PROG_LIBTOOL | |||
AC_PROG_RANLIB | |||
dnl Uncomment "AC_DISABLE_SHARED" to make shared librraries not get | |||
dnl built by default. You can also turn shared libs on and off from | |||
dnl the command line with --enable-shared and --disable-shared. | |||
dnl AC_DISABLE_SHARED | |||
AC_SUBST(LIBTOOL_DEPS) | |||
dnl AC_SUBST(LIBTOOL_DEPS) | |||
dnl Check for optional stuff | |||
AC_ARG_WITH(rtsig, | |||
@@ -133,7 +133,7 @@ AC_HEADER_TIME | |||
dnl Checks for library functions. | |||
AC_CHECK_FUNCS(gettimeofday vasprintf fcntl clock_gettime strtok_r) | |||
AC_REPLACE_FUNCS(strlcpy) | |||
dnl AC_REPLACE_FUNCS(strlcpy) | |||
if test "x$ac_cv_func_clock_gettime" = "xyes"; then | |||
AC_DEFINE(DNS_USE_CPU_CLOCK_FOR_ID, 1, [Define if clock_gettime is available in libc]) | |||
@@ -369,4 +369,4 @@ AC_TRY_COMPILE([], | |||
[Define to appropriate substitue if compiler doesnt have __func__]))) | |||
AC_OUTPUT(Makefile test/Makefile sample/Makefile) | |||
AC_OUTPUT(Makefile) |
@@ -1,413 +0,0 @@ | |||
/* | |||
* Copyright (c) 2002-2004 Niels Provos <provos@citi.umich.edu> | |||
* All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in the | |||
* documentation and/or other materials provided with the distribution. | |||
* 3. The name of the author may not be used to endorse or promote products | |||
* derived from this software without specific prior written permission. | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
*/ | |||
#include <sys/types.h> | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
#ifdef HAVE_SYS_TIME_H | |||
#include <sys/time.h> | |||
#endif | |||
#include <errno.h> | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
#ifdef HAVE_STDARG_H | |||
#include <stdarg.h> | |||
#endif | |||
#include "event.h" | |||
/* prototypes */ | |||
void bufferevent_setwatermark(struct bufferevent *, short, size_t, size_t); | |||
void bufferevent_read_pressure_cb(struct evbuffer *, size_t, size_t, void *); | |||
static int | |||
bufferevent_add(struct event *ev, int timeout) | |||
{ | |||
struct timeval tv, *ptv = NULL; | |||
if (timeout) { | |||
timerclear(&tv); | |||
tv.tv_sec = timeout; | |||
ptv = &tv; | |||
} | |||
return (event_add(ev, ptv)); | |||
} | |||
/* | |||
* This callback is executed when the size of the input buffer changes. | |||
* We use it to apply back pressure on the reading side. | |||
*/ | |||
void | |||
bufferevent_read_pressure_cb(struct evbuffer *buf, size_t old, size_t now, | |||
void *arg) { | |||
struct bufferevent *bufev = arg; | |||
/* | |||
* If we are below the watermark then reschedule reading if it's | |||
* still enabled. | |||
*/ | |||
if (bufev->wm_read.high == 0 || now < bufev->wm_read.high) { | |||
evbuffer_setcb(buf, NULL, NULL); | |||
if (bufev->enabled & EV_READ) | |||
bufferevent_add(&bufev->ev_read, bufev->timeout_read); | |||
} | |||
} | |||
static void | |||
bufferevent_readcb(int fd, short event, void *arg) | |||
{ | |||
struct bufferevent *bufev = arg; | |||
int res = 0; | |||
short what = EVBUFFER_READ; | |||
size_t len; | |||
int howmuch = -1; | |||
if (event == EV_TIMEOUT) { | |||
what |= EVBUFFER_TIMEOUT; | |||
goto error; | |||
} | |||
/* | |||
* If we have a high watermark configured then we don't want to | |||
* read more data than would make us reach the watermark. | |||
*/ | |||
if (bufev->wm_read.high != 0) | |||
howmuch = bufev->wm_read.high; | |||
res = evbuffer_read(bufev->input, fd, howmuch); | |||
if (res == -1) { | |||
if (errno == EAGAIN || errno == EINTR) | |||
goto reschedule; | |||
/* error case */ | |||
what |= EVBUFFER_ERROR; | |||
} else if (res == 0) { | |||
/* eof case */ | |||
what |= EVBUFFER_EOF; | |||
} | |||
if (res <= 0) | |||
goto error; | |||
bufferevent_add(&bufev->ev_read, bufev->timeout_read); | |||
/* See if this callbacks meets the water marks */ | |||
len = EVBUFFER_LENGTH(bufev->input); | |||
if (bufev->wm_read.low != 0 && len < bufev->wm_read.low) | |||
return; | |||
if (bufev->wm_read.high != 0 && len > bufev->wm_read.high) { | |||
struct evbuffer *buf = bufev->input; | |||
event_del(&bufev->ev_read); | |||
/* Now schedule a callback for us */ | |||
evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev); | |||
return; | |||
} | |||
/* Invoke the user callback - must always be called last */ | |||
if (bufev->readcb != NULL) | |||
(*bufev->readcb)(bufev, bufev->cbarg); | |||
return; | |||
reschedule: | |||
bufferevent_add(&bufev->ev_read, bufev->timeout_read); | |||
return; | |||
error: | |||
(*bufev->errorcb)(bufev, what, bufev->cbarg); | |||
} | |||
static void | |||
bufferevent_writecb(int fd, short event, void *arg) | |||
{ | |||
struct bufferevent *bufev = arg; | |||
int res = 0; | |||
short what = EVBUFFER_WRITE; | |||
if (event == EV_TIMEOUT) { | |||
what |= EVBUFFER_TIMEOUT; | |||
goto error; | |||
} | |||
if (EVBUFFER_LENGTH(bufev->output)) { | |||
res = evbuffer_write(bufev->output, fd); | |||
if (res == -1) { | |||
#ifndef WIN32 | |||
/*todo. evbuffer uses WriteFile when WIN32 is set. WIN32 system calls do not | |||
*set errno. thus this error checking is not portable*/ | |||
if (errno == EAGAIN || | |||
errno == EINTR || | |||
errno == EINPROGRESS) | |||
goto reschedule; | |||
/* error case */ | |||
what |= EVBUFFER_ERROR; | |||
#else | |||
goto reschedule; | |||
#endif | |||
} else if (res == 0) { | |||
/* eof case */ | |||
what |= EVBUFFER_EOF; | |||
} | |||
if (res <= 0) | |||
goto error; | |||
} | |||
if (EVBUFFER_LENGTH(bufev->output) != 0) | |||
bufferevent_add(&bufev->ev_write, bufev->timeout_write); | |||
/* | |||
* Invoke the user callback if our buffer is drained or below the | |||
* low watermark. | |||
*/ | |||
if (bufev->writecb != NULL && | |||
EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low) | |||
(*bufev->writecb)(bufev, bufev->cbarg); | |||
return; | |||
reschedule: | |||
if (EVBUFFER_LENGTH(bufev->output) != 0) | |||
bufferevent_add(&bufev->ev_write, bufev->timeout_write); | |||
return; | |||
error: | |||
(*bufev->errorcb)(bufev, what, bufev->cbarg); | |||
} | |||
/* | |||
* Create a new buffered event object. | |||
* | |||
* The read callback is invoked whenever we read new data. | |||
* The write callback is invoked whenever the output buffer is drained. | |||
* The error callback is invoked on a write/read error or on EOF. | |||
* | |||
* Both read and write callbacks maybe NULL. The error callback is not | |||
* allowed to be NULL and have to be provided always. | |||
*/ | |||
struct bufferevent * | |||
bufferevent_new(int fd, evbuffercb readcb, evbuffercb writecb, | |||
everrorcb errorcb, void *cbarg) | |||
{ | |||
struct bufferevent *bufev; | |||
if ((bufev = calloc(1, sizeof(struct bufferevent))) == NULL) | |||
return (NULL); | |||
if ((bufev->input = evbuffer_new()) == NULL) { | |||
free(bufev); | |||
return (NULL); | |||
} | |||
if ((bufev->output = evbuffer_new()) == NULL) { | |||
evbuffer_free(bufev->input); | |||
free(bufev); | |||
return (NULL); | |||
} | |||
event_set(&bufev->ev_read, fd, EV_READ, bufferevent_readcb, bufev); | |||
event_set(&bufev->ev_write, fd, EV_WRITE, bufferevent_writecb, bufev); | |||
bufev->readcb = readcb; | |||
bufev->writecb = writecb; | |||
bufev->errorcb = errorcb; | |||
bufev->cbarg = cbarg; | |||
/* | |||
* Set to EV_WRITE so that using bufferevent_write is going to | |||
* trigger a callback. Reading needs to be explicitly enabled | |||
* because otherwise no data will be available. | |||
*/ | |||
bufev->enabled = EV_WRITE; | |||
return (bufev); | |||
} | |||
int | |||
bufferevent_priority_set(struct bufferevent *bufev, int priority) | |||
{ | |||
if (event_priority_set(&bufev->ev_read, priority) == -1) | |||
return (-1); | |||
if (event_priority_set(&bufev->ev_write, priority) == -1) | |||
return (-1); | |||
return (0); | |||
} | |||
/* Closing the file descriptor is the responsibility of the caller */ | |||
void | |||
bufferevent_free(struct bufferevent *bufev) | |||
{ | |||
event_del(&bufev->ev_read); | |||
event_del(&bufev->ev_write); | |||
evbuffer_free(bufev->input); | |||
evbuffer_free(bufev->output); | |||
free(bufev); | |||
} | |||
/* | |||
* Returns 0 on success; | |||
* -1 on failure. | |||
*/ | |||
int | |||
bufferevent_write(struct bufferevent *bufev, void *data, size_t size) | |||
{ | |||
int res; | |||
res = evbuffer_add(bufev->output, data, size); | |||
if (res == -1) | |||
return (res); | |||
/* If everything is okay, we need to schedule a write */ | |||
if (size > 0 && (bufev->enabled & EV_WRITE)) | |||
bufferevent_add(&bufev->ev_write, bufev->timeout_write); | |||
return (res); | |||
} | |||
int | |||
bufferevent_write_buffer(struct bufferevent *bufev, struct evbuffer *buf) | |||
{ | |||
int res; | |||
res = bufferevent_write(bufev, buf->buffer, buf->off); | |||
if (res != -1) | |||
evbuffer_drain(buf, buf->off); | |||
return (res); | |||
} | |||
size_t | |||
bufferevent_read(struct bufferevent *bufev, void *data, size_t size) | |||
{ | |||
struct evbuffer *buf = bufev->input; | |||
if (buf->off < size) | |||
size = buf->off; | |||
/* Copy the available data to the user buffer */ | |||
memcpy(data, buf->buffer, size); | |||
if (size) | |||
evbuffer_drain(buf, size); | |||
return (size); | |||
} | |||
int | |||
bufferevent_enable(struct bufferevent *bufev, short event) | |||
{ | |||
if (event & EV_READ) { | |||
if (bufferevent_add(&bufev->ev_read, bufev->timeout_read) == -1) | |||
return (-1); | |||
} | |||
if (event & EV_WRITE) { | |||
if (bufferevent_add(&bufev->ev_write, bufev->timeout_write) == -1) | |||
return (-1); | |||
} | |||
bufev->enabled |= event; | |||
return (0); | |||
} | |||
int | |||
bufferevent_disable(struct bufferevent *bufev, short event) | |||
{ | |||
if (event & EV_READ) { | |||
if (event_del(&bufev->ev_read) == -1) | |||
return (-1); | |||
} | |||
if (event & EV_WRITE) { | |||
if (event_del(&bufev->ev_write) == -1) | |||
return (-1); | |||
} | |||
bufev->enabled &= ~event; | |||
return (0); | |||
} | |||
/* | |||
* Sets the read and write timeout for a buffered event. | |||
*/ | |||
void | |||
bufferevent_settimeout(struct bufferevent *bufev, | |||
int timeout_read, int timeout_write) { | |||
bufev->timeout_read = timeout_read; | |||
bufev->timeout_write = timeout_write; | |||
} | |||
/* | |||
* Sets the water marks | |||
*/ | |||
void | |||
bufferevent_setwatermark(struct bufferevent *bufev, short events, | |||
size_t lowmark, size_t highmark) | |||
{ | |||
if (events & EV_READ) { | |||
bufev->wm_read.low = lowmark; | |||
bufev->wm_read.high = highmark; | |||
} | |||
if (events & EV_WRITE) { | |||
bufev->wm_write.low = lowmark; | |||
bufev->wm_write.high = highmark; | |||
} | |||
/* If the watermarks changed then see if we should call read again */ | |||
bufferevent_read_pressure_cb(bufev->input, | |||
0, EVBUFFER_LENGTH(bufev->input), bufev); | |||
} | |||
int | |||
bufferevent_base_set(struct event_base *base, struct bufferevent *bufev) | |||
{ | |||
int res; | |||
res = event_base_set(base, &bufev->ev_read); | |||
if (res == -1) | |||
return (res); | |||
res = event_base_set(base, &bufev->ev_write); | |||
return (res); | |||
} |
@@ -1,322 +0,0 @@ | |||
.\" | |||
.\" Copyright (c) 2006 Niels Provos <provos@citi.umich.edu> | |||
.\" All rights reserved. | |||
.\" | |||
.\" Redistribution and use in source and binary forms, with or without | |||
.\" modification, are permitted provided that the following conditions | |||
.\" are met: | |||
.\" | |||
.\" 1. Redistributions of source code must retain the above copyright | |||
.\" notice, this list of conditions and the following disclaimer. | |||
.\" 2. Redistributions in binary form must reproduce the above copyright | |||
.\" notice, this list of conditions and the following disclaimer in the | |||
.\" documentation and/or other materials provided with the distribution. | |||
.\" 3. The name of the author may not be used to endorse or promote products | |||
.\" derived from this software without specific prior written permission. | |||
.\" | |||
.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, | |||
.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY | |||
.\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | |||
.\" THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |||
.\" EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |||
.\" PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |||
.\" OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |||
.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |||
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |||
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
.\" | |||
.Dd October 7, 2006 | |||
.Dt EVDNS 3 | |||
.Os | |||
.Sh NAME | |||
.Nm evdns_init | |||
.Nm evdns_shutdown | |||
.Nm evdns_err_to_string | |||
.Nm evdns_nameserver_add | |||
.Nm evdns_count_nameservers | |||
.Nm evdns_clear_nameservers_and_suspend | |||
.Nm evdns_resume | |||
.Nm evdns_nameserver_ip_add | |||
.Nm evdns_resolve_ipv4 | |||
.Nm evdns_resolve_reverse | |||
.Nm evdns_resolv_conf_parse | |||
.Nm evdns_config_windows_nameservers | |||
.Nm evdns_search_clear | |||
.Nm evdns_search_add | |||
.Nm evdns_search_ndots_set | |||
.Nm evdns_set_log_fn | |||
.Nd asynchronous functions for DNS resolution. | |||
.Sh SYNOPSIS | |||
.Fd #include <sys/time.h> | |||
.Fd #include <event.h> | |||
.Fd #include <evdns.h> | |||
.Ft int | |||
.Fn evdns_init | |||
.Ft void | |||
.Fn evdns_shutdown "int fail_requests" | |||
.Ft "const char *" | |||
.Fn evdns_err_to_string "int err" | |||
.Ft int | |||
.Fn evdns_nameserver_add "unsigned long int address" | |||
.Ft int | |||
.Fn evdns_count_nameservers | |||
.Ft int | |||
.Fn evdns_clear_nameservers_and_suspend | |||
.Ft int | |||
.Fn evdns_resume | |||
.Ft int | |||
.Fn evdns_nameserver_ip_add(const char *ip_as_string); | |||
.Ft int | |||
.Fn evdns_resolve_ipv4 "const char *name" "int flags" "evdns_callback_type callback" "void *ptr" | |||
.Ft int | |||
.Fn evdns_resolve_reverse "struct in_addr *in" "int flags" "evdns_callback_type callback" "void *ptr" | |||
.Ft int | |||
.Fn evdns_resolv_conf_parse "int flags" "const char *" | |||
.Ft void | |||
.Fn evdns_search_clear | |||
.Ft void | |||
.Fn evdns_search_add "const char *domain" | |||
.Ft void | |||
.Fn evdns_search_ndots_set "const int ndots" | |||
.Ft void | |||
.Fn evdns_set_log_fn "evdns_debug_log_fn_type fn" | |||
.Ft int | |||
.Fn evdns_config_windows_nameservers | |||
.Sh DESCRIPTION | |||
Welcome, gentle reader | |||
.Pp | |||
Async DNS lookups are really a whole lot harder than they should be, | |||
mostly stemming from the fact that the libc resolver has never been | |||
very good at them. Before you use this library you should see if libc | |||
can do the job for you with the modern async call getaddrinfo_a | |||
(see http://www.imperialviolet.org/page25.html#e498). Otherwise, | |||
please continue. | |||
.Pp | |||
This code is based on libevent and you must call event_init before | |||
any of the APIs in this file. You must also seed the OpenSSL random | |||
source if you are using OpenSSL for ids (see below). | |||
.Pp | |||
This library is designed to be included and shipped with your source | |||
code. You statically link with it. You should also test for the | |||
existence of strtok_r and define HAVE_STRTOK_R if you have it. | |||
.Pp | |||
The DNS protocol requires a good source of id numbers and these | |||
numbers should be unpredictable for spoofing reasons. There are | |||
three methods for generating them here and you must define exactly | |||
one of them. In increasing order of preference: | |||
.Pp | |||
.Bl -tag -width "DNS_USE_GETTIMEOFDAY_FOR_ID" -compact -offset indent | |||
.It DNS_USE_GETTIMEOFDAY_FOR_ID | |||
Using the bottom 16 bits of the usec result from gettimeofday. This | |||
is a pretty poor solution but should work anywhere. | |||
.It DNS_USE_CPU_CLOCK_FOR_ID | |||
Using the bottom 16 bits of the nsec result from the CPU's time | |||
counter. This is better, but may not work everywhere. Requires | |||
POSIX realtime support and you'll need to link against -lrt on | |||
glibc systems at least. | |||
.It DNS_USE_OPENSSL_FOR_ID | |||
Uses the OpenSSL RAND_bytes call to generate the data. You must | |||
have seeded the pool before making any calls to this library. | |||
.El | |||
.Pp | |||
The library keeps track of the state of nameservers and will avoid | |||
them when they go down. Otherwise it will round robin between them. | |||
.Pp | |||
Quick start guide: | |||
#include "evdns.h" | |||
void callback(int result, char type, int count, int ttl, | |||
void *addresses, void *arg); | |||
evdns_resolv_conf_parse(DNS_OPTIONS_ALL, "/etc/resolv.conf"); | |||
evdns_resolve("www.hostname.com", 0, callback, NULL); | |||
.Pp | |||
When the lookup is complete the callback function is called. The | |||
first argument will be one of the DNS_ERR_* defines in evdns.h. | |||
Hopefully it will be DNS_ERR_NONE, in which case type will be | |||
DNS_IPv4_A, count will be the number of IP addresses, ttl is the time | |||
which the data can be cached for (in seconds), addresses will point | |||
to an array of uint32_t's and arg will be whatever you passed to | |||
evdns_resolve. | |||
.Pp | |||
Searching: | |||
.Pp | |||
In order for this library to be a good replacement for glibc's resolver it | |||
supports searching. This involves setting a list of default domains, in | |||
which names will be queried for. The number of dots in the query name | |||
determines the order in which this list is used. | |||
.Pp | |||
Searching appears to be a single lookup from the point of view of the API, | |||
although many DNS queries may be generated from a single call to | |||
evdns_resolve. Searching can also drastically slow down the resolution | |||
of names. | |||
.Pp | |||
To disable searching: | |||
.Bl -enum -compact -offset indent | |||
.It | |||
Never set it up. If you never call | |||
.Fn evdns_resolv_conf_parse, | |||
.Fn evdns_init, | |||
or | |||
.Fn evdns_search_add | |||
then no searching will occur. | |||
.It | |||
If you do call | |||
.Fn evdns_resolv_conf_parse | |||
then don't pass | |||
.Va DNS_OPTION_SEARCH | |||
(or | |||
.Va DNS_OPTIONS_ALL, | |||
which implies it). | |||
.It | |||
When calling | |||
.Fn evdns_resolve, | |||
pass the | |||
.Va DNS_QUERY_NO_SEARCH | |||
flag. | |||
.El | |||
.Pp | |||
The order of searches depends on the number of dots in the name. If the | |||
number is greater than the ndots setting then the names is first tried | |||
globally. Otherwise each search domain is appended in turn. | |||
.Pp | |||
The ndots setting can either be set from a resolv.conf, or by calling | |||
evdns_search_ndots_set. | |||
.Pp | |||
For example, with ndots set to 1 (the default) and a search domain list of | |||
["myhome.net"]: | |||
Query: www | |||
Order: www.myhome.net, www. | |||
.Pp | |||
Query: www.abc | |||
Order: www.abc., www.abc.myhome.net | |||
.Pp | |||
.Sh API reference | |||
.Pp | |||
.Bl -tag -width 0123456 | |||
.It Ft int Fn evdns_init | |||
Initializes support for non-blocking name resolution by calling | |||
.Fn evdns_resolv_conf_parse | |||
on UNIX and | |||
.Fn evdns_config_windows_nameservers | |||
on Windows. | |||
.It Ft int Fn evdns_nameserver_add "unsigned long int address" | |||
Add a nameserver. The address should be an IP address in | |||
network byte order. The type of address is chosen so that | |||
it matches in_addr.s_addr. | |||
Returns non-zero on error. | |||
.It Ft int Fn evdns_nameserver_ip_add "const char *ip_as_string" | |||
This wraps the above function by parsing a string as an IP | |||
address and adds it as a nameserver. | |||
Returns non-zero on error | |||
.It Ft int Fn evdns_resolve "const char *name" "int flags" "evdns_callback_type callback" "void *ptr" | |||
Resolve a name. The name parameter should be a DNS name. | |||
The flags parameter should be 0, or DNS_QUERY_NO_SEARCH | |||
which disables searching for this query. (see defn of | |||
searching above). | |||
.Pp | |||
The callback argument is a function which is called when | |||
this query completes and ptr is an argument which is passed | |||
to that callback function. | |||
.Pp | |||
Returns non-zero on error | |||
.It Ft void Fn evdns_search_clear | |||
Clears the list of search domains | |||
.It Ft void Fn evdns_search_add "const char *domain" | |||
Add a domain to the list of search domains | |||
.It Ft void Fn evdns_search_ndots_set "int ndots" | |||
Set the number of dots which, when found in a name, causes | |||
the first query to be without any search domain. | |||
.It Ft int Fn evdns_count_nameservers "void" | |||
Return the number of configured nameservers (not necessarily the | |||
number of running nameservers). This is useful for double-checking | |||
whether our calls to the various nameserver configuration functions | |||
have been successful. | |||
.It Ft int Fn evdns_clear_nameservers_and_suspend "void" | |||
Remove all currently configured nameservers, and suspend all pending | |||
resolves. Resolves will not necessarily be re-attempted until | |||
evdns_resume() is called. | |||
.It Ft int Fn evdns_resume "void" | |||
Re-attempt resolves left in limbo after an earlier call to | |||
evdns_clear_nameservers_and_suspend(). | |||
.It Ft int Fn evdns_config_windows_nameservers "void" | |||
Attempt to configure a set of nameservers based on platform settings on | |||
a win32 host. Preferentially tries to use GetNetworkParams; if that fails, | |||
looks in the registry. Returns 0 on success, nonzero on failure. | |||
.It Ft int Fn evdns_resolv_conf_parse "int flags" "const char *filename" | |||
Parse a resolv.conf like file from the given filename. | |||
.Pp | |||
See the man page for resolv.conf for the format of this file. | |||
The flags argument determines what information is parsed from | |||
this file: | |||
.Bl -tag -width "DNS_OPTION_NAMESERVERS" -offset indent -compact -nested | |||
.It DNS_OPTION_SEARCH | |||
domain, search and ndots options | |||
.It DNS_OPTION_NAMESERVERS | |||
nameserver lines | |||
.It DNS_OPTION_MISC | |||
timeout and attempts options | |||
.It DNS_OPTIONS_ALL | |||
all of the above | |||
.El | |||
.Pp | |||
The following directives are not parsed from the file: | |||
sortlist, rotate, no-check-names, inet6, debug | |||
.Pp | |||
Returns non-zero on error: | |||
.Bl -tag -width "0" -offset indent -compact -nested | |||
.It 0 | |||
no errors | |||
.It 1 | |||
failed to open file | |||
.It 2 | |||
failed to stat file | |||
.It 3 | |||
file too large | |||
.It 4 | |||
out of memory | |||
.It 5 | |||
short read from file | |||
.El | |||
.El | |||
.Sh Internals: | |||
Requests are kept in two queues. The first is the inflight queue. In | |||
this queue requests have an allocated transaction id and nameserver. | |||
They will soon be transmitted if they haven't already been. | |||
.Pp | |||
The second is the waiting queue. The size of the inflight ring is | |||
limited and all other requests wait in waiting queue for space. This | |||
bounds the number of concurrent requests so that we don't flood the | |||
nameserver. Several algorithms require a full walk of the inflight | |||
queue and so bounding its size keeps thing going nicely under huge | |||
(many thousands of requests) loads. | |||
.Pp | |||
If a nameserver loses too many requests it is considered down and we | |||
try not to use it. After a while we send a probe to that nameserver | |||
(a lookup for google.com) and, if it replies, we consider it working | |||
again. If the nameserver fails a probe we wait longer to try again | |||
with the next probe. | |||
.Sh SEE ALSO | |||
.Xr event 3 , | |||
.Xr gethostbyname 3 , | |||
.Xr resolv.conf 5 | |||
.Sh HISTORY | |||
The | |||
.Nm evdns | |||
API was developed by Adam Langley on top of the | |||
.Nm libevent | |||
API. | |||
The code was integrate into | |||
.Nm Tor | |||
by Nick Mathewson and finally put into | |||
.Nm libevent | |||
itself by Niels Provos. | |||
.Sh AUTHORS | |||
The | |||
.Nm evdns | |||
API and code was written by Adam Langley with significant | |||
contributions by Nick Mathewson. | |||
.Sh BUGS | |||
This documentation is neither complete nor authoritative. | |||
If you are in doubt about the usage of this API then | |||
check the source code to find out how it works, write | |||
up the missing piece of documentation and send it to | |||
me for inclusion in this man page. |
@@ -1,578 +0,0 @@ | |||
.\" $OpenBSD: event.3,v 1.4 2002/07/12 18:50:48 provos Exp $ | |||
.\" | |||
.\" Copyright (c) 2000 Artur Grabowski <art@openbsd.org> | |||
.\" All rights reserved. | |||
.\" | |||
.\" Redistribution and use in source and binary forms, with or without | |||
.\" modification, are permitted provided that the following conditions | |||
.\" are met: | |||
.\" | |||
.\" 1. Redistributions of source code must retain the above copyright | |||
.\" notice, this list of conditions and the following disclaimer. | |||
.\" 2. Redistributions in binary form must reproduce the above copyright | |||
.\" notice, this list of conditions and the following disclaimer in the | |||
.\" documentation and/or other materials provided with the distribution. | |||
.\" 3. The name of the author may not be used to endorse or promote products | |||
.\" derived from this software without specific prior written permission. | |||
.\" | |||
.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, | |||
.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY | |||
.\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | |||
.\" THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |||
.\" EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |||
.\" PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |||
.\" OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |||
.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |||
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |||
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
.\" | |||
.Dd August 8, 2000 | |||
.Dt EVENT 3 | |||
.Os | |||
.Sh NAME | |||
.Nm event_init , | |||
.Nm event_dispatch , | |||
.Nm event_loop , | |||
.Nm event_loopexit , | |||
.Nm event_set , | |||
.Nm event_base_dispatch , | |||
.Nm event_base_loop , | |||
.Nm event_base_loopexit , | |||
.Nm event_base_set , | |||
.Nm event_add , | |||
.Nm event_del , | |||
.Nm event_once , | |||
.Nm event_pending , | |||
.Nm event_initialized , | |||
.Nm event_priority_init , | |||
.Nm event_priority_set , | |||
.Nm evtimer_set , | |||
.Nm evtimer_add , | |||
.Nm evtimer_del , | |||
.Nm evtimer_pending , | |||
.Nm evtimer_initialized , | |||
.Nm signal_set , | |||
.Nm signal_add , | |||
.Nm signal_del , | |||
.Nm signal_pending , | |||
.Nm signal_initialized , | |||
.Nm bufferevent_new , | |||
.Nm bufferevent_free , | |||
.Nm bufferevent_write , | |||
.Nm bufferevent_write_buffer , | |||
.Nm bufferevent_read , | |||
.Nm bufferevent_enable , | |||
.Nm bufferevent_disable , | |||
.Nm bufferevent_settimeout , | |||
.Nm bufferevent_base_set , | |||
.Nm evbuffer_new , | |||
.Nm evbuffer_free , | |||
.Nm evbuffer_add , | |||
.Nm evbuffer_add_buffer , | |||
.Nm evbuffer_add_printf , | |||
.Nm evbuffer_add_vprintf , | |||
.Nm evbuffer_drain , | |||
.Nm evbuffer_write , | |||
.Nm evbuffer_read , | |||
.Nm evbuffer_find , | |||
.Nm evbuffer_readline , | |||
.Nm evhttp_start , | |||
.Nm evhttp_free | |||
.Nd execute a function when a specific event occurs | |||
.Sh SYNOPSIS | |||
.Fd #include <sys/time.h> | |||
.Fd #include <event.h> | |||
.Ft "struct event_base *" | |||
.Fn "event_init" | |||
.Ft int | |||
.Fn "event_dispatch" | |||
.Ft int | |||
.Fn "event_loop" "int flags" | |||
.Ft int | |||
.Fn "event_loopexit" "struct timeval *tv" | |||
.Ft void | |||
.Fn "event_set" "struct event *ev" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg" | |||
.Ft int | |||
.Fn "event_base_dispatch" "struct event_base *base" | |||
.Ft int | |||
.Fn "event_base_loop" "struct event_base *base" "int flags" | |||
.Ft int | |||
.Fn "event_base_loopexit" "struct event_base *base" "struct timeval *tv" | |||
.Ft int | |||
.Fn "event_base_set" "struct event_base *base" "struct event *" | |||
.Ft int | |||
.Fn "event_add" "struct event *ev" "struct timeval *tv" | |||
.Ft int | |||
.Fn "event_del" "struct event *ev" | |||
.Ft int | |||
.Fn "event_once" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg" "struct timeval *tv" | |||
.Ft int | |||
.Fn "event_pending" "struct event *ev" "short event" "struct timeval *tv" | |||
.Ft int | |||
.Fn "event_initialized" "struct event *ev" | |||
.Ft int | |||
.Fn "event_priority_init" "int npriorities" | |||
.Ft int | |||
.Fn "event_priority_set" "struct event *ev" "int priority" | |||
.Ft void | |||
.Fn "evtimer_set" "struct event *ev" "void (*fn)(int, short, void *)" "void *arg" | |||
.Ft void | |||
.Fn "evtimer_add" "struct event *ev" "struct timeval *" | |||
.Ft void | |||
.Fn "evtimer_del" "struct event *ev" | |||
.Ft int | |||
.Fn "evtimer_pending" "struct event *ev" "struct timeval *tv" | |||
.Ft int | |||
.Fn "evtimer_initialized" "struct event *ev" | |||
.Ft void | |||
.Fn "signal_set" "struct event *ev" "int signal" "void (*fn)(int, short, void *)" "void *arg" | |||
.Ft void | |||
.Fn "signal_add" "struct event *ev" "struct timeval *" | |||
.Ft void | |||
.Fn "signal_del" "struct event *ev" | |||
.Ft int | |||
.Fn "signal_pending" "struct event *ev" "struct timeval *tv" | |||
.Ft int | |||
.Fn "signal_initialized" "struct event *ev" | |||
.Ft "struct bufferevent *" | |||
.Fn "bufferevent_new" "int fd" "evbuffercb readcb" "evbuffercb writecb" "everrorcb" "void *cbarg" | |||
.Ft void | |||
.Fn "bufferevent_free" "struct bufferevent *bufev" | |||
.Ft int | |||
.Fn "bufferevent_write" "struct bufferevent *bufev" "void *data" "size_t size" | |||
.Ft int | |||
.Fn "bufferevent_write_buffer" "struct bufferevent *bufev" "struct evbuffer *buf" | |||
.Ft size_t | |||
.Fn "bufferevent_read" "struct bufferevent *bufev" "void *data" "size_t size" | |||
.Ft int | |||
.Fn "bufferevent_enable" "struct bufferevent *bufev" "short event" | |||
.Ft int | |||
.Fn "bufferevent_disable" "struct bufferevent *bufev" "short event" | |||
.Ft void | |||
.Fn "bufferevent_settimeout" "struct bufferevent *bufev" "int timeout_read" "int timeout_write" | |||
.Ft int | |||
.Fn "bufferevent_base_set" "struct event_base *base" "struct bufferevent *bufev" | |||
.Ft "struct evbuffer *" | |||
.Fn "evbuffer_new" "void" | |||
.Ft void | |||
.Fn "evbuffer_free" "struct evbuffer *buf" | |||
.Ft int | |||
.Fn "evbuffer_add" "struct evbuffer *buf" "u_char *data" "size_t size" | |||
.Ft int | |||
.Fn "evbuffer_add_buffer" "struct evbuffer *dst" "struct evbuffer *src" | |||
.Ft int | |||
.Fn "evbuffer_add_printf" "struct evbuffer *buf" "char *fmt" "..." | |||
.Ft int | |||
.Fn "evbuffer_add_vprintf" "struct evbuffer *buf" "const char *fmt" "va_list ap" | |||
.Ft void | |||
.Fn "evbuffer_drain" "struct evbuffer *buf" "size_t size" | |||
.Ft int | |||
.Fn "evbuffer_write" "struct evbuffer *buf" "int fd" | |||
.Ft int | |||
.Fn "evbuffer_read" "struct evbuffer *buf" "int fd" "int size" | |||
.Ft "u_char *" | |||
.Fn "evbuffer_find" "struct evbuffer *buf" "u_char *data" "size_t size" | |||
.Ft "char *" | |||
.Fn "evbuffer_readline" "struct evbuffer *buf" | |||
.Ft "struct evhttp *" | |||
.Fn "evhttp_start" "const char *address" "u_short port" | |||
.Ft "void" | |||
.Fn "evhttp_free" "struct evhttp* http" | |||
.Ft int | |||
.Fa (*event_sigcb)(void) ; | |||
.Ft int | |||
.Fa event_gotsig ; | |||
.Sh DESCRIPTION | |||
The | |||
.Nm event | |||
API provides a mechanism to execute a function when a specific event | |||
on a file descriptor occurs or after a given time has passed. | |||
.Pp | |||
The | |||
.Nm event | |||
API needs to be initialized with | |||
.Fn event_init | |||
before it can be used. | |||
.Pp | |||
In order to process events, an application needs to call | |||
.Fn event_dispatch . | |||
This function only returns on error, and should replace the event core | |||
of the application program. | |||
.Pp | |||
In order to avoid races in signal handlers, the | |||
.Nm event | |||
API provides two variables: | |||
.Va event_sigcb | |||
and | |||
.Va event_gotsig . | |||
A signal handler | |||
sets | |||
.Va event_gotsig | |||
to indicate that a signal has been received. | |||
The application sets | |||
.Va event_sigcb | |||
to a callback function. | |||
After the signal handler sets | |||
.Va event_gotsig , | |||
.Nm event_dispatch | |||
will execute the callback function to process received signals. | |||
The callback returns 1 when no events are registered any more. | |||
It can return -1 to indicate an error to the | |||
.Nm event | |||
library, causing | |||
.Fn event_dispatch | |||
to terminate with | |||
.Va errno | |||
set to | |||
.Er EINTR . | |||
.Pp | |||
The | |||
.Nm event_loop | |||
function provides an interface for single pass execution of pending | |||
events. | |||
The flags | |||
.Va EVLOOP_ONCE | |||
and | |||
.Va EVLOOP_NONBLOCK | |||
are recognized. | |||
The | |||
.Nm event_loopexit | |||
function allows the loop to be terminated after some amount of time | |||
has passed. | |||
The parameter indicates the time after which the loop should terminate. | |||
.Pp | |||
It is the responsibility of the caller to provide these functions with | |||
pre-allocated event structures. | |||
.Pp | |||
The function | |||
.Fn event_set | |||
prepares the event structure | |||
.Fa ev | |||
to be used in future calls to | |||
.Fn event_add | |||
and | |||
.Fn event_del . | |||
The event will be prepared to call the function specified by the | |||
.Fa fn | |||
argument with an | |||
.Fa int | |||
argument indicating the file descriptor, a | |||
.Fa short | |||
argument indicating the type of event, and a | |||
.Fa void * | |||
argument given in the | |||
.Fa arg | |||
argument. | |||
The | |||
.Fa fd | |||
indicates the file descriptor that should be monitored for events. | |||
The events can be either | |||
.Va EV_READ , | |||
.Va EV_WRITE , | |||
or both, | |||
indicating that an application can read or write from the file descriptor | |||
respectively without blocking. | |||
.Pp | |||
The function | |||
.Fa fn | |||
will be called with the file descriptor that triggered the event and | |||
the type of event which will be either | |||
.Va EV_TIMEOUT , | |||
.Va EV_SIGNAL , | |||
.Va EV_READ , | |||
or | |||
.Va EV_WRITE . | |||
The additional flag | |||
.Va EV_PERSIST | |||
makes an | |||
.Fn event_add | |||
persistent until | |||
.Fn event_del | |||
has been called. | |||
.Pp | |||
Once initialized, the | |||
.Fa ev | |||
structure can be used repeatedly with | |||
.Fn event_add | |||
and | |||
.Fn event_del | |||
and does not need to be reinitialized unless the function called and/or | |||
the argument to it are to be changed. | |||
However, when an | |||
.Fa ev | |||
structure has been added to libevent using | |||
.Fn event_add | |||
the structure must persist until the event occurs (assuming | |||
.Fa EV_PERSIST | |||
is not set) or is removed | |||
using | |||
.Fn event_del . | |||
You may not reuse the same | |||
.Fa ev | |||
structure for multiple monitored descriptors; each descriptor | |||
needs its own | |||
.Fa ev . | |||
.Pp | |||
The function | |||
.Fn event_add | |||
schedules the execution of the | |||
.Fa ev | |||
event when the event specified in | |||
.Fn event_set | |||
occurs or in at least the time specified in the | |||
.Fa tv . | |||
If | |||
.Fa tv | |||
is | |||
.Dv NULL , | |||
no timeout occurs and the function will only be called | |||
if a matching event occurs on the file descriptor. | |||
The event in the | |||
.Fa ev | |||
argument must be already initialized by | |||
.Fn event_set | |||
and may not be used in calls to | |||
.Fn event_set | |||
until it has timed out or been removed with | |||
.Fn event_del . | |||
If the event in the | |||
.Fa ev | |||
argument already has a scheduled timeout, the old timeout will be | |||
replaced by the new one. | |||
.Pp | |||
The function | |||
.Fn event_del | |||
will cancel the event in the argument | |||
.Fa ev . | |||
If the event has already executed or has never been added | |||
the call will have no effect. | |||
.Pp | |||
The function | |||
.Fn event_once | |||
is similar to | |||
.Fn event_set . | |||
However, it schedules a callback to be called exactly once and does not | |||
require the caller to prepare an | |||
.Fa event | |||
structure. | |||
This function supports | |||
.Fa EV_TIMEOUT , | |||
.Fa EV_READ , | |||
and | |||
.Fa EV_WRITE . | |||
.Pp | |||
The | |||
.Fn event_pending | |||
function can be used to check if the event specified by | |||
.Fa event | |||
is pending to run. | |||
If | |||
.Va EV_TIMEOUT | |||
was specified and | |||
.Fa tv | |||
is not | |||
.Dv NULL , | |||
the expiration time of the event will be returned in | |||
.Fa tv . | |||
.Pp | |||
The | |||
.Fn event_initialized | |||
macro can be used to check if an event has been initialized. | |||
.Pp | |||
The functions | |||
.Fn evtimer_set , | |||
.Fn evtimer_add , | |||
.Fn evtimer_del , | |||
.Fn evtimer_initialized , | |||
and | |||
.Fn evtimer_pending | |||
are abbreviations for common situations where only a timeout is required. | |||
The file descriptor passed will be \-1, and the event type will be | |||
.Va EV_TIMEOUT . | |||
.Pp | |||
The functions | |||
.Fn signal_set , | |||
.Fn signal_add , | |||
.Fn signal_del , | |||
.Fn signal_initialized , | |||
and | |||
.Fn signal_pending | |||
are abbreviations. | |||
The event type will be a persistent | |||
.Va EV_SIGNAL . | |||
That means | |||
.Fn signal_set | |||
adds | |||
.Va EV_PERSIST . | |||
.Pp | |||
It is possible to disable support for | |||
.Va epoll , kqueue , devpoll , poll | |||
or | |||
.Va select | |||
by setting the environment variable | |||
.Va EVENT_NOEPOLL , EVENT_NOKQUEUE , EVENT_NODEVPOLL , EVENT_NOPOLL | |||
or | |||
.Va EVENT_NOSELECT , | |||
respectively. | |||
By setting the environment variable | |||
.Va EVENT_SHOW_METHOD , | |||
.Nm libevent | |||
displays the kernel notification method that it uses. | |||
.Sh EVENT PRIORITIES | |||
By default | |||
.Nm libevent | |||
schedules all active events with the same priority. | |||
However, sometimes it is desirable to process some events with a higher | |||
priority than others. | |||
For that reason, | |||
.Nm libevent | |||
supports strict priority queues. | |||
Active events with a lower priority are always processed before events | |||
with a higher priority. | |||
.Pp | |||
The number of different priorities can be set initially with the | |||
.Fn event_priority_init | |||
function. | |||
This function should be called before the first call to | |||
.Fn event_dispatch . | |||
The | |||
.Fn event_priority_set | |||
function can be used to assign a priority to an event. | |||
By default, | |||
.Nm libevent | |||
assigns the middle priority to all events unless their priority | |||
is explicitly set. | |||
.Sh THREAD SAFE EVENTS | |||
.Nm Libevent | |||
has experimental support for thread-safe events. | |||
When initializing the library via | |||
.Fn event_init , | |||
an event base is returned. | |||
This event base can be used in conjunction with calls to | |||
.Fn event_base_set , | |||
.Fn event_base_dispatch , | |||
.Fn event_base_loop , | |||
.Fn event_base_loopexit , | |||
and | |||
.Fn bufferevent_base_set . | |||
.Fn event_base_set | |||
should be called after preparing an event with | |||
.Fn event_set , | |||
as | |||
.Fn event_set | |||
assigns the provided event to the most recently created event base. | |||
.Fn bufferevent_base_set | |||
should be called after preparing a bufferevent with | |||
.Fn bufferevent_new . | |||
.Sh BUFFERED EVENTS | |||
.Nm libevent | |||
provides an abstraction on top of the regular event callbacks. | |||
This abstraction is called a | |||
.Va "buffered event" . | |||
A buffered event provides input and output buffers that get filled | |||
and drained automatically. | |||
The user of a buffered event no longer deals directly with the IO, | |||
but instead is reading from input and writing to output buffers. | |||
.Pp | |||
A new bufferevent is created by | |||
.Fn bufferevent_new . | |||
The parameter | |||
.Fa fd | |||
specifies the file descriptor from which data is read and written to. | |||
This file descriptor is not allowed to be a | |||
.Xr pipe 2 . | |||
The next three parameters are callbacks. | |||
The read and write callback have the following form: | |||
.Ft void | |||
.Fn "(*cb)" "struct bufferevent *bufev" "void *arg" . | |||
The error callback has the following form: | |||
.Ft void | |||
.Fn "(*cb)" "struct bufferevent *bufev" "short what" "void *arg" . | |||
The argument is specified by the fourth parameter | |||
.Fa "cbarg" . | |||
A | |||
.Fa bufferevent struct | |||
pointer is returned on success, NULL on error. | |||
Both the read and the write callback may be NULL. | |||
The error callback has to be always provided. | |||
.Pp | |||
Once initialized, the bufferevent structure can be used repeatedly with | |||
bufferevent_enable() and bufferevent_disable(). The flags parameter can | |||
be a combination of | |||
.Va EV_READ | |||
and | |||
.Va EV_WRITE . | |||
When read enabled the bufferevent will try to read from the file | |||
descriptor and call the read callback. The write callback is executed | |||
whenever the output buffer is drained below the write low watermark, | |||
which is | |||
.Va 0 | |||
by default. | |||
.Pp | |||
The | |||
.Fn bufferevent_write | |||
function can be used to write data to the file descriptor. | |||
The data is appended to the output buffer and written to the descriptor | |||
automatically as it becomes available for writing. | |||
The | |||
.Fn bufferevent_read | |||
function is used to read data from the input buffer. | |||
Both functions return the amount of data written or read. | |||
.Pp | |||
If multiple bases are in use, bufferevent_base_set() must be called before | |||
enabling the bufferevent for the first time. | |||
.Sh NON-BLOCKING HTTP SUPPORT | |||
.Nm libevent | |||
provides a very thin HTTP layer that can be used both to host an HTTP | |||
server and also to make HTTP requests. | |||
An HTTP server can be created by calling | |||
.Fn evhttp_start . | |||
When the HTTP server is no longer used, it can be freed via | |||
.Fn evhttp_free . | |||
.Pp | |||
To be notified of HTTP requests, a user needs to register callbacks with the | |||
HTTP server. | |||
This can be done by calling | |||
.Fn evhttp_set_cb . | |||
The second argument is the URI for which a callback is being registered. | |||
The corresponding callback will receive an | |||
.Va struct evhttp_request | |||
object that contains all information about the request. | |||
.Pp | |||
This section does not document all the possible function calls, please | |||
check | |||
.Va event.h | |||
for the public interfaces. | |||
.Sh RETURN VALUES | |||
Upon successful completion | |||
.Fn event_add | |||
and | |||
.Fn event_del | |||
return 0. | |||
Otherwise, \-1 is returned and the global variable errno is | |||
set to indicate the error. | |||
.Sh SEE ALSO | |||
.Xr kqueue 2 , | |||
.Xr poll 2 , | |||
.Xr select 2 , | |||
.Xr timeout 9 | |||
.Sh HISTORY | |||
The | |||
.Nm event | |||
API manpage is based on the | |||
.Xr timeout 9 | |||
manpage by Artur Grabowski. | |||
The port of | |||
.Nm libevent | |||
to Windows is due to Michael A. Davis. | |||
Support for real-time signals is due to Taral. | |||
.Sh AUTHORS | |||
The | |||
.Nm event | |||
library was written by Niels Provos. | |||
.Sh BUGS | |||
This documentation is neither complete nor authoritative. | |||
If you are in doubt about the usage of this API then | |||
check the source code to find out how it works, write | |||
up the missing piece of documentation and send it to | |||
me for inclusion in this man page. |
@@ -1,360 +0,0 @@ | |||
/* | |||
* Copyright (c) 2003, 2004 Niels Provos <provos@citi.umich.edu> | |||
* All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in the | |||
* documentation and/or other materials provided with the distribution. | |||
* 3. The name of the author may not be used to endorse or promote products | |||
* derived from this software without specific prior written permission. | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
*/ | |||
#include <sys/types.h> | |||
#include <sys/param.h> | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
#include <sys/ioctl.h> | |||
#include <sys/tree.h> | |||
#include <sys/queue.h> | |||
#ifdef HAVE_SYS_TIME_H | |||
#include <sys/time.h> | |||
#endif | |||
#include <errno.h> | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
#include <syslog.h> | |||
#include <unistd.h> | |||
#include "event.h" | |||
#include "log.h" | |||
int decode_int(u_int32_t *pnumber, struct evbuffer *evbuf); | |||
static struct evbuffer *_buf; | |||
void | |||
evtag_init() | |||
{ | |||
if ((_buf = evbuffer_new()) == NULL) | |||
event_err(1, "%s: malloc", __func__); | |||
} | |||
/* | |||
* We encode integer's by nibbles; the first nibble contains the number | |||
* of significant nibbles - 1; this allows us to encode up to 64-bit | |||
* integers. This function is byte-order independent. | |||
*/ | |||
void | |||
encode_int(struct evbuffer *evbuf, u_int32_t number) | |||
{ | |||
int off = 1, nibbles = 0; | |||
u_int8_t data[5]; | |||
memset(data, 0, sizeof(data)); | |||
while (number) { | |||
if (off & 0x1) | |||
data[off/2] = (data[off/2] & 0xf0) | (number & 0x0f); | |||
else | |||
data[off/2] = (data[off/2] & 0x0f) | | |||
((number & 0x0f) << 4); | |||
number >>= 4; | |||
off++; | |||
} | |||
if (off > 2) | |||
nibbles = off - 2; | |||
/* Off - 1 is the number of encoded nibbles */ | |||
data[0] = (data[0] & 0x0f) | ((nibbles & 0x0f) << 4); | |||
evbuffer_add(evbuf, data, (off + 1) / 2); | |||
} | |||
/* | |||
* Marshal a data type, the general format is as follows: | |||
* | |||
* tag number: one byte; length: var bytes; payload: var bytes | |||
*/ | |||
void | |||
evtag_marshal(struct evbuffer *evbuf, u_int8_t tag, | |||
const void *data, u_int16_t len) | |||
{ | |||
evbuffer_add(evbuf, &tag, sizeof(tag)); | |||
encode_int(evbuf, len); | |||
evbuffer_add(evbuf, (void *)data, len); | |||
} | |||
/* Marshaling for integers */ | |||
void | |||
evtag_marshal_int(struct evbuffer *evbuf, u_int8_t tag, u_int32_t integer) | |||
{ | |||
evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf)); | |||
encode_int(_buf, integer); | |||
evbuffer_add(evbuf, &tag, sizeof(tag)); | |||
encode_int(evbuf, EVBUFFER_LENGTH(_buf)); | |||
evbuffer_add_buffer(evbuf, _buf); | |||
} | |||
void | |||
evtag_marshal_string(struct evbuffer *buf, u_int8_t tag, const char *string) | |||
{ | |||
evtag_marshal(buf, tag, string, strlen(string)); | |||
} | |||
void | |||
evtag_marshal_timeval(struct evbuffer *evbuf, u_int8_t tag, struct timeval *tv) | |||
{ | |||
evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf)); | |||
encode_int(_buf, tv->tv_sec); | |||
encode_int(_buf, tv->tv_usec); | |||
evtag_marshal(evbuf, tag, EVBUFFER_DATA(_buf), | |||
EVBUFFER_LENGTH(_buf)); | |||
} | |||
static int __inline | |||
decode_int_internal(u_int32_t *pnumber, struct evbuffer *evbuf, int dodrain) | |||
{ | |||
u_int32_t number = 0; | |||
u_int8_t *data = EVBUFFER_DATA(evbuf); | |||
int len = EVBUFFER_LENGTH(evbuf); | |||
int nibbles = 0, off; | |||
if (!len) | |||
return (-1); | |||
nibbles = ((data[0] & 0xf0) >> 4) + 1; | |||
if (nibbles > 8 || (nibbles >> 1) > len - 1) | |||
return (-1); | |||
off = nibbles; | |||
while (off > 0) { | |||
number <<= 4; | |||
if (off & 0x1) | |||
number |= data[off >> 1] & 0x0f; | |||
else | |||
number |= (data[off >> 1] & 0xf0) >> 4; | |||
off--; | |||
} | |||
len = (nibbles >> 1) + 1; | |||
if (dodrain) | |||
evbuffer_drain(evbuf, len); | |||
*pnumber = number; | |||
return (len); | |||
} | |||
int | |||
decode_int(u_int32_t *pnumber, struct evbuffer *evbuf) | |||
{ | |||
return (decode_int_internal(pnumber, evbuf, 1) == -1 ? -1 : 0); | |||
} | |||
int | |||
evtag_peek(struct evbuffer *evbuf, u_int8_t *ptag) | |||
{ | |||
if (EVBUFFER_LENGTH(evbuf) < 2) | |||
return (-1); | |||
*ptag = EVBUFFER_DATA(evbuf)[0]; | |||
return (0); | |||
} | |||
int | |||
evtag_peek_length(struct evbuffer *evbuf, u_int32_t *plength) | |||
{ | |||
struct evbuffer tmp; | |||
int res; | |||
if (EVBUFFER_LENGTH(evbuf) < 2) | |||
return (-1); | |||
tmp = *evbuf; | |||
tmp.buffer += 1; | |||
tmp.off -= 1; | |||
res = decode_int_internal(plength, &tmp, 0); | |||
if (res == -1) | |||
return (-1); | |||
*plength += res + 1; | |||
return (0); | |||
} | |||
int | |||
evtag_payload_length(struct evbuffer *evbuf, u_int32_t *plength) | |||
{ | |||
struct evbuffer tmp; | |||
int res; | |||
if (EVBUFFER_LENGTH(evbuf) < 2) | |||
return (-1); | |||
tmp = *evbuf; | |||
tmp.buffer += 1; | |||
tmp.off -= 1; | |||
res = decode_int_internal(plength, &tmp, 0); | |||
if (res == -1) | |||
return (-1); | |||
return (0); | |||
} | |||
int | |||
evtag_consume(struct evbuffer *evbuf) | |||
{ | |||
u_int32_t len; | |||
evbuffer_drain(evbuf, 1); | |||
if (decode_int(&len, evbuf) == -1) | |||
return (-1); | |||
evbuffer_drain(evbuf, len); | |||
return (0); | |||
} | |||
/* Reads the data type from an event buffer */ | |||
int | |||
evtag_unmarshal(struct evbuffer *src, u_int8_t *ptag, struct evbuffer *dst) | |||
{ | |||
u_int8_t tag; | |||
u_int16_t len; | |||
u_int32_t integer; | |||
if (evbuffer_remove(src, &tag, sizeof(tag)) != sizeof(tag)) | |||
return (-1); | |||
if (decode_int(&integer, src) == -1) | |||
return (-1); | |||
len = integer; | |||
if (EVBUFFER_LENGTH(src) < len) | |||
return (-1); | |||
if (evbuffer_add(dst, EVBUFFER_DATA(src), len) == -1) | |||
return (-1); | |||
evbuffer_drain(src, len); | |||
*ptag = tag; | |||
return (len); | |||
} | |||
/* Marshaling for integers */ | |||
int | |||
evtag_unmarshal_int(struct evbuffer *evbuf, u_int8_t need_tag, | |||
u_int32_t *pinteger) | |||
{ | |||
u_int8_t tag; | |||
u_int16_t len; | |||
u_int32_t integer; | |||
if (evbuffer_remove(evbuf, &tag, sizeof(tag)) != sizeof(tag) || | |||
tag != need_tag) | |||
return (-1); | |||
if (decode_int(&integer, evbuf) == -1) | |||
return (-1); | |||
len = integer; | |||
if (EVBUFFER_LENGTH(evbuf) < len) | |||
return (-1); | |||
evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf)); | |||
if (evbuffer_add(_buf, EVBUFFER_DATA(evbuf), len) == -1) | |||
return (-1); | |||
evbuffer_drain(evbuf, len); | |||
return (decode_int(pinteger, _buf)); | |||
} | |||
/* Unmarshal a fixed length tag */ | |||
int | |||
evtag_unmarshal_fixed(struct evbuffer *src, u_int8_t need_tag, void *data, | |||
size_t len) | |||
{ | |||
u_int8_t tag; | |||
/* Initialize this event buffer so that we can read into it */ | |||
evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf)); | |||
/* Now unmarshal a tag and check that it matches the tag we want */ | |||
if (evtag_unmarshal(src, &tag, _buf) == -1 || tag != need_tag) | |||
return (-1); | |||
if (EVBUFFER_LENGTH(_buf) != len) | |||
return (-1); | |||
memcpy(data, EVBUFFER_DATA(_buf), len); | |||
return (0); | |||
} | |||
int | |||
evtag_unmarshal_string(struct evbuffer *evbuf, u_int8_t need_tag, | |||
char **pstring) | |||
{ | |||
u_int8_t tag; | |||
evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf)); | |||
if (evtag_unmarshal(evbuf, &tag, _buf) == -1 || tag != need_tag) | |||
return (-1); | |||
*pstring = calloc(EVBUFFER_LENGTH(_buf) + 1, 1); | |||
if (*pstring == NULL) | |||
event_err(1, "%s: calloc", __func__); | |||
evbuffer_remove(_buf, *pstring, EVBUFFER_LENGTH(_buf)); | |||
return (0); | |||
} | |||
int | |||
evtag_unmarshal_timeval(struct evbuffer *evbuf, u_int8_t need_tag, | |||
struct timeval *ptv) | |||
{ | |||
u_int8_t tag; | |||
u_int32_t integer; | |||
evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf)); | |||
if (evtag_unmarshal(evbuf, &tag, _buf) == -1 || tag != need_tag) | |||
return (-1); | |||
if (decode_int(&integer, _buf) == -1) | |||
return (-1); | |||
ptv->tv_sec = integer; | |||
if (decode_int(&integer, _buf) == -1) | |||
return (-1); | |||
ptv->tv_usec = integer; | |||
return (0); | |||
} |
@@ -1,128 +0,0 @@ | |||
/* | |||
* Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu> | |||
* All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in the | |||
* documentation and/or other materials provided with the distribution. | |||
* 3. The name of the author may not be used to endorse or promote products | |||
* derived from this software without specific prior written permission. | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
*/ | |||
#ifndef _EVHTTP_H_ | |||
#define _EVHTTP_H_ | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
#ifdef WIN32 | |||
#define WIN32_LEAN_AND_MEAN | |||
#include <windows.h> | |||
#undef WIN32_LEAN_AND_MEAN | |||
typedef unsigned char u_char; | |||
#endif | |||
/* | |||
* Basic support for HTTP serving. | |||
* | |||
* As libevent is a library for dealing with event notification and most | |||
* interesting applications are networked today, I have often found the | |||
* need to write HTTP code. The following prototypes and definitions provide | |||
* an application with a minimal interface for making HTTP requests and for | |||
* creating a very simple HTTP server. | |||
*/ | |||
/* Response codes */ | |||
#define HTTP_OK 200 | |||
#define HTTP_MOVEPERM 301 | |||
#define HTTP_MOVETEMP 302 | |||
#define HTTP_NOTFOUND 404 | |||
struct evhttp; | |||
struct evhttp_request; | |||
struct evkeyvalq; | |||
/* Start an HTTP server on the specified address and port */ | |||
struct evhttp *evhttp_start(const char *address, u_short port); | |||
/* | |||
* Free the previously create HTTP server. Works only if no requests are | |||
* currently being served. | |||
*/ | |||
void evhttp_free(struct evhttp* http); | |||
/* Set a callback for a specified URI */ | |||
void evhttp_set_cb(struct evhttp *, const char *, | |||
void (*)(struct evhttp_request *, void *), void *); | |||
/* Set a callback for all requests that are not caught by specific callbacks */ | |||
void evhttp_set_gencb(struct evhttp *, | |||
void (*)(struct evhttp_request *, void *), void *); | |||
void evhttp_send_error(struct evhttp_request *, int, const char *); | |||
void evhttp_send_reply(struct evhttp_request *, int, const char *, | |||
struct evbuffer *); | |||
/* Interfaces for making requests */ | |||
enum evhttp_cmd_type { EVHTTP_REQ_GET, EVHTTP_REQ_POST, EVHTTP_REQ_HEAD }; | |||
/* | |||
* Creates a new request object that needs to be filled in with the request | |||
* parameters. The callback is executed when the request completed or an | |||
* error occurred. | |||
*/ | |||
struct evhttp_request *evhttp_request_new( | |||
void (*cb)(struct evhttp_request *, void *), void *arg); | |||
/* Frees the request object and removes associated events. */ | |||
void evhttp_request_free(struct evhttp_request *req); | |||
/* | |||
* A connection object that can be used to for making HTTP requests. The | |||
* connection object tries to establish the connection when it is given an | |||
* http request object. | |||
*/ | |||
struct evhttp_connection *evhttp_connection_new( | |||
const char *address, unsigned short port); | |||
/* Frees an http connection */ | |||
void evhttp_connection_free(struct evhttp_connection *evcon); | |||
/* The connection gets ownership of the request */ | |||
int evhttp_make_request(struct evhttp_connection *evcon, | |||
struct evhttp_request *req, | |||
enum evhttp_cmd_type type, const char *uri); | |||
const char *evhttp_request_uri(struct evhttp_request *req); | |||
/* Interfaces for dealing with HTTP headers */ | |||
const char *evhttp_find_header(struct evkeyvalq *, const char *); | |||
int evhttp_remove_header(struct evkeyvalq *, const char *); | |||
int evhttp_add_header(struct evkeyvalq *, const char *, const char *); | |||
void evhttp_clear_headers(struct evkeyvalq *); | |||
/* Miscellaneous utility functions */ | |||
void evhttp_parse_query(const char *uri, struct evkeyvalq *); | |||
char *evhttp_htmlescape(const char *html); | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
#endif /* _EVHTTP_H_ */ |
@@ -1,137 +0,0 @@ | |||
/* | |||
* Copyright 2001 Niels Provos <provos@citi.umich.edu> | |||
* All rights reserved. | |||
* | |||
* This header file contains definitions for dealing with HTTP requests | |||
* that are internal to libevent. As user of the library, you should not | |||
* need to know about these. | |||
*/ | |||
#ifndef _HTTP_H_ | |||
#define _HTTP_H_ | |||
#define HTTP_CONNECT_TIMEOUT 45 | |||
#define HTTP_WRITE_TIMEOUT 50 | |||
#define HTTP_READ_TIMEOUT 50 | |||
#define HTTP_PREFIX "http://" | |||
#define HTTP_DEFAULTPORT 80 | |||
struct evbuffer; | |||
struct addrinfo; | |||
struct evhttp_request; | |||
/* A stupid connection object - maybe make this a bufferevent later */ | |||
enum evhttp_connection_state { | |||
EVCON_DISCONNECTED, /* not currently connected not trying either */ | |||
EVCON_CONNECTING, /* tries to currently connect */ | |||
EVCON_CONNECTED /* connection is established */ | |||
}; | |||
struct evhttp_connection { | |||
int fd; | |||
struct event ev; | |||
struct evbuffer *input_buffer; | |||
struct evbuffer *output_buffer; | |||
char *address; | |||
u_short port; | |||
int flags; | |||
#define EVHTTP_CON_INCOMING 0x0001 /* only one request on it ever */ | |||
#define EVHTTP_CON_OUTGOING 0x0002 /* multiple requests possible */ | |||
enum evhttp_connection_state state; | |||
TAILQ_HEAD(evcon_requestq, evhttp_request) requests; | |||
void (*cb)(struct evhttp_connection *, void *); | |||
void *cb_arg; | |||
}; | |||
enum evhttp_request_kind { EVHTTP_REQUEST, EVHTTP_RESPONSE }; | |||
struct evhttp_request { | |||
TAILQ_ENTRY(evhttp_request) next; | |||
/* the connection object that this request belongs to */ | |||
struct evhttp_connection *evcon; | |||
int flags; | |||
#define EVHTTP_REQ_OWN_CONNECTION 0x0001 | |||
struct evkeyvalq *input_headers; | |||
struct evkeyvalq *output_headers; | |||
/* xxx: do we still need these? */ | |||
char *remote_host; | |||
u_short remote_port; | |||
enum evhttp_request_kind kind; | |||
enum evhttp_cmd_type type; | |||
char *uri; /* uri after HTTP request was parsed */ | |||
char major; /* HTTP Major number */ | |||
char minor; /* HTTP Minor number */ | |||
int got_firstline; | |||
int response_code; /* HTTP Response code */ | |||
char *response_code_line; /* Readable response */ | |||
struct evbuffer *input_buffer; /* read data */ | |||
int ntoread; | |||
struct evbuffer *output_buffer; /* outgoing post or data */ | |||
/* Callback */ | |||
void (*cb)(struct evhttp_request *, void *); | |||
void *cb_arg; | |||
}; | |||
struct evhttp_cb { | |||
TAILQ_ENTRY(evhttp_cb) next; | |||
char *what; | |||
void (*cb)(struct evhttp_request *req, void *); | |||
void *cbarg; | |||
}; | |||
struct evhttp { | |||
struct event bind_ev; | |||
TAILQ_HEAD(httpcbq, evhttp_cb) callbacks; | |||
void (*gencb)(struct evhttp_request *req, void *); | |||
void *gencbarg; | |||
}; | |||
/* resets the connection; can be reused for more requests */ | |||
void evhttp_connection_reset(struct evhttp_connection *); | |||
/* connects if necessary */ | |||
int evhttp_connection_connect(struct evhttp_connection *); | |||
/* notifies the current request that it failed; resets connection */ | |||
void evhttp_connection_fail(struct evhttp_connection *); | |||
void evhttp_get_request(int, struct sockaddr *, socklen_t, | |||
void (*)(struct evhttp_request *, void *), void *); | |||
int evhttp_hostportfile(char *, char **, u_short *, char **); | |||
int evhttp_parse_lines(struct evhttp_request *, struct evbuffer*); | |||
void evhttp_start_read(struct evhttp_connection *); | |||
void evhttp_read_header(int, short, void *); | |||
void evhttp_make_header(struct evhttp_connection *, struct evhttp_request *); | |||
void evhttp_write_buffer(struct evhttp_connection *, | |||
void (*)(struct evhttp_connection *, void *), void *); | |||
/* response sending HTML the data in the buffer */ | |||
void evhttp_response_code(struct evhttp_request *, int, const char *); | |||
void evhttp_send_page(struct evhttp_request *, struct evbuffer *); | |||
#endif /* _HTTP_H */ |
@@ -1,238 +0,0 @@ | |||
#! /bin/sh | |||
# | |||
# install - install a program, script, or datafile | |||
# This comes from X11R5. | |||
# | |||
# Calling this script install-sh is preferred over install.sh, to prevent | |||
# `make' implicit rules from creating a file called install from it | |||
# when there is no Makefile. | |||
# | |||
# This script is compatible with the BSD install script, but was written | |||
# from scratch. | |||
# | |||
# set DOITPROG to echo to test this script | |||
# Don't use :- since 4.3BSD and earlier shells don't like it. | |||
doit="${DOITPROG-}" | |||
# put in absolute paths if you don't have them in your path; or use env. vars. | |||
mvprog="${MVPROG-mv}" | |||
cpprog="${CPPROG-cp}" | |||
chmodprog="${CHMODPROG-chmod}" | |||
chownprog="${CHOWNPROG-chown}" | |||
chgrpprog="${CHGRPPROG-chgrp}" | |||
stripprog="${STRIPPROG-strip}" | |||
rmprog="${RMPROG-rm}" | |||
mkdirprog="${MKDIRPROG-mkdir}" | |||
tranformbasename="" | |||
transform_arg="" | |||
instcmd="$mvprog" | |||
chmodcmd="$chmodprog 0755" | |||
chowncmd="" | |||
chgrpcmd="" | |||
stripcmd="" | |||
rmcmd="$rmprog -f" | |||
mvcmd="$mvprog" | |||
src="" | |||
dst="" | |||
dir_arg="" | |||
while [ x"$1" != x ]; do | |||
case $1 in | |||
-c) instcmd="$cpprog" | |||
shift | |||
continue;; | |||
-d) dir_arg=true | |||
shift | |||
continue;; | |||
-m) chmodcmd="$chmodprog $2" | |||
shift | |||
shift | |||
continue;; | |||
-o) chowncmd="$chownprog $2" | |||
shift | |||
shift | |||
continue;; | |||
-g) chgrpcmd="$chgrpprog $2" | |||
shift | |||
shift | |||
continue;; | |||
-s) stripcmd="$stripprog" | |||
shift | |||
continue;; | |||
-t=*) transformarg=`echo $1 | sed 's/-t=//'` | |||
shift | |||
continue;; | |||
-b=*) transformbasename=`echo $1 | sed 's/-b=//'` | |||
shift | |||
continue;; | |||
*) if [ x"$src" = x ] | |||
then | |||
src=$1 | |||
else | |||
# this colon is to work around a 386BSD /bin/sh bug | |||
: | |||
dst=$1 | |||
fi | |||
shift | |||
continue;; | |||
esac | |||
done | |||
if [ x"$src" = x ] | |||
then | |||
echo "install: no input file specified" | |||
exit 1 | |||
else | |||
true | |||
fi | |||
if [ x"$dir_arg" != x ]; then | |||
dst=$src | |||
src="" | |||
if [ -d $dst ]; then | |||
instcmd=: | |||
else | |||
instcmd=mkdir | |||
fi | |||
else | |||
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command | |||
# might cause directories to be created, which would be especially bad | |||
# if $src (and thus $dsttmp) contains '*'. | |||
if [ -f $src -o -d $src ] | |||
then | |||
true | |||
else | |||
echo "install: $src does not exist" | |||
exit 1 | |||
fi | |||
if [ x"$dst" = x ] | |||
then | |||
echo "install: no destination specified" | |||
exit 1 | |||
else | |||
true | |||
fi | |||
# If destination is a directory, append the input filename; if your system | |||
# does not like double slashes in filenames, you may need to add some logic | |||
if [ -d $dst ] | |||
then | |||
dst="$dst"/`basename $src` | |||
else | |||
true | |||
fi | |||
fi | |||
## this sed command emulates the dirname command | |||
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` | |||
# Make sure that the destination directory exists. | |||
# this part is taken from Noah Friedman's mkinstalldirs script | |||
# Skip lots of stat calls in the usual case. | |||
if [ ! -d "$dstdir" ]; then | |||
defaultIFS=' | |||
' | |||
IFS="${IFS-${defaultIFS}}" | |||
oIFS="${IFS}" | |||
# Some sh's can't handle IFS=/ for some reason. | |||
IFS='%' | |||
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` | |||
IFS="${oIFS}" | |||
pathcomp='' | |||
while [ $# -ne 0 ] ; do | |||
pathcomp="${pathcomp}${1}" | |||
shift | |||
if [ ! -d "${pathcomp}" ] ; | |||
then | |||
$mkdirprog "${pathcomp}" | |||
else | |||
true | |||
fi | |||
pathcomp="${pathcomp}/" | |||
done | |||
fi | |||
if [ x"$dir_arg" != x ] | |||
then | |||
$doit $instcmd $dst && | |||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && | |||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && | |||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && | |||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi | |||
else | |||
# If we're going to rename the final executable, determine the name now. | |||
if [ x"$transformarg" = x ] | |||
then | |||
dstfile=`basename $dst` | |||
else | |||
dstfile=`basename $dst $transformbasename | | |||
sed $transformarg`$transformbasename | |||
fi | |||
# don't allow the sed command to completely eliminate the filename | |||
if [ x"$dstfile" = x ] | |||
then | |||
dstfile=`basename $dst` | |||
else | |||
true | |||
fi | |||
# Make a temp file name in the proper directory. | |||
dsttmp=$dstdir/#inst.$$# | |||
# Move or copy the file name to the temp name | |||
$doit $instcmd $src $dsttmp && | |||
trap "rm -f ${dsttmp}" 0 && | |||
# and set any options; do chmod last to preserve setuid bits | |||
# If any of these fail, we abort the whole thing. If we want to | |||
# ignore errors from any of these, just make sure not to ignore | |||
# errors from the above "$doit $instcmd $src $dsttmp" command. | |||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && | |||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && | |||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && | |||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && | |||
# Now rename the file to the real destination. | |||
$doit $rmcmd -f $dstdir/$dstfile && | |||
$doit $mvcmd $dsttmp $dstdir/$dstfile | |||
fi && | |||
exit 0 |
@@ -1,360 +0,0 @@ | |||
#! /bin/sh | |||
# Common stub for a few missing GNU programs while installing. | |||
scriptversion=2003-09-02.23 | |||
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003 | |||
# Free Software Foundation, Inc. | |||
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996. | |||
# This program is free software; you can redistribute it and/or modify | |||
# it under the terms of the GNU General Public License as published by | |||
# the Free Software Foundation; either version 2, or (at your option) | |||
# any later version. | |||
# This program is distributed in the hope that it will be useful, | |||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
# GNU General Public License for more details. | |||
# You should have received a copy of the GNU General Public License | |||
# along with this program; if not, write to the Free Software | |||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | |||
# 02111-1307, USA. | |||
# As a special exception to the GNU General Public License, if you | |||
# distribute this file as part of a program that contains a | |||
# configuration script generated by Autoconf, you may include it under | |||
# the same distribution terms that you use for the rest of that program. | |||
if test $# -eq 0; then | |||
echo 1>&2 "Try \`$0 --help' for more information" | |||
exit 1 | |||
fi | |||
run=: | |||
# In the cases where this matters, `missing' is being run in the | |||
# srcdir already. | |||
if test -f configure.ac; then | |||
configure_ac=configure.ac | |||
else | |||
configure_ac=configure.in | |||
fi | |||
msg="missing on your system" | |||
case "$1" in | |||
--run) | |||
# Try to run requested program, and just exit if it succeeds. | |||
run= | |||
shift | |||
"$@" && exit 0 | |||
# Exit code 63 means version mismatch. This often happens | |||
# when the user try to use an ancient version of a tool on | |||
# a file that requires a minimum version. In this case we | |||
# we should proceed has if the program had been absent, or | |||
# if --run hadn't been passed. | |||
if test $? = 63; then | |||
run=: | |||
msg="probably too old" | |||
fi | |||
;; | |||
esac | |||
# If it does not exist, or fails to run (possibly an outdated version), | |||
# try to emulate it. | |||
case "$1" in | |||
-h|--h|--he|--hel|--help) | |||
echo "\ | |||
$0 [OPTION]... PROGRAM [ARGUMENT]... | |||
Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an | |||
error status if there is no known handling for PROGRAM. | |||
Options: | |||
-h, --help display this help and exit | |||
-v, --version output version information and exit | |||
--run try to run the given command, and emulate it if it fails | |||
Supported PROGRAM values: | |||
aclocal touch file \`aclocal.m4' | |||
autoconf touch file \`configure' | |||
autoheader touch file \`config.h.in' | |||
automake touch all \`Makefile.in' files | |||
bison create \`y.tab.[ch]', if possible, from existing .[ch] | |||
flex create \`lex.yy.c', if possible, from existing .c | |||
help2man touch the output file | |||
lex create \`lex.yy.c', if possible, from existing .c | |||
makeinfo touch the output file | |||
tar try tar, gnutar, gtar, then tar without non-portable flags | |||
yacc create \`y.tab.[ch]', if possible, from existing .[ch] | |||
Send bug reports to <bug-automake@gnu.org>." | |||
;; | |||
-v|--v|--ve|--ver|--vers|--versi|--versio|--version) | |||
echo "missing $scriptversion (GNU Automake)" | |||
;; | |||
-*) | |||
echo 1>&2 "$0: Unknown \`$1' option" | |||
echo 1>&2 "Try \`$0 --help' for more information" | |||
exit 1 | |||
;; | |||
aclocal*) | |||
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then | |||
# We have it, but it failed. | |||
exit 1 | |||
fi | |||
echo 1>&2 "\ | |||
WARNING: \`$1' is $msg. You should only need it if | |||
you modified \`acinclude.m4' or \`${configure_ac}'. You might want | |||
to install the \`Automake' and \`Perl' packages. Grab them from | |||
any GNU archive site." | |||
touch aclocal.m4 | |||
;; | |||
autoconf) | |||
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then | |||
# We have it, but it failed. | |||
exit 1 | |||
fi | |||
echo 1>&2 "\ | |||
WARNING: \`$1' is $msg. You should only need it if | |||
you modified \`${configure_ac}'. You might want to install the | |||
\`Autoconf' and \`GNU m4' packages. Grab them from any GNU | |||
archive site." | |||
touch configure | |||
;; | |||
autoheader) | |||
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then | |||
# We have it, but it failed. | |||
exit 1 | |||
fi | |||
echo 1>&2 "\ | |||
WARNING: \`$1' is $msg. You should only need it if | |||
you modified \`acconfig.h' or \`${configure_ac}'. You might want | |||
to install the \`Autoconf' and \`GNU m4' packages. Grab them | |||
from any GNU archive site." | |||
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` | |||
test -z "$files" && files="config.h" | |||
touch_files= | |||
for f in $files; do | |||
case "$f" in | |||
*:*) touch_files="$touch_files "`echo "$f" | | |||
sed -e 's/^[^:]*://' -e 's/:.*//'`;; | |||
*) touch_files="$touch_files $f.in";; | |||
esac | |||
done | |||
touch $touch_files | |||
;; | |||
automake*) | |||
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then | |||
# We have it, but it failed. | |||
exit 1 | |||
fi | |||
echo 1>&2 "\ | |||
WARNING: \`$1' is $msg. You should only need it if | |||
you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. | |||
You might want to install the \`Automake' and \`Perl' packages. | |||
Grab them from any GNU archive site." | |||
find . -type f -name Makefile.am -print | | |||
sed 's/\.am$/.in/' | | |||
while read f; do touch "$f"; done | |||
;; | |||
autom4te) | |||
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then | |||
# We have it, but it failed. | |||
exit 1 | |||
fi | |||
echo 1>&2 "\ | |||
WARNING: \`$1' is needed, but is $msg. | |||
You might have modified some files without having the | |||
proper tools for further handling them. | |||
You can get \`$1' as part of \`Autoconf' from any GNU | |||
archive site." | |||
file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` | |||
test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` | |||
if test -f "$file"; then | |||
touch $file | |||
else | |||
test -z "$file" || exec >$file | |||
echo "#! /bin/sh" | |||
echo "# Created by GNU Automake missing as a replacement of" | |||
echo "# $ $@" | |||
echo "exit 0" | |||
chmod +x $file | |||
exit 1 | |||
fi | |||
;; | |||
bison|yacc) | |||
echo 1>&2 "\ | |||
WARNING: \`$1' $msg. You should only need it if | |||
you modified a \`.y' file. You may need the \`Bison' package | |||
in order for those modifications to take effect. You can get | |||
\`Bison' from any GNU archive site." | |||
rm -f y.tab.c y.tab.h | |||
if [ $# -ne 1 ]; then | |||
eval LASTARG="\${$#}" | |||
case "$LASTARG" in | |||
*.y) | |||
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` | |||
if [ -f "$SRCFILE" ]; then | |||
cp "$SRCFILE" y.tab.c | |||
fi | |||
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` | |||
if [ -f "$SRCFILE" ]; then | |||
cp "$SRCFILE" y.tab.h | |||
fi | |||
;; | |||
esac | |||
fi | |||
if [ ! -f y.tab.h ]; then | |||
echo >y.tab.h | |||
fi | |||
if [ ! -f y.tab.c ]; then | |||
echo 'main() { return 0; }' >y.tab.c | |||
fi | |||
;; | |||
lex|flex) | |||
echo 1>&2 "\ | |||
WARNING: \`$1' is $msg. You should only need it if | |||
you modified a \`.l' file. You may need the \`Flex' package | |||
in order for those modifications to take effect. You can get | |||
\`Flex' from any GNU archive site." | |||
rm -f lex.yy.c | |||
if [ $# -ne 1 ]; then | |||
eval LASTARG="\${$#}" | |||
case "$LASTARG" in | |||
*.l) | |||
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` | |||
if [ -f "$SRCFILE" ]; then | |||
cp "$SRCFILE" lex.yy.c | |||
fi | |||
;; | |||
esac | |||
fi | |||
if [ ! -f lex.yy.c ]; then | |||
echo 'main() { return 0; }' >lex.yy.c | |||
fi | |||
;; | |||
help2man) | |||
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then | |||
# We have it, but it failed. | |||
exit 1 | |||
fi | |||
echo 1>&2 "\ | |||
WARNING: \`$1' is $msg. You should only need it if | |||
you modified a dependency of a manual page. You may need the | |||
\`Help2man' package in order for those modifications to take | |||
effect. You can get \`Help2man' from any GNU archive site." | |||
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` | |||
if test -z "$file"; then | |||
file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` | |||
fi | |||
if [ -f "$file" ]; then | |||
touch $file | |||
else | |||
test -z "$file" || exec >$file | |||
echo ".ab help2man is required to generate this page" | |||
exit 1 | |||
fi | |||
;; | |||
makeinfo) | |||
if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then | |||
# We have makeinfo, but it failed. | |||
exit 1 | |||
fi | |||
echo 1>&2 "\ | |||
WARNING: \`$1' is $msg. You should only need it if | |||
you modified a \`.texi' or \`.texinfo' file, or any other file | |||
indirectly affecting the aspect of the manual. The spurious | |||
call might also be the consequence of using a buggy \`make' (AIX, | |||
DU, IRIX). You might want to install the \`Texinfo' package or | |||
the \`GNU make' package. Grab either from any GNU archive site." | |||
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` | |||
if test -z "$file"; then | |||
file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` | |||
file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` | |||
fi | |||
touch $file | |||
;; | |||
tar) | |||
shift | |||
if test -n "$run"; then | |||
echo 1>&2 "ERROR: \`tar' requires --run" | |||
exit 1 | |||
fi | |||
# We have already tried tar in the generic part. | |||
# Look for gnutar/gtar before invocation to avoid ugly error | |||
# messages. | |||
if (gnutar --version > /dev/null 2>&1); then | |||
gnutar "$@" && exit 0 | |||
fi | |||
if (gtar --version > /dev/null 2>&1); then | |||
gtar "$@" && exit 0 | |||
fi | |||
firstarg="$1" | |||
if shift; then | |||
case "$firstarg" in | |||
*o*) | |||
firstarg=`echo "$firstarg" | sed s/o//` | |||
tar "$firstarg" "$@" && exit 0 | |||
;; | |||
esac | |||
case "$firstarg" in | |||
*h*) | |||
firstarg=`echo "$firstarg" | sed s/h//` | |||
tar "$firstarg" "$@" && exit 0 | |||
;; | |||
esac | |||
fi | |||
echo 1>&2 "\ | |||
WARNING: I can't seem to be able to run \`tar' with the given arguments. | |||
You may want to install GNU tar or Free paxutils, or check the | |||
command line arguments." | |||
exit 1 | |||
;; | |||
*) | |||
echo 1>&2 "\ | |||
WARNING: \`$1' is needed, and is $msg. | |||
You might have modified some files without having the | |||
proper tools for further handling them. Check the \`README' file, | |||
it often tells you about the needed prerequisites for installing | |||
this package. You may also peek at any GNU archive site, in case | |||
some other package would contain this missing \`$1' program." | |||
exit 1 | |||
;; | |||
esac | |||
exit 0 | |||
# Local variables: | |||
# eval: (add-hook 'write-file-hooks 'time-stamp) | |||
# time-stamp-start: "scriptversion=" | |||
# time-stamp-format: "%:y-%02m-%02d.%02H" | |||
# time-stamp-end: "$" | |||
# End: |
@@ -1,40 +0,0 @@ | |||
#! /bin/sh | |||
# mkinstalldirs --- make directory hierarchy | |||
# Author: Noah Friedman <friedman@prep.ai.mit.edu> | |||
# Created: 1993-05-16 | |||
# Public domain | |||
# $Id: mkinstalldirs 11 2002-04-09 17:52:23Z nprovos $ | |||
errstatus=0 | |||
for file | |||
do | |||
set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` | |||
shift | |||
pathcomp= | |||
for d | |||
do | |||
pathcomp="$pathcomp$d" | |||
case "$pathcomp" in | |||
-* ) pathcomp=./$pathcomp ;; | |||
esac | |||
if test ! -d "$pathcomp"; then | |||
echo "mkdir $pathcomp" | |||
mkdir "$pathcomp" || lasterr=$? | |||
if test ! -d "$pathcomp"; then | |||
errstatus=$lasterr | |||
fi | |||
fi | |||
pathcomp="$pathcomp/" | |||
done | |||
done | |||
exit $errstatus | |||
# mkinstalldirs ends here |
@@ -1,15 +0,0 @@ | |||
AUTOMAKE_OPTIONS = foreign no-dependencies | |||
LDADD = ../libevent.la | |||
CPPFPLAGS = -I.. | |||
CFLAGS = -I../compat | |||
noinst_PROGRAMS = event-test time-test signal-test | |||
event_test_sources = event-test.c | |||
time_test_sources = time-test.c | |||
signal_test_sources = signal-test.c | |||
verify: | |||
DISTCLEANFILES = *~ |
@@ -1,135 +0,0 @@ | |||
/* | |||
* Compile with: | |||
* cc -I/usr/local/include -o event-test event-test.c -L/usr/local/lib -levent | |||
*/ | |||
#include <sys/types.h> | |||
#include <sys/stat.h> | |||
#ifndef WIN32 | |||
#include <sys/queue.h> | |||
#include <unistd.h> | |||
#include <sys/time.h> | |||
#else | |||
#include <windows.h> | |||
#endif | |||
#include <fcntl.h> | |||
#include <stdlib.h> | |||
#include <stdio.h> | |||
#include <string.h> | |||
#include <errno.h> | |||
#include <event.h> | |||
void | |||
fifo_read(int fd, short event, void *arg) | |||
{ | |||
char buf[255]; | |||
int len; | |||
struct event *ev = arg; | |||
#ifdef WIN32 | |||
DWORD dwBytesRead; | |||
#endif | |||
/* Reschedule this event */ | |||
event_add(ev, NULL); | |||
fprintf(stderr, "fifo_read called with fd: %d, event: %d, arg: %p\n", | |||
fd, event, arg); | |||
#ifdef WIN32 | |||
len = ReadFile((HANDLE)fd, buf, sizeof(buf) - 1, &dwBytesRead, NULL); | |||
// Check for end of file. | |||
if(len && dwBytesRead == 0) { | |||
fprintf(stderr, "End Of File"); | |||
event_del(ev); | |||
return; | |||
} | |||
buf[dwBytesRead] = '\0'; | |||
#else | |||
len = read(fd, buf, sizeof(buf) - 1); | |||
if (len == -1) { | |||
perror("read"); | |||
return; | |||
} else if (len == 0) { | |||
fprintf(stderr, "Connection closed\n"); | |||
return; | |||
} | |||
buf[len] = '\0'; | |||
#endif | |||
fprintf(stdout, "Read: %s\n", buf); | |||
} | |||
int | |||
main (int argc, char **argv) | |||
{ | |||
struct event evfifo; | |||
#ifdef WIN32 | |||
HANDLE socket; | |||
// Open a file. | |||
socket = CreateFile("test.txt", // open File | |||
GENERIC_READ, // open for reading | |||
0, // do not share | |||
NULL, // no security | |||
OPEN_EXISTING, // existing file only | |||
FILE_ATTRIBUTE_NORMAL, // normal file | |||
NULL); // no attr. template | |||
if(socket == INVALID_HANDLE_VALUE) | |||
return 1; | |||
#else | |||
struct stat st; | |||
char *fifo = "event.fifo"; | |||
int socket; | |||
if (lstat (fifo, &st) == 0) { | |||
if ((st.st_mode & S_IFMT) == S_IFREG) { | |||
errno = EEXIST; | |||
perror("lstat"); | |||
exit (1); | |||
} | |||
} | |||
unlink (fifo); | |||
if (mkfifo (fifo, 0600) == -1) { | |||
perror("mkfifo"); | |||
exit (1); | |||
} | |||
/* Linux pipes are broken, we need O_RDWR instead of O_RDONLY */ | |||
#ifdef __linux | |||
socket = open (fifo, O_RDWR | O_NONBLOCK, 0); | |||
#else | |||
socket = open (fifo, O_RDONLY | O_NONBLOCK, 0); | |||
#endif | |||
if (socket == -1) { | |||
perror("open"); | |||
exit (1); | |||
} | |||
fprintf(stderr, "Write data to %s\n", fifo); | |||
#endif | |||
/* Initalize the event library */ | |||
event_init(); | |||
/* Initalize one event */ | |||
#ifdef WIN32 | |||
event_set(&evfifo, (int)socket, EV_READ, fifo_read, &evfifo); | |||
#else | |||
event_set(&evfifo, socket, EV_READ, fifo_read, &evfifo); | |||
#endif | |||
/* Add it to the active events, without a timeout */ | |||
event_add(&evfifo, NULL); | |||
event_dispatch(); | |||
#ifdef WIN32 | |||
CloseHandle(socket); | |||
#endif | |||
return (0); | |||
} | |||
@@ -1,62 +0,0 @@ | |||
/* | |||
* Compile with: | |||
* cc -I/usr/local/include -o time-test time-test.c -L/usr/local/lib -levent | |||
*/ | |||
#include <sys/types.h> | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
#include <sys/stat.h> | |||
#ifndef WIN32 | |||
#include <sys/queue.h> | |||
#include <unistd.h> | |||
#include <sys/time.h> | |||
#else | |||
#include <windows.h> | |||
#endif | |||
#include <signal.h> | |||
#include <fcntl.h> | |||
#include <stdlib.h> | |||
#include <stdio.h> | |||
#include <string.h> | |||
#include <errno.h> | |||
#include <event.h> | |||
int called = 0; | |||
void | |||
signal_cb(int fd, short event, void *arg) | |||
{ | |||
struct event *signal = arg; | |||
printf("%s: got signal %d\n", __func__, EVENT_SIGNAL(signal)); | |||
if (called >= 2) | |||
event_del(signal); | |||
called++; | |||
} | |||
int | |||
main (int argc, char **argv) | |||
{ | |||
struct event signal_int; | |||
/* Initalize the event library */ | |||
event_init(); | |||
/* Initalize one event */ | |||
event_set(&signal_int, SIGINT, EV_SIGNAL|EV_PERSIST, signal_cb, | |||
&signal_int); | |||
event_add(&signal_int, NULL); | |||
event_dispatch(); | |||
return (0); | |||
} | |||
@@ -1,70 +0,0 @@ | |||
/* | |||
* Compile with: | |||
* cc -I/usr/local/include -o time-test time-test.c -L/usr/local/lib -levent | |||
*/ | |||
#include <sys/types.h> | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
#include <sys/stat.h> | |||
#ifndef WIN32 | |||
#include <sys/queue.h> | |||
#include <unistd.h> | |||
#else | |||
#include <time.h> | |||
#endif | |||
#ifdef HAVE_SYS_TIME_H | |||
#include <sys/time.h> | |||
#endif | |||
#include <fcntl.h> | |||
#include <stdlib.h> | |||
#include <stdio.h> | |||
#include <string.h> | |||
#include <errno.h> | |||
#include <event.h> | |||
int lasttime; | |||
void | |||
timeout_cb(int fd, short event, void *arg) | |||
{ | |||
struct timeval tv; | |||
struct event *timeout = arg; | |||
int newtime = time(NULL); | |||
printf("%s: called at %d: %d\n", __func__, newtime, | |||
newtime - lasttime); | |||
lasttime = newtime; | |||
timerclear(&tv); | |||
tv.tv_sec = 2; | |||
event_add(timeout, &tv); | |||
} | |||
int | |||
main (int argc, char **argv) | |||
{ | |||
struct event timeout; | |||
struct timeval tv; | |||
/* Initalize the event library */ | |||
event_init(); | |||
/* Initalize one event */ | |||
evtimer_set(&timeout, timeout_cb, &timeout); | |||
timerclear(&tv); | |||
tv.tv_sec = 2; | |||
event_add(&timeout, &tv); | |||
lasttime = time(NULL); | |||
event_dispatch(); | |||
return (0); | |||
} | |||
@@ -1 +0,0 @@ | |||
timestamp |
@@ -1,74 +0,0 @@ | |||
/* $OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $ */ | |||
/* | |||
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> | |||
* All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in the | |||
* documentation and/or other materials provided with the distribution. | |||
* 3. The name of the author may not be used to endorse or promote products | |||
* derived from this software without specific prior written permission. | |||
* | |||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, | |||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY | |||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | |||
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
*/ | |||
#if defined(LIBC_SCCS) && !defined(lint) | |||
static char *rcsid = "$OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $"; | |||
#endif /* LIBC_SCCS and not lint */ | |||
#include <sys/types.h> | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif /* HAVE_CONFIG_H */ | |||
#include <string.h> | |||
/* | |||
* Copy src to string dst of size siz. At most siz-1 characters | |||
* will be copied. Always NUL terminates (unless siz == 0). | |||
* Returns strlen(src); if retval >= siz, truncation occurred. | |||
*/ | |||
size_t | |||
strlcpy(dst, src, siz) | |||
char *dst; | |||
const char *src; | |||
size_t siz; | |||
{ | |||
register char *d = dst; | |||
register const char *s = src; | |||
register size_t n = siz; | |||
/* Copy as many bytes as will fit */ | |||
if (n != 0 && --n != 0) { | |||
do { | |||
if ((*d++ = *s++) == 0) | |||
break; | |||
} while (--n != 0); | |||
} | |||
/* Not enough room in dst, add NUL and traverse rest of src */ | |||
if (n == 0) { | |||
if (siz != 0) | |||
*d = '\0'; /* NUL-terminate dst */ | |||
while (*s++) | |||
; | |||
} | |||
return(s - src - 1); /* count does not include NUL */ | |||
} |
@@ -1,31 +0,0 @@ | |||
AUTOMAKE_OPTIONS = foreign no-dependencies | |||
LDADD = ../libevent.la | |||
CPPFPLAGS = -I.. | |||
CFLAGS = -I../compat @CFLAGS@ | |||
EXTRA_DIST = regress.rpc | |||
noinst_PROGRAMS = test-init test-eof test-weof test-time regress bench | |||
BUILT_SOURCES = regress.gen.c regress.gen.h | |||
test_init_SOURCES = test-init.c | |||
test_eof_SOURCES = test-eof.c | |||
test_weof_SOURCES = test-weof.c | |||
test_time_SOURCES = test-time.c | |||
regress_SOURCES = regress.c regress.h regress_http.c regress_dns.c \ | |||
regress.gen.c regress.gen.h | |||
bench_SOURCES = bench.c | |||
regress.gen.c regress.gen.h: regress.rpc | |||
../event_rpcgen.py regress.rpc || echo "No Python installed" | |||
DISTCLEANFILES = *~ | |||
CLEANFILES = regress.gen.h regress.gen.c | |||
test: test-init test-eof test-weof test-time regress | |||
verify: test | |||
@./test.sh | |||
bench test-init test-eof test-weof test-time: ../libevent.la |
@@ -1,181 +0,0 @@ | |||
/* | |||
* Copyright 2003 Niels Provos <provos@citi.umich.edu> | |||
* All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in the | |||
* documentation and/or other materials provided with the distribution. | |||
* 4. The name of the author may not be used to endorse or promote products | |||
* derived from this software without specific prior written permission. | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
* | |||
* | |||
* Mon 03/10/2003 - Modified by Davide Libenzi <davidel@xmailserver.org> | |||
* | |||
* Added chain event propagation to improve the sensitivity of | |||
* the measure respect to the event loop efficency. | |||
* | |||
* | |||
*/ | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
#include <sys/types.h> | |||
#include <sys/stat.h> | |||
#include <sys/time.h> | |||
#include <sys/socket.h> | |||
#include <sys/signal.h> | |||
#include <sys/resource.h> | |||
#include <fcntl.h> | |||
#include <stdlib.h> | |||
#include <stdio.h> | |||
#include <string.h> | |||
#include <unistd.h> | |||
#include <errno.h> | |||
#include <event.h> | |||
static int count, writes, fired; | |||
static int *pipes; | |||
static int num_pipes, num_active, num_writes; | |||
static struct event *events; | |||
void | |||
read_cb(int fd, short which, void *arg) | |||
{ | |||
int idx = (int) arg, widx = idx + 1; | |||
u_char ch; | |||
count += read(fd, &ch, sizeof(ch)); | |||
if (writes) { | |||
if (widx >= num_pipes) | |||
widx -= num_pipes; | |||
write(pipes[2 * widx + 1], "e", 1); | |||
writes--; | |||
fired++; | |||
} | |||
} | |||
struct timeval * | |||
run_once(void) | |||
{ | |||
int *cp, i, space; | |||
static struct timeval ts, te; | |||
for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) { | |||
event_del(&events[i]); | |||
event_set(&events[i], cp[0], EV_READ | EV_PERSIST, read_cb, (void *) i); | |||
event_add(&events[i], NULL); | |||
} | |||
event_loop(EVLOOP_ONCE | EVLOOP_NONBLOCK); | |||
fired = 0; | |||
space = num_pipes / num_active; | |||
space = space * 2; | |||
for (i = 0; i < num_active; i++, fired++) | |||
write(pipes[i * space + 1], "e", 1); | |||
count = 0; | |||
writes = num_writes; | |||
{ int xcount = 0; | |||
gettimeofday(&ts, NULL); | |||
do { | |||
event_loop(EVLOOP_ONCE | EVLOOP_NONBLOCK); | |||
xcount++; | |||
} while (count != fired); | |||
gettimeofday(&te, NULL); | |||
if (xcount != count) fprintf(stderr, "Xcount: %d, Rcount: %d\n", xcount, count); | |||
} | |||
timersub(&te, &ts, &te); | |||
return (&te); | |||
} | |||
int | |||
main (int argc, char **argv) | |||
{ | |||
struct rlimit rl; | |||
int i, c; | |||
struct timeval *tv; | |||
int *cp; | |||
extern char *optarg; | |||
num_pipes = 100; | |||
num_active = 1; | |||
num_writes = num_pipes; | |||
while ((c = getopt(argc, argv, "n:a:w:")) != -1) { | |||
switch (c) { | |||
case 'n': | |||
num_pipes = atoi(optarg); | |||
break; | |||
case 'a': | |||
num_active = atoi(optarg); | |||
break; | |||
case 'w': | |||
num_writes = atoi(optarg); | |||
break; | |||
default: | |||
fprintf(stderr, "Illegal argument \"%c\"\n", c); | |||
exit(1); | |||
} | |||
} | |||
rl.rlim_cur = rl.rlim_max = num_pipes * 2 + 50; | |||
if (setrlimit(RLIMIT_NOFILE, &rl) == -1) { | |||
perror("setrlimit"); | |||
exit(1); | |||
} | |||
events = calloc(num_pipes, sizeof(struct event)); | |||
pipes = calloc(num_pipes * 2, sizeof(int)); | |||
if (events == NULL || pipes == NULL) { | |||
perror("malloc"); | |||
exit(1); | |||
} | |||
event_init(); | |||
for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) { | |||
#ifdef USE_PIPES | |||
if (pipe(cp) == -1) { | |||
#else | |||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, cp) == -1) { | |||
#endif | |||
perror("pipe"); | |||
exit(1); | |||
} | |||
} | |||
for (i = 0; i < 25; i++) { | |||
tv = run_once(); | |||
if (tv == NULL) | |||
exit(1); | |||
fprintf(stdout, "%ld\n", | |||
tv->tv_sec * 1000000L + tv->tv_usec); | |||
} | |||
exit(0); | |||
} |
@@ -1,923 +0,0 @@ | |||
/* | |||
* Copyright (c) 2003, 2004 Niels Provos <provos@citi.umich.edu> | |||
* All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in the | |||
* documentation and/or other materials provided with the distribution. | |||
* 3. The name of the author may not be used to endorse or promote products | |||
* derived from this software without specific prior written permission. | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
*/ | |||
#ifdef WIN32 | |||
#include <winsock2.h> | |||
#include <windows.h> | |||
#endif | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
#include <sys/types.h> | |||
#include <sys/stat.h> | |||
#ifdef HAVE_SYS_TIME_H | |||
#include <sys/time.h> | |||
#endif | |||
#include <sys/queue.h> | |||
#ifndef WIN32 | |||
#include <sys/socket.h> | |||
#include <sys/signal.h> | |||
#include <unistd.h> | |||
#endif | |||
#include <netdb.h> | |||
#include <fcntl.h> | |||
#include <stdlib.h> | |||
#include <stdio.h> | |||
#include <string.h> | |||
#include <errno.h> | |||
#include "event.h" | |||
#include "log.h" | |||
#include "regress.h" | |||
#include "regress.gen.h" | |||
int pair[2]; | |||
int test_ok; | |||
static int called; | |||
static char wbuf[4096]; | |||
static char rbuf[4096]; | |||
static int woff; | |||
static int roff; | |||
static int usepersist; | |||
static struct timeval tset; | |||
static struct timeval tcalled; | |||
static struct event_base *event_base; | |||
#define TEST1 "this is a test" | |||
#define SECONDS 1 | |||
void | |||
simple_read_cb(int fd, short event, void *arg) | |||
{ | |||
char buf[256]; | |||
int len; | |||
len = read(fd, buf, sizeof(buf)); | |||
if (len) { | |||
if (!called) { | |||
if (event_add(arg, NULL) == -1) | |||
exit(1); | |||
} | |||
} else if (called == 1) | |||
test_ok = 1; | |||
called++; | |||
} | |||
void | |||
simple_write_cb(int fd, short event, void *arg) | |||
{ | |||
int len; | |||
len = write(fd, TEST1, strlen(TEST1) + 1); | |||
if (len == -1) | |||
test_ok = 0; | |||
else | |||
test_ok = 1; | |||
} | |||
void | |||
multiple_write_cb(int fd, short event, void *arg) | |||
{ | |||
struct event *ev = arg; | |||
int len; | |||
len = 128; | |||
if (woff + len >= sizeof(wbuf)) | |||
len = sizeof(wbuf) - woff; | |||
len = write(fd, wbuf + woff, len); | |||
if (len == -1) { | |||
fprintf(stderr, "%s: write\n", __func__); | |||
if (usepersist) | |||
event_del(ev); | |||
return; | |||
} | |||
woff += len; | |||
if (woff >= sizeof(wbuf)) { | |||
shutdown(fd, SHUT_WR); | |||
if (usepersist) | |||
event_del(ev); | |||
return; | |||
} | |||
if (!usepersist) { | |||
if (event_add(ev, NULL) == -1) | |||
exit(1); | |||
} | |||
} | |||
void | |||
multiple_read_cb(int fd, short event, void *arg) | |||
{ | |||
struct event *ev = arg; | |||
int len; | |||
len = read(fd, rbuf + roff, sizeof(rbuf) - roff); | |||
if (len == -1) | |||
fprintf(stderr, "%s: read\n", __func__); | |||
if (len <= 0) { | |||
if (usepersist) | |||
event_del(ev); | |||
return; | |||
} | |||
roff += len; | |||
if (!usepersist) { | |||
if (event_add(ev, NULL) == -1) | |||
exit(1); | |||
} | |||
} | |||
void | |||
timeout_cb(int fd, short event, void *arg) | |||
{ | |||
struct timeval tv; | |||
int diff; | |||
gettimeofday(&tcalled, NULL); | |||
if (timercmp(&tcalled, &tset, >)) | |||
timersub(&tcalled, &tset, &tv); | |||
else | |||
timersub(&tset, &tcalled, &tv); | |||
diff = tv.tv_sec*1000 + tv.tv_usec/1000 - SECONDS * 1000; | |||
if (diff < 0) | |||
diff = -diff; | |||
if (diff < 100) | |||
test_ok = 1; | |||
} | |||
void | |||
signal_cb(int fd, short event, void *arg) | |||
{ | |||
struct event *ev = arg; | |||
signal_del(ev); | |||
test_ok = 1; | |||
} | |||
struct both { | |||
struct event ev; | |||
int nread; | |||
}; | |||
void | |||
combined_read_cb(int fd, short event, void *arg) | |||
{ | |||
struct both *both = arg; | |||
char buf[128]; | |||
int len; | |||
len = read(fd, buf, sizeof(buf)); | |||
if (len == -1) | |||
fprintf(stderr, "%s: read\n", __func__); | |||
if (len <= 0) | |||
return; | |||
both->nread += len; | |||
if (event_add(&both->ev, NULL) == -1) | |||
exit(1); | |||
} | |||
void | |||
combined_write_cb(int fd, short event, void *arg) | |||
{ | |||
struct both *both = arg; | |||
char buf[128]; | |||
int len; | |||
len = sizeof(buf); | |||
if (len > both->nread) | |||
len = both->nread; | |||
len = write(fd, buf, len); | |||
if (len == -1) | |||
fprintf(stderr, "%s: write\n", __func__); | |||
if (len <= 0) { | |||
shutdown(fd, SHUT_WR); | |||
return; | |||
} | |||
both->nread -= len; | |||
if (event_add(&both->ev, NULL) == -1) | |||
exit(1); | |||
} | |||
/* Test infrastructure */ | |||
int | |||
setup_test(char *name) | |||
{ | |||
fprintf(stdout, "%s", name); | |||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) { | |||
fprintf(stderr, "%s: socketpair\n", __func__); | |||
exit(1); | |||
} | |||
#ifdef HAVE_FCNTL | |||
if (fcntl(pair[0], F_SETFL, O_NONBLOCK) == -1) | |||
fprintf(stderr, "fcntl(O_NONBLOCK)"); | |||
if (fcntl(pair[1], F_SETFL, O_NONBLOCK) == -1) | |||
fprintf(stderr, "fcntl(O_NONBLOCK)"); | |||
#endif | |||
test_ok = 0; | |||
called = 0; | |||
return (0); | |||
} | |||
int | |||
cleanup_test(void) | |||
{ | |||
#ifndef WIN32 | |||
close(pair[0]); | |||
close(pair[1]); | |||
#else | |||
CloseHandle((HANDLE)pair[0]); | |||
CloseHandle((HANDLE)pair[1]); | |||
#endif | |||
if (test_ok) | |||
fprintf(stdout, "OK\n"); | |||
else { | |||
fprintf(stdout, "FAILED\n"); | |||
exit(1); | |||
} | |||
return (0); | |||
} | |||
void | |||
test_simpleread(void) | |||
{ | |||
struct event ev; | |||
/* Very simple read test */ | |||
setup_test("Simple read: "); | |||
write(pair[0], TEST1, strlen(TEST1)+1); | |||
shutdown(pair[0], SHUT_WR); | |||
event_set(&ev, pair[1], EV_READ, simple_read_cb, &ev); | |||
if (event_add(&ev, NULL) == -1) | |||
exit(1); | |||
event_dispatch(); | |||
cleanup_test(); | |||
} | |||
void | |||
test_simplewrite(void) | |||
{ | |||
struct event ev; | |||
/* Very simple write test */ | |||
setup_test("Simple write: "); | |||
event_set(&ev, pair[0], EV_WRITE, simple_write_cb, &ev); | |||
if (event_add(&ev, NULL) == -1) | |||
exit(1); | |||
event_dispatch(); | |||
cleanup_test(); | |||
} | |||
void | |||
test_multiple(void) | |||
{ | |||
struct event ev, ev2; | |||
int i; | |||
/* Multiple read and write test */ | |||
setup_test("Multiple read/write: "); | |||
memset(rbuf, 0, sizeof(rbuf)); | |||
for (i = 0; i < sizeof(wbuf); i++) | |||
wbuf[i] = i; | |||
roff = woff = 0; | |||
usepersist = 0; | |||
event_set(&ev, pair[0], EV_WRITE, multiple_write_cb, &ev); | |||
if (event_add(&ev, NULL) == -1) | |||
exit(1); | |||
event_set(&ev2, pair[1], EV_READ, multiple_read_cb, &ev2); | |||
if (event_add(&ev2, NULL) == -1) | |||
exit(1); | |||
event_dispatch(); | |||
if (roff == woff) | |||
test_ok = memcmp(rbuf, wbuf, sizeof(wbuf)) == 0; | |||
cleanup_test(); | |||
} | |||
void | |||
test_persistent(void) | |||
{ | |||
struct event ev, ev2; | |||
int i; | |||
/* Multiple read and write test with persist */ | |||
setup_test("Persist read/write: "); | |||
memset(rbuf, 0, sizeof(rbuf)); | |||
for (i = 0; i < sizeof(wbuf); i++) | |||
wbuf[i] = i; | |||
roff = woff = 0; | |||
usepersist = 1; | |||
event_set(&ev, pair[0], EV_WRITE|EV_PERSIST, multiple_write_cb, &ev); | |||
if (event_add(&ev, NULL) == -1) | |||
exit(1); | |||
event_set(&ev2, pair[1], EV_READ|EV_PERSIST, multiple_read_cb, &ev2); | |||
if (event_add(&ev2, NULL) == -1) | |||
exit(1); | |||
event_dispatch(); | |||
if (roff == woff) | |||
test_ok = memcmp(rbuf, wbuf, sizeof(wbuf)) == 0; | |||
cleanup_test(); | |||
} | |||
void | |||
test_combined(void) | |||
{ | |||
struct both r1, r2, w1, w2; | |||
setup_test("Combined read/write: "); | |||
memset(&r1, 0, sizeof(r1)); | |||
memset(&r2, 0, sizeof(r2)); | |||
memset(&w1, 0, sizeof(w1)); | |||
memset(&w2, 0, sizeof(w2)); | |||
w1.nread = 4096; | |||
w2.nread = 8192; | |||
event_set(&r1.ev, pair[0], EV_READ, combined_read_cb, &r1); | |||
event_set(&w1.ev, pair[0], EV_WRITE, combined_write_cb, &w1); | |||
event_set(&r2.ev, pair[1], EV_READ, combined_read_cb, &r2); | |||
event_set(&w2.ev, pair[1], EV_WRITE, combined_write_cb, &w2); | |||
if (event_add(&r1.ev, NULL) == -1) | |||
exit(1); | |||
if (event_add(&w1.ev, NULL)) | |||
exit(1); | |||
if (event_add(&r2.ev, NULL)) | |||
exit(1); | |||
if (event_add(&w2.ev, NULL)) | |||
exit(1); | |||
event_dispatch(); | |||
if (r1.nread == 8192 && r2.nread == 4096) | |||
test_ok = 1; | |||
cleanup_test(); | |||
} | |||
void | |||
test_simpletimeout(void) | |||
{ | |||
struct timeval tv; | |||
struct event ev; | |||
setup_test("Simple timeout: "); | |||
tv.tv_usec = 0; | |||
tv.tv_sec = SECONDS; | |||
evtimer_set(&ev, timeout_cb, NULL); | |||
evtimer_add(&ev, &tv); | |||
gettimeofday(&tset, NULL); | |||
event_dispatch(); | |||
cleanup_test(); | |||
} | |||
#ifndef WIN32 | |||
void | |||
test_simplesignal(void) | |||
{ | |||
struct event ev; | |||
struct itimerval itv; | |||
setup_test("Simple signal: "); | |||
signal_set(&ev, SIGALRM, signal_cb, &ev); | |||
signal_add(&ev, NULL); | |||
memset(&itv, 0, sizeof(itv)); | |||
itv.it_value.tv_sec = 1; | |||
if (setitimer(ITIMER_REAL, &itv, NULL) == -1) | |||
goto skip_simplesignal; | |||
event_dispatch(); | |||
skip_simplesignal: | |||
if (signal_del(&ev) == -1) | |||
test_ok = 0; | |||
cleanup_test(); | |||
} | |||
#endif | |||
void | |||
test_loopexit(void) | |||
{ | |||
struct timeval tv, tv_start, tv_end; | |||
struct event ev; | |||
setup_test("Loop exit: "); | |||
tv.tv_usec = 0; | |||
tv.tv_sec = 60*60*24; | |||
evtimer_set(&ev, timeout_cb, NULL); | |||
evtimer_add(&ev, &tv); | |||
tv.tv_usec = 0; | |||
tv.tv_sec = 1; | |||
event_loopexit(&tv); | |||
gettimeofday(&tv_start, NULL); | |||
event_dispatch(); | |||
gettimeofday(&tv_end, NULL); | |||
timersub(&tv_end, &tv_start, &tv_end); | |||
evtimer_del(&ev); | |||
if (tv.tv_sec < 2) | |||
test_ok = 1; | |||
cleanup_test(); | |||
} | |||
void | |||
test_evbuffer(void) { | |||
setup_test("Evbuffer: "); | |||
struct evbuffer *evb = evbuffer_new(); | |||
evbuffer_add_printf(evb, "%s/%d", "hello", 1); | |||
if (EVBUFFER_LENGTH(evb) == 7 && | |||
strcmp(EVBUFFER_DATA(evb), "hello/1") == 0) | |||
test_ok = 1; | |||
cleanup_test(); | |||
} | |||
void | |||
readcb(struct bufferevent *bev, void *arg) | |||
{ | |||
if (EVBUFFER_LENGTH(bev->input) == 8333) { | |||
bufferevent_disable(bev, EV_READ); | |||
test_ok++; | |||
} | |||
} | |||
void | |||
writecb(struct bufferevent *bev, void *arg) | |||
{ | |||
if (EVBUFFER_LENGTH(bev->output) == 0) | |||
test_ok++; | |||
} | |||
void | |||
errorcb(struct bufferevent *bev, short what, void *arg) | |||
{ | |||
test_ok = -2; | |||
} | |||
void | |||
test_bufferevent(void) | |||
{ | |||
struct bufferevent *bev1, *bev2; | |||
char buffer[8333]; | |||
int i; | |||
setup_test("Bufferevent: "); | |||
bev1 = bufferevent_new(pair[0], readcb, writecb, errorcb, NULL); | |||
bev2 = bufferevent_new(pair[1], readcb, writecb, errorcb, NULL); | |||
bufferevent_disable(bev1, EV_READ); | |||
bufferevent_enable(bev2, EV_READ); | |||
for (i = 0; i < sizeof(buffer); i++) | |||
buffer[0] = i; | |||
bufferevent_write(bev1, buffer, sizeof(buffer)); | |||
event_dispatch(); | |||
bufferevent_free(bev1); | |||
bufferevent_free(bev2); | |||
if (test_ok != 2) | |||
test_ok = 0; | |||
cleanup_test(); | |||
} | |||
struct test_pri_event { | |||
struct event ev; | |||
int count; | |||
}; | |||
void | |||
test_priorities_cb(int fd, short what, void *arg) | |||
{ | |||
struct test_pri_event *pri = arg; | |||
struct timeval tv; | |||
if (pri->count == 3) { | |||
event_loopexit(NULL); | |||
return; | |||
} | |||
pri->count++; | |||
timerclear(&tv); | |||
event_add(&pri->ev, &tv); | |||
} | |||
void | |||
test_priorities(int npriorities) | |||
{ | |||
char buf[32]; | |||
struct test_pri_event one, two; | |||
struct timeval tv; | |||
snprintf(buf, sizeof(buf), "Priorities %d: ", npriorities); | |||
setup_test(buf); | |||
event_base_priority_init(event_base, npriorities); | |||
memset(&one, 0, sizeof(one)); | |||
memset(&two, 0, sizeof(two)); | |||
timeout_set(&one.ev, test_priorities_cb, &one); | |||
if (event_priority_set(&one.ev, 0) == -1) { | |||
fprintf(stderr, "%s: failed to set priority", __func__); | |||
exit(1); | |||
} | |||
timeout_set(&two.ev, test_priorities_cb, &two); | |||
if (event_priority_set(&two.ev, npriorities - 1) == -1) { | |||
fprintf(stderr, "%s: failed to set priority", __func__); | |||
exit(1); | |||
} | |||
timerclear(&tv); | |||
if (event_add(&one.ev, &tv) == -1) | |||
exit(1); | |||
if (event_add(&two.ev, &tv) == -1) | |||
exit(1); | |||
event_dispatch(); | |||
event_del(&one.ev); | |||
event_del(&two.ev); | |||
if (npriorities == 1) { | |||
if (one.count == 3 && two.count == 3) | |||
test_ok = 1; | |||
} else if (npriorities == 2) { | |||
/* Two is called once because event_loopexit is priority 1 */ | |||
if (one.count == 3 && two.count == 1) | |||
test_ok = 1; | |||
} else { | |||
if (one.count == 3 && two.count == 0) | |||
test_ok = 1; | |||
} | |||
cleanup_test(); | |||
} | |||
static void | |||
test_multiple_cb(int fd, short event, void *arg) | |||
{ | |||
if (event & EV_READ) | |||
test_ok |= 1; | |||
else if (event & EV_WRITE) | |||
test_ok |= 2; | |||
} | |||
void | |||
test_multiple_events_for_same_fd(void) | |||
{ | |||
struct event e1, e2; | |||
setup_test("Multiple events for same fd: "); | |||
event_set(&e1, pair[0], EV_READ, test_multiple_cb, NULL); | |||
event_add(&e1, NULL); | |||
event_set(&e2, pair[0], EV_WRITE, test_multiple_cb, NULL); | |||
event_add(&e2, NULL); | |||
event_loop(EVLOOP_ONCE); | |||
event_del(&e2); | |||
write(pair[1], TEST1, strlen(TEST1)+1); | |||
event_loop(EVLOOP_ONCE); | |||
event_del(&e1); | |||
if (test_ok != 3) | |||
test_ok = 0; | |||
cleanup_test(); | |||
} | |||
int decode_int(u_int32_t *pnumber, struct evbuffer *evbuf); | |||
void | |||
read_once_cb(int fd, short event, void *arg) | |||
{ | |||
char buf[256]; | |||
int len; | |||
len = read(fd, buf, sizeof(buf)); | |||
if (called) { | |||
test_ok = 0; | |||
} else if (len) { | |||
/* Assumes global pair[0] can be used for writing */ | |||
write(pair[0], TEST1, strlen(TEST1)+1); | |||
test_ok = 1; | |||
} | |||
called++; | |||
} | |||
void | |||
test_want_only_once(void) | |||
{ | |||
struct event ev; | |||
struct timeval tv; | |||
/* Very simple read test */ | |||
setup_test("Want read only once: "); | |||
write(pair[0], TEST1, strlen(TEST1)+1); | |||
/* Setup the loop termination */ | |||
timerclear(&tv); | |||
tv.tv_sec = 1; | |||
event_loopexit(&tv); | |||
event_set(&ev, pair[1], EV_READ, read_once_cb, &ev); | |||
if (event_add(&ev, NULL) == -1) | |||
exit(1); | |||
event_dispatch(); | |||
cleanup_test(); | |||
} | |||
#define TEST_MAX_INT 6 | |||
void | |||
evtag_int_test(void) | |||
{ | |||
struct evbuffer *tmp = evbuffer_new(); | |||
u_int32_t integers[TEST_MAX_INT] = { | |||
0xaf0, 0x1000, 0x1, 0xdeadbeef, 0x00, 0xbef000 | |||
}; | |||
u_int32_t integer; | |||
int i; | |||
for (i = 0; i < TEST_MAX_INT; i++) { | |||
int oldlen, newlen; | |||
oldlen = EVBUFFER_LENGTH(tmp); | |||
encode_int(tmp, integers[i]); | |||
newlen = EVBUFFER_LENGTH(tmp); | |||
fprintf(stdout, "\t\tencoded 0x%08x with %d bytes\n", | |||
integers[i], newlen - oldlen); | |||
} | |||
for (i = 0; i < TEST_MAX_INT; i++) { | |||
if (decode_int(&integer, tmp) == -1) { | |||
fprintf(stderr, "decode %d failed", i); | |||
exit(1); | |||
} | |||
if (integer != integers[i]) { | |||
fprintf(stderr, "got %x, wanted %x", | |||
integer, integers[i]); | |||
exit(1); | |||
} | |||
} | |||
if (EVBUFFER_LENGTH(tmp) != 0) { | |||
fprintf(stderr, "trailing data"); | |||
exit(1); | |||
} | |||
evbuffer_free(tmp); | |||
fprintf(stdout, "\t%s: OK\n", __func__); | |||
} | |||
void | |||
evtag_fuzz() | |||
{ | |||
u_char buffer[4096]; | |||
struct evbuffer *tmp = evbuffer_new(); | |||
struct timeval tv; | |||
int i, j; | |||
int not_failed = 0; | |||
for (j = 0; j < 100; j++) { | |||
for (i = 0; i < sizeof(buffer); i++) | |||
buffer[i] = rand(); | |||
evbuffer_drain(tmp, -1); | |||
evbuffer_add(tmp, buffer, sizeof(buffer)); | |||
if (evtag_unmarshal_timeval(tmp, 0, &tv) != -1) | |||
not_failed++; | |||
} | |||
/* The majority of decodes should fail */ | |||
if (not_failed >= 10) { | |||
fprintf(stderr, "evtag_unmarshal should have failed"); | |||
exit(1); | |||
} | |||
/* Now insert some corruption into the tag length field */ | |||
evbuffer_drain(tmp, -1); | |||
timerclear(&tv); | |||
tv.tv_sec = 1; | |||
evtag_marshal_timeval(tmp, 0, &tv); | |||
evbuffer_add(tmp, buffer, sizeof(buffer)); | |||
EVBUFFER_DATA(tmp)[1] = 0xff; | |||
if (evtag_unmarshal_timeval(tmp, 0, &tv) != -1) { | |||
fprintf(stderr, "evtag_unmarshal_timeval should have failed"); | |||
exit(1); | |||
} | |||
evbuffer_free(tmp); | |||
fprintf(stdout, "\t%s: OK\n", __func__); | |||
} | |||
void | |||
evtag_test(void) | |||
{ | |||
fprintf(stdout, "Testing Tagging:\n"); | |||
evtag_init(); | |||
evtag_int_test(); | |||
evtag_fuzz(); | |||
fprintf(stdout, "OK\n"); | |||
} | |||
void | |||
rpc_test(void) | |||
{ | |||
struct msg *msg, *msg2; | |||
struct kill *kill; | |||
struct run *run; | |||
struct evbuffer *tmp = evbuffer_new(); | |||
int i; | |||
fprintf(stdout, "Testing RPC: "); | |||
msg = msg_new(); | |||
EVTAG_ASSIGN(msg, from_name, "niels"); | |||
EVTAG_ASSIGN(msg, to_name, "phoenix"); | |||
if (EVTAG_GET(msg, kill, &kill) == -1) { | |||
fprintf(stderr, "Failed to set kill message.\n"); | |||
exit(1); | |||
} | |||
EVTAG_ASSIGN(kill, weapon, "feather"); | |||
EVTAG_ASSIGN(kill, action, "tickle"); | |||
for (i = 0; i < 3; ++i) { | |||
run = EVTAG_ADD(msg, run); | |||
if (run == NULL) { | |||
fprintf(stderr, "Failed to add run message.\n"); | |||
exit(1); | |||
} | |||
EVTAG_ASSIGN(run, how, "very fast"); | |||
} | |||
if (msg_complete(msg) == -1) { | |||
fprintf(stderr, "Failed to make complete message.\n"); | |||
exit(1); | |||
} | |||
evtag_marshal_msg(tmp, 0, msg); | |||
msg2 = msg_new(); | |||
if (evtag_unmarshal_msg(tmp, 0, msg2) == -1) { | |||
fprintf(stderr, "Failed to unmarshal message.\n"); | |||
exit(1); | |||
} | |||
if (!EVTAG_HAS(msg2, from_name) || | |||
!EVTAG_HAS(msg2, to_name) || | |||
!EVTAG_HAS(msg2, kill)) { | |||
fprintf(stderr, "Missing data structures.\n"); | |||
exit(1); | |||
} | |||
if (EVTAG_LEN(msg2, run) != 3) { | |||
fprintf(stderr, "Wrong number of run messages.\n"); | |||
exit(1); | |||
} | |||
msg_free(msg); | |||
msg_free(msg2); | |||
fprintf(stdout, "OK\n"); | |||
} | |||
int | |||
main (int argc, char **argv) | |||
{ | |||
#ifdef WIN32 | |||
WORD wVersionRequested; | |||
WSADATA wsaData; | |||
int err; | |||
wVersionRequested = MAKEWORD( 2, 2 ); | |||
err = WSAStartup( wVersionRequested, &wsaData ); | |||
#endif | |||
setvbuf(stdout, NULL, _IONBF, 0); | |||
/* Initalize the event library */ | |||
event_base = event_init(); | |||
http_suite(); | |||
dns_suite(); | |||
test_simpleread(); | |||
test_simplewrite(); | |||
test_multiple(); | |||
test_persistent(); | |||
test_combined(); | |||
test_simpletimeout(); | |||
#ifndef WIN32 | |||
test_simplesignal(); | |||
#endif | |||
test_loopexit(); | |||
test_evbuffer(); | |||
test_bufferevent(); | |||
test_priorities(1); | |||
test_priorities(2); | |||
test_priorities(3); | |||
test_multiple_events_for_same_fd(); | |||
test_want_only_once(); | |||
evtag_test(); | |||
rpc_test(); | |||
return (0); | |||
} | |||
@@ -1,43 +0,0 @@ | |||
/* | |||
* Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu> | |||
* All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in the | |||
* documentation and/or other materials provided with the distribution. | |||
* 3. The name of the author may not be used to endorse or promote products | |||
* derived from this software without specific prior written permission. | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
*/ | |||
#ifndef _REGRESS_H_ | |||
#define _REGRESS_H_ | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
void http_suite(void); | |||
void http_basic_test(void); | |||
void dns_suite(void); | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
#endif /* _REGRESS_H_ */ |
@@ -1,17 +0,0 @@ | |||
/* tests data packing and unpacking */ | |||
struct msg { | |||
string from_name = 1; | |||
string to_name = 2; | |||
optional struct[kill] kill = 3; | |||
array struct[run] run = 4; | |||
} | |||
struct kill { | |||
string weapon = 1; | |||
string action = 2; | |||
} | |||
struct run { | |||
string how = 1; | |||
} |
@@ -1,144 +0,0 @@ | |||
/* | |||
* Copyright (c) 2003-2006 Niels Provos <provos@citi.umich.edu> | |||
* All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in the | |||
* documentation and/or other materials provided with the distribution. | |||
* 3. The name of the author may not be used to endorse or promote products | |||
* derived from this software without specific prior written permission. | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
*/ | |||
#ifdef WIN32 | |||
#include <winsock2.h> | |||
#include <windows.h> | |||
#endif | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
#include <sys/types.h> | |||
#include <sys/stat.h> | |||
#ifdef HAVE_SYS_TIME_H | |||
#include <sys/time.h> | |||
#endif | |||
#include <sys/queue.h> | |||
#ifndef WIN32 | |||
#include <sys/socket.h> | |||
#include <sys/signal.h> | |||
#include <netinet/in.h> | |||
#include <arpa/inet.h> | |||
#include <unistd.h> | |||
#endif | |||
#include <netdb.h> | |||
#include <fcntl.h> | |||
#include <stdlib.h> | |||
#include <stdio.h> | |||
#include <string.h> | |||
#include <errno.h> | |||
#include "event.h" | |||
#include "evdns.h" | |||
#include "log.h" | |||
static int dns_ok = 0; | |||
void | |||
dns_gethostbyname_cb(int result, char type, int count, int ttl, | |||
void *addresses, void *arg) | |||
{ | |||
dns_ok = 0; | |||
if (result != DNS_ERR_NONE) | |||
goto out; | |||
fprintf(stderr, "type: %d, count: %d, ttl: %d: ", type, count, ttl); | |||
switch (type) { | |||
case DNS_IPv4_A: { | |||
struct in_addr *in_addrs = addresses; | |||
int i; | |||
/* a resolution that's not valid does not help */ | |||
if (ttl < 0) | |||
goto out; | |||
for (i = 0; i < count; ++i) | |||
fprintf(stderr, "%s ", inet_ntoa(in_addrs[0])); | |||
break; | |||
} | |||
case DNS_PTR: | |||
/* may get at most one PTR */ | |||
if (count != 1) | |||
goto out; | |||
fprintf(stderr, "%s ", *(char **)addresses); | |||
break; | |||
default: | |||
goto out; | |||
} | |||
dns_ok = 1; | |||
out: | |||
event_loopexit(NULL); | |||
} | |||
void | |||
dns_gethostbyname() | |||
{ | |||
fprintf(stdout, "Simple DNS resolve: "); | |||
dns_ok = 0; | |||
evdns_resolve_ipv4("www.monkey.org", 0, dns_gethostbyname_cb, NULL); | |||
event_dispatch(); | |||
if (dns_ok) { | |||
fprintf(stdout, "OK\n"); | |||
} else { | |||
fprintf(stdout, "FAILED\n"); | |||
exit(1); | |||
} | |||
} | |||
void | |||
dns_gethostbyaddr() | |||
{ | |||
struct in_addr in; | |||
in.s_addr = htonl(0x7f000001ul); /* 127.0.0.1 */ | |||
fprintf(stdout, "Simple reverse DNS resolve: "); | |||
dns_ok = 0; | |||
evdns_resolve_reverse(&in, 0, dns_gethostbyname_cb, NULL); | |||
event_dispatch(); | |||
if (dns_ok) { | |||
fprintf(stdout, "OK\n"); | |||
} else { | |||
fprintf(stdout, "FAILED\n"); | |||
exit(1); | |||
} | |||
} | |||
void | |||
dns_suite(void) | |||
{ | |||
evdns_init(); | |||
dns_gethostbyname(); | |||
dns_gethostbyaddr(); | |||
evdns_shutdown(0); | |||
} |
@@ -1,426 +0,0 @@ | |||
/* | |||
* Copyright (c) 2003-2006 Niels Provos <provos@citi.umich.edu> | |||
* All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in the | |||
* documentation and/or other materials provided with the distribution. | |||
* 3. The name of the author may not be used to endorse or promote products | |||
* derived from this software without specific prior written permission. | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
*/ | |||
#ifdef WIN32 | |||
#include <winsock2.h> | |||
#include <windows.h> | |||
#endif | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
#include <sys/types.h> | |||
#include <sys/stat.h> | |||
#ifdef HAVE_SYS_TIME_H | |||
#include <sys/time.h> | |||
#endif | |||
#include <sys/queue.h> | |||
#ifndef WIN32 | |||
#include <sys/socket.h> | |||
#include <sys/signal.h> | |||
#include <unistd.h> | |||
#endif | |||
#include <netdb.h> | |||
#include <fcntl.h> | |||
#include <stdlib.h> | |||
#include <stdio.h> | |||
#include <string.h> | |||
#include <errno.h> | |||
#include "event.h" | |||
#include "evhttp.h" | |||
#include "log.h" | |||
#include "http-internal.h" | |||
extern int pair[]; | |||
extern int test_ok; | |||
static struct evhttp *http; | |||
void http_basic_cb(struct evhttp_request *req, void *arg); | |||
void http_post_cb(struct evhttp_request *req, void *arg); | |||
struct evhttp * | |||
http_setup(short *pport) | |||
{ | |||
int i; | |||
struct evhttp *myhttp; | |||
short port = -1; | |||
/* Try a few different ports */ | |||
for (i = 0; i < 50; ++i) { | |||
myhttp = evhttp_start("127.0.0.1", 8080 + i); | |||
if (myhttp != NULL) { | |||
port = 8080 + i; | |||
break; | |||
} | |||
} | |||
if (port == -1) | |||
event_errx(1, "Could not start web server"); | |||
/* Register a callback for certain types of requests */ | |||
evhttp_set_cb(myhttp, "/test", http_basic_cb, NULL); | |||
evhttp_set_cb(myhttp, "/postit", http_post_cb, NULL); | |||
*pport = port; | |||
return (myhttp); | |||
} | |||
int | |||
http_connect(const char *address, u_short port) | |||
{ | |||
/* Stupid code for connecting */ | |||
struct addrinfo ai, *aitop; | |||
char strport[NI_MAXSERV]; | |||
int fd; | |||
memset(&ai, 0, sizeof (ai)); | |||
ai.ai_family = AF_INET; | |||
ai.ai_socktype = SOCK_STREAM; | |||
snprintf(strport, sizeof (strport), "%d", port); | |||
if (getaddrinfo(address, strport, &ai, &aitop) != 0) { | |||
event_warn("getaddrinfo"); | |||
return (-1); | |||
} | |||
fd = socket(AF_INET, SOCK_STREAM, 0); | |||
if (fd == -1) | |||
event_err(1, "socket failed"); | |||
if (connect(fd, aitop->ai_addr, aitop->ai_addrlen) == -1) | |||
event_err(1, "connect failed"); | |||
freeaddrinfo(aitop); | |||
return (fd); | |||
} | |||
void | |||
http_readcb(struct bufferevent *bev, void *arg) | |||
{ | |||
const char *what = "This is funny"; | |||
event_debug(("%s: %s\n", __func__, EVBUFFER_DATA(bev->input))); | |||
if (evbuffer_find(bev->input, what, strlen(what)) != NULL) { | |||
struct evhttp_request *req = evhttp_request_new(NULL, NULL); | |||
req->kind = EVHTTP_RESPONSE; | |||
int done = evhttp_parse_lines(req, bev->input); | |||
if (done == 1 && | |||
evhttp_find_header(req->input_headers, | |||
"Content-Type") != NULL) | |||
test_ok++; | |||
evhttp_request_free(req); | |||
bufferevent_disable(bev, EV_READ); | |||
event_loopexit(NULL); | |||
} | |||
} | |||
void | |||
http_writecb(struct bufferevent *bev, void *arg) | |||
{ | |||
if (EVBUFFER_LENGTH(bev->output) == 0) { | |||
/* enable reading of the reply */ | |||
bufferevent_enable(bev, EV_READ); | |||
test_ok++; | |||
} | |||
} | |||
void | |||
http_errorcb(struct bufferevent *bev, short what, void *arg) | |||
{ | |||
test_ok = -2; | |||
event_loopexit(NULL); | |||
} | |||
void | |||
http_basic_cb(struct evhttp_request *req, void *arg) | |||
{ | |||
event_debug((stderr, "%s: called\n", __func__)); | |||
struct evbuffer *evb = evbuffer_new(); | |||
evbuffer_add_printf(evb, "This is funny"); | |||
evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb); | |||
evbuffer_free(evb); | |||
} | |||
void | |||
http_basic_test(void) | |||
{ | |||
struct bufferevent *bev; | |||
int fd; | |||
char *http_request; | |||
short port = -1; | |||
test_ok = 0; | |||
fprintf(stdout, "Testing Basic HTTP Server: "); | |||
http = http_setup(&port); | |||
fd = http_connect("127.0.0.1", port); | |||
/* Stupid thing to send a request */ | |||
bev = bufferevent_new(fd, http_readcb, http_writecb, | |||
http_errorcb, NULL); | |||
http_request = | |||
"GET /test HTTP/1.1\r\n" | |||
"Host: somehost \r\n" | |||
"\r\n"; | |||
bufferevent_write(bev, http_request, strlen(http_request)); | |||
event_dispatch(); | |||
bufferevent_free(bev); | |||
close(fd); | |||
evhttp_free(http); | |||
if (test_ok != 2) { | |||
fprintf(stdout, "FAILED\n"); | |||
exit(1); | |||
} | |||
fprintf(stdout, "OK\n"); | |||
} | |||
void http_request_done(struct evhttp_request *, void *); | |||
void | |||
http_connection_test(void) | |||
{ | |||
short port = -1; | |||
struct evhttp_connection *evcon = NULL; | |||
struct evhttp_request *req = NULL; | |||
test_ok = 0; | |||
fprintf(stdout, "Testing Basic HTTP Connection: "); | |||
http = http_setup(&port); | |||
evcon = evhttp_connection_new("127.0.0.1", port); | |||
if (evcon == NULL) { | |||
fprintf(stdout, "FAILED\n"); | |||
exit(1); | |||
} | |||
/* | |||
* At this point, we want to schedule a request to the HTTP | |||
* server using our make request method. | |||
*/ | |||
req = evhttp_request_new(http_request_done, NULL); | |||
/* Add the information that we care about */ | |||
evhttp_add_header(req->output_headers, "Host", "somehost"); | |||
/* We give ownership of the request to the connection */ | |||
if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) { | |||
fprintf(stdout, "FAILED\n"); | |||
exit(1); | |||
} | |||
event_dispatch(); | |||
evhttp_connection_free(evcon); | |||
evhttp_free(http); | |||
if (test_ok != 1) { | |||
fprintf(stdout, "FAILED\n"); | |||
exit(1); | |||
} | |||
fprintf(stdout, "OK\n"); | |||
} | |||
void | |||
http_request_done(struct evhttp_request *req, void *arg) | |||
{ | |||
const char *what = "This is funny"; | |||
if (req->response_code != HTTP_OK) { | |||
fprintf(stderr, "FAILED\n"); | |||
exit(1); | |||
} | |||
if (evhttp_find_header(req->input_headers, "Content-Type") == NULL) { | |||
fprintf(stderr, "FAILED\n"); | |||
exit(1); | |||
} | |||
if (EVBUFFER_LENGTH(req->input_buffer) != strlen(what)) { | |||
fprintf(stderr, "FAILED\n"); | |||
exit(1); | |||
} | |||
if (memcmp(EVBUFFER_DATA(req->input_buffer), what, strlen(what)) != 0) { | |||
fprintf(stderr, "FAILED\n"); | |||
exit(1); | |||
} | |||
test_ok = 1; | |||
event_loopexit(NULL); | |||
} | |||
/* | |||
* HTTP POST test. | |||
*/ | |||
void http_postrequest_done(struct evhttp_request *, void *); | |||
#define POST_DATA "Okay. Not really printf" | |||
void | |||
http_post_test(void) | |||
{ | |||
short port = -1; | |||
struct evhttp_connection *evcon = NULL; | |||
struct evhttp_request *req = NULL; | |||
test_ok = 0; | |||
fprintf(stdout, "Testing HTTP POST Request: "); | |||
http = http_setup(&port); | |||
evcon = evhttp_connection_new("127.0.0.1", port); | |||
if (evcon == NULL) { | |||
fprintf(stdout, "FAILED\n"); | |||
exit(1); | |||
} | |||
/* | |||
* At this point, we want to schedule an HTTP POST request | |||
* server using our make request method. | |||
*/ | |||
req = evhttp_request_new(http_postrequest_done, NULL); | |||
if (req == NULL) { | |||
fprintf(stdout, "FAILED\n"); | |||
exit(1); | |||
} | |||
/* Add the information that we care about */ | |||
evhttp_add_header(req->output_headers, "Host", "somehost"); | |||
evbuffer_add_printf(req->output_buffer, POST_DATA); | |||
if (evhttp_make_request(evcon, req, EVHTTP_REQ_POST, "/postit") == -1) { | |||
fprintf(stdout, "FAILED\n"); | |||
exit(1); | |||
} | |||
event_dispatch(); | |||
evhttp_connection_free(evcon); | |||
evhttp_free(http); | |||
if (test_ok != 1) { | |||
fprintf(stdout, "FAILED: %d\n", test_ok); | |||
exit(1); | |||
} | |||
fprintf(stdout, "OK\n"); | |||
} | |||
void | |||
http_post_cb(struct evhttp_request *req, void *arg) | |||
{ | |||
event_debug((stderr, "%s: called\n", __func__)); | |||
/* Yes, we are expecting a post request */ | |||
if (req->type != EVHTTP_REQ_POST) { | |||
fprintf(stdout, "FAILED (post type)\n"); | |||
exit(1); | |||
} | |||
if (EVBUFFER_LENGTH(req->input_buffer) != strlen(POST_DATA)) { | |||
fprintf(stdout, "FAILED (length: %ld vs %ld)\n", | |||
EVBUFFER_LENGTH(req->input_buffer), strlen(POST_DATA)); | |||
exit(1); | |||
} | |||
if (memcmp(EVBUFFER_DATA(req->input_buffer), POST_DATA, | |||
strlen(POST_DATA))) { | |||
fprintf(stdout, "FAILED (data)\n"); | |||
fprintf(stdout, "Got :%s\n", EVBUFFER_DATA(req->input_buffer)); | |||
fprintf(stdout, "Want:%s\n", POST_DATA); | |||
exit(1); | |||
} | |||
struct evbuffer *evb = evbuffer_new(); | |||
evbuffer_add_printf(evb, "This is funny"); | |||
evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb); | |||
evbuffer_free(evb); | |||
} | |||
void | |||
http_postrequest_done(struct evhttp_request *req, void *arg) | |||
{ | |||
const char *what = "This is funny"; | |||
if (req->response_code != HTTP_OK) { | |||
fprintf(stderr, "FAILED (response code)\n"); | |||
exit(1); | |||
} | |||
if (evhttp_find_header(req->input_headers, "Content-Type") == NULL) { | |||
fprintf(stderr, "FAILED (content type)\n"); | |||
exit(1); | |||
} | |||
if (EVBUFFER_LENGTH(req->input_buffer) != strlen(what)) { | |||
fprintf(stderr, "FAILED (length %ld vs %ld)\n", | |||
EVBUFFER_LENGTH(req->input_buffer), strlen(what)); | |||
exit(1); | |||
} | |||
if (memcmp(EVBUFFER_DATA(req->input_buffer), what, strlen(what)) != 0) { | |||
fprintf(stderr, "FAILED (data)\n"); | |||
exit(1); | |||
} | |||
test_ok = 1; | |||
event_loopexit(NULL); | |||
} | |||
void | |||
http_suite(void) | |||
{ | |||
http_basic_test(); | |||
http_connection_test(); | |||
http_post_test(); | |||
} |
@@ -1,68 +0,0 @@ | |||
/* | |||
* Compile with: | |||
* cc -I/usr/local/include -o time-test time-test.c -L/usr/local/lib -levent | |||
*/ | |||
#include <sys/types.h> | |||
#include <sys/stat.h> | |||
#include <sys/time.h> | |||
#include <sys/socket.h> | |||
#include <fcntl.h> | |||
#include <stdlib.h> | |||
#include <stdio.h> | |||
#include <string.h> | |||
#include <unistd.h> | |||
#include <errno.h> | |||
#include <event.h> | |||
int test_okay = 1; | |||
int called = 0; | |||
void | |||
read_cb(int fd, short event, void *arg) | |||
{ | |||
char buf[256]; | |||
int len; | |||
len = read(fd, buf, sizeof(buf)); | |||
printf("%s: read %d%s\n", __func__, | |||
len, len ? "" : " - means EOF"); | |||
if (len) { | |||
if (!called) | |||
event_add(arg, NULL); | |||
} else if (called == 1) | |||
test_okay = 0; | |||
called++; | |||
} | |||
int | |||
main (int argc, char **argv) | |||
{ | |||
struct event ev; | |||
char *test = "test string"; | |||
int pair[2]; | |||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) | |||
return (1); | |||
write(pair[0], test, strlen(test)+1); | |||
shutdown(pair[0], SHUT_WR); | |||
/* Initalize the event library */ | |||
event_init(); | |||
/* Initalize one event */ | |||
event_set(&ev, pair[1], EV_READ, read_cb, &ev); | |||
event_add(&ev, NULL); | |||
event_dispatch(); | |||
return (test_okay); | |||
} | |||
@@ -1,27 +0,0 @@ | |||
/* | |||
* Compile with: | |||
* cc -I/usr/local/include -o time-test time-test.c -L/usr/local/lib -levent | |||
*/ | |||
#include <sys/types.h> | |||
#include <sys/stat.h> | |||
#include <sys/time.h> | |||
#include <sys/socket.h> | |||
#include <fcntl.h> | |||
#include <stdlib.h> | |||
#include <stdio.h> | |||
#include <string.h> | |||
#include <unistd.h> | |||
#include <errno.h> | |||
#include <event.h> | |||
int | |||
main(int argc, char **argv) | |||
{ | |||
/* Initalize the event library */ | |||
event_init(); | |||
return (0); | |||
} | |||
@@ -1,68 +0,0 @@ | |||
/* | |||
* Compile with: | |||
* cc -I/usr/local/include -o time-test time-test.c -L/usr/local/lib -levent | |||
*/ | |||
#include <sys/types.h> | |||
#include <sys/stat.h> | |||
#include <sys/time.h> | |||
#include <fcntl.h> | |||
#include <stdlib.h> | |||
#include <stdio.h> | |||
#include <string.h> | |||
#include <unistd.h> | |||
#include <errno.h> | |||
#include <event.h> | |||
int called = 0; | |||
#define NEVENT 20000 | |||
struct event *ev[NEVENT]; | |||
void | |||
time_cb(int fd, short event, void *arg) | |||
{ | |||
struct timeval tv; | |||
int i, j; | |||
called++; | |||
if (called < 10*NEVENT) { | |||
for (i = 0; i < 10; i++) { | |||
j = random() % NEVENT; | |||
tv.tv_sec = 0; | |||
tv.tv_usec = random() % 50000L; | |||
if (tv.tv_usec % 2) | |||
evtimer_add(ev[j], &tv); | |||
else | |||
evtimer_del(ev[j]); | |||
} | |||
} | |||
} | |||
int | |||
main (int argc, char **argv) | |||
{ | |||
struct timeval tv; | |||
int i; | |||
/* Initalize the event library */ | |||
event_init(); | |||
for (i = 0; i < NEVENT; i++) { | |||
ev[i] = malloc(sizeof(struct event)); | |||
/* Initalize one event */ | |||
evtimer_set(ev[i], time_cb, ev[i]); | |||
tv.tv_sec = 0; | |||
tv.tv_usec = random() % 50000L; | |||
evtimer_add(ev[i], &tv); | |||
} | |||
event_dispatch(); | |||
return (called < NEVENT); | |||
} | |||
@@ -1,68 +0,0 @@ | |||
/* | |||
* Compile with: | |||
* cc -I/usr/local/include -o time-test time-test.c -L/usr/local/lib -levent | |||
*/ | |||
#include <sys/types.h> | |||
#include <sys/stat.h> | |||
#include <sys/time.h> | |||
#include <sys/socket.h> | |||
#include <fcntl.h> | |||
#include <stdlib.h> | |||
#include <stdio.h> | |||
#include <string.h> | |||
#include <signal.h> | |||
#include <unistd.h> | |||
#include <errno.h> | |||
#include <event.h> | |||
int pair[2]; | |||
int test_okay = 1; | |||
int called = 0; | |||
void | |||
write_cb(int fd, short event, void *arg) | |||
{ | |||
char *test = "test string"; | |||
int len; | |||
len = write(fd, test, strlen(test) + 1); | |||
printf("%s: write %d%s\n", __func__, | |||
len, len ? "" : " - means EOF"); | |||
if (len > 0) { | |||
if (!called) | |||
event_add(arg, NULL); | |||
close(pair[0]); | |||
} else if (called == 1) | |||
test_okay = 0; | |||
called++; | |||
} | |||
int | |||
main (int argc, char **argv) | |||
{ | |||
struct event ev; | |||
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) | |||
return (1); | |||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) | |||
return (1); | |||
/* Initalize the event library */ | |||
event_init(); | |||
/* Initalize one event */ | |||
event_set(&ev, pair[1], EV_WRITE, write_cb, &ev); | |||
event_add(&ev, NULL); | |||
event_dispatch(); | |||
return (test_okay); | |||
} | |||
@@ -1,91 +0,0 @@ | |||
#!/bin/sh | |||
setup () { | |||
EVENT_NOKQUEUE=yes; export EVENT_NOKQUEUE | |||
EVENT_NODEVPOLL=yes; export EVENT_NODEVPOLL | |||
EVENT_NOPOLL=yes; export EVENT_NOPOLL | |||
EVENT_NOSELECT=yes; export EVENT_NOSELECT | |||
EVENT_NOEPOLL=yes; export EVENT_NOEPOLL | |||
EVENT_NORTSIG=yes; export EVENT_NORTSIG | |||
} | |||
test () { | |||
if ./test-init 2>/dev/null ; | |||
then | |||
true | |||
else | |||
echo Skipping test | |||
return | |||
fi | |||
echo -n " test-eof: " | |||
if ./test-eof >/dev/null ; | |||
then | |||
echo OKAY ; | |||
else | |||
echo FAILED ; | |||
fi | |||
echo -n " test-weof: " | |||
if ./test-weof >/dev/null ; | |||
then | |||
echo OKAY ; | |||
else | |||
echo FAILED ; | |||
fi | |||
echo -n " test-time: " | |||
if ./test-time >/dev/null ; | |||
then | |||
echo OKAY ; | |||
else | |||
echo FAILED ; | |||
fi | |||
echo -n " regress: " | |||
if ./regress >/dev/null ; | |||
then | |||
echo OKAY ; | |||
else | |||
echo FAILED ; | |||
fi | |||
} | |||
echo "Running tests:" | |||
# Need to do this by hand? | |||
setup | |||
unset EVENT_NOKQUEUE | |||
export EVENT_NOKQUEUE | |||
echo "KQUEUE" | |||
test | |||
setup | |||
unset EVENT_NODEVPOLL | |||
export EVENT_NODEVPOLL | |||
echo "DEVPOLL" | |||
test | |||
setup | |||
unset EVENT_NOPOLL | |||
export EVENT_NOPOLL | |||
echo "POLL" | |||
test | |||
setup | |||
unset EVENT_NOSELECT | |||
export EVENT_NOSELECT | |||
echo "SELECT" | |||
test | |||
setup | |||
unset EVENT_NORTSIG | |||
export EVENT_NORTSIG | |||
echo "RTSIG" | |||
test | |||
setup | |||
unset EVENT_NOEPOLL | |||
export EVENT_NOEPOLL | |||
echo "EPOLL" | |||
test | |||