void nonBlockFifo(int clientFd) /* * See if the input is a fifo, and setup the fcntl correctly */ { struct stat info; int flags; int dataFd = fileno(gDataFile); fstat(dataFd, &info); if ( info.st_mode & S_IFIFO ) { if ( gReadRewind ) { CapError(clientFd, CAP_SEV_FATAL, gProgramName, "Cannot -r (rewind) FIFO"); exit(1); } #ifndef _WIN32 flags = fcntl(dataFd,F_GETFL); fcntl(dataFd,F_SETFL,flags|FNONBLK); #endif } }
static void get_data(int client_fd) { channelInfo *chan = gChannels; char *tokBuffer; char *lp; int i; char *errOverFlow = "Input buffer overflow line length greater than -b %d"; if ( gReadReopen ) { if ( NULL != gDataFile ) fclose(gDataFile); gDataFile = fopen(gDataPath, "r"); if (NULL == gDataFile) { CapError(client_fd, CAP_SEV_FATAL, gProgramName, NULL); exit(1); } nonBlockFifo(client_fd); } else if ( gReadRewind ) rewind(gDataFile); /* * find the data record */ while ( lp = fgets(gBuffers[gReadBuffer] + gBufferOffset, gBufferSize - gBufferOffset, gDataFile) ) { gBufferOffset = strlen(lp); if ( '\n' == lp[gBufferOffset-1] ) { /* This completes a full record */ gReadBuffer = 1 - gReadBuffer; gBufferOffset = 0; /* * RFE: add support for leading character "comments" */ if (gReadNext) break; } else if ( gBufferSize <= gBufferOffset ) { CapError(client_fd, CAP_SEV_FATAL, gProgramName, errOverFlow, gBufferSize ); exit(1); } } /* * gReadBuffer is the buffer to read or in process 1-grb is complete! */ tokBuffer = gBuffers[1 - gReadBuffer]; while (chan != NULL) { float val; channelInfo *next = chan->next; for ( i = 0; i< chan->info->p1.dim; i++) { char *tok = strtok(tokBuffer," \n\t"); tokBuffer = NULL; /* how strtok works ;-o */ if ( NULL == tok || ( 1 != sscanf(tok,"%g", &val) )) { next = NULL; break; } chan->data[i] = val; } chan = next; } channelInfoSetData(gChannels, 1, NULL); return; }
static int handle_client(int client_fd) { int status; size_t size, nitems; FILE *serial_file; char buf[1024]; /* buffer for serial IO */ CapCommand cmd; char ruser[64], rhost[64], realhost[64]; double rate, time; fd_set rd_fds; struct timeval timeout, now, *timeoutPtr; int recording = 0; double recordNow = 0.; double recordNext = 0.; double recordPeriod = 0.; double recordDelta = 0.; #ifdef _WIN32 int ms; #endif while (1) { FD_ZERO(&rd_fds); FD_SET(client_fd, &rd_fds); if ( !recording ) { timeoutPtr = NULL; } else { /* record and schedule the next recording */ #ifdef LINUX gettimeofday(&now, NULL); #else gettimeofday(&now); #endif recordNow = toDouble(now); if ( recordNext == 0.0 ) /* The first record */ recordNext = recordNow; while ( recordNext <= recordNow ) { get_data(client_fd); recordNext = recordNext + recordPeriod; } timeout = toTimeval( recordNext - recordNow ); timeoutPtr = &timeout; } /* * wait for commands or a timeout */ #ifndef _WIN32 status = select(FD_SETSIZE, &rd_fds, NULL, NULL, timeoutPtr); #else /* Should really use CapWaitTimeout when possible */ ms = -1; if (timeoutPtr) ms = timeoutPtr->tv_sec*1000 + timeoutPtr->tv_usec/1000; status = CapWaitTimeout(client_fd, ms); #endif if (status < 0 ) { if (errno == EINTR) { /* Ignore signals and try again */ continue; } /* Otherwise, give a fatal error message */ CapError(client_fd, CAP_SEV_FATAL, gProgramName, "select failed"); CapError(client_fd, CAP_SEV_FATAL, "select", NULL); exit(1); } else if (status == 0) { /* Try again */ continue; } /* There is data on the client file descriptor */ cmd = CapGetCommand(client_fd); switch (cmd) { case CAP_CMD_QUIT: return 0; case CAP_CMD_AUTHORIZE: status = CapGetAuthInfo(client_fd, ruser, rhost, realhost); if (status < 0) { return -1; } /* * If user@host is not authorized to use this server then: * * status = CapAuthorize(client_fd, 0); */ status = CapAuthorize(client_fd, 1); break; case CAP_CMD_INIT: /* Initial client/server handshake */ status = CapInitialize(client_fd, gProgramName); break; case CAP_CMD_VERSION: /* Send version information */ status = CapVersion(client_fd, gProgramName, "1.0", "Extern server (example) - v1.0"); break; case CAP_CMD_INFO: if (NULL == gChannels) { /* Only create the channel data once */ gChannels = create_channels(gConfigFile, client_fd); if ( NULL == gChannels) { status = CapError(client_fd, CAP_SEV_ERROR, gProgramName, "Missing or empty config file"); } } /* Return the recording information. gMaxRecordRate <= 0. * says recording is not supported */ { size_t buf_size = 0; if ( 0. < gMaxRecordRate) buf_size = INT_MAX; status = CapInfo(client_fd, gMinRecordRate, gMaxRecordRate, gDefRecordRate, buf_size, 1); } break; case CAP_CMD_DATA: /* Send frame data */ if (!recording ) get_data(client_fd); status = CapData(client_fd); break; case CAP_CMD_START_RECORD: /* Start recording */ rate = CapGetRequestedRecordRate(client_fd); size = CapGetRequestedRecordSize(client_fd); /* * Set up for recording operations */ if (rate < gMinRecordRate ) rate = gMinRecordRate; else if (rate > gMaxRecordRate ) rate = gMaxRecordRate; status = CapStartRecord(client_fd, rate, size); if (status != -1) { recordPeriod = 1.0 / rate; recordNext = 0.; recording = 1; } break; case CAP_CMD_STOP_RECORD: /* Stop recording */ status = CapStopRecord(client_fd); recording = 0; break; default: /* Ignore unknown commands */ status = CapError(client_fd, CAP_SEV_ERROR, gProgramName, "Unknown server command."); break; } if (status < 0) { return -1; } } /* return 0; */ }
int main(int argc, char **argv) { int status; int client_fd = -1; /* * on err, this exits... */ parseArgs( argc, argv); /* * Initialization... */ gBuffers[0] = malloc(gBufferSize); gBuffers[1] = malloc(gBufferSize); if ( ( NULL == gBuffers[0] ) || ( NULL == gBuffers[1] ) ) { CapError(-1, CAP_SEV_FATAL, gProgramName, "out of memory, -b %d failed",gBufferSize); exit(1); } *(gBuffers[0]) = '\0'; *(gBuffers[1]) = '\0'; if (gInetdMode) { /* * The socket to the client is open on file descriptor 0. * Handle one client and then exit. */ client_fd = 0; } if (gDaemonMode) { /* * Convert this process into a standard unix type daemon process. * It will be running in the background with no controlling terminal * and using syslog to report error messages. */ status = CapDaemonize(); if (status < 0) { CapError(-1, CAP_SEV_FATAL, gProgramName, NULL); exit(1); } } /* * open the configuration and data files */ gChannels = create_channels(gConfigFile, client_fd); if ( NULL == gChannels ) { CapError(-1, CAP_SEV_FATAL, gProgramName, NULL); exit(1); } if ( 0 == strcmp(gDataPath,"-") ) { gDataFile = stdin; } else { /* * RFE: delay opening until first read */ gDataFile = fopen(gDataPath, "r"); if ( !gReadReopen && (NULL == gDataFile) ) { CapError(-1, CAP_SEV_FATAL, gProgramName, NULL); exit(1); } } if ( NULL != gDataFile ) nonBlockFifo(-1); if (gInetdMode) { /* * The socket to the client is already open on file descriptor 0. * Handle one client and then exit. */ status = handle_client(client_fd); exit(status); } else { while (1) { /* * Set up the server socket and wait for a connection. */ client_fd = CapServe(gServerName); if (client_fd < 0) { CapError(-1, CAP_SEV_FATAL, gProgramName, NULL); exit(1); } /* Handle client requests */ status = handle_client(client_fd); if (status < 0) { CapError(-1, CAP_SEV_FATAL, gProgramName, NULL); } /* Shutdown the client */ closesocket(client_fd); client_fd = -1; /* Go back and wait for another connection request */ continue; } } }
static int handle_client(int client_fd) { int status; CapCommand cmd; char ruser[64], rhost[64], realhost[64]; fd_set rd_fds; struct timeval base_timeout, timeout; int recording = 0; static int channels_created = 0; base_timeout.tv_sec = 1; base_timeout.tv_usec = 0; while (1) { FD_ZERO(&rd_fds); FD_SET((unsigned int)client_fd, &rd_fds); timeout.tv_sec = base_timeout.tv_sec; timeout.tv_usec = base_timeout.tv_usec; status = select(FD_SETSIZE, &rd_fds, NULL, NULL, &timeout); if (status < 0) { #ifndef _WIN32 if (errno == EINTR) { /* Ignore signals and try again */ continue; } #endif /*WIN32*/ /* Otherwise, give a fatal error message */ CapError(client_fd, CAP_SEV_FATAL, program, "select failed"); CapError(client_fd, CAP_SEV_FATAL, "select", NULL); exit(1); } else if (status == 0) { /* We got a timeout */ if (recording) get_data(client_fd); /* Try again */ continue; } else { /* There is data on the client file descriptor */ cmd = CapGetCommand(client_fd); switch (cmd) { case CAP_CMD_QUIT: return 0; #ifdef _WIN32 case CAP_CMD_ERROR: return -1; #endif case CAP_CMD_AUTHORIZE: status = CapGetAuthInfo(client_fd, ruser, rhost, realhost); if (status < 0) { return -1; } /* * If user@host is not authorized to use this server then: * * status = CapAuthorize(client_fd, 0); */ status = CapAuthorize(client_fd, 1); break; case CAP_CMD_INIT: /* Initial client/server handshake */ status = CapInitialize(client_fd, program); break; case CAP_CMD_VERSION: /* Send version information */ status = CapVersion(client_fd, program, "1.0", "Clock capture server - v1.0"); break; case CAP_CMD_INFO: if (!channels_created) { /* Only create the channel data once */ status = create_channels(client_fd); if (status < 0) { break; } channels_created = 1; } #ifdef SERVER_SIDE_RECORDING /* The server side recording returns incorrect time in * the current version */ status = CapInfo(client_fd, 1.0, 100.0, 10.0, 512 * 1024, 1); #else status = CapInfo(client_fd, 0.0, 0.0, 0.0, 512 * 1024, 1); #endif break; case CAP_CMD_DATA: /* Send frame data */ get_data(client_fd); status = CapData(client_fd); break; #ifdef SERVER_SIDE_RECORDING /* The server side recording returns incorrect time in * the current version */ case CAP_CMD_START_RECORD: /* Start recording */ { int size = 0; float rate = 0.0f, time = 0.0f; rate = CapGetRequestedRecordRate(client_fd); size = CapGetRequestedRecordSize(client_fd); /* Convert rate in Hz to a timeout value in a timeval structure */ if (rate < 1.0) rate = 1.0; if (rate > 100.0) rate = 100.0; time = 1.0 / rate; base_timeout.tv_sec = time; base_timeout.tv_usec = (time - base_timeout.tv_sec) * 1000000; status = CapStartRecord(client_fd, rate, size); if (status != -1) { recording = 1; } break; } case CAP_CMD_STOP_RECORD: /* Stop recording */ status = CapStopRecord(client_fd); recording = 0; base_timeout.tv_sec = 1; base_timeout.tv_usec = 0; break; #endif /* server side recording */ default: /* Ignore unknown commands */ status = CapError(client_fd, CAP_SEV_ERROR, program, "Unknown server command."); break; } if (status < 0) { return -1; } } } /* return 0; */ }
int main(int argc, char **argv) { int opt; #ifndef _WIN32 char *cptr; #endif int status; int client_fd = -1; /* * Grab a copy of the program name */ #ifdef _WIN32 _splitpath (argv[0], NULL, NULL, program, NULL); #else cptr = strrchr(argv[0], '/'); if (cptr) { strcpy(program, (cptr + 1)); } else { strcpy(program, argv[0]); } #endif //WIN32 /* * Parse the options */ #ifdef DEVEL while ((opt = getopt(argc, argv, "hdvDin:")) != -1) #else /* DEVEL */ while ((opt = getopt(argc, argv, "hdn:")) != -1) #endif /* DEVEL */ { switch (opt) { case 'h': show_usage++; break; case 'd': daemon_mode++; break; case 'D': debug_mode++; break; case 'i': inetd_mode++; break; case 'n': server_name = optarg; break; case 'v': verbose++; break; case GETOPTHUH: show_usage++; } } /* * Check for errors */ if (daemon_mode && inetd_mode) show_usage++; if (optind < argc) show_usage++; if (show_usage) { fprintf(stderr, "Usage:\n"); #ifdef DEVEL fprintf(stderr, " %s [-hdvDi] [-n name]\n", program); #else /* DEVEL */ fprintf(stderr, " %s [-hd] [-n name]\n", program); #endif /* DEVEL */ fprintf(stderr, "\n"); fprintf(stderr, " -h Print this help message\n"); fprintf(stderr, " -d Run as a daemon in the background\n"); #ifdef DEVEL fprintf(stderr, " -i Run from inetd\n"); fprintf(stderr, " -D Set the debug flag\n"); fprintf(stderr, " -v Set the vebose flag\n"); #endif /* DEVEL */ fprintf(stderr, " -n name Set the UNIX socket name to name\n"); fprintf(stderr, "\n"); fprintf(stderr, "Defaults:\n"); fprintf(stderr, " %s -n %s\n", program, program); fprintf(stderr, "\n"); exit(1); } if (inetd_mode) { /* * The socket to the client is open on file descriptor 0. * Handle one client and then exit. */ client_fd = 0; } if (daemon_mode) { /* * Convert this process into a standard unix type daemon process. * It will be running in the background with no controlling terminal * and using syslog to report error messages. */ status = CapDaemonize(); if (status < 0) { CapError(-1, CAP_SEV_FATAL, program, NULL); exit(1); } } if (inetd_mode) { /* * The socket to the client is already open on file descriptor 0. * Handle one client and then exit. */ status = handle_client(client_fd); exit(status); } else { while (1) { /* * Set up the server socket and wait for a connection. */ client_fd = CapServe(server_name); if (client_fd < 0) { CapError(-1, CAP_SEV_FATAL, program, NULL); exit(1); } /* Handle client requests */ status = handle_client(client_fd); if (status < 0) { CapError(-1, CAP_SEV_FATAL, program, NULL); } /* Shutdown the client */ closesocket(client_fd); client_fd = -1; /* Go back and wait for another connection request */ continue; } } return 0; }