/** * @brief - Decoding string line as a status line * * @param p_start_line * @param rtsp_msg_buffer * @param rtsp_msg_len * * @return */ static inline rtsp_error_t rtsp_parse_status_line(rtsp_start_line_t *p_start_line,const char *rtsp_msg_buffer, int32_t rtsp_msg_len , const char **endptr){ const char *parse_string = NULL, *end = NULL, *temp = NULL; rtsp_error_t e_ret_val = RTSP_E_FAILURE; if(!p_start_line || !rtsp_msg_buffer || rtsp_msg_len <= 0){ return (RTSP_E_INVALID_ARG); } /* R[7.1] * Status-Line = RTSP-Version SP Status-Code SP Reason-Phrase CRLF * Allowing multiple SP since RFC Text R[7.1] suggests */ parse_string = rtsp_msg_buffer; end = rtsp_msg_buffer + rtsp_msg_len; /* RTSP-Version */ e_ret_val = rtsp_get_version(&p_start_line->version, parse_string, rtsp_msg_len, &parse_string); switch (e_ret_val){ case RTSP_E_SUCCESS: /* Found Version String Start Hence it is status line */ p_start_line->msg_type = RTSP_MSG_RESPONSE; /* SP */ temp = skip_SP(parse_string, end); if((NULL == temp) || (temp==parse_string)){ /* No spaces */ e_ret_val = RTSP_E_FAILURE; }else if(temp == end){ /* Only spaces till end */ e_ret_val = RTSP_E_INCOMPLETE; break; } parse_string = temp; /* Status-Code */ if((parse_string + RTSP_STATUS_CODE_LEN) <= end){ if(0 == (p_start_line->response.status_code = RTSP_STATUS_CODE(parse_string))){ e_ret_val = RTSP_E_FAILURE; break; } } else { e_ret_val = RTSP_E_INCOMPLETE; break; } parse_string += RTSP_STATUS_CODE_LEN; /* SP */ temp = skip_SP(parse_string, end); if((NULL == temp) || (temp==parse_string)){ /* No spaces */ e_ret_val = RTSP_E_FAILURE; }else if(temp==end){ /* Only spaces till end */ e_ret_val = RTSP_E_INCOMPLETE; break; } parse_string = temp; /* Reason-Phrase */ p_start_line->response.reason_phrase = parse_string; while((parse_string <= end) && is_text(*parse_string)) parse_string++; ; /* CRLF */ if((parse_string+1) <= end){ if(RTSP_CR == *parse_string++ && RTSP_LF ==*parse_string++){ p_start_line->response.reason_len = (int32_t)((rtsp_msg_buffer - parse_string)+ rtsp_msg_len); } else { e_ret_val = RTSP_E_FAILURE; break; } } else { e_ret_val = RTSP_E_INCOMPLETE; break; } if(endptr) *endptr = parse_string; e_ret_val = RTSP_E_SUCCESS; break; case RTSP_E_UNSUPPORTED: /* Version Not supported */ case RTSP_E_FAILURE: default: /* Must Be Request-Line */ break; } return (e_ret_val); }
static inline rtsp_error_t rtsp_parse_request_line(rtsp_start_line_t *p_start_line, const char *rtsp_msg_buffer, int32_t rtsp_msg_len, const char **endptr){ const char *parse_string = rtsp_msg_buffer; const char *end = rtsp_msg_buffer + rtsp_msg_len; const char *temp = NULL; rtsp_error_t e_ret_val = RTSP_E_FAILURE; if(!p_start_line || !rtsp_msg_buffer || rtsp_msg_len <= 0){ return (RTSP_E_INVALID_ARG); } /* R[6.1] * Request-Line = Method SP Request-URI SP RTSP-Version CRLF * Allowing multiple SP since RFC Text H[5.1] suggests */ e_ret_val = rtsp_get_method(&p_start_line->request.method, parse_string, rtsp_msg_len, &parse_string); if(e_ret_val != RTSP_E_SUCCESS ){ return (e_ret_val); } /* Found valid Method Hence it is request line */ p_start_line->msg_type = RTSP_MSG_REQUEST; /* SP */ temp = skip_SP(parse_string, end); if((NULL == temp) || (temp==parse_string)){ /* No spaces */ e_ret_val = RTSP_E_FAILURE; return(e_ret_val); }else if(temp==end){ /* Only spaces till end */ e_ret_val = RTSP_E_INCOMPLETE; return(e_ret_val); } parse_string = temp; /* Request-URI */ e_ret_val = rtsp_get_url(&p_start_line->request.url ,parse_string, (rtsp_msg_len - (parse_string - rtsp_msg_buffer)), &parse_string); if(e_ret_val != RTSP_E_SUCCESS){ ERR_LOG("Failed to parse URI"); return (e_ret_val); } /* SP */ temp = skip_SP(parse_string, end); if((NULL == temp) || (temp==parse_string)){ /* No spaces */ e_ret_val = RTSP_E_FAILURE; return(e_ret_val); }else if(temp==end){ /* Only spaces till end */ e_ret_val = RTSP_E_INCOMPLETE; return(e_ret_val); } parse_string = temp; /* RTSP-Version */ e_ret_val = rtsp_get_version(&p_start_line->version, parse_string, (rtsp_msg_len - (parse_string - rtsp_msg_buffer)) , &parse_string); if(e_ret_val != RTSP_E_SUCCESS){ return (e_ret_val); } /* CRLF */ if((parse_string+2) < end){ if((*parse_string++ == RTSP_CR) && (*parse_string++ == RTSP_LF)){ e_ret_val = RTSP_E_SUCCESS; } else { e_ret_val = RTSP_E_FAILURE; } } else { e_ret_val = RTSP_E_INCOMPLETE; } if(endptr) *endptr = parse_string; return (e_ret_val); }
static void rtsp_server_handle(struct rtsp_server_request_t *req, void* parser) { int major, minor; const char* uri; const char* method; req->parser = parser; rtsp_get_version(parser, &major, &minor); if(1 != major && 0 != minor) { //505 RTSP Version Not Supported rtsp_server_reply(req, 505); return; } if(0 != rtsp_get_header_by_name2(parser, "CSeq", (int*)&req->cseq)) { // 400 Bad Request rtsp_server_reply(req, 400); return; } uri = rtsp_get_request_uri(parser); method = rtsp_get_request_method(parser); switch(*method) { case 'o': case 'O': if(0 == stricmp("OPTIONS", method)) { rtsp_server_options(req, parser, uri); return; } break; case 'd': case 'D': if(0 == stricmp("DESCRIBE", method)) { rtsp_server_describe(req, parser, uri); return; } break; case 's': case 'S': if(0 == stricmp("SETUP", method)) { rtsp_server_setup(req, parser, uri); return; } break; case 'p': case 'P': if(0 == stricmp("PLAY", method)) { rtsp_server_play(req, parser, uri); return; } else if(0 == stricmp("PAUSE", method)) { rtsp_server_pause(req, parser, uri); return; } break; case 't': case 'T': if(0 == stricmp("TEARDOWN", method)) { rtsp_server_teardown(req, parser, uri); return; } break; } // 501 Not implemented rtsp_server_reply(req, 501); }