void handleRequest(void* ptr){ struct targs* args = ptr; int sock, copied; time_t seconds; char buf[4096]; char packets[10][4096]; char packet[8192]; int packetIndex; strcpy(packet, ""); sock = args -> newSock; //read in data recv(sock, buf, sizeof(buf), 0); int x; strcat(packet, buf); for(x=0;x<4096;x++)buf[x] = 0; int keepalive = 1; do{ packetIndex = -1; //read whatever is on the socket fully while(copied = recv(sock, buf, sizeof(buf), MSG_DONTWAIT) > 0){ int i; strcat(packet, buf); for(i=0;i<4096;i++)buf[i] = 0; } //extract data from packet if(strlen(packet) > 0){ char packetsCop[8192]; strcpy(packetsCop, packet); //split the received data into packets char* token = strtok(packetsCop, "\n"); while(token != NULL){ int e = strlen(token); if(strstr(token, "HTTP/") != NULL){ packetIndex += 1; strcpy( packets[packetIndex], ""); } strcat(packets[packetIndex], token); strcat(packets[packetIndex], "\n"); token = strtok(NULL, "\n"); } int t; //iterate throught each packet and process appropriately for(t = 0; t <= packetIndex; t++){ //update our timeout seconds = time(NULL); char method[2048]; char http[512]; //check if the method is ok if(methodOk(packets[t], method) < 0){ sendBad(sock, method, 0); //send 400: invalid method keepalive = 0; } //check if the http version is ok else if(httpOk(packets[t], http) < 0){ sendBad(sock, http, 2); //send 400: invalid http version keepalive = 0; } else{ //check whether or not we want to keep the connection open getKeepAlive(packets[t], (int*)&keepalive); char fileName[4096]; int status; //get the file name from the packet and do additional processing status = getFileName(packets[t], fileName); //determine what to do with packet if(status == 200){ sendFile(sock, fileName, keepalive); } else if(status == 404){ sendNotFound(sock, fileName); keepalive = 0; } else if(status == 400){ sendBad(sock, fileName, 1); keepalive = 0; } else if(status == 501){ sendBad(sock, fileName, 3); keepalive = 0; } } } int r; for(r=0;r<packetIndex;r++)packets[r][0] = 0; } int i; for(i=0;i<sizeof(packet);i++)packet[i] = 0; strcpy(packet, ""); }while(keepalive && ((time(NULL)) - (seconds) < 10)); close(sock); free(args); pthread_exit((void*)(0)); }
/*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; }