Lupuz.de: Artikel-Portal / Magazin

Zurück   Postpla.net - die Forum Community > PC, Internet und Technik > Coder's Area

Daemon in c

Anzeigen:

Thema geschlossen
 
Themen-Optionen
Christian
Alt 09.01.2002, 13:02   #1
Beitrag Daemon in c

hi,

kann mir jemand sagen wie man mit c einen daemon unter linux programmiert?
 
 
Nach oben
SilverSky
Alt 09.01.2002, 14:50   #2
Beitrag

// Sample code file: echo-daemon.c
// Warning: This code has been marked up for HTML


/*
* THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES.
* USE AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO THE LICENSE AGREEMENT
* ACCOMPANYING THE SOFTWARE DEVELOPMENT KIT (SDK) THAT CONTAINS THIS WORK.
* PURSUANT TO THE SDK LICENSE AGREEMENT, NOVELL HEREBY GRANTS TO DEVELOPER A
* ROYALTY-FREE, NON-EXCLUSIVE LICENSE TO INCLUDE NOVELL'S SAMPLE CODE IN ITS
* PRODUCT. NOVELL GRANTS DEVELOPER WORLDWIDE DISTRIBUTION RIGHTS TO MARKET,
* DISTRIBUTE, OR SELL NOVELL'S SAMPLE CODE AS A COMPONENT OF DEVELOPER'S
* PRODUCTS. NOVELL SHALL HAVE NO OBLIGATIONS TO DEVELOPER OR DEVELOPER'S
* CUSTOMERS WITH RESPECT TO THIS CODE.
*
*
* echod.nlm
*
* echo-daemon listens on plain and ssl sockets for requests from an echo
* client. by default it simply returns (echoes) to the client whatever the
* echo client sends. using the -h option, echo-daemon can also interpret
* simple HTTP GET requests.
*
* echo-daemon starts by default with 1 thread each for plain and ssl socket
* accepts and adds threads as traffic warrants. after accept a connection
* the socket (and completing the ssl handshake in the case of a ssl socket),
* the plain or ssl connection is serviced by a plain or ssl select thread.
* when select indicates that a plain or ssl socket must be serviced, the
* socket is removed from the fd_set and passed to a plain or ssl read/write
* thread which by default reads data from the connection and echoes to the
* client. the socket is re-added to the appropriate fd_set and returned to
* the appropriate (plain or ssl) select thread.
*
* the socket is removed from the fd_set and closed only when the client
* resets or aborts the connection or some other socket error occurs.
*
*/

/*
* define any combination of TRACE, TRACE_ERRORS, and TRACE_VERBOSE. can
* also undefine all TRACE*. define TRACE to see what's happening on each
* thread.
*/
#define TRACE 1

/*
* define TRACE_ERRORS to see errors only
*/
#define TRACE_ERRORS 1

/*
* like TRACE but (surprise) more verbose
*/
#define TRACE_VERBOSE 1

/*
* must be defined in order to include SSL specific stuff in ws2nlm.h and
* winsock2.h
*/
#define WS_SSL

/*
* Winsock fd set size - standard Winsock default is 64
*/
#define FD_SETSIZE 64

/*
* SO_SNDBUF|SO_RCVBUF maximum TCP buffer size
*/
#define SO_BUFFER_SIZE 0xFFFF
/*
* maximum number of plain and ssl accept and rw threads
*/
#define MAX_ACCEPT_THREADS 16
#define MAX_RW_THREADS 16

/*
* echo-daemon buffer size
*/
#define BUFFER_SIZE 4096

/*
* echo-daemon thread stack size
*/
#define THREAD_STACK_SIZE 0x8000

#define MAX_EVENTS 2

#define ERROR (-1)
#define SHUTDOWN(s) {shutdown(s,2);closesocket(s);}

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <ws2nlm.h>

#include <signal.h>
#include <nwsemaph.h>
#include <nwconio.h>
#include <nwthread.h>

#define CONSOLE(a) ConsolePrintf(a)
#define EXIT ExitThread(EXIT_THREAD, 0)
#define FOUT stdout
#define FPRINTF(a,b) {MUTEX_LOCK; SetCurrentScreen(a); fprintf##b; MUTEX_UNLOCK;}
#define MUTEX_LOCK SemWait(ioMutex)
#define MUTEX_UNLOCK SemSignal(ioMutex)
#define SCREEN_CREATE(a,b) b = CreateScreen(a, AUTO_DESTROY_SCREEN)
#define SCREEN_DESTROY(a) {MUTEX_LOCK; DestroyScreen(a); MUTEX_UNLOCK;}
#define SEM unsigned long
#define THREAD int
#define THREADFUNC(a,p) THREAD a(void* p)
#define THREAD_START(p) {p##->hThread = BeginThread(p##->func,p##->pStack,THREAD_STACK_SIZE,p);RenameThread(p# #->hThread,p##->pcName);}
#define THREAD_DESTROY(a)

SEM ioMutex;
SEM coMutex;
SEM coMutexSsl;
typedef int SCR;
typedef int threadfunc(void *p);

enum eThreadType { ePlain = 0, eSsl = 1, eMaxThreadType = 0xffffffff };
enum eAuthType { eServer = 0, eClient = 1, eMaxAuthType = 0xffffffff };
enum eSocketState { eAccept = 0, eRw = 1, eMaxState = 0xffffffff };

/*
* number of current plain socket accept threads - start with 1 and add
* threads as traffic warrants
*/
unsigned uNumberOfAcceptThreads = 1;

/*
* number of current ssl socket accept threads - start with 1 and add
* threads as traffic warrants
*/
unsigned uNumberOfSslAcceptThreads = 1;

/*
* number of current plain socket read/write threads - start with 1 and add
* threads as traffic warrants
*/
unsigned uNumberOfRwThreads = 1;

/*
* number of current ssl socket read/write threads - start with 1 and add
* threads as traffic warrants
*/
unsigned uNumberOfSslRwThreads = 1;

enum eAuthType eAuth = eServer;

struct sThreadPars {
THREAD hThread;
SEM hSem;
SCR hScreen;
void *pStack;
int iThread;
enum eThreadType eType;
threadfunc *func;
char pcName[80];
} sThreadPars;

struct sSocketInfo {
unsigned long addr;
enum eSocketState state;
} sSocketInfo;

struct sRw {
struct sThreadPars p;
SOCKET s;
struct sSocketInfo sInfo;
char *pcBuffer;
struct sSelect *psSelect;
unsigned long ulIterations;
} *psRw, *psSslRw;

struct sAccept {
struct sThreadPars p;
SOCKET s;
struct sSocketInfo sInfo;
struct sSelect *psSelect;
unsigned long ulIterations;
} *psAccept, *psSslAccept;

struct sListen {
struct sThreadPars p;
SOCKET s;
struct sSocketInfo sInfo;
WSAEVENT e;
unsigned *uNumberOfAcceptThreads;
int iPort;
struct sAccept *psAccept;
} sListen, sSslListen;

struct sSelect {
struct sThreadPars p;
fd_set *rd;
fd_set *wr;
fd_set *ex;
SEM hSem;
unsigned *uNumberOfRwThreads;
struct sRw *psRw;
unsigned long ulIterations;
} sSelect, sSslSelect;

int fAddFd(SOCKET, fd_set*, SEM, SEM, SCR);
void fExit(void);
void fExitDaemon(void);
int fHttp(char*, int*);
THREADFUNC(fAccept,p);
THREADFUNC(fListen,p);
THREADFUNC(fRw,p);
THREADFUNC(fSelect,p);
int fParseArgs(int, char*[]);
void fShowUsage(char *);
int fStatistics(void*);
int fSslStatistics(void*);
int fStart(int, int);
int fRemoveFd(SOCKET, fd_set*, SEM, SCR);
SEM SemCreate(void*, unsigned long);
int SemDestroy(SEM);
int SemSignal(SEM);
int SemTest(SEM);
int SemWait(SEM);
void fStartThread(struct sThreadPars *, char*, int);
void fWSATerminationHandler(int iSignal);

int exitFlag = 0;
SCR hScreen;
int iHttp = FALSE;
char *pcFile=NULL;
char *pcHttpRoot = "SYS:";
char *pcKeyfile=(char*)"SSL Key";
int iListenPort = 80;
int iSidLifetime = 100;
int iSslListenPort = 443;

int main(int argc, char *argv[])
{
if(!fParseArgs(argc, argv)) {
/* fStart() does all the work of starting threads */
if(fStart(iListenPort, iSslListenPort))
return -1;
EXIT;
}
return 0;
} /* main */

THREADFUNC(fListen,p)
{
struct sListen *ps = (struct sListen *)p;
int iStatus = 0;
struct sockaddr_in sin;
int iMode = 0;
unsigned long ulSocketBufferSize = SO_BUFFER_SIZE;
WSAPROTOCOL_INFO sProtocolInfo;
#if TRACE || TRACE_VERBOSE || TRACE_ERRORS

SCREEN_CREATE(ps->p.pcName,ps->p.hScreen);
#endif /* TRACE || TRACE_VERBOSE || TRACE_ERRORS */

memset(&sProtocolInfo, 0, sizeof(WSAPROTOCOL_INFO));
sProtocolInfo.iAddressFamily = AF_INET;
sProtocolInfo.iSocketType = SOCK_STREAM;
sProtocolInfo.iProtocol = IPPROTO_TCP;
/*
* This statement is the only difference between creating a plain and a
* ssl socket.
*/
if(ps->p.eType == eSsl)
sProtocolInfo.iSecurityScheme = SECURITY_PROTOCOL_SSL;

#if TRACE
FPRINTF(ps->p.hScreen,(FOUT,"WSASocket...\n"));
#endif /* TRACE */
ps->s = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, &sProtocolInfo, NULL, NULL);
if(ps->s == INVALID_SOCKET) {
#if TRACE_ERRORS
FPRINTF(ps->p.hScreen,(FOUT,"WSASocket failed %d\n",WSAGetLastError()));
#endif /* TRACE_ERRORS */
return 0;
}
#if TRACE
else
FPRINTF(ps->p.hScreen,(FOUT,"WSASocket OK [%1d]\n",ps->s));
#endif /* TRACE */

memset((char *)&sin,0,sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons((u_short)ps->iPort);

#if TRACE
FPRINTF(ps->p.hScreen,(FOUT,"bind...\n"));
#endif /* TRACE */
iStatus = bind(ps->s, (struct sockaddr*)&sin, sizeof(sin));
if(iStatus < 0) {
#if TRACE_ERRORS
FPRINTF(ps->p.hScreen,(FOUT,"bind failed %d\n",WSAGetLastError()));
#endif /* TRACE_ERRORS */
closesocket(ps->s);
return 0;
}
#if TRACE
else
FPRINTF(ps->p.hScreen,(FOUT,"bind OK\n"));
#endif /* TRACE */

/*
* This statement names the key material object (kmo) that will be used by
* echo-daemon, determines the ssl session id lifetime, and establishes
* the size of the ssl session id cache. The kmo must be created using
* ConsoleOne.
*/
if(ps->p.eType == eSsl) {
struct sslserveropts sSslServerOpts = {NULL, 0, 100, 1000, NULL};
#if TRACE
FPRINTF(ps->p.hScreen,(FOUT,"WSAIoctl [SO_SSL_SET_SERVER]...\n"));
#endif /* TRACE */
sSslServerOpts.cert = pcKeyfile;
sSslServerOpts.certlen = strlen(pcKeyfile);
iStatus = WSAIoctl(ps->s, SO_SSL_SET_SERVER, &sSslServerOpts, sizeof(struct sslserveropts),
NULL, 0, NULL, NULL, NULL);
if(iStatus < 0) {
#if TRACE_ERRORS
FPRINTF(ps->p.hScreen,(FOUT,"WSAIoctl [SO_SSL_SET_SERVER] failed %d\n",WSAGetLastError()));
#endif /* TRACE_ERRORS */
closesocket(ps->s);
return 0;
}
#if TRACE
else
FPRINTF(ps->p.hScreen,(FOUT,"WSAIoctl [SO_SSL_SET_SERVER] OK\n"));
#endif /* TRACE */
if(eAuth == eClient) {
unsigned int uiAuthClient = SO_SSL_AUTH_CLIENT;
#if TRACE
FPRINTF(ps->p.hScreen,(FOUT,"WSAIoctl [SO_SSL_AUTH_CLIENT]...\n"));
#endif /* TRACE */
iStatus = WSAIoctl(ps->s, SO_SSL_SET_FLAGS, &uiAuthClient, sizeof(uiAuthClient),
NULL, 0, NULL, NULL, NULL);
if(iStatus < 0) {
#if TRACE_ERRORS
FPRINTF(ps->p.hScreen,(FOUT,"WSAIoctl [SO_SSL_AUTH_CLIENT] failed %d\n",WSAGetLastError()));
#endif /* TRACE_ERRORS */
closesocket(ps->s);
return 0;
}
#if TRACE
else
FPRINTF(ps->p.hScreen,(FOUT,"WSAIoctl [SO_SSL_AUTH_CLIENT] OK\n"));
#endif /* TRACE */
}
}

#if TRACE
FPRINTF(ps->p.hScreen,(FOUT,"ioctlsocket...\n"));
#endif /* TRACE */
iStatus = ioctlsocket(ps->s, FIONBIO, (u_long FAR*)&iMode);
if( iStatus == -1 ) {
#if TRACE_ERRORS
FPRINTF(ps->p.hScreen,(FOUT,"ioctlsocket FIONBIO failed %d\n",WSAGetLastError()));
#endif /* TRACE_ERRORS */
closesocket(ps->s);
return ERROR;
}
#if TRACE
else
FPRINTF(ps->p.hScreen,(FOUT,"ioctlsocket FIONBIO OK\n"));

FPRINTF(ps->p.hScreen,(FOUT,"setsockopt...\n"));
#endif /* TRACE */
iStatus = setsockopt(ps->s, SOL_SOCKET, SO_SNDBUF, (void*)&ulSocketBufferSize, sizeof(ulSocketBufferSize));
if(iStatus < 0) {
#if TRACE_ERRORS
FPRINTF(ps->p.hScreen,(FOUT,"setsockopt SNDBUF failed %d\n",WSAGetLastError()));
#endif /* TRACE_ERRORS */
closesocket(ps->s);
}
#if TRACE
else {
unsigned long ulBufferSize;
int i = sizeof(ulBufferSize);
getsockopt(ps->s, SOL_SOCKET, SO_SNDBUF, (void*)&ulBufferSize, &i);
FPRINTF(ps->p.hScreen,(FOUT,"setsockopt SO_SNDBUF OK - buffer size = %lu\n", ulBufferSize));
}

FPRINTF(ps->p.hScreen,(FOUT,"setsockopt...\n"));
#endif /* TRACE */
iStatus = setsockopt(ps->s, SOL_SOCKET, SO_RCVBUF, (void*)&ulSocketBufferSize, sizeof(ulSocketBufferSize));
if(iStatus < 0) {
#if TRACE_ERRORS
FPRINTF(ps->p.hScreen,(FOUT,"setsockopt failed %d\n",WSAGetLastError()));
#endif /* TRACE_ERRORS */
closesocket(ps->s);
return 0;
}
#if TRACE
else {
unsigned long ulBufferSize;
int i = sizeof(ulBufferSize);
getsockopt(ps->s, SOL_SOCKET, SO_RCVBUF, (void*)&ulBufferSize, &i);
FPRINTF(ps->p.hScreen,(FOUT,"setsockopt SO_RCVBUF OK - buffer size = %lu\n", ulBufferSize));
}

FPRINTF(ps->p.hScreen,(FOUT,"WSACreateEvent...\n"));
#endif /* TRACE */
ps->e = WSACreateEvent();
if(ps->e == WSA_INVALID_EVENT) {
#if TRACE_ERRORS
FPRINTF(ps->p.hScreen,(FOUT,"WSACreateEvent failed %d\n",WSAGetLastError()));
#endif /* TRACE_ERRORS */
closesocket(ps->s);
return 0;
}
#if TRACE
else
FPRINTF(ps->p.hScreen,(FOUT,"WSACreateEvent OK\n"));

FPRINTF(ps->p.hScreen,(FOUT,"WSAEventSelect...\n"));
#endif /* TRACE */
iStatus = WSAEventSelect(ps->s, ps->e, FD_ACCEPT);
if(iStatus == SOCKET_ERROR) {
#if TRACE_ERRORS
FPRINTF(ps->p.hScreen,(FOUT,"WSAEventSelect failed %d\n",WSAGetLastError()));
#endif /* TRACE_ERRORS */
closesocket(ps->s);
return 0;
}
#if TRACE
else
FPRINTF(ps->p.hScreen,(FOUT,"WSAEventSelect OK\n"));

FPRINTF(ps->p.hScreen,(FOUT,"listen...\n"));
#endif /* TRACE */
iStatus = listen(ps->s, SOMAXCONN);
if(iStatus < 0) {
#if TRACE_ERRORS
FPRINTF(ps->p.hScreen,(FOUT,"listen failed %d\n",WSAGetLastError()));
#endif /* TRACE_ERRORS */
shutdown(ps->s,2);
closesocket(ps->s);
return ERROR;
}
#if TRACE
else
FPRINTF(ps->p.hScreen,(FOUT,"listen listening on port %d OK\n",ps->iPort));
#endif /* TRACE */

while(1) {
if(exitFlag) {
SemSignal(ps->p.hSem);
EXIT;
}
#if TRACE
FPRINTF(ps->p.hScreen,(FOUT,"WSAWaitForMultipleEvents...\n "));
#endif /* TRACE */

iStatus = WSAWaitForMultipleEvents(1, (const WSAEVENT *)&(ps->e), FALSE, 10000, FALSE);
if(iStatus == WSA_WAIT_FAILED) {
#if TRACE_ERRORS
FPRINTF(ps->p.hScreen,(FOUT,"WSAWaitForMultipleEvents failed %d\n",WSAGetLastError()));
#endif /* TRACE_ERRORS */
/* is it necessary to re-associate the socket and event after failure? */
continue;
}
else if(iStatus == WSA_WAIT_TIMEOUT) {
#if TRACE_ERRORS
FPRINTF(ps->p.hScreen,(FOUT,"WSAWaitForMultipleEvents timeout\n"));
#endif /* TRACE_ERRORS */
continue;
}
else {
int i;
#if TRACE
FPRINTF(ps->p.hScreen,(FOUT,"WSAWaitForMultipleEvents OK\n"));
#endif /* TRACE */
for(i = 0; i < *(ps->uNumberOfAcceptThreads); ++i) {
if(ps->psAccept[i].s == INVALID_SOCKET) {
/* signal the accept thread */
#if TRACE_VERBOSE
FPRINTF(ps->p.hScreen,(FOUT,"Signal accept thread %1d (socket %1d)\n",i,ps->s));
#endif /* TRACE_VERBOSE */
ps->psAccept[i].s = ps->s;
SemSignal(ps->psAccept[i].p.hSem);
ThreadSwitchWithDelay();
break;
}
}
if(i == *(ps->uNumberOfAcceptThreads) && i < MAX_ACCEPT_THREADS) {
fStartThread((struct sThreadPars *)&ps->psAccept[i], "Echo Daemon Accept", *ps->uNumberOfAcceptThreads);
++*(ps->uNumberOfAcceptThreads);
#if TRACE_VERBOSE
FPRINTF(ps->p.hScreen,(FOUT,"Signal accept thread %1d [socket %1d]\n",i,ps->s));
#endif /* TRACE_VERBOSE */
while(SemTest(ps->psAccept[i].p.hSem) == 0)
ThreadSwitchWithDelay();
ps->psAccept[i].s = ps->s;
SemSignal(ps->psAccept[i].p.hSem);
ThreadSwitchWithDelay();
}
else if(i == MAX_ACCEPT_THREADS)
CONSOLE("\nNumber of accept requests exceeded maximum accept threads\n\n");
}
}
} /* fListen */

THREADFUNC(fAccept,p)
{
struct sAccept *ps = (struct sAccept *)p;
struct sockaddr_in sin;
unsigned long addr;
int al = sizeof(struct sockaddr_in);
SOCKET s;
#if TRACE || TRACE_VERBOSE || TRACE_ERRORS

SCREEN_CREATE(ps->p.pcName,ps->p.hScreen);
#endif /* TRACE || TRACE_VERBOSE || TRACE_ERRORS */

while(1) { /* loop forever */
/* indicate thread availability */
ps->s = INVALID_SOCKET;
#if TRACE_VERBOSE
FPRINTF(ps->p.hScreen, (FOUT,"%s waiting...[%8d]\n",ps->p.pcName,++ps->ulIterations));
#endif /* TRACE_VERBOSE */
SemWait(ps->p.hSem);
if(exitFlag) {
SemSignal(ps->p.hSem);
EXIT;
}

#if TRACE
FPRINTF(ps->p.hScreen,(FOUT,"accept...\n"));
#endif /* TRACE */
EWOULDBLOCK:
s = accept(ps->s, (struct sockaddr*)&sin, &al);
if(s == INVALID_SOCKET) {
if(WSAGetLastError() == WSAEWOULDBLOCK) {
/* should never happen since WSAWaitForMultipleEvents guarantees that */
/* accept should succeed? */
#if TRACE_ERRORS
FPRINTF(ps->p.hScreen,(FOUT,"accept [socket %1d] WSAEWOULDBLOCK\n",ps->s));
#endif /* TRACE_ERRORS */
ThreadSwitchWithDelay();
goto EWOULDBLOCK;
}
else {
#if TRACE_ERRORS
FPRINTF(ps->p.hScreen,(FOUT,"accept [socket %1d] failed %1d\n",ps->s,WSAGetLastError()));
#endif /* TRACE_ERRORS */
SHUTDOWN(ps->s);
continue;
}
}
else {
ps->s = s;
#if TRACE
FPRINTF(ps->p.hScreen,(FOUT,"accept [socket %1d] OK\n",s));
#endif /* TRACE */
}
#if STATISTICS
ps->tElapsed += (clock() - start);
++ps->ulConnectSuccess;
#endif /* STATISTICS */

addr = ntohl(sin.sin_addr.s_addr);
#if TRACE
FPRINTF(ps->p.hScreen,(FOUT,"Establishing connection with %d.%d.%d.%d:%d\n",(addr>>24)&0xff,
(addr>>16)&0xff,(addr>>8)&0xff,(addr&g t;>0)&0xff,ps->s));
#endif /* TRACE */

/* add socket to fd set */
fAddFd(s, ps->psSelect->rd, ps->psSelect->hSem, ps->psSelect->p.hSem, ps->p.hScreen);
/* indicate thread availability */
ps->s = INVALID_SOCKET;
}
return 0;
} /* fAccept */

THREADFUNC(fSelect,p)
{
struct sSelect *ps = (struct sSelect *)p;
int iStatus = 0;
int i, k;
struct timeval time = {10,0};
fd_set rd;
SOCKET s;
char *pcName = "Echo Daemon Rw";
char *pcSslName = "Echo Daemon Ssl Rw";
#if TRACE || TRACE_VERBOSE || TRACE_ERRORS

SCREEN_CREATE(ps->p.pcName,ps->p.hScreen);
#endif /* TRACE || TRACE_VERBOSE || TRACE_ERRORS */

/* select forever */
while(1) {
#if TRACE_VERBOSE
FPRINTF(ps->p.hScreen,(FOUT,"%s waiting...\t[%8d]\n",ps->p.pcName,++ps->ulIterations));
#endif /* TRACE_VERBOSE */
if(exitFlag) {
SemWait(ps->hSem);
for(i = 0; i < FD_SETSIZE; ++i)
SHUTDOWN(ps->rd->fd_array[i]);
SemSignal(ps->hSem);
SemSignal(ps->p.hSem);
EXIT;
}

while(1) {
SemWait(ps->hSem);
memcpy(&rd, ps->rd, sizeof(fd_set));
SemSignal(ps->hSem);
/* wait 'til somebody puts something in the fd_set ... */
if(ps->rd->fd_count == 0)
SemWait(ps->p.hSem);
/* fd_set has at least one socket so continue */
else
break;
}
#if TRACE_VERBOSE
FPRINTF(ps->p.hScreen,(FOUT,"select [fd count %1d] : ",rd.fd_count));
for(i = 0; i < rd.fd_count; ++i)
FPRINTF(ps->p.hScreen,(FOUT,"%1d ",rd.fd_array[i]));
FPRINTF(ps->p.hScreen,(FOUT,"...\n"));
#endif /* TRACE_VERBOSE */
iStatus = select(rd.fd_count, &rd, NULL, NULL, &time);
if(iStatus == SOCKET_ERROR) {
if(WSAGetLastError() == WSAEINTR) {
#if TRACE_VERBOSE
FPRINTF(ps->p.hScreen,(FOUT,"select EINTR\n"));
#endif /* TRACE_VERBOSE */
continue;
}
else {
#if TRACE_ERRORS
FPRINTF(ps->p.hScreen,(FOUT,"select failed %d\n",WSAGetLastError()));
#endif /* TRACE_ERRORS */
continue;
}
}
else {
#if TRACE_VERBOSE
if(rd.fd_count == 0) {
FPRINTF(ps->p.hScreen,(FOUT,"select [fd count %1d] : ",rd.fd_count));
}
else {
FPRINTF(ps->p.hScreen,(FOUT,"select [fd count %1d] : ",rd.fd_count));
for(i = 0; i < rd.fd_count; ++i)
FPRINTF(ps->p.hScreen,(FOUT,"%1d ",rd.fd_array[i]));
}
FPRINTF(ps->p.hScreen,(FOUT,"OK\n"));
#endif /* TRACE_VERBOSE */
if(rd.fd_count == 0)
continue;
for(i = 0; i<rd.fd_count; ++i) {
s = rd.fd_array[i];
fRemoveFd(s, ps->rd, ps->hSem, ps->p.hScreen);
for(k = 0; k < *(ps->uNumberOfRwThreads); ++k) {
if(ps->psRw[k].s == INVALID_SOCKET) {
/* signal the rw thread */
#if TRACE_VERBOSE
FPRINTF(ps->p.hScreen,(FOUT,"Signal rw thread %1d [socket %1d]\n",k,s));
#endif /* TRACE_VERBOSE */
ps->psRw[k].s = s;
SemSignal(ps->psRw[k].p.hSem);
break;
}
}
if(k == *(ps->uNumberOfRwThreads) && k < MAX_RW_THREADS) {
#if TRACE_VERBOSE
FPRINTF(ps->p.hScreen,(FOUT,"Signal rw thread %1d [socket %1d]\n",k,s));
#endif /* TRACE_VERBOSE */
if(ps->p.eType == ePlain)
fStartThread((struct sThreadPars *)&ps->psRw[k], pcName, *ps->uNumberOfRwThreads);
else
fStartThread((struct sThreadPars *)&ps->psRw[k], pcSslName, *ps->uNumberOfRwThreads);
++*(ps->uNumberOfRwThreads);
while(SemTest(ps->psRw[k].p.hSem) == 0)
ThreadSwitchWithDelay();
ps->psRw[k].s = s;
SemSignal(ps->psRw[k].p.hSem);
ThreadSwitchWithDelay();
}
else if(k == MAX_RW_THREADS) {
SHUTDOWN(s);
#if TRACE_ERRORS
FPRINTF(ps->p.hScreen,(FOUT,"SHUTDOWN %1d OK\n",s));
#endif /* TRACE_ERRORS */
CONSOLE("\nNumber of rw requests exceeded maximum rw threads\n\n");
}
}
}
}
return 0;
} /* fSelect */

THREADFUNC(fRw,p)
{
struct sRw *ps = (struct sRw *)p;
int iRd, iWr, iTotal, iBufferSize;
unsigned long ulOffset;
clock_t start;
#if TRACE || TRACE_VERBOSE || TRACE_ERRORS

SCREEN_CREATE(ps->p.pcName,ps->p.hScreen);
#endif /* TRACE || TRACE_VERBOSE || TRACE_ERRORS */

while(1) { /* loop forever */
/* indicate thread availability */
ps->s = INVALID_SOCKET;
#if TRACE_VERBOSE
FPRINTF(ps->p.hScreen, (FOUT,"%s waiting...[%8d]\n",ps->p.pcName,++ps->ulIterations));
#endif /* TRACE_VERBOSE */
SemWait(ps->p.hSem);
if(exitFlag) {
SemSignal(ps->p.hSem);
EXIT;
}

/* select indicates that thread socket is active */
ulOffset = iTotal = 0;
memset(ps->pcBuffer, 0, BUFFER_SIZE);
iBufferSize = BUFFER_SIZE;
WSASetLastError(0);
#if TRACE_VERBOSE
FPRINTF(ps->p.hScreen,(FOUT,"recv socket %1d...\n",ps->s));
#endif /* TRACE_VERBOSE */
iRd = recv(ps->s, ps->pcBuffer+ulOffset, iBufferSize, 0);
if(iRd == 0) {
/* socket was closed gracefully by client */
#if TRACE_VERBOSE
FPRINTF(ps->p.hScreen,(FOUT,"recv socket %1d closed\n",ps->s));
#endif /* TRACE_VERBOSE */
closesocket(ps->s);
#if TRACE_VERBOSE
FPRINTF(ps->p.hScreen,(FOUT,"closesocket %1d OK\n",ps->s));
#endif /* TRACE_ERRORS */
continue;
}
else if(iRd == SOCKET_ERROR) {
/* if recv fails w/ ECONNRESET, add fd to fd_set */
if(WSAGetLastError() == WSAECONNRESET) {
#if TRACE_VERBOSE
FPRINTF(ps->p.hScreen,(FOUT,"recv socket %1d ECONNRESET\n",ps->s));
#endif /* TRACE_VERBOSE */
closesocket(ps->s);
#if TRACE_VERBOSE
FPRINTF(ps->p.hScreen,(FOUT,"closesocket %1d OK\n",ps->s));
#endif /* TRACE_ERRORS */
continue;
}
else if(WSAGetLastError() == WSAECONNABORTED) {
#if TRACE_VERBOSE
FPRINTF(ps->p.hScreen,(FOUT,"recv socket %1d ECONNABORTED\n",ps->s));
#endif /* TRACE_VERBOSE */
closesocket(ps->s);
#if TRACE_VERBOSE
FPRINTF(ps->p.hScreen,(FOUT,"closesocket %1d OK\n",ps->s));
#endif /* TRACE_ERRORS */
continue;
}
else {
#if TRACE_ERRORS
FPRINTF(ps->p.hScreen,(FOUT,"recv socket %1d failed [error %d]\n",ps->s,WSAGetLastError()));
#endif /* TRACE_ERRORS */
SHUTDOWN(ps->s);
#if TRACE_VERBOSE
FPRINTF(ps->p.hScreen,(FOUT,"SHUTDOWN %1d OK\n",ps->s));
#endif /* TRACE_ERRORS */
continue;
}
}
else {
#if TRACE_VERBOSE
FPRINTF(ps->p.hScreen,(FOUT,"recv socket %1d [%1d bytes rd] OK\n",ps->s,iRd));
#endif /* TRACE_VERBOSE */
}
if(iHttp)
fHttp(ps->pcBuffer, &iTotal);
/* write only if the client has written */
#if TRACE_VERBOSE
FPRINTF(ps->p.hScreen,(FOUT,"send socket %1d...\n",ps->s));
#endif /* TRACE_VERBOSE */
start = clock();
iWr = send(ps->s, ps->pcBuffer, iRd, 0);
if(iWr == SOCKET_ERROR) {
#if TRACE_ERRORS
FPRINTF(ps->p.hScreen,(FOUT,"send socket %1d failed [error %d]\n",ps->s,WSAGetLastError()));
#endif /* TRACE_ERRORS */
SHUTDOWN(ps->s);
continue;
}
else {
#if TRACE_VERBOSE
FPRINTF(ps->p.hScreen,(FOUT,"send socket %1d [%1d bytes wr] OK\n",ps->s,iWr));
#endif /* TRACE_VERBOSE */
}
if(iHttp) {
SHUTDOWN(ps->s);
continue;
}
/* add socket to fd_set for fSelect */
fAddFd(ps->s, ps->psSelect->rd, ps->psSelect->hSem, ps->psSelect->p.hSem, ps->p.hScreen);
}
return 0;
} /* fRw */

int fHttp(char *pcBuffer, int *iLength)
{
#define SEPARATOR_CHARS "\x20\x0A\x0D"
#define FILE_NAME_SIZE 512
char *pcToken = NULL;
char pcFile[FILE_NAME_SIZE];
int iChar;
int iFileSize;
FILE *f;

/* look for GET and assume everything that follows is a file name */
pcToken = strtok(pcBuffer, SEPARATOR_CHARS);
if(!stricmp(pcToken, "GET")) {
pcToken = strtok(NULL, SEPARATOR_CHARS); /* returns file name w/o leading "/" */
if(pcToken) {
memset(pcFile, 0, FILE_NAME_SIZE);
if(pcHttpRoot)
strcpy(pcFile, pcHttpRoot);
strcat(pcFile, pcToken);
f = fopen(pcFile, "r");
if(f) {
fseek(f, 0L, SEEK_END);
iFileSize = ftell(f);
fseek(f, 0L, SEEK_SET);
if(iFileSize <= BUFFER_SIZE) {
memset(pcBuffer, 0, BUFFER_SIZE);
strcat(pcBuffer, "HTTP/1.0 200 OK\x0D\x0A");
*iLength = 17;
while((iChar = fgetc(f)) != EOF)
pcBuffer[(*iLength)++] = iChar;
fclose(f);
return 0;
}
else {
#if TRACE_ERRORS
ConsolePrintf("file %s too big - must be %d or less\n", pcFile, BUFFER_SIZE);
#endif /* TRACE_ERRORS */
return -1;
}
}
else {
#if TRACE_ERRORS
ConsolePrintf("fopen for %s failed errno = %d\n", pcFile, WSAGetLastError());
#endif /* TRACE_ERRORS */
return -1;
}
}
else {
if(strlen(pcBuffer) > 72)
*(pcBuffer+72) = 0;
#if TRACE_ERRORS
ConsolePrintf("\nInvalid HTTP request received (%s)\n\n", pcBuffer);
#endif /* TRACE_ERRORS */
memset(pcBuffer, 0, BUFFER_SIZE);
strcat(pcBuffer, "HTTP/1.0 400 Bad Request\x0D\x0A");
*iLength = 26;
return 0;
}
}
else {
if(strlen(pcBuffer) > 72)
*(pcBuffer+72) = 0;
#if TRACE_ERRORS
ConsolePrintf("\nInvalid HTTP request received (%s)\n\n", pcBuffer);
#endif /* TRACE_ERRORS */
memset(pcBuffer, 0, BUFFER_SIZE);
strcat(pcBuffer, "HTTP/1.0 405 Method Not Allowed\x0D\x0A");
*iLength = 33;
return 0;
}
} /* fHttp */

int fAddFd(SOCKET s, fd_set *pSet, SEM hSem, SEM hSemSelect, SCR hScreen)
{
int i = 0;

#if TRACE_VERBOSE
FPRINTF(hScreen,(FOUT,"\tfAddFd add socket %1d to fd_set [fd_count = %1d]...\n",s,pSet->fd_count));
#endif /* TRACE_VERBOSE */
/* wait 'til nobody is using the fd set */
SemWait(hSem);
FD_SET(s, pSet);
/* if fd_count was 0, then fSelect or fSslSelect is waiting on */
/* sSelect.hSem or sSslSelect.hSem */
if(pSet->fd_count == 1)
SemSignal(hSemSelect);
/* somebody else can use the fd set now */
SemSignal(hSem);
if(i == FD_SETSIZE) {
#if TRACE_VERBOSE
FPRINTF(hScreen,(FOUT,"\tfAddFd socket %1d to fd_set [fd_count = %1d] failed\n",s,pSet->fd_count))
#endif /* TRACE_VERBOSE */
return s; /* fd set is full - s not added */
}
#if TRACE_VERBOSE
FPRINTF(hScreen,(FOUT,"\tfAddFd add socket %d to fd_set [fd_count = %1d] OK\n",s,pSet->fd_count))
#endif /* TRACE_VERBOSE */
return 0; /* fd added to fd set */
} /* fAddFd */

int fRemoveFd(SOCKET s, fd_set *pSet, SEM hSem, SCR hScreen)
{
int i = 0;

#if TRACE_VERBOSE
FPRINTF(hScreen,(FOUT,"\tfRemoveFd socket %1d from fd_set [fd_count = %1d]...\n",s,pSet->fd_count))
#endif /* TRACE_VERBOSE */
/* wait 'til nobody is using the fd set */
SemWait(hSem);
FD_CLR(s, pSet);
/* somebody else can use the fd set now */
SemSignal(hSem);
if(i == FD_SETSIZE) {
#if TRACE_VERBOSE
FPRINTF(hScreen,(FOUT,"\tfRemoveFd socket %1d from fd_set [fd_count = %1d] failed\n",s,pSet->fd_count))
#endif /* TRACE_VERBOSE */
return s; /* s not found in pSet */
}
else {
#if TRACE_VERBOSE
FPRINTF(hScreen,(FOUT,"\tfRemoveFd socket %d from fd_set [fd_count = %1d] OK\n",s,pSet->fd_count));
#endif /* TRACE_VERBOSE */
return 0; /* fd found in pSet */
}
} /* fRemoveFd */

SEM SemCreate(void *pName, unsigned long value)
{
return OpenLocalSemaphore(value);
}

int SemDestroy(SEM s)
{
return CloseLocalSemaphore(s);
} /* SemDestroy */

int SemWait(SEM s)
{
return WaitOnLocalSemaphore(s);
} /* SemWait */

int SemTest(SEM s)
{
int status;
status = ExamineLocalSemaphore(s);
if(status > 0)
return 0;
else
return 1;
} /* SemTest */

int SemSignal(SEM s)
{
if(SignalLocalSemaphore(s) == 0)
return 0;
else
return -1;
} /* SemSignal */

int InitWinSock(void)
{
WSADATA wsa_data;
WORD version_requested = MAKEWORD(1, 1);

if(WSAStartup(version_requested, &wsa_data))
return -1;
return 0;
} /* InitWinSock */

void fStartThread(struct sThreadPars *p, char *pcName, int iThread)
{
p->pStack = malloc(THREAD_STACK_SIZE);
p->hSem = SemCreate(p->pcName, 0);
sprintf(p->pcName,"%s Semaphore", pcName);
p->iThread = iThread;
sprintf(p->pcName,"%s %1d", pcName, p->iThread);
THREAD_START(p);
ThreadSwitchWithDelay();
} /* fStartThread */

int fStart(int iListenPort, int iSslListenPort)
{
int i;
WORD wVersionRequested;
WSADATA wsaData;

hScreen = GetCurrentScreen();
ioMutex = SemCreate("Echo Daemon IO Mutex", 1);
coMutex = SemCreate("Echo Daemon Connect Mutex", 1);
coMutexSsl = SemCreate("Echo Daemon Ssl Connect Mutex", 1);

#if TRACE
FPRINTF(hScreen,(FOUT,"WSAStartup...\n"));
#endif /* TRACE */
wVersionRequested = MAKEWORD(2,2);
if(WSAStartup(wVersionRequested, &wsaData)) {
#if TRACE_ERRORS
FPRINTF(hScreen,(FOUT,"WSAStartup failed\n"));
#endif /* TRACE_ERRORS */
return ERROR;
}
#if TRACE
else
FPRINTF(hScreen,(FOUT,"WSAStartup OK\n"));
#endif /* TRACE */

#if TRACE
FPRINTF(hScreen,(FOUT,"signal...\n"));
#endif /* TRACE */
if(signal(SIGTERM, fWSATerminationHandler) == SIG_ERR) {
#if TRACE_ERRORS
FPRINTF(hScreen,(FOUT,"signal failed\n"));
#endif /* TRACE_ERRORS */
return ERROR;
}
#if TRACE
else
FPRINTF(hScreen,(FOUT,"signal OK\n"));
#endif /* TRACE */

atexit(fExitDaemon);
AtUnload(fExitDaemon);

/* initialize all listen thread structs */
memset(&sListen, 0, sizeof(struct sListen));
memset(&sSslListen, 0, sizeof(struct sListen));

/* allocate and initialize all rw thread structs */
psRw = (struct sRw *)malloc(sizeof(struct sRw)*MAX_RW_THREADS);
memset(psRw, 0, sizeof(struct sRw)*MAX_RW_THREADS);
psSslRw = (struct sRw *)malloc(sizeof(struct sRw)*MAX_RW_THREADS);
memset(psSslRw, 0, sizeof(struct sRw)*MAX_RW_THREADS);

/* allocate and initialize all accept thread structs */
psAccept = (struct sAccept *)malloc(sizeof(struct sAccept)*MAX_ACCEPT_THREADS);
memset(psAccept, 0, sizeof(struct sAccept)*MAX_ACCEPT_THREADS);
psSslAccept = (struct sAccept *)malloc(sizeof(struct sAccept)*MAX_ACCEPT_THREADS);
memset(psSslAccept, 0, sizeof(struct sAccept)*MAX_ACCEPT_THREADS);

for(i = 0; i < MAX_RW_THREADS; ++i) {
/* plain threads */
psRw[i].p.func = fRw;
psRw[i].p.eType = ePlain;
psRw[i].s = INVALID_SOCKET;
psRw[i].psSelect = &sSelect;
psRw[i].pcBuffer = malloc(BUFFER_SIZE);
/* ssl threads */
psSslRw[i].p.func = fRw;
psSslRw[i].p.eType = eSsl;
psSslRw[i].s = INVALID_SOCKET;
psSslRw[i].psSelect = &sSslSelect;
psSslRw[i].pcBuffer = malloc(BUFFER_SIZE);
}
for(i = 0; i < MAX_ACCEPT_THREADS; ++i) {
/* plain threads */
psAccept[i].p.func = fAccept;
psAccept[i].p.eType = ePlain;
psAccept[i].s = INVALID_SOCKET;
psAccept[i].psSelect = &sSelect;
/* ssl threads */
psSslAccept[i].p.func = fAccept;
psSslAccept[i].p.eType = eSsl;
psSslAccept[i].s = INVALID_SOCKET;
psSslAccept[i].psSelect = &sSslSelect;
}

if(iListenPort) {
/* listen thread */
sListen.p.func = fListen;
sListen.p.eType = ePlain;
sListen.uNumberOfAcceptThreads = &uNumberOfAcceptThreads;
sListen.iPort = iListenPort;
sListen.psAccept = psAccept;
fStartThread((struct sThreadPars *)&sListen, "Echo Daemon Listen", 0);

/* accept thread */
for(i = 0; i < uNumberOfAcceptThreads; ++i)
fStartThread((struct sThreadPars *)&psAccept[0], "Echo Daemon Accept", i);

/* select thread */
sSelect.rd = (fd_set *)malloc(sizeof(fd_set));
memset(sSelect.rd, 0, sizeof(fd_set));
sSelect.wr = (fd_set *)malloc(sizeof(fd_set));
memset(sSelect.wr, 0, sizeof(fd_set));
sSelect.ex = (fd_set *)malloc(sizeof(fd_set));
memset(sSelect.ex, 0, sizeof(fd_set));
sSelect.hSem = SemCreate("Echo Daemon Socket Fd Set Semaphore", 1);
sSelect.uNumberOfRwThreads = &uNumberOfRwThreads;
sSelect.psRw = psRw;
sSelect.p.eType = ePlain;
sSelect.p.func = fSelect;
fStartThread((struct sThreadPars *)&sSelect, "Echo Daemon Select", 0);

/* rw threads */
for(i = 0; i < uNumberOfRwThreads; ++i)
fStartThread((struct sThreadPars *)&psRw[i], "Echo Daemon Rw", i);
}

if(iSslListenPort) {
/* ssl listen thread */
sSslListen.p.func = fListen;
sSslListen.p.eType = eSsl;
sSslListen.uNumberOfAcceptThreads = &uNumberOfSslAcceptThreads;
sSslListen.iPort = iSslListenPort;
sSslListen.psAccept = psSslAccept;
fStartThread((struct sThreadPars *)&sSslListen, "Echo Daemon Ssl Listen", 0);

/* accept thread */
for(i = 0; i < uNumberOfSslAcceptThreads; ++i)
fStartThread((struct sThreadPars *)&psSslAccept[0], "Echo Daemon Ssl Accept", i);

/* select thread */
sSslSelect.rd = (fd_set *)malloc(sizeof(fd_set));
memset(sSslSelect.rd, 0, sizeof(fd_set));
sSslSelect.wr = (fd_set *)malloc(sizeof(fd_set));
memset(sSslSelect.wr, 0, sizeof(fd_set));
sSslSelect.ex = (fd_set *)malloc(sizeof(fd_set));
memset(sSslSelect.ex, 0, sizeof(fd_set));
sSslSelect.hSem = SemCreate("Echo Daemon Socket Ssl Fd Set Semaphore", 1);
sSslSelect.uNumberOfRwThreads = &uNumberOfSslRwThreads;
sSslSelect.psRw = psSslRw;
sSslSelect.p.eType = eSsl;
sSslSelect.p.func = fSelect;
fStartThread((struct sThreadPars *)&sSslSelect, "Echo Daemon Ssl Select", 0);

/* ssl rw threads */
for(i = 0; i < uNumberOfSslRwThreads; ++i)
fStartThread((struct sThreadPars *)&psSslRw[i], "Echo Daemon Ssl Rw", i);
}
return 0;
} /* fStart */

void fExitDaemon(void)
{
if(!exitFlag)
fExit();
} /* fExitDaemon */

void fCheck(void)
{
exitFlag = 1;
fWSATerminationHandler(SIGTERM);
exitFlag = 0;
} /* fCheck */

void fWSATerminationHandler(int iSignal)
{
static int flag = 0;
int i;

if(!flag) {
if(iSignal == SIGTERM) {
/* close all sockets used by listen threads */
SHUTDOWN(sListen.s);
SHUTDOWN(sSslListen.s);
/* close all sockets used by fAccept */
for(i = 0; i < uNumberOfAcceptThreads; ++i)
SHUTDOWN(psAccept[i].s);
for(i = 0; i < uNumberOfSslAcceptThreads; ++i)
SHUTDOWN(psSslAccept[i].s);
/* close all sockets in the fd_set's used by fSelect */
for(i = 0; i<FD_SETSIZE; ++i) {
SHUTDOWN(sSelect.rd->fd_array[i]);
SHUTDOWN(sSslSelect.rd->fd_array[i]);
}
/* close all sockets used by fRw */
for(i = 0; i < uNumberOfRwThreads; ++i)
SHUTDOWN(psRw[i].s);
for(i = 0; i < uNumberOfSslRwThreads; ++i)
SHUTDOWN(psSslRw[i].s);
}
if(WSACleanup()) {
#if TRACE_VERBOSE
ConsolePrintf("WSACleanup failed %d\n", WSAGetLastError());
#endif /* TRACE_VERBOSE */
}
}
flag = TRUE;
return;
} /* fWSATerminationHandler */

void fExit(void)
{
int i;

exitFlag = 1;

if(iListenPort) {
/* kill listen thread */
if(SemTest(sListen.p.hSem) > 0)
SemSignal(sListen.p.hSem);
SemWait(sListen.p.hSem);
SemDestroy(sListen.p.hSem);
THREAD_DESTROY(sListen.p.hThread);
free(sListen.p.pStack);
/* clean up select thread */
if(SemTest(sSelect.p.hSem) > 0)
SemSignal(sSelect.p.hSem);
SemWait(sSelect.p.hSem);
SemDestroy(sSelect.p.hSem);
SemDestroy(sSelect.hSem);
free(sSelect.rd);
free(sSelect.wr);
free(sSelect.ex);
THREAD_DESTROY(sSelect.p.hThread);
free(sSelect.p.pStack);
}

if(iSslListenPort) {
/* kill ssl listen thread */
if(SemTest(sSslListen.p.hSem) > 0)
SemSignal(sSslListen.p.hSem);
SemWait(sSslListen.p.hSem);
SemDestroy(sSslListen.p.hSem);
THREAD_DESTROY(sSslListen.p.hThread);
free(sSslListen.p.pStack);
/* clean up ssl select thread */
if(SemTest(sSslSelect.p.hSem) > 0)
SemSignal(sSslSelect.p.hSem);
SemWait(sSslSelect.p.hSem);
SemDestroy(sSslSelect.p.hSem);
SemDestroy(sSslSelect.hSem);
free(sSslSelect.rd);
free(sSslSelect.wr);
free(sSslSelect.ex);
THREAD_DESTROY(sSslSelect.p.hThread);
free(sSslSelect.p.pStack);
}

/* clean up rw threads */
for(i = 0; i < uNumberOfRwThreads; ++i)
if(SemTest(psRw[i].p.hSem) > 0)
SemSignal(psRw[i].p.hSem);
for(i = 0; i < uNumberOfRwThreads; ++i) {
SemWait(psRw[i].p.hSem);
SemDestroy(psRw[i].p.hSem);
free(psRw[i].pcBuffer);
THREAD_DESTROY(psRw[i].p.hThread);
free(psRw[i].p.pStack);
}
free(psRw);

/* clean up ssl rw threads */
for(i = 0; i < uNumberOfSslRwThreads; ++i)
if(SemTest(psSslRw[i].p.hSem) > 0)
SemSignal(psSslRw[i].p.hSem);
for(i = 0; i < uNumberOfSslRwThreads; ++i) {
SemWait(psSslRw[i].p.hSem);
SemDestroy(psSslRw[i].p.hSem);
free(psSslRw[i].pcBuffer);
THREAD_DESTROY(psSslRw[i].p.hThread);
free(psSslRw[i].p.pStack);
}
free(psSslRw);

/* clean up accept threads */
for(i = 0; i < uNumberOfAcceptThreads; ++i)
if(SemTest(psAccept[i].p.hSem) > 0)
SemSignal(psAccept[i].p.hSem);
for(i = 0; i < uNumberOfAcceptThreads; ++i) {
SemWait(psAccept[i].p.hSem);
SemDestroy(psAccept[i].p.hSem);
THREAD_DESTROY(psAccept[i].p.hThread);
free(psAccept[i].p.pStack);
}
free(psAccept);

/* clean up ssl accept threads */
for(i = 0; i < uNumberOfSslAcceptThreads; ++i)
if(SemTest(psSslAccept[i].p.hSem) > 0)
SemSignal(psSslAccept[i].p.hSem);
for(i = 0; i < uNumberOfSslAcceptThreads; ++i) {
SemWait(psSslAccept[i].p.hSem);
SemDestroy(psSslAccept[i].p.hSem);
THREAD_DESTROY(psSslAccept[i].p.hThread);
free(psSslAccept[i].p.pStack);
}
free(psSslAccept);

SemDestroy(ioMutex);
SemDestroy(coMutex);

} /* fExit */

void fShowUsage(char *pcName)
{
fprintf(stdout, "\n");
fprintf(stdout, "Usage is: %s <options>\n", pcName);
fprintf(stdout, "\n");
fprintf(stdout, " -? show usage\n");
fprintf(stdout, " -c authenticate SSL client (Default: NO CLIENT AUTHENICATION)\n");
fprintf(stdout, " -h <root> interpret recv'd data as an http GET request (Default: OFF\n");
fprintf(stdout, " Default <root> = %s)\n", pcHttpRoot);
fprintf(stdout, " -l <lifetime> session id lifetime (Default: 100)\n");
fprintf(stdout, " -k <key> name of key material object (Default: 'SAS Key')\n");
fprintf(stdout, " -p <port> port for sockets (Default: 80)\n");
fprintf(stdout, " -s <port> port for ssl sockets (Default: 443)\n");
fprintf(stdout, " -t <type> <n> initial number of threads of type <type>\n");
fprintf(stdout, " type = [SSL]ACCEPT | [SSL]RW and n = <unsigned int>\n");
fprintf(stdout, " for type = ACCEPT Default n = %d (maximum %d)\n", uNumberOfAcceptThreads, MAX_ACCEPT_THREADS);
fprintf(stdout, " type = RW Default n = %d (maximum %d)\n", uNumberOfRwThreads, MAX_RW_THREADS);
fprintf(stdout, " for type = SSLACCEPT Default n = %d (maximum %d)\n", uNumberOfSslAcceptThreads, MAX_ACCEPT_THREADS);
fprintf(stdout, " type = SSLRW Default n = %d (maximum %d)\n", uNumberOfSslRwThreads, MAX_RW_THREADS);
fprintf(stdout, "\n");
} /* fShowUsage */

int fParseArgs(int argc, char *argv[])
{
int iargc = 0;
unsigned length;

while(++iargc < argc) {
if(*argv[iargc] == '/' || *argv[iargc] == '-') {
++argv[iargc];
length = strlen(argv[iargc]);
switch(*argv[iargc]) {
case 'c':
case 'C':
eAuth = eClient;
break;
case 'f':
case 'F':
pcFile = argv[++iargc];
break;
case 'h':
case 'H':
iHttp = TRUE;
if(iargc+1 < argc && *argv[iargc+1] != '/' && *argv[iargc+1] != '-')
pcHttpRoot = argv[++iargc];
break;
case 'k':
case 'K':
pcKeyfile = argv[++iargc];
break;
case 'l':
case 'L':
iSidLifetime = atoi(argv[++iargc]);
break;
case 'p':
case 'P':
iListenPort = atoi(argv[++iargc]);
break;
case 's':
case 'S':
iSslListenPort = atoi(argv[++iargc]);
break;
case 't':
case 'T':
++iargc;
if(!stricmp(argv[iargc], "ACCEPT"))
uNumberOfAcceptThreads = atoi(argv[++iargc]);
else if(!stricmp(argv[iargc], "SSLACCEPT"))
uNumberOfSslAcceptThreads = atoi(argv[++iargc]);
else if(!stricmp(argv[iargc], "SSLRW"))
uNumberOfSslRwThreads = atoi(argv[++iargc]);
else if(!stricmp(argv[iargc], "RW"))
uNumberOfRwThreads = atoi(argv[++iargc]);
break;
case '?':
fShowUsage(argv[0]);
return -1;
default: /* argv is bad */
--argv[argc];
fprintf(stderr, "%s.parseArgs-1: Bad command line option: %s\n", argv[0], argv[iargc]);
return -1;
}
}
else {
fprintf(stderr, "%s.parseArgs-2: Bad command line: %s\n", argv[0], argv[iargc]);
return -1;
}
}

return 0;

} /* fParseArgs */


lalalala............
 
 
Nach oben
SilverSky
Alt 09.01.2002, 14:51   #3
Beitrag

is allerdings für novell... sorry mehr hab ich net
 
 
Nach oben
Ähnliche Themen, die dich vielleicht interessieren
Thema Autor Forum Antworten Letzter Beitrag
DVD-LW und Daemon erkennen keine DVDs Blasteroid Betriebssysteme und Software 2 07.09.2006 18:48
[WinXP Pro Corp] daemon B³nny Betriebssysteme und Software 3 02.10.2003 16:07
Anzeigen:
Thema geschlossen

« C unter Linux | pps »
Themen-Optionen



Alle Zeitangaben in WEZ +2. Es ist jetzt 04:48 Uhr.


Lupuz.de - wir können auch anders!
©1998 - 2008, Lupuz:Information-Network
Powered by vBulletin Version 3.7.1 (Deutsch), Jelsoft Enterprises Ltd.
Grüne Links?

SEO by vBSEO 3.1.0 ©2007, Crawlability, Inc.