int main(int argc, char *argv[]) { fd_set rset; struct timeval timeout; char * IP; //IP address of socket char * PTY; //Pseudo Terminal Name unsigned char cBuff[BUFFER]; //char c[BUFFER]; int csize; int pty = -1; //Pseudo Terminal File Descriptor int sockfd1, sockfd2 = -1; int x; int args = 0; int tmp; char argSerial[] = "-serial"; char argHelp[] = "-help"; char argPort[] = "-port"; char argPTY[] = "-pty"; char argStrip[] = "-strip"; char argBaud[] = "-baud"; char argDebug[] = "-debug"; int SOCKET_PORT, BAUD, STRIP, DEBUG = 0; char SERIAL[100]; for (x = 0; x < argc; x++){//Cycle through the command line arguments if (!strcmp(argSerial,argv[x])) {//Look for the -serial option strcpy(SERIAL,argv[x+1]); //Copies the port to SERIAL if(BAUD>0){ //If the baud option has been passed sockfd2 = connectSerial(SERIAL, BAUD); //Open the serial port and return the file descriptor if (sockfd2 < 0) { close(sockfd2); if(sockfd1>=0) close(sockfd1); if(pty>=0) close(pty); return -1; }else{ args+=3; } }else{ args+=3; } } else if (!strcmp(argPort,argv[x])) { //Look for -port option SOCKET_PORT = atoi(argv[x+1]); //Convert string address into int sockfd1 = makeSocket(SOCKET_PORT); //Make the socket and return the file descriptor if (sockfd1 < 0) { close(sockfd1); if(sockfd2>=0) close(sockfd2); if(pty>=0) close(pty); return -1; }else{ args+=5; } } else if (!strcmp(argPTY,argv[x])) { //Look for -pty option pty = pseudoTY(&PTY); if(pty<0){ close(pty); if(sockfd2>=0) close(sockfd2); if(sockfd1>=0) close(sockfd1); return -1; }else{ args+=7; } } else if (!strcmp(argBaud,argv[x])) { //Look for -baud option tmp = atoi(argv[x+1]); //Convert string baud rate to int switch (tmp) { //Make sure the value is supported case 115200: BAUD = B115200; break; case 38400: BAUD = B38400; break; case 19200: BAUD = B19200; break; case 9600: BAUD = B9600; break; default: printf("ERROR!: Unknown baud rate.\n"); return -1; break; } if(strlen(SERIAL) != 0) //If we got the tag for a serial port, create the serial port sockfd2 = connectSerial(SERIAL, BAUD); //Open the serial port and return the file descriptor args+=1; } else if ( (args != 9 && args != 11 && args !=16 && x == argc-1) || (!strcmp(argHelp,argv[x]))) { //If not enough arguments, output usage directions and exit // Serial <=> Socket w/ baud = 9 // Serial <=> PTY w/ baud = 11 // Serial <=> Socket, Serial <=> PTY w/ baud = 16 printf("--------------------------------------\n"); printf("------------ SerialDaemon ------------\n"); printf("--------------------------------------\n"); printf("Usage:"); printf("\t./serialdaemon [options] [arguments]\n"); printf("\t-serial [Use to indicate which serial port to connect to. E.G. /dev/ttyS1]\n"); printf("\t-port [Use to indicate which TCP/IP port of the local host to connect to. E.G. 5000]\n"); printf("\t-pty [Create a pseudo terminal for the serial port to connect to.]\n"); printf("\t-baud [Serial port baudrate.]\n"); printf("\t\t115200\n"); printf("\t\t38400\n"); printf("\t\t19200\n"); printf("\t\t9600\n"); printf("\t-strip [Strip the endline character and replace with a space.]\n"); printf("\t-debug [Set the verbose debug mode for help.]\n"); printf("\t-help [For this help screen.]\n\n"); printf("Example Usage:\t./serialdaemon -serial /dev/ttyS1 -baud 115200 -pty -port 5000\n"); printf("This will link ttyS1 to localhost:5000 and ttyS1 to a pseudo terminal. The connection to ttyS1 will have a baudrate of 115200.\n"); return -1; } else if (!strcmp(argStrip,argv[x])){STRIP = 1;} //Look for the -strip option else if (!strcmp(argDebug,argv[x])){DEBUG = 1; printf ("DEBUG: debug mode on!\n");} //Look for the -debug option } signal(SIGINT, controlC); // catch ^C so we can close sockets & exit cleanly IP = getIP(); //Get the local IP address if(args == 9)//Serial to Socket printf("Connections made: \n\t\t\t%s < = > http://%s:%d\n",SERIAL,IP,SOCKET_PORT); else if(args == 11)//Serial to PTY printf("Connections made: \n\t\t\t%s < = > %s\n",SERIAL,PTY); else if(args == 16)//Serial to PTY & Serial to Socket printf("Connections made: \n\t\t\t%s < = > http://%s:%d\n\t\t\t%s < = > %s\n",SERIAL,IP,SOCKET_PORT,SERIAL,PTY); sd1 = waitOnSocket(sockfd1); //Check for a connection to the socket while(1){ /* Select on sockets */ if(sd1 > 0){ //If There is a connection to the socket then potentially set up these connections: tty < = > socket and tty < = > pty if (DEBUG) printf("DEBUG: New client socket opened.\n"); if (sd1 < 0) { //Error in creating connection close(sd1); return -1; } sd2 = sockfd2; //File descriptor of the serial port if (sd2 < 0) { //If an error close(sd1); close(sd2); return -1; } FD_ZERO(&rset); //Clear file descriptors in the rset set while(1) { FD_SET(sd1,&rset);//Set sd1 in rset FD_SET(sd2,&rset);//Set sd2 in rset if(pty!=-1) {//If a virtual port is requested FD_SET(pty,&rset); select(max(max(sd1,sd2),pty)+1,&rset,NULL,NULL,NULL); //Select specifies which of the file descriptors is ready for reading or writing }else { select(max(sd1,sd2)+1,&rset,NULL,NULL,NULL); //Select tests file descriptors in the range of 0 to nfds-1 or in this case 0 to max(sd1,sd2). } //----------------Check The Socket For Data ------------------ if (FD_ISSET(sd1,&rset)) { //Is there stuff to read from the socket /* There's stuff to read */ if ((csize= read(sd1, &cBuff, BUFFER)) >= 1) { //If there's something worth reading if (STRIP==1) { //Remove endline characters and replace with space for(x = 0 ; x < csize; x++) { if (cBuff[x] == '\n' ) { cBuff[x] = ' '; if (DEBUG) printf ("DEBUG: **STRIPPED**\n"); } } } if (DEBUG) { //Replace &cBuff and cBuff with c //cBuff[csize] = '\0'; printf("\nDEBUG: %s <== ",SERIAL); for(x=0; x<csize;x++){ printf("%#.2x ",cBuff[x]); } printf("\n"); } write(sd2, &cBuff, csize);//Write data from sd1 to sd2 }else{break;}// Failed -- port closed } //----------------Check The Serial Port For Data ------------------ if (FD_ISSET(sd2,&rset)) {//Is there stuff to read from the serial port if ((csize = read(sd2, &cBuff, BUFFER)) >= 1) {//If there is something worth reading from the serial port write(sd1, &cBuff, csize); //Write this data to the socket if(pty != -1){write(pty,&cBuff,csize);} //Write this data to the virtual com port if (DEBUG) { //Replace &cBuff and cBuff with c //cBuff[csize] = '\0'; printf("DEBUG: http://%s:%d <== ",IP,SOCKET_PORT); for(x=0; x<csize;x++){ printf("%#.2x ",cBuff[x]); } printf("\n"); if(pty !=-1){ printf("DEBUG: %s <== ",PTY); for(x=0; x<csize;x++){ printf("%#.2x ",cBuff[x]); } printf("\n"); } } } //else break; /* Failed */ } //----------------Check The PTY Port For Data ------------------ if (pty != -1 && FD_ISSET(pty,&rset)) {//If there is a virtual port, and data is ready, write data from if ((csize = read(pty, &cBuff, BUFFER)) >= 1) {//If there is something worth reading from the serial port write(sd2, &cBuff, csize); //Write this data to the serial port if (DEBUG) { //Replace &cBuff and cBuff with c //cBuff[csize] = '\0'; printf("\nDEBUG: %s <== ",SERIAL); for(x=0; x<csize;x++){ printf("%#.2x ",cBuff[x]); } printf("\n"); } } //else break; /* Failed */ } } printf("Restarting\n"); close(sd1);/* clean up */ sd1 = waitOnSocket(sockfd1); //Check for a connection to the socket }else if(pty != -1) {//Else, if there is a virtual port then tty <=> pty sd2 = sockfd2; //File descriptor of the serial port if (sd2 < 0) { //If an error close(sd2); close(pty); return -1; } FD_ZERO(&rset); //Clear file descriptors in the rset set while(1) { FD_SET(sd2,&rset);//Set sd2 in rset FD_SET(pty,&rset);//Set pty in rset sd1 = waitOnSocket(sockfd1); if(sd1 >= 0){break;} //Check for socket connection, if there is, break out of this loop. select(max(sd2,pty)+1,&rset,NULL,NULL,NULL); // Specifies which of the file descriptors is ready for reading or writing if (FD_ISSET(pty,&rset)) { //If there is a virtual port, and data is ready, write data from if ((csize = read(pty, &cBuff, BUFFER)) >= 1) {//If there is something worth reading from the serial port write(sd2, &cBuff, csize); //Write this data to the serial port if (DEBUG) { //Replace &cBuff and cBuff with c //cBuff[csize] = '\0'; printf("\nDEBUG: %s <== ",SERIAL); for(x=0; x<csize;x++){ printf("%#.2x ",cBuff[x]); } printf("\n"); } } //else break; // Failed } if (FD_ISSET(sd2,&rset)) {//Is there stuff to read from the serial port if ((csize = read(sd2, &cBuff, BUFFER)) >= 1) { //If there is something worth reading from the serial port write(pty, &cBuff, csize); //Write this data to the virtual com port if (DEBUG) { //Replace &cBuff and cBuff with c //cBuff[csize] = '\0'; printf("DEBUG: %s <== ",PTY); for(x=0; x<csize;x++){ printf("%#.2x ",cBuff[x]); } printf("\n"); } } //else break; /* Failed */ } } }else {//If there isn't a pty, then check the socket for a connection once a second if(DEBUG) printf("\rWaiting on the socket connection...\n"); sd1 = waitOnSocket(sockfd1); //Check for a connection to the socket sleep(1); } } }
int main(int argc, char *argv[]) { fd_set rset; struct timeval timeout; char c[BUFFER_SIZE]; int csize; int mode; int x; int y; int args = 0; int tmp; int result; int blockerror = 0; char argSerial[] = "-serial"; char argPort[] = "-port"; char argStrip[] = "-strip"; char argBaud[] = "-baud"; char argDebug[] = "-debug"; char argInDebug[] = "-indebug"; char argOutDebug[] = "-outdebug"; char argNonblock[] = "-nonblock"; char argAux[] = "-aux"; int SOCKET_PORT = 0; int BAUD = 0; int STRIP = 0; int NONBLOCK = 0; int AUX_PORT = 0; char SERIAL[100]; for (x=1; x<argc; x++) { if (!strcmp(argSerial,argv[x])) { strcpy(SERIAL,argv[x+1]); x++; args++; } else if (!strcmp(argPort,argv[x])) { SOCKET_PORT = atoi(argv[x+1]); x++; args++; } else if (!strcmp(argBaud,argv[x])) { BAUD = parseBaudRates(argv[x+1]); if (!BAUD) return 1; x++; args++; } else if (!strcmp(argAux, argv[x])) { AUX_PORT = atoi(argv[x+1]); x++; } else if (!strcmp(argStrip,argv[x])) STRIP = 1; else if (!strcmp(argInDebug,argv[x])) INDEBUG = 1; else if (!strcmp(argOutDebug,argv[x])) OUTDEBUG = 1; else if (!strcmp(argDebug,argv[x])) INDEBUG = OUTDEBUG = 1; else if (!strcmp(argNonblock,argv[x])) NONBLOCK = 1; else { printf("ERROR!: Unknown argument %s\n", argv[x]); return 1; } } if (args < 3) { printf("--------------------------------------------------------------\n"); printf("------------------ GMU SerialDaemon ------------------------\n"); printf("--------------------------------------------------------------\n"); printf("Usage:\n"); printf("\tserialdaemon\n"); printf("\t\t-serial [serialPort]\n"); printf("\t\t-port [TCP/IP Port]\n"); printf("\t\t-aux [auxiliary TCP/IP Port]\n"); printf("\t\t-baud [baudRate]\n"); printf("\t\t\t500000 (available on Linux only)\n"); printf("\t\t\t460800 (available on Linux only)\n"); printf("\t\t\t230400\n"); printf("\t\t\t115200\n"); printf("\t\t\t57600\n"); printf("\t\t\t38400\n"); printf("\t\t\t19200\n"); printf("\t\t\t9600\n"); printf("\t\t-strip\n"); printf("\t\t-indebug\n"); printf("\t\t-outdebug\n"); printf("\t\t-debug\n"); printf("\t\t-nonblock\n"); printf("\n"); printf("Notes:\n"); printf("1) If you have declared an auxiliary port, your client program\n"); printf(" must connect to the primary TCP/IP port, THEN the auxiliary\n"); printf(" port, and both must be connected before any traffic is sent\n"); printf("2) Baud rates 460800 and 500000 are not available on OS/X\n"); return(1); } if (INDEBUG || OUTDEBUG) printf ("DEBUG: debug mode on!\n"); sockfd_pre = makeSocket(SOCKET_PORT); if (sockfd_pre <= 0) { printf("ERROR: couldn't make TCP/IP socket!\n"); closeAll(); return; } if (AUX_PORT != 0) { auxfd_pre = makeSocket(AUX_PORT); if (auxfd_pre <= 0) { printf("ERROR: couldn't make TCP/IP socket!\n"); closeAll(); return; } } serialfd = makeSerialPortFd(SERIAL, BAUD); if (serialfd <= 0) { printf("ERROR: couldn't open serial port!\n"); closeAll(); return; } if (argc <= 1) mode = 0; else mode = atoi(argv[1]); printf("Listening for data connections on port: %i\n",SOCKET_PORT); if (AUX_PORT != 0) { printf("Listening for aux connections on port: %i\n",AUX_PORT); } while(1) { /* Wait for connection on data socket */ sockfd = waitOnSocket(sockfd_pre); if (INDEBUG || OUTDEBUG) printf("DEBUG: New data socket opened.\n"); if (sockfd < 0) { closeAll(); return; } /* Set data socket to non-blocking */ if (NONBLOCK) { if (fcntl(sockfd, F_SETFL, O_NONBLOCK) != 0) { printf("ERROR: couldn't make TCP/IP socket non-blocking!\n"); closeAll(); return; } } /* Wait for connection on AUX socket (if specified) */ if (auxfd_pre != NOTHING) { auxfd = waitOnSocket(auxfd_pre); if (INDEBUG || OUTDEBUG) printf("DEBUG: New aux socket opened.\n"); if (auxfd < 0) { closeAll(); return; } } /* Must have a serial file descriptor (else, why are we running?) */ if (serialfd < 0) { closeAll(); return; } FD_ZERO(&rset); /* Main Loop */ while(1) { /* Add connections to set */ FD_SET(sockfd,&rset); if (auxfd!=NOTHING) FD_SET(auxfd,&rset); FD_SET(serialfd,&rset); /* Select on connection */ select(max(max(sockfd,auxfd),serialfd)+1,&rset,NULL,NULL,NULL); /* There's stuff to read on AUX */ if (FD_ISSET(auxfd,&rset)) { if ((csize = readline(auxfd, c, BUFFER_SIZE)) >= 1) { c[csize] = '\0'; // after length, so no problem char cmd = c[0]; if (c[1] != ' ') printf("ERROR!: Malformed AUX command; ignoring\n"); char* data = &c[2]; switch (cmd) { case 'B': if (INDEBUG) { printf("DEBUG: AUX baud change\n"); } auxShiftBaud(data); break; default: printf("ERROR!: Unknown AUX command; ignoring\n"); break; } } else break; /* Failed */ } /* There's stuff to read on SOCKET */ if (FD_ISSET(sockfd,&rset)) { if ((csize= read(sockfd, c, BUFFER_SIZE)) >= 1) { y = csize; if (STRIP==1) { for(x = 0, y = 0 ; x < csize; x++, y++) { if (c[x] == '\n') { // get rid of it y--; if (OUTDEBUG) printf ("DEBUG: **STRIPPED**\n"); } else c[y] = c[x]; } } if (OUTDEBUG) { c[y] = '\0'; // after length, so no problem printf("DEBUG: serial <=="); printDebugString(c, y); } result = write(serialfd, c, y); if (OUTDEBUG) { printf("DEBUG: wrote %d/%d\n", result, y); } } else break; /* Failed */ } /* There's stuff to read on SERIAL */ if (FD_ISSET(serialfd,&rset)) { if ((csize = read(serialfd, c, BUFFER_SIZE)) >= 1) { if (STRIP==1) { for(x = 0 ; x < csize; x++) { if (c[x] == '\r' ) { // get rid of it c[x] = '\n'; if (OUTDEBUG) printf ("DEBUG: **STRIPPED**\n"); } else c[y] = c[x]; } } if (INDEBUG) { c[csize] = '\0'; // after length, so no problem printf("DEBUG: serial ==>"); printDebugString(c, csize); } result = write(sockfd, c, csize); if (result == EWOULDBLOCK) { if (!blockerror) { blockerror = 1; printf("ERROR: dropping bytes writing to socket\n"); } } else if (INDEBUG) { printf("DEBUG: read %d/%d\n", result, csize); } } else break; /* Failed */ } } /* Restart connection-wait loop */ printf("Restarting\n"); close(sockfd); /* clean up */ } }