X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=codemux.c;h=34ffc306b985116cb1937f3393698b04383f6609;hb=8b9393a727c5eef446a0d4e5a3cc0f4863740013;hp=c554cd0b4920d740ed68b651a8a39a0dd479849c;hpb=0004e089d32f355a47338f6394b8d2780494b047;p=codemux.git diff --git a/codemux.c b/codemux.c index c554cd0..34ffc30 100644 --- a/codemux.c +++ b/codemux.c @@ -15,9 +15,17 @@ #include #include "codemuxlib.h" +#define DEBUG 0 + +#ifdef DEBUG +#define TRACE(fmt, msg...) fprintf(stderr, "[%s,%d] " fmt, __FUNCTION__, __LINE__, ##msg) +#else +#define TRACE(fmt, msg...) (void)0 +#endif + #define CONF_FILE "/etc/codemux/codemux.conf" #define DEMUX_PORT 80 -#define REAL_WEBSERVER_CONFLINE "* root 1080" +#define PIDFILE "/var/run/codemux.pid" #define TARG_SETSIZE 4096 /* set aside some small number of fds for us, allow the rest for @@ -31,6 +39,8 @@ among them */ #define FAIRNESS_CUTOFF (MAX_CONNS * 0.85) +/* codemux version */ +#define CODEMUX_VERSION "0.3" typedef struct FlowBuf { int fb_refs; /* num refs */ @@ -86,8 +96,6 @@ static int numNeedingHeaders; /* how many conns waiting on headers? */ static int numForks; -//HANDLE hdebugLog; - #ifndef SO_SETXID #define SO_SETXID SO_PEERCRED #endif @@ -109,8 +117,10 @@ DumpStatus(int fd) int len; sprintf(start, + "CoDemux version %s\n" "numForks %d, numActiveSlices %d, numTotalSliceConns %d\n" "numNeedingHeaders %d, anySliceXidsNeeded %d\n", + CODEMUX_VERSION, numForks, numActiveSlices, numTotalSliceConns, numNeedingHeaders, anySliceXidsNeeded); start += strlen(start); @@ -281,14 +291,9 @@ ReadConfFile(void) int port; if (line != NULL) free(line); - - /* on the first pass, put in a fake entry for apache */ - if (num == 0) - line = strdup(REAL_WEBSERVER_CONFLINE); - else { - if ((line = GetNextLine(f)) == NULL) - break; - } + + if ((line = GetNextLine(f)) == NULL) + break; memset(&serv, 0, sizeof(serv)); if (WordCount(line) != 3) { @@ -303,6 +308,13 @@ ReadConfFile(void) serv.ss_host = GetWord(line, 0); serv.ss_slice = GetWord(line, 1); + + if (num == 0 && /* the first row must be an entry for apache */ + (strcmp(serv.ss_host, "*") != 0 || + strcmp(serv.ss_slice, "root") != 0)) { + fprintf(stderr, "first row has to be for webserver\n"); + exit(-1); + } if (num >= numAlloc) { numAlloc = MAX(numAlloc * 2, 8); servs = realloc(servs, numAlloc * sizeof(ServiceSig)); @@ -645,6 +657,10 @@ ReallyCloseSocks(void) SliceConnsDec(sockInfo[fd].si_whichService); sockInfo[fd].si_whichService = -1; } + /* KyoungSoo*/ + if (sockInfo[fd].si_peerFd >= 0) { + sockInfo[sockInfo[fd].si_peerFd].si_peerFd = -1; + } } numSocksToClose = 0; } @@ -676,7 +692,7 @@ SocketReadyToRead(int fd) fb->fb_buf = malloc(FB_ALLOCSIZE); /* determine read buffer size - if 0, then block reads and return */ - if ((spaceLeft = FB_SIZE - fb->fb_used) < 0) { + if ((spaceLeft = FB_SIZE - fb->fb_used) <= 0) { if (si->si_needsHeaderSince) { write(fd, err400BadRequest, strlen(err400BadRequest)); CloseSock(fd); @@ -686,8 +702,8 @@ SocketReadyToRead(int fd) ClearFd(fd, &masterReadSet); return; } - } - + } + /* read as much as allowed, and is available */ if ((res = read(fd, &fb->fb_buf[fb->fb_used], spaceLeft)) == 0) { CloseSock(fd); @@ -700,6 +716,7 @@ SocketReadyToRead(int fd) if (res == -1) { if (errno == EAGAIN) return; + TRACE("fd=%d errno=%d errstr=%s\n",fd, errno, strerror(errno)); CloseSock(fd); if (fb->fb_used == 0 && si->si_peerFd >= 0) { CloseSock(si->si_peerFd); @@ -709,7 +726,7 @@ SocketReadyToRead(int fd) } fb->fb_used += res; fb->fb_buf[fb->fb_used] = 0; /* terminate it for convenience */ - printf("sock %d, read %d, total %d\n", fd, res, fb->fb_used); + // printf("sock %d, read %d, total %d\n", fd, res, fb->fb_used); /* if we need header, check if we've gotten it. if so, do modifications and continue. if not, check if we've read the @@ -725,10 +742,10 @@ SocketReadyToRead(int fd) return; } - printf("trying to find service\n"); + // printf("trying to find service\n"); if (FindService(fb, &whichService, si->si_cliAddr) != SUCCESS) return; - printf("found service %d\n", whichService); + // printf("found service %d\n", whichService); slice = ServiceToSlice(whichService); /* no service can have more than some absolute max number of @@ -738,21 +755,28 @@ SocketReadyToRead(int fd) (numTotalSliceConns > FAIRNESS_CUTOFF && slice->si_numConns > MAX_CONNS/numActiveSlices)) { write(fd, err503TooBusy, strlen(err503TooBusy)); + TRACE("CloseSock(): fd=%d too busy\n", fd); CloseSock(fd); return; } if (slice->si_xid > 0) { + static int first = 1; setsockopt(fd, SOL_SOCKET, SO_SETXID, &slice->si_xid, sizeof(slice->si_xid)); - fprintf(stderr, "setsockopt() with XID = %d name = %s\n", - slice->si_xid, slice->si_sliceName); + if (first) { + /* just to log it for once */ + fprintf(stderr, "setsockopt() with XID = %d name = %s\n", + slice->si_xid, slice->si_sliceName); + first = 0; + } } si->si_needsHeaderSince = 0; numNeedingHeaders--; if (StartConnect(fd, whichService) != SUCCESS) { write(fd, err503Unavailable, strlen(err503Unavailable)); + TRACE("CloseSock(): fd=%d StartConnect() failed\n", fd); CloseSock(fd); return; } @@ -762,9 +786,13 @@ SocketReadyToRead(int fd) /* write anything possible */ if (WriteAvailData(si->si_peerFd) != SUCCESS) { /* assume the worst and close */ + TRACE("CloseSock(): fd=%d WriteAvailData() failed errno=%d errstr=%s\n", + fd, errno, strerror(errno)); CloseSock(fd); - CloseSock(si->si_peerFd); - si->si_peerFd = -1; + if (si->si_peerFd >=0) { + CloseSock(si->si_peerFd); + si->si_peerFd = -1; + } } } /*-----------------------------------------------------------------*/ @@ -785,6 +813,8 @@ SocketReadyToWrite(int fd) /* if we have data, write it */ if (WriteAvailData(fd) != SUCCESS) { /* assume the worst and close */ + TRACE("CloseSock(): fd=%d WriteAvailData() failed errno=%d errstr=%s\n", + fd, errno, strerror(errno)); CloseSock(fd); if (si->si_peerFd >= 0) { CloseSock(si->si_peerFd); @@ -794,8 +824,9 @@ SocketReadyToWrite(int fd) } /* if peer is closed and we're done writing, we should close */ - if (si->si_peerFd < 0 && si->si_writeBuf->fb_used == 0) + if (si->si_peerFd < 0 && si->si_writeBuf->fb_used == 0) { CloseSock(fd); + } } /*-----------------------------------------------------------------*/ static void @@ -831,7 +862,7 @@ CloseReqlessConns(void) /* if it's too old, close it */ for (i = 0; i < highestSetFd+1; i++) { if (sockInfo[i].si_needsHeaderSince && - (now - sockInfo[i].si_needsHeaderSince) > maxAge) + (now - sockInfo[i].si_needsHeaderSince) > maxAge) CloseSock(i); } } @@ -905,6 +936,11 @@ MainLoop(int lisSock) socklen_t lenAddr = sizeof(addr); if ((newSock = accept(lisSock, (struct sockaddr *) &addr, &lenAddr)) >= 0) { + /* make socket non-blocking */ + if (fcntl(newSock, F_SETFL, O_NONBLOCK) < 0) { + close(newSock); + continue; + } memset(&sockInfo[newSock], 0, sizeof(SockInfo)); sockInfo[newSock].si_needsHeaderSince = now; numNeedingHeaders++; @@ -917,17 +953,113 @@ MainLoop(int lisSock) } } /*-----------------------------------------------------------------*/ +static int +InitDaemon(void) +{ + pid_t pid; + FILE *pidfile; + + pidfile = fopen(PIDFILE, "w"); + if (pidfile == NULL) { + fprintf(stderr, "%s creation failed\n", PIDFILE); + return(-1); + } + + if ((pid = fork()) < 0) { + fclose(pidfile); + return(-1); + } + else if (pid != 0) { + /* i'm the parent, writing down the child pid */ + fprintf(pidfile, "%u\n", pid); + fclose(pidfile); + exit(0); + } + + /* close the pid file */ + fclose(pidfile); + + /* routines for any daemon process + 1. create a new session + 2. change directory to the root + 3. change the file creation permission + */ + setsid(); + chdir("/"); + umask(0); + + return(0); +} +/*-----------------------------------------------------------------*/ +static int +OpenLogFile(void) +{ + static const char* logfile = "/var/log/codemux.log"; + static const char* oldlogfile = "/var/log/codemux.log.old"; + int logfd; + + /* if the previous log file exists, + rename it to the oldlogfile */ + if (access(logfile, F_OK) == 0) { + if (rename(logfile, oldlogfile) < 0) { + fprintf(stderr, "cannot rotate the logfile err=%s\n", + strerror(errno)); + exit(-1); + } + } + + logfd = open(logfile, O_WRONLY | O_APPEND | O_CREAT, 0600); + if (logfd < 0) { + fprintf(stderr, "cannot open the logfile err=%s\n", + strerror(errno)); + exit(-1); + } + + /* duplicate logfile to stderr */ + if (dup2(logfd, STDERR_FILENO) != STDERR_FILENO) { + fprintf(stderr, "cannot open the logfile err=%s\n", + strerror(errno)); + exit(-1); + } + + /* set the close-on-exec flag */ + if (fcntl(STDERR_FILENO, F_SETFD, 1) != 0) { + fprintf(stderr, "fcntl to set the close-on-exec flag failed err=%s\n", + strerror(errno)); + exit(-1); + } + + return logfd; +} +/*-----------------------------------------------------------------*/ int main(int argc, char *argv[]) { int lisSock; + int logFd; + /* do the daemon stuff */ + if (argc <= 1 || strcmp(argv[1], "-d") != 0) { + if (InitDaemon() < 0) { + fprintf(stderr, "codemux daemon_init() failed\n"); + exit(-1); + } + } + + /* create the accept socket */ if ((lisSock = CreatePrivateAcceptSocket(DEMUX_PORT, TRUE)) < 0) { fprintf(stderr, "failed creating accept socket\n"); exit(-1); } SetFd(lisSock, &masterReadSet); + /* open the log file */ + logFd = OpenLogFile(); + + + /* write down the version */ + fprintf(stderr, "CoDemux version %s started\n", CODEMUX_VERSION); + while (1) { numForks++; if (fork()) {