/* A simple server in the internet domain using TCP The port number is passed as an argument */ #include #include #include #include #include #include #include #include #include #define BUFFER_LENGTH (256) #define PENDING_QUEUE_LENGTH (5) const char* READ_COMMAND = "read "; const char* READ_SILENT_COMMAND = "read_silent "; const char* WRITE_COMMAND = "write "; const char* WRITE_BYTES_COMMAND = "write_bytes "; const char* WAIT_COMMAND = "wait"; const char* READ_SOCKET_COMMAND = "readSocket"; const char* WRITE_SOCKET_COMMAND = "writeSocket"; const char* BIND_COMMAND = "bind"; const char* EXIT_COMMAND = "exit"; const char* OPEN_COMMAND = "open"; const char* FLUSH_COMMAND = "flush"; const char* DATE_COMMAND = "date"; const char* NOP_COMMAND = "nop"; void printError(const char* message) { fprintf(stderr, "%s\n", message); exit(1); } void printCommandFileError(const char* message, const char* commandFilePath, int lineNumber) { fprintf(stderr, "%s in %s, line no. %d\n", message, lineNumber); } void commandFileLoop(const char* command, const char* commandFilePath, int commandFileLineNumber, int* serverSocketDescriptor, int* serverPortNumber, FILE** fileToOpen) { // 'read' command clause if(!strncasecmp(command, READ_COMMAND, strlen(READ_COMMAND))) { char filePathToRead[BUFFER_LENGTH]; char fileToReadBuffer[BUFFER_LENGTH]; FILE* fileToRead = NULL; if(sscanf(command + strlen(READ_COMMAND), "%s", filePathToRead) != 1) { printCommandFileError("No file to read specified", commandFilePath, commandFileLineNumber); return; } if((fileToRead = fopen(filePathToRead, "r")) == NULL) { printCommandFileError("Unable to open the specified file", commandFilePath, commandFileLineNumber); return; } while(fgets(fileToReadBuffer, BUFFER_LENGTH, fileToRead) != NULL) { printf("%s", fileToReadBuffer); fflush(stdout); } fclose(fileToRead); } // 'read_silent' command clause if(!strncasecmp(command, READ_SILENT_COMMAND, strlen(READ_SILENT_COMMAND))) { char filePathToRead[BUFFER_LENGTH]; char fileToReadBuffer[BUFFER_LENGTH]; FILE* fileToRead = NULL; if(sscanf(command + strlen(READ_SILENT_COMMAND), "%s", filePathToRead) != 1) { printCommandFileError("No file to read specified", commandFilePath, commandFileLineNumber); return; } if((fileToRead = fopen(filePathToRead, "r")) == NULL) { printCommandFileError("Unable to open the specified file", commandFilePath, commandFileLineNumber); return; } while(fgets(fileToReadBuffer, BUFFER_LENGTH, fileToRead) != NULL); fclose(fileToRead); } // 'write' command clause else if(!strncasecmp(command, WRITE_COMMAND, strlen(WRITE_COMMAND))) { char filePathToWrite[BUFFER_LENGTH]; char message[BUFFER_LENGTH]; FILE* fileToWrite = NULL; if(sscanf(command + strlen(WRITE_COMMAND), "%s %s", filePathToWrite, message) != 2) { printCommandFileError("No file and/or message to write specified", commandFilePath, commandFileLineNumber); return; } if((fileToWrite = fopen(filePathToWrite, "w")) == NULL) { printCommandFileError("Unable to open the specified file", commandFilePath, commandFileLineNumber); return; } if(fprintf(fileToWrite, "%s\n", message) < 0) { printCommandFileError("Unable to write to the specified file", commandFilePath, commandFileLineNumber); return; } fclose(fileToWrite); } // 'write_bytes' command clause else if(!strncasecmp(command, WRITE_BYTES_COMMAND, strlen(WRITE_BYTES_COMMAND))) { char filePathToWrite[BUFFER_LENGTH]; int fileToWriteSize = -1; int bytesCounter = 0; FILE* fileToWrite = NULL; char bytesBuffer[BUFFER_LENGTH + 1] = "00000000000000000000000000000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000000000000000000000000000" "0000000000000000"; if(sscanf(command + strlen(WRITE_BYTES_COMMAND), "%s %d", filePathToWrite, &fileToWriteSize) != 2) { printCommandFileError("No file and/or file to write size specified", commandFilePath, commandFileLineNumber); return; } if((fileToWrite = fopen(filePathToWrite, "w")) == NULL) { printCommandFileError("Unable to open the specified file", commandFilePath, commandFileLineNumber); return; } if(fileToWriteSize <= 0) { printCommandFileError("Illegal file to write size", commandFilePath, commandFileLineNumber); return; } for(bytesCounter = 0; bytesCounter < (double)fileToWriteSize / BUFFER_LENGTH; bytesCounter ++) { if(fprintf(fileToWrite, "%s", bytesBuffer) < 0) { printCommandFileError("Unable to write to the specified file", commandFilePath, commandFileLineNumber); return; } } fclose(fileToWrite); } // 'wait' command clause else if(!strncasecmp(command, WAIT_COMMAND, strlen(WAIT_COMMAND))) { int secondsToWait = 0; if(sscanf(command + strlen(WAIT_COMMAND), "%d", &secondsToWait) != 1) printCommandFileError("No number of seconds to wait specified", commandFilePath, commandFileLineNumber); sleep(secondsToWait); } // 'readSocket' command clause else if(!strncasecmp(command, READ_SOCKET_COMMAND, strlen(READ_SOCKET_COMMAND))) { struct sockaddr_in clientAddress; char buffer[BUFFER_LENGTH]; int clientLength = sizeof(clientAddress); int bytesRead = -1; int clientSocketDescriptor = accept(*serverSocketDescriptor, (struct sockaddr*) &clientAddress, &clientLength); if(clientSocketDescriptor < 0) { printCommandFileError("Failed to accept a socket from remote " "client", commandFilePath, commandFileLineNumber); return; } bzero(buffer, BUFFER_LENGTH); bytesRead = read(clientSocketDescriptor, buffer, (BUFFER_LENGTH - 1)); close(clientSocketDescriptor); if(bytesRead < 0) { printCommandFileError("Failed to read from the socket", commandFilePath, commandFileLineNumber); return; } commandFileLoop(buffer, commandFilePath, commandFileLineNumber, serverSocketDescriptor, serverPortNumber, fileToOpen); } // 'writeSocket' command clause else if(!strncasecmp(command, WRITE_SOCKET_COMMAND, strlen(WRITE_SOCKET_COMMAND))) { char remoteServerName[BUFFER_LENGTH]; char message[BUFFER_LENGTH]; struct sockaddr_in remoteServerAddress; struct hostent* remoteServer; int remoteServerPort = -1; int socketToWriteDescriptor = -1; int bytesWritten = -1; int remoteServerPortLength = -1; const char* remoteCommandBase = NULL; if(sscanf(command + strlen(WRITE_SOCKET_COMMAND), "%s %d %s", remoteServerName, &remoteServerPort, message) != 3) { printCommandFileError("No remote server name and/or port and/or " "message to write specified", commandFilePath, commandFileLineNumber); return; } socketToWriteDescriptor = socket(AF_INET, SOCK_STREAM, 0); if(socketToWriteDescriptor < 0) { printCommandFileError("Unable to open a socket", commandFilePath, commandFileLineNumber); return; } if((remoteServer = gethostbyname(remoteServerName)) == NULL) { printCommandFileError("No such host", commandFilePath, commandFileLineNumber); close(socketToWriteDescriptor); return; } bzero((char*) &remoteServerAddress, sizeof(remoteServerAddress)); remoteServerAddress.sin_family = AF_INET; bcopy((char*)remoteServer->h_addr, (char*)&remoteServerAddress.sin_addr.s_addr, remoteServer->h_length); remoteServerAddress.sin_port = htons(remoteServerPort); if(connect(socketToWriteDescriptor, (struct sockaddr *)&remoteServerAddress, sizeof(remoteServerAddress)) < 0) { printCommandFileError("Unable to connect to remote server", commandFilePath, commandFileLineNumber); close(socketToWriteDescriptor); return; } remoteServerPortLength = (int)log10(remoteServerPort) + 1; remoteCommandBase = command + strlen(WRITE_SOCKET_COMMAND) + 1 + strlen(remoteServerName) + 1 + remoteServerPortLength + 1; if((bytesWritten = write(socketToWriteDescriptor, remoteCommandBase, strlen(remoteCommandBase))) < 0) { printCommandFileError("Unable to write to the remote server", commandFilePath, commandFileLineNumber); close(socketToWriteDescriptor); return; } close(socketToWriteDescriptor); } // 'bind' command clause else if(!strncasecmp(command, BIND_COMMAND, strlen(BIND_COMMAND))) { struct sockaddr_in serverAddress; if(sscanf(command + strlen(BIND_COMMAND), "%d", serverPortNumber) != 1) printError("No command port specified"); *serverSocketDescriptor = socket(AF_INET, SOCK_STREAM, 0); if (*serverSocketDescriptor < 0) printError("Failed to open a socket"); bzero((char*) &serverAddress, sizeof(serverAddress)); serverAddress.sin_family = AF_INET; serverAddress.sin_addr.s_addr = INADDR_ANY; serverAddress.sin_port = htons(*serverPortNumber); if (bind(*serverSocketDescriptor, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) < 0) printError("Failed to bind to the chosen port"); listen(*serverSocketDescriptor, PENDING_QUEUE_LENGTH); } // 'open' command clause else if(!strncasecmp(command, OPEN_COMMAND, strlen(OPEN_COMMAND))) { char filePathToOpen[BUFFER_LENGTH]; if(sscanf(command + strlen(OPEN_COMMAND) + 1, "%s", filePathToOpen) != 1) { printCommandFileError("No file to open specified", commandFilePath, commandFileLineNumber); return; } if((*fileToOpen = fopen(filePathToOpen, "w")) == NULL) { printCommandFileError("Unable to open the specified file", commandFilePath, commandFileLineNumber); return; } } // 'flush' command clause else if(!strncasecmp(command, FLUSH_COMMAND, strlen(FLUSH_COMMAND))) { char message[BUFFER_LENGTH]; if(*fileToOpen == NULL) { printCommandFileError("No file was opened to flush a data into it", commandFilePath, commandFileLineNumber); return; } if(sscanf(command + strlen(FLUSH_COMMAND) + 1, "%s", message) != 1) { printCommandFileError("No message to flush specified", commandFilePath, commandFileLineNumber); fclose(*fileToOpen); *fileToOpen = NULL; return; } if(fprintf(*fileToOpen, "%s\n", message) < 0) { printCommandFileError("Unable to flush the message into the " "specified file", commandFilePath, commandFileLineNumber); fclose(*fileToOpen); *fileToOpen = NULL; return; } fflush(*fileToOpen); fclose(*fileToOpen); *fileToOpen = NULL; } // 'date' command clause else if(!strncasecmp(command, DATE_COMMAND, strlen(DATE_COMMAND))) { time_t currentTime = time(NULL); printf("%s", ctime(¤tTime)); fflush(stdout); } // 'nop' command clause else if(!strncasecmp(command, NOP_COMMAND, strlen(NOP_COMMAND))) { } // 'exit' command clause else if(!strncasecmp(command, EXIT_COMMAND, strlen(EXIT_COMMAND))) { printf("Exiting\n"); exit(0); } } /* Function : main * Arguments : argv[1] - the commands file path * Return value: success/failure value * Usage : TestServer * Description : test server program; it receives the commands file path as * an argument and runs its commands. The commands might be one * of the following types: * read - read the content of the given file and * print it to the standard output * read_silent - just read the content of the given file * write - write message to the given * file * write_bytes - write bytes number * of symbols to the specified path * wait - wait the specified number of * seconds * readSocket - read the message, sent to the command socket * and execute it * writeSocket - * write the specified message to the address, specified by * the receiving server name and port, to execution by the * remote server * bind - bind this server to the specified port; * the command file must start with this * command * open - opens the give file, but does not close * it * flush - flushes the given message into the file, * opened by means of 'open' command and * closes the file * date - outputs the current time and date * nop - do nothing * exit - successfully exit the program */ int main(int argc, char *argv[]) { FILE* commandFile = NULL; // file that is to be opened and flushed during server cycles FILE* fileToOpen = NULL; char commandBuffer[BUFFER_LENGTH]; //struct sockaddr_in serverAddress;//, clientAddress; int commandFileLineNumber = 0; int serverSocketDescriptor = -1;//, clientSocketDescriptor = -1; int serverPortNumber = -1; //int clientLength; //int bytesRead = -1, bytesWritten = -1; if(argc < 2) printError("No configuration file provided\n" "Usage: TestServer "); if((commandFile = fopen(argv[1], "r")) == NULL) printError("Unable to open the configuration file"); while(fgets(commandBuffer, BUFFER_LENGTH, commandFile) != NULL) { commandFileLineNumber ++; commandFileLoop(commandBuffer, argv[1], commandFileLineNumber, &serverSocketDescriptor, &serverPortNumber, &fileToOpen); } // Finalizing the server structures fclose(commandFile); close(serverSocketDescriptor); return 0; }