/*Handle Client Request Function Variable Definition: -- client_socket: socket connected to the client Return Value: NULL */ void handleClientRequest(int client_socket) { FILE *channel; //file stream for client socket char request_line[STRING_SIZE]; //client request line char *return_value; //each line header pointer //Initialize request_line buffer memset(request_line, 0, STRING_SIZE); //Create an input stream from the socket channel = fdopen(client_socket, "r"); if (channel == NULL) { dieWithSystemMessage("fdopen() failed"); } //Get client Request Line (Jump the blank line) do { return_value = fgets(request_line, STRING_SIZE, channel); } while (syntaxChecking(return_value, BLANK_LINE)); //Output the client_socket id and Request Line printf("Got a call on %d: request = %s", client_socket, request_line); //Get client Header Lines & Response the client request respondClientRequest(request_line, getHeaderLines(channel), client_socket); //Close client socket close(client_socket); //Close file stream fclose(channel); return; }
bool headerLinesIncorrect(RTSP_HEADER *header, char *field_value){ RTSP_HEADER *node; for (node = header->next; node != NULL; node = node->next) { //Use regular expression to check header lines' syntax if (!syntaxChecking(node->header_line, HEADER_LINE)) { sprintf(field_value, "Header line: [%s] is syntacically incorrect!", node->header_line); return true; } } return false; }
/*Respond Client Request Function Variable Definition: -- request: client request line -- header: client header lines -- client_socket: socket connected to the client Return Value: NULL */ void respondClientRequest(char *request, RTSP_HEADER *header, int client_socket) { char method[STRING_SIZE]; //method field: SETUP, PLAY, PAUSE, or TEARDOWN char url[STRING_SIZE]; //url field: for example, rtsp://localhost:5678/movie.Mjpeg char version[STRING_SIZE]; //rtsp version field: RTSP/1.0 char field_value[HALFBUF_SIZE]; //field value string u_int32 cseq_number = 0; //cseq number //Initialize method, url, version, and field_value buffer memset(method, 0, STRING_SIZE); memset(url, 0, STRING_SIZE); memset(version, 0, STRING_SIZE); memset(field_value, 0, HALFBUF_SIZE); //Test the client RTSP Request Line if (!syntaxChecking(request, REQUEST_LINE)) { //400 Bad Request: the request could not be understood by the server sendBadRequest("Request Line is syntactically incorrect!", client_socket); return; } //Get the method, url, and rtsp version sscanf(request, "%s%s%s", method, url, version); //Decode the URL(if it has %HEX code) decodeURL(url); //Test the method if (methodNotAllow(method)) { //405 Method Not Allowed: the method field is neither "SETUP", "PLAY", "PAUSE" nor "TEARDOWN" sendMethodNotAllowed(method, client_socket); return; } //Test the Requested URL else if (!syntaxChecking(url, URL_FORMAT)) { //400 Bad Request: the request could not be understood by the server sendBadRequest("Requested URL is syntactically incorrect!", client_socket); return; } //Test the RTSP version else if (!syntaxChecking(version, RTSP_VERSION)) { //400 Bad Request: the request could not be understood by the server sendBadRequest("RTSP Version is syntactically incorrect!", client_socket); return; } //Test the RTSP version 1.0 else if (!syntaxChecking(version, RTSP_VERSION_1)) { //505 RTSP Version Not Supported: the requested RTSP protocol version is not supported by server sendRTSPVersionNotSupported(version, client_socket); return; } #ifdef DEBUG RTSP_HEADER *debug_header_node; DEBUG_START; fputs("RTSP request header lines:\n", stdout); //Output the RTSP request header lines for (debug_header_node = header->next; debug_header_node != NULL; debug_header_node = debug_header_node->next) { fputs(debug_header_node->field_name, stdout); fputs(": ", stdout); fputs(debug_header_node->field_value, stdout); fputc('\n', stdout); } DEBUG_END; #endif //Test the Header Line if (headerLinesIncorrect(header, field_value)) { //400 Bad Request: the request could not be understood by the server sendBadRequest(field_value, client_socket); return; } //Test the "CSeq" field else if (fieldNotExist(header, "cseq", field_value)) { //400 Bad Request: the request could not be understood by the server sendBadRequest("CSeq field does not exist!", client_socket); return; } //Test the "Session" field else if ((!methodIsSetup(method)) && fieldNotExist(header, "session", field_value)) { //400 Bad Request: the request could not be understood by the server sendBadRequest("Session field does not exist!", client_socket); return; } //Test the "Transport" field else if (methodIsSetup(method) && fieldNotExist(header, "transport", field_value)) { //400 Bad Request: the request could not be understood by the server sendBadRequest("Transport field does not exist!", client_socket); return; } //Test the "Range" field else if ((!(fieldNotExist(header, "range", field_value))) && (!syntaxChecking(field_value, RANGE_FORMAT))) { //400 Bad Request: the request could not be understood by the server sendBadRequest("Range field value(npt=number[-number]) is syntactically incorrect!", client_socket); return; } //Test the "If-Modified-Since" field else if ((!(fieldNotExist(header, "if-modified-since", field_value))) && (!syntaxChecking(field_value, TIME_FORMAT))) { //400 Bad Request: the request could not be understood by the server sendBadRequest("If-Modified-Since field value(time format) is syntactically incorrect!", client_socket); return; } //Now we are sure that the request message is SYNTACTICALLY CORRECT //Get the Requested File or Directory's name pathBelowCurrentDirectory(url); printf("Requested File or Directory is %s\n", url); //Test the requested file on the server if (urlNotExist(url)) { //404 Not Found: the requested document does not exist on this server sendNotFound(url, client_socket); return; } //Test the requested url is a directory else if (urlIsADirectory(url)) { //404 Not Found: the requested document does not exist on this server sendNotFound(url, client_socket); return; } //Test the method is valid in special state else if (methodIsNotValidInState(method)) { //455 Method is not valid in this state: the method is not valid in this state sendMethodNotValidInThisState(method, client_socket); return; } //Get the RTSP Request Message information cseq_number = getRTSPInfo(header); //Test the "Session" field's value if (cseq_number == 0) { //454 Session Not Found: the session id is not equal to the server's sendSessionNotFound(client_socket); return; } //Test the protocol type else if (strcmp(protocol_type, PROTOCOL_TYPE) != 0) { //461 Unsupported Transport: the transport protocol is not supported by the server sendUnsupportedTransport(protocol_type, client_socket); return; } //Test the "If-Modified-Since" field else if (fieldNotExist(header, "if-modified-since", field_value)) { //200 OK: the request is good sendOK(url, method, cseq_number, client_socket); return; } //Test the "If-Modified-Since" field value else if (compareModifiedTime(url, field_value)) { //304 Not Modified: the request does not Modified since If-Modified-Since field sendNotModified(url, cseq_number, client_socket); return; } else { //200 OK: the request is good sendOK(url, method, cseq_number, client_socket); return; } }
/*Respond Client Request Function Variable Definition: -- request: client request line -- header: client header lines -- client_socket: socket connected to the client Return Value: NULL */ void respondClientRequest(char *request, struct http_header *header, int client_socket){ char method[STRING_SIZE]; //method field: GET or HEAD char url[STRING_SIZE]; //url field: /TestServer char version[STRING_SIZE]; //http version field: HTTP/1.1 char field_value[HALFBUF_SIZE]; //field value string bool modified_signal; //whether if-modified-since field exist //Initialize method, url and version buffer memset(method, 0, STRING_SIZE); memset(url, 0, STRING_SIZE); memset(version, 0, STRING_SIZE); memset(field_value, 0, HALFBUF_SIZE); //Test the client HTTP Request Line if (!syntaxChecking(request, 'R')){ //400 Bad Request: the request could not be understood by the server sendBadRequest("Request Line is syntactically incorrect!", client_socket); return; } //Get the method, url, and http version // NC: i don't think this works: need sscanf(request, "%s %s %s", method, url, version); sscanf(request, "%s%s%s", method, url, version); //Decode the URL(if it has %HEX code) decodeURL(url); //Test the method if ((strcmp(method, "GET") != 0) && (strcmp(method, "HEAD") != 0)){ //405 Method Not Allowed: the method field is neither "GET" nor "HEAD" sendMethodNotAllowed(method, client_socket); return; } //Test the Requested URL else if (!syntaxChecking(url, 'U')){ // NC: but, "the only legal Request-URI is the abs_path “/TestServer”. Generate a 404 Response to all other Request-URIs." // #17: -1 //400 Bad Request: the request could not be understood by the server sendBadRequest("Requested URL is syntactically incorrect!", client_socket); return; } //Test the HTTP version else if (!syntaxChecking(version, 'V')){ //400 Bad Request: the request could not be understood by the server sendBadRequest("HTTP Version is syntactically incorrect!", client_socket); return; } else if (!syntaxChecking(version, 'O')){ //505 HTTP Version Not Supported: the requested HTTP protocol version is not supported by server sendHTTPVersionNotSupported(version, client_socket); return; } //Test the Header Line if (headerLinesIncorrect(header, field_value)){ //400 Bad Request: the request could not be understood by the server sendBadRequest(field_value, client_socket); return; } //Test the "Host" field else if (fieldNotExist(header, "host", field_value)){ //400 Bad Request: the request could not be understood by the server sendBadRequest("Host field does not exist!", client_socket); return; } else if (!syntaxChecking(field_value, 'I')){ //400 Bad Request: the request could not be understood by the server sendBadRequest("Host field value(domain name, IP address, or port format) is syntactically incorrect!", client_socket); return; } //Test the "If-Modified-Since" field else if ((!(modified_signal = fieldNotExist(header, "if-modified-since", field_value))) && (!syntaxChecking(field_value, 'T'))){ //400 Bad Request: the request could not be understood by the server sendBadRequest("If-Modified-Since field value(time format) is syntactically incorrect!", client_socket); return; } //Now we are sure that the request message is SYNTACTICALLY CORRECT //Get the Requested File or Directory's name pathBelowCurrentDirectory(url); printf("Requested File or Directory is %s\n", url); // NC: but OUR server doesn't do this //Test the requested file on the server if (urlNotExist(url)){ //404 Not Found: the requested document does not exist on this server sendNotFound(url, client_socket); } else if (urlIsADirectory(url)){ //List the File Name of Directory sendFileNameInDirectory(url, method, client_socket); } else if (modified_signal){ //200 OK: the request is good sendOK(url, method, client_socket); } else if (compareModifiedTime(url, field_value)){ //304 Not Modified: the request does not Modified since If-Modified-Since field sendNotModified(url, client_socket); } else{ //200 OK: the request is good sendOK(url, method, client_socket); } return; }