/*************************************************************************************** * * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. * * By downloading, copying, installing or using the software you agree to this license. * If you do not agree to this license, do not download, install, * copy or use the software. * * Copyright (C) 2014-2024, Happytimesoft Corporation, all rights reserved. * * Redistribution and use in binary forms, with or without modification, are permitted. * * Unless required by applicable law or agreed to in writing, software distributed * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific * language governing permissions and limitations under the License. * ****************************************************************************************/ #include "sys_inc.h" #include "http.h" #include "http_parse.h" #include "sys_buf.h" typedef struct { HTTP_MT msg_type; char msg_str[32]; int msg_len; } REQMTV; static const REQMTV req_mtvs[] = { {HTTP_MT_GET, "GET", 3}, {HTTP_MT_POST, "POST", 4}, {HTTP_MT_HEAD, "HEAD", 4}, {HTTP_MT_MPOST, "M-POST", 6}, {HTTP_MT_MSEARCH, "M-SEARCH", 8}, {HTTP_MT_NOTIFY, "NOTIFY", 6}, {HTTP_MT_SUBSCRIBE, "SUBSCRIBE", 9}, {HTTP_MT_UNSUBSCRIBE, "UNSUBSCRIBE", 11} }; HT_API BOOL http_is_http_msg(char * msg_buf) { uint32 i; for (i=0; i 0 && word_len < 31) { memcpy(p_msg->first_line.header, pline, word_len); p_msg->first_line.header[word_len] = '\0'; while (pline[next_word_offset] == ' ') { next_word_offset++; } p_msg->first_line.value_string = pline+next_word_offset; if (strcasecmp(word_buf,"HTTP/1.1") == 0 || strcasecmp(word_buf,"HTTP/1.0") == 0) { if (bHaveNextWord) { bHaveNextWord = GetLineWord(pline, next_word_offset, llen, word_buf, sizeof(word_buf), &next_word_offset, WORD_TYPE_NUM); word_len = (int)strlen(word_buf); if (word_len > 0) { p_msg->msg_type = 1; p_msg->msg_sub_type = atoi(word_buf); } } } else { uint32 i; p_msg->msg_type = 0; for (i=0; imsg_sub_type = req_mtvs[i].msg_type; break; } } } } } HT_API int http_line_parse(char * p_buf, int max_len, char sep_char, PPSN_CTX * p_ctx) { char word_buf[256]; BOOL bHaveNextLine = TRUE; int line_len = 0; int parse_len = 0; char * ptr = p_buf; do { int next_word_offset = 0; char nchar; HDRV * pHdrV; if (GetSipLine(ptr, max_len, &line_len, &bHaveNextLine) == FALSE) { log_print(HT_LOG_ERR, "%s, get sip line error!!!\r\n", __FUNCTION__); return -1; } if (line_len == 2) { return (parse_len + 2); } GetLineWord(ptr, 0, line_len-2, word_buf, sizeof(word_buf), &next_word_offset, WORD_TYPE_STRING); while (ptr[next_word_offset] == ' ') { next_word_offset++; } nchar = *(ptr + next_word_offset); if (nchar != sep_char) // SIP is ':',SDP is '=' { log_print(HT_LOG_ERR, "%s, format error!!!\r\n", __FUNCTION__); return -1; } next_word_offset++; while (ptr[next_word_offset] == ' ') { next_word_offset++; } pHdrV = hdrv_buf_get_idle(); if (pHdrV == NULL) { log_print(HT_LOG_ERR, "%s, hdrv_buf_get_idle return NULL!!!\r\n", __FUNCTION__); return -1; } strncpy(pHdrV->header, word_buf, 32); pHdrV->value_string = ptr+next_word_offset; pps_ctx_ul_add(p_ctx, pHdrV); ptr += line_len; max_len -= line_len; parse_len += line_len; } while (bHaveNextLine); return parse_len; } HT_API BOOL http_get_headline_uri(HTTPMSG * rx_msg, char * p_uri, int size) { int len; char * p_end; char * p_ptr = rx_msg->first_line.value_string; if (p_ptr == NULL) { return FALSE; } p_end = p_ptr; while (*p_end != ' ') p_end++; len = (int) (p_end - p_ptr); if (len >= size) { return FALSE; } memcpy(p_uri, p_ptr, len); p_uri[len] = '\0'; return TRUE; } HT_API int http_ctt_parse(HTTPMSG * p_msg) { int flag = 0; HTTPCTT w_ctx_type; HDRV * pHdrV = (HDRV *)pps_lookup_start(&(p_msg->hdr_ctx)); while (pHdrV != NULL) { if (strcasecmp(pHdrV->header, "Content-Length") == 0) { p_msg->ctt_len = atol(pHdrV->value_string); flag++; } else if (strcasecmp(pHdrV->header, "Content-Type") == 0) { char type_word[64]; int next_tmp; GetLineWord(pHdrV->value_string, 0, (int)strlen(pHdrV->value_string), type_word, sizeof(type_word), &next_tmp, WORD_TYPE_STRING); if (strcasecmp(type_word, "application/sdp") == 0) { w_ctx_type = CTT_SDP; } else if (strcasecmp(type_word, "application/soap+xml") == 0 || strcasecmp(type_word, "text/xml") == 0) { w_ctx_type = CTT_XML; } else if (strcasecmp(type_word, "text/plain") == 0) { w_ctx_type = CTT_TXT; } else if (strcasecmp(type_word, "text/html") == 0) { w_ctx_type = CTT_HTM; } else if (strcasecmp(type_word, "application/octet-stream") == 0) { w_ctx_type = CTT_BIN; } else if (strcasecmp(type_word, "image/jpeg") == 0) { w_ctx_type = CTT_JPG; } else if (strcasecmp(type_word, "application/x-rtsp-tunnelled") == 0) { w_ctx_type = CTT_RTSP_TUNNELLED; } else if (strcasecmp(type_word, "multipart/x-mixed-replace") == 0) { char * boundary = NULL; w_ctx_type = CTT_MULTIPART; boundary = strstr(pHdrV->value_string, "boundary="); if (boundary) { int offset = 0; while (*(boundary+9+offset) == '-') { offset++; } strcpy(p_msg->boundary, boundary+9+offset); } } else if (strcasecmp(type_word, "video/x-flv") == 0) { w_ctx_type = CTT_FLV; } else { w_ctx_type = CTT_NULL; } p_msg->ctt_type = w_ctx_type; flag++; } pHdrV = (HDRV *)pps_lookup_next(&(p_msg->hdr_ctx), pHdrV); } pps_lookup_end(&(p_msg->hdr_ctx)); if (p_msg->ctt_type && p_msg->ctt_len) { return 1; } return 0; } HT_API int http_msg_parse(char * msg_buf, int msg_buf_len, HTTPMSG * msg) { BOOL bHaveNextLine; int line_len = 0; char * p_buf = msg_buf; msg->msg_type = (uint32) -1; if (GetSipLine(p_buf, msg_buf_len, &line_len, &bHaveNextLine) == FALSE) { return -1; } if (line_len > 0) { http_headl_parse(p_buf, line_len-2, msg); } if (msg->msg_type == (uint32) -1) { return -1; } p_buf += line_len; msg->hdr_len = http_line_parse(p_buf, msg_buf_len-line_len, ':', &(msg->hdr_ctx)); if (msg->hdr_len <= 0) { return -1; } p_buf += msg->hdr_len; if (http_ctt_parse(msg) == 1 && msg->ctt_len > 0) { int slen; HDRV * pHdrV; pHdrV = hdrv_buf_get_idle(); if (pHdrV == NULL) { log_print(HT_LOG_ERR, "%s, hdrv_buf_get_idle return NULL!!!\r\n", __FUNCTION__); return -1; } strcpy(pHdrV->header, ""); pHdrV->value_string = p_buf; pps_ctx_ul_add(&(msg->ctt_ctx), pHdrV); slen = (int)strlen(p_buf); if (slen != msg->ctt_len) { log_print(HT_LOG_ERR, "%s, text xml strlen[%d] != ctx len[%d]!!!\r\n", __FUNCTION__, slen, msg->ctt_len); } } return (line_len + msg->hdr_len + msg->ctt_len); } HT_API int http_msg_parse_part1(char * p_buf, int buf_len, HTTPMSG * msg) { BOOL bHaveNextLine; int line_len = 0; msg->msg_type = (uint32) -1; if (GetSipLine(p_buf, buf_len, &line_len, &bHaveNextLine) == FALSE) { return -1; } if (line_len > 0) { http_headl_parse(p_buf, line_len-2, msg); } if (msg->msg_type == (uint32) -1) { return -1; } p_buf += line_len; msg->hdr_len = http_line_parse(p_buf, buf_len-line_len, ':', &(msg->hdr_ctx)); if (msg->hdr_len <= 0) { return -1; } http_ctt_parse(msg); return (line_len + msg->hdr_len); } HT_API int http_msg_parse_part2(char * p_buf, int buf_len, HTTPMSG * msg) { int slen; HDRV * pHdrV; pHdrV = hdrv_buf_get_idle(); if (pHdrV == NULL) { log_print(HT_LOG_ERR, "%s, hdrv_buf_get_idle return NULL!!!\r\n", __FUNCTION__); return -1; } strcpy(pHdrV->header, ""); pHdrV->value_string = p_buf; pps_ctx_ul_add(&(msg->ctt_ctx), pHdrV); slen = buf_len; if (ctt_is_string(msg->ctt_type)) { slen = (int)strlen(p_buf); if (slen != msg->ctt_len) { log_print(HT_LOG_ERR, "%s, text xml strlen[%d] != ctx len[%d]!!!\r\n", __FUNCTION__, slen, msg->ctt_len); } } return slen; } HT_API HDRV * http_find_headline(HTTPMSG * msg, const char * head) { HDRV * line; if (msg == NULL || head == NULL) { return NULL; } line = (HDRV *)pps_lookup_start(&(msg->hdr_ctx)); while (line != NULL) { if (strcasecmp(line->header, head) == 0) { pps_lookup_end(&(msg->hdr_ctx)); return line; } line = (HDRV *)pps_lookup_next(&(msg->hdr_ctx), line); } pps_lookup_end(&(msg->hdr_ctx)); return NULL; } HT_API HDRV * http_find_headline_next(HTTPMSG * msg, const char * head, HDRV * hrv) { HDRV * line; if (msg == NULL || head == NULL) { return NULL; } line = (HDRV *)pps_lookup_start(&(msg->hdr_ctx)); while (line != NULL) { if (line == hrv) { line = (HDRV *)pps_lookup_next(&(msg->hdr_ctx), line); break; } line = (HDRV *)pps_lookup_next(&(msg->hdr_ctx), line); } while (line != NULL) { if (strcasecmp(line->header, head) == 0) { pps_lookup_end(&(msg->hdr_ctx)); return line; } line = (HDRV *)pps_lookup_next(&(msg->hdr_ctx), line); } pps_lookup_end(&(msg->hdr_ctx)); return NULL; } HT_API char * http_get_headline(HTTPMSG * msg, const char * head) { HDRV * p_hdrv = http_find_headline(msg, head); if (p_hdrv == NULL) { return NULL; } return p_hdrv->value_string; } void http_add_tx_line(HTTPMSG * tx_msg, const char * msg_hdr, const char * msg_fmt,...) { va_list argptr; int slen; HDRV *pHdrV; if (tx_msg == NULL || tx_msg->msg_buf == NULL) { return; } pHdrV = hdrv_buf_get_idle(); if (pHdrV == NULL) { log_print(HT_LOG_ERR, "%s, hdrv_buf_get_idle return NULL!!!\r\n", __FUNCTION__); return; } pHdrV->value_string = tx_msg->msg_buf + tx_msg->buf_offset; strncpy(pHdrV->header, msg_hdr, 31); va_start(argptr, msg_fmt); #if __LINUX_OS__ slen = vsnprintf(pHdrV->value_string, 1600-tx_msg->buf_offset, msg_fmt, argptr); #else slen = vsprintf(pHdrV->value_string, msg_fmt, argptr); #endif va_end(argptr); if (slen < 0) { log_print(HT_LOG_ERR, "%s, vsnprintf return %d !!!\r\n", __FUNCTION__, slen); hdrv_buf_free(pHdrV); return; } pHdrV->value_string[slen] = '\0'; tx_msg->buf_offset += slen + 1; pps_ctx_ul_add(&(tx_msg->hdr_ctx), pHdrV); } HT_API HDRV * http_find_ctt_headline(HTTPMSG * msg, const char * head) { HDRV * line; if (msg == NULL || head == NULL) { return NULL; } line = (HDRV *)pps_lookup_start(&(msg->ctt_ctx)); while (line != NULL) { if (strcasecmp(line->header, head) == 0) { pps_lookup_end(&(msg->ctt_ctx)); return line; } line = (HDRV *)pps_lookup_next(&(msg->ctt_ctx), line); } pps_lookup_end(&(msg->ctt_ctx)); return NULL; } HT_API char * http_get_ctt(HTTPMSG * msg) { HDRV * line; if (msg == NULL) { return NULL; } line = (HDRV *)pps_lookup_start(&(msg->ctt_ctx)); pps_lookup_end(&(msg->ctt_ctx)); if (line) { return line->value_string; } return NULL; } HT_API BOOL http_get_auth_digest_info(HTTPMSG * rx_msg, HD_AUTH_INFO * p_auth) { int len; int next_offset; char word_buf[128]; char * p; HDRV * res_line = http_find_headline(rx_msg, "Authorization"); if (res_line == NULL) { return FALSE; } GetLineWord(res_line->value_string, 0, (int)strlen(res_line->value_string), word_buf, sizeof(word_buf), &next_offset, WORD_TYPE_STRING); if (strcasecmp(word_buf, "digest") != 0) { return FALSE; } p = res_line->value_string+next_offset; len = (int)strlen(res_line->value_string)-next_offset; if (!GetNameValuePair(p, len, "username", p_auth->auth_name, sizeof(p_auth->auth_name))) { return FALSE; } if (!GetNameValuePair(p, len, "realm", p_auth->auth_realm, sizeof(p_auth->auth_realm))) { return FALSE; } if (!GetNameValuePair(p, len, "nonce", p_auth->auth_nonce, sizeof(p_auth->auth_nonce))) { return FALSE; } if (!GetNameValuePair(p, len, "uri", p_auth->auth_uri, sizeof(p_auth->auth_uri))) { return FALSE; } if (!GetNameValuePair(p, len, "response", p_auth->auth_response, sizeof(p_auth->auth_response))) { return FALSE; } if (!GetNameValuePair(p, len, "algorithm", p_auth->auth_algorithm, sizeof(p_auth->auth_algorithm))) { p_auth->auth_algorithm[0] = '\0'; } if (GetNameValuePair(p, len, "qop", p_auth->auth_qop, sizeof(p_auth->auth_qop))) { char * stop_string; if (!GetNameValuePair(p, len, "cnonce", p_auth->auth_cnonce, sizeof(p_auth->auth_cnonce))) { p_auth->auth_cnonce[0] = '\0'; } if (!GetNameValuePair(p, len, "nc", p_auth->auth_ncstr, sizeof(p_auth->auth_ncstr))) { p_auth->auth_ncstr[0] = '\0'; } p_auth->auth_nc = strtol(p_auth->auth_ncstr, &stop_string, 16); if (strlen(stop_string) > 0) { return FALSE; } } else { p_auth->auth_qop[0] = '\0'; p_auth->auth_cnonce[0] = '\0'; p_auth->auth_ncstr[0] = '\0'; p_auth->auth_nc = 0; } return TRUE; } /***********************************************************************/ static PPSN_CTX * msg_buf_fl = NULL; static int http_msg_buf_init_count = 0; HT_API BOOL http_msg_buf_init(int num) { http_msg_buf_init_count++; if (msg_buf_fl) { return TRUE; } msg_buf_fl = pps_ctx_fl_init(num, sizeof(HTTPMSG), TRUE); if (msg_buf_fl == NULL) { return FALSE; } return TRUE; } HT_API void http_msg_buf_deinit() { http_msg_buf_init_count--; if (http_msg_buf_init_count == 0) { if (msg_buf_fl) { pps_fl_free(msg_buf_fl); msg_buf_fl = NULL; } } if (http_msg_buf_init_count < 0)http_msg_buf_init_count = 0;//Reset } HT_API HTTPMSG * http_get_msg_buf(int size) { HTTPMSG * tx_msg = (HTTPMSG *)pps_fl_pop(msg_buf_fl); if (tx_msg == NULL) { log_print(HT_LOG_ERR, "%s, pop null!!!\r\n", __FUNCTION__); return NULL; } memset(tx_msg, 0, sizeof(HTTPMSG)); if (size > (int) net_buf_get_size()) { tx_msg->msg_buf = (char *)malloc(size); } else { tx_msg->msg_buf = net_buf_get_idle(); } if (tx_msg->msg_buf == NULL) { log_print(HT_LOG_ERR, "%s, net_buf_get_idle failed\r\n", __FUNCTION__); http_free_msg_buf(tx_msg); return NULL; } http_msg_ctx_init(tx_msg); return tx_msg; } HT_API void http_msg_ctx_init(HTTPMSG * msg) { pps_ctx_ul_init_nm(hdrv_buf_fl, &(msg->hdr_ctx)); pps_ctx_ul_init_nm(hdrv_buf_fl, &(msg->ctt_ctx)); } HT_API void http_free_msg_buf(HTTPMSG * msg) { pps_fl_push(msg_buf_fl, msg); } HT_API uint32 http_idle_msg_buf_num() { return msg_buf_fl->node_num; } HT_API void http_free_msg(HTTPMSG * msg) { if (msg == NULL) { return; } http_free_msg_content(msg); http_free_msg_buf(msg); } HT_API void http_free_msg_content(HTTPMSG * msg) { if (msg == NULL) { return; } http_free_msg_ctx(msg, 0); http_free_msg_ctx(msg, 1); net_buf_free(msg->msg_buf); } HT_API void http_free_msg_ctx(HTTPMSG * msg, int type) { PPSN_CTX * p_free_ctx = NULL; switch (type) { case 0: p_free_ctx = &(msg->hdr_ctx); break; case 1: p_free_ctx = &(msg->ctt_ctx); break; } if (p_free_ctx == NULL) { return; } hdrv_ctx_free(p_free_ctx); }