📄 rtsp_response.c
字号:
/*-------------------------------------------------------- COPYRIGHT 2007 (C) DVN (Holdings) Ltd (Hongkong) AUTHOR: wangry@dvnchina.com PURPOSE: kasenna simple rtsp lib CREATED: 2007-12-10 MODIFICATION HISTORY Date By Details ---------- ----- ---------------------------------------------------------------*/#include "rtsp_client.h"#include "rtsp_sock.h"#include "rtsp_response.h"#define SEPERATOR "\r\n"#define SKIP_SPACE(a) {while (isspace(*(a)) && (*(a) != '\0'))(a)++;}#define SET_DEC_FIELD(a) set_dec_field(&dec->a, line)static void set_dec_field (char **field, const char *line){ if (*field == 0) { *field = strdup(line); } else { RTSP_ERR("decoder fileld exist, old:%s new:%s\n", *field, line); }}#define RTSP_HEADER_FUNC(a) static void a (const char *line, rtsp_resp_t *dec)RTSP_HEADER_FUNC(rtsp_header_allow_public){ SET_DEC_FIELD(allow_public);}RTSP_HEADER_FUNC(rtsp_header_connection){ if (strncasecmp(line, "close", strlen("close")) == 0) { dec->close_connection = 1; } else { dec->close_connection = 0; }}RTSP_HEADER_FUNC(rtsp_header_cookie){ SET_DEC_FIELD(cookie);}RTSP_HEADER_FUNC(rtsp_header_content_base){ SET_DEC_FIELD(content_base);}RTSP_HEADER_FUNC(rtsp_header_content_length){ dec->content_length = atoi(line);}RTSP_HEADER_FUNC(rtsp_header_content_loc){ SET_DEC_FIELD(content_location);}RTSP_HEADER_FUNC(rtsp_header_content_type){ SET_DEC_FIELD(content_type);}RTSP_HEADER_FUNC(rtsp_header_cseq){ dec->cseq = atoi(line);}RTSP_HEADER_FUNC(rtsp_header_location){ SET_DEC_FIELD(location);}RTSP_HEADER_FUNC(rtsp_header_range){ SET_DEC_FIELD(range);}RTSP_HEADER_FUNC(rtsp_header_retry_after){ SET_DEC_FIELD(retry_after);}RTSP_HEADER_FUNC(rtsp_header_rtp){ SET_DEC_FIELD(rtp_info);}RTSP_HEADER_FUNC(rtsp_header_session){ SET_DEC_FIELD(session);}RTSP_HEADER_FUNC(rtsp_header_speed){ SET_DEC_FIELD(speed);}RTSP_HEADER_FUNC(rtsp_header_transport){ SET_DEC_FIELD(transport);}RTSP_HEADER_FUNC(rtsp_header_www){ SET_DEC_FIELD(www_authenticate);}RTSP_HEADER_FUNC(rtsp_header_accept){ SET_DEC_FIELD(accept);}RTSP_HEADER_FUNC(rtsp_header_accept_enc){ SET_DEC_FIELD(accept_encoding);}RTSP_HEADER_FUNC(rtsp_header_accept_lang){ SET_DEC_FIELD(accept_language);}RTSP_HEADER_FUNC(rtsp_header_auth){ SET_DEC_FIELD(authorization);}RTSP_HEADER_FUNC(rtsp_header_bandwidth){ SET_DEC_FIELD(bandwidth);}RTSP_HEADER_FUNC(rtsp_header_blocksize){ SET_DEC_FIELD(blocksize);}RTSP_HEADER_FUNC(rtsp_header_cache_control){ SET_DEC_FIELD(cache_control);}RTSP_HEADER_FUNC(rtsp_header_content_enc){ SET_DEC_FIELD(content_encoding);}RTSP_HEADER_FUNC(rtsp_header_content_lang){ SET_DEC_FIELD(content_language);}RTSP_HEADER_FUNC(rtsp_header_date){ SET_DEC_FIELD(date);}RTSP_HEADER_FUNC(rtsp_header_expires){ SET_DEC_FIELD(expires);}RTSP_HEADER_FUNC(rtsp_header_from){ SET_DEC_FIELD(from);}RTSP_HEADER_FUNC(rtsp_header_ifmod){ SET_DEC_FIELD(if_modified_since);}RTSP_HEADER_FUNC(rtsp_header_lastmod){ SET_DEC_FIELD(last_modified);}RTSP_HEADER_FUNC(rtsp_header_proxyauth){ SET_DEC_FIELD(proxy_authenticate);}RTSP_HEADER_FUNC(rtsp_header_proxyreq){ SET_DEC_FIELD(proxy_require);}RTSP_HEADER_FUNC(rtsp_header_referer){ SET_DEC_FIELD(referer);}RTSP_HEADER_FUNC(rtsp_header_scale){ SET_DEC_FIELD(scale);}RTSP_HEADER_FUNC(rtsp_header_server){ SET_DEC_FIELD(server);}RTSP_HEADER_FUNC(rtsp_header_unsup){ SET_DEC_FIELD(unsupported);}RTSP_HEADER_FUNC(rtsp_header_uagent){ SET_DEC_FIELD(user_agent);}RTSP_HEADER_FUNC(rtsp_header_via){ SET_DEC_FIELD(via);}static struct{ const char *val; int val_length; void (*parse_routine)(const char *line, rtsp_resp_t *decode);} header_types[] ={#define HEAD_TYPE(a, b) { a, sizeof(a) - 1, b } HEAD_TYPE("AlLow", rtsp_header_allow_public), HEAD_TYPE("Public", rtsp_header_allow_public), HEAD_TYPE("Connection", rtsp_header_connection), HEAD_TYPE("Content-Base", rtsp_header_content_base), HEAD_TYPE("Content-Length", rtsp_header_content_length), HEAD_TYPE("Content-Location", rtsp_header_content_loc), HEAD_TYPE("Content-Type", rtsp_header_content_type), HEAD_TYPE("CSeq", rtsp_header_cseq), HEAD_TYPE("Location", rtsp_header_location), HEAD_TYPE("Range", rtsp_header_range), HEAD_TYPE("Retry-After", rtsp_header_retry_after), HEAD_TYPE("RTP-client", rtsp_header_rtp), HEAD_TYPE("Session", rtsp_header_session), HEAD_TYPE("Set-Cookie", rtsp_header_cookie), HEAD_TYPE("Speed", rtsp_header_speed), HEAD_TYPE("Transport", rtsp_header_transport), HEAD_TYPE("WWW-Authenticate", rtsp_header_www), HEAD_TYPE("Accept", rtsp_header_accept), HEAD_TYPE("Accept-Encoding", rtsp_header_accept_enc), HEAD_TYPE("Accept-Language", rtsp_header_accept_lang), HEAD_TYPE("Authorization", rtsp_header_auth), HEAD_TYPE("Bandwidth", rtsp_header_bandwidth), HEAD_TYPE("Blocksize", rtsp_header_blocksize), HEAD_TYPE("Cache-Control", rtsp_header_cache_control), HEAD_TYPE("Content-Encoding", rtsp_header_content_enc), HEAD_TYPE("Content-Language", rtsp_header_content_lang), HEAD_TYPE("Date", rtsp_header_date), HEAD_TYPE("Expires", rtsp_header_expires), HEAD_TYPE("From", rtsp_header_from), HEAD_TYPE("If-Modified-Since", rtsp_header_ifmod), HEAD_TYPE("Last-Modified", rtsp_header_lastmod), HEAD_TYPE("Proxy-Authenticate", rtsp_header_proxyauth), HEAD_TYPE("Proxy-Require", rtsp_header_proxyreq), HEAD_TYPE("Referer", rtsp_header_referer), HEAD_TYPE("Scale", rtsp_header_scale), HEAD_TYPE("Server", rtsp_header_server), HEAD_TYPE("Unsupported", rtsp_header_unsup), HEAD_TYPE("User-Agent", rtsp_header_uagent), HEAD_TYPE("Via", rtsp_header_via), { 0, 0, 0 },};static void rtsp_decode_header (const char *line, rtsp_resp_t *response){ int i; const char *after; i = 0; while (header_types[i].val != 0) { if (strncasecmp(line, header_types[i].val, header_types[i].val_length) == 0) { after = line + header_types[i].val_length; SKIP_SPACE(after); if (*after == ':') { after++; SKIP_SPACE(after); (header_types[i].parse_routine)(after, response); return; } } i++; } RTSP_ALERT("%s [not processing]\n", line);}static int buffer_read (rtsp_client_t *client, int len){ assert(client->m_buffer_len + len <= RECV_BUFF_DEFAULT_LEN); int ret; ret = rtsp_receive_socket(client, client->m_recv_buffer + client->m_buffer_len, len); if (ret <= 0) { return ret; } client->m_buffer_len += ret; client->m_recv_buffer[client->m_buffer_len] = '\0'; return ret;}static int buffer_read_all (rtsp_client_t *client){ return buffer_read(client, RECV_BUFF_DEFAULT_LEN - client->m_buffer_len);}static int buffer_len (rtsp_client_t *client){ int ret = client->m_buffer_len - client->m_offset_on; assert(ret >= 0 && ret <= RECV_BUFF_DEFAULT_LEN); return ret;}static void buffer_move_head (rtsp_client_t *client){ int len; len = client->m_buffer_len - client->m_offset_on; if (len > 0) { memmove(client->m_recv_buffer, client->m_recv_buffer + client->m_offset_on, len); } client->m_offset_on = 0; client->m_buffer_len = len; RTSP_DBG("=====> move memory size = %d\n", len); }static int buffer_move_and_read_all (rtsp_client_t *client){ if (buffer_len(client) == RECV_BUFF_DEFAULT_LEN)/*全满*/ { RTSP_ALERT("buffer is full when read, len=%d\n", RECV_BUFF_DEFAULT_LEN); return RECV_BUFF_DEFAULT_LEN; } buffer_move_head(client); buffer_read_all(client); return buffer_len(client);/*总长*/}static const char *get_next_line (rtsp_client_t *client){ int ret; char *sep; if (buffer_len(client) == 0) { if (buffer_move_and_read_all(client) == 0) { return 0; } } sep = strstr(client->m_recv_buffer + client->m_offset_on, SEPERATOR); if (sep != 0) { const char *retval = client->m_recv_buffer + client->m_offset_on; client->m_offset_on = sep - client->m_recv_buffer; client->m_offset_on += strlen(SEPERATOR); *sep = '\0'; return retval; } if (client->m_offset_on == 0) { RTSP_DBG("====> have no seperator in full buffer\n"); return 0; } if (buffer_move_and_read_all(client) == 0) { RTSP_DBG("====> read fail after have no seperator in full buffer\n"); return 0; } sep = strstr(client->m_recv_buffer + client->m_offset_on, SEPERATOR); if (sep != 0) { const char *retval = client->m_recv_buffer + client->m_offset_on; client->m_offset_on = sep - client->m_recv_buffer; client->m_offset_on += strlen(SEPERATOR); *sep = '\0'; RTSP_DBG("====> get seperator at second try\n"); return retval; } RTSP_DBG("====> have no seperator in full buffer at second read\n"); return 0;}int rtsp_recv_response (rtsp_client_t *client, rtsp_resp_t *response){ const char *line; const char *p; rtsp_resp_t *decode; int done; int len; decode = response; if (buffer_move_and_read_all(client) == 0) { RTSP_ERR("string buffer is null and no data recv\n"); return -1; } do { line = get_next_line(client); if (line == 0) { RTSP_ERR("couldn't get response first line\n"); return -1; } } while (*line == '\0'); RTSP_INFO("%s\n", line); if (strncasecmp(line, "RTSP/1.0", strlen("RTSP/1.0")) != 0) { char str[20]; p = line; while ( *p != ' ') { p++; } memcpy(str, line, p - line); str[p-line] = '\0'; decode->caption = strdup(str); } else { p = line + strlen("RTSP/1.0"); SKIP_SPACE(p); memcpy(decode->retcode, p, 3); decode->retcode[3] = '\0'; p += 3; SKIP_SPACE(p); decode->retresp = strdup(p); decode->caption = strdup("RTSP/1.0"); } done = 0; do { line = get_next_line(client); if (line == 0) { RTSP_ERR("couldn't get line from response content\n"); return -1; } if (*line != '\0') { RTSP_INFO("%s\n", line); rtsp_decode_header(line, response); } else { done = 1; } } while (done == 0); if (decode->content_length != 0) { decode->body = (char*)malloc(decode->content_length + 1); decode->body[decode->content_length] = '\0'; len = buffer_len(client); RTSP_DBG("response body length=%d, current buffer size=%d, offset=%d\n", decode->content_length, len, client->m_offset_on); if (len < decode->content_length) { memcpy(decode->body, client->m_recv_buffer + client->m_offset_on, len); while (len < decode->content_length) { int left; int ret; client->m_offset_on = 0; client->m_buffer_len = 0; ret = buffer_read_all(client); if (ret <= 0) { RTSP_ERR("recv fail at get rtsp body\n"); return -1; } left = decode->content_length - len; if (left < client->m_buffer_len) { memcpy(decode->body + len, client->m_recv_buffer, left); len += left; client->m_offset_on = left; } else { memcpy(decode->body + len, client->m_recv_buffer, client->m_buffer_len); len += client->m_buffer_len; client->m_offset_on = client->m_buffer_len; } } } else { memcpy(decode->body, client->m_recv_buffer + client->m_offset_on, decode->content_length); client->m_offset_on += decode->content_length; } } if (decode->body != 0) { RTSP_INFO("%s", decode->body); } RTSP_INFO("complete recv response, buffer state: offset=%d len=%d\n", client->m_offset_on, buffer_len(client)); return 0;}int rtsp_recv_interleave_data(rtsp_client_t *client, char *buffer, int *length, int *interleave_id){ int len, ts_len, left, pos; char* head; len = buffer_len(client); if (len > 0) { RTSP_DBG("rtsp_recv_interleave_data, local buffer len = %d\n", len); buffer_move_head(client); if (len < 4) { if (buffer_read(client, 4-len) != 4-len) { RTSP_ERR("read rtsp interleave head fail\n"); return -1; } } } else { buffer_move_head(client); len = buffer_read(client, 4); if (len != 4) { RTSP_ERR("read rtsp interleave head fail, len=%d\n", len); return -1; } } len = buffer_len(client); if (len > 4) { head = client->m_recv_buffer; if (head[0] != '$') { RTSP_ERR("rtsp interleave head not match '$', it is '%c'\n", head[0]); return -2; } ts_len = head[2] << 8 | head[3]; *interleave_id = head[1]; *length = ts_len; client->m_offset_on += 4; len -= 4; if (len >= ts_len) { memcpy(buffer, client->m_recv_buffer + client->m_offset_on, ts_len); client->m_offset_on += ts_len; } else { memcpy(buffer, client->m_recv_buffer + client->m_offset_on, len); client->m_offset_on += len; left = ts_len - len; pos = len; while (left > 0) { int n; n = rtsp_receive_socket(client, buffer + pos, left); if (n <= 0) { RTSP_ERR("read rtsp interleave data fail, len=%d cur_len=%d\n", len, pos); return -1; } left -= n; pos += n; } } } else { head = client->m_recv_buffer; if (head[0] != '$') { RTSP_ERR("rtsp interleave head not match '$', it is '%c'\n", head[0]); return -2; } ts_len = head[2] << 8 | head[3]; *interleave_id = head[1]; *length = ts_len; client->m_offset_on += 4; left = ts_len; pos = 0; while (left != 0) { int n; n = rtsp_receive_socket(client, buffer + pos, left); if (n <= 0) { RTSP_ERR("read rtsp interleave data fail, len=%d cur_len=%d\n", len, pos); return -1; } left -= n; pos += n; } } return 0;}void clear_response (rtsp_resp_t *resp){ CHECK_AND_FREE(resp->caption); CHECK_AND_FREE(resp->retresp); CHECK_AND_FREE(resp->body); CHECK_AND_FREE(resp->accept); CHECK_AND_FREE(resp->accept_encoding); CHECK_AND_FREE(resp->accept_language); CHECK_AND_FREE(resp->allow_public); CHECK_AND_FREE(resp->authorization); CHECK_AND_FREE(resp->bandwidth); CHECK_AND_FREE(resp->blocksize); CHECK_AND_FREE(resp->cache_control); CHECK_AND_FREE(resp->content_base); CHECK_AND_FREE(resp->content_encoding); CHECK_AND_FREE(resp->content_language); CHECK_AND_FREE(resp->content_location); CHECK_AND_FREE(resp->content_type); CHECK_AND_FREE(resp->date); CHECK_AND_FREE(resp->cookie); CHECK_AND_FREE(resp->expires); CHECK_AND_FREE(resp->from); CHECK_AND_FREE(resp->if_modified_since); CHECK_AND_FREE(resp->last_modified); CHECK_AND_FREE(resp->location); CHECK_AND_FREE(resp->proxy_authenticate); CHECK_AND_FREE(resp->proxy_require); CHECK_AND_FREE(resp->range); CHECK_AND_FREE(resp->referer); CHECK_AND_FREE(resp->require); CHECK_AND_FREE(resp->retry_after); CHECK_AND_FREE(resp->rtp_info); CHECK_AND_FREE(resp->scale); CHECK_AND_FREE(resp->server); CHECK_AND_FREE(resp->session); CHECK_AND_FREE(resp->speed); CHECK_AND_FREE(resp->transport); CHECK_AND_FREE(resp->unsupported); CHECK_AND_FREE(resp->user_agent); CHECK_AND_FREE(resp->via); CHECK_AND_FREE(resp->www_authenticate); resp->content_length = 0; resp->cseq = 0; resp->close_connection = 0;}void free_response (rtsp_resp_t *resp){ if (resp != 0) { clear_response(resp); free(resp); }}int simple_parse_sdp(char* sdp){ return 7361;}int simple_parse_range(char* range){ char str[20]; char* p1; char* p2; printf("======>begin parse range\n"); p1 = strchr(range, '='); p1++; p2 = strchr(range, '.'); p2--; memset(str, 0, 20); strncpy(str, p1, p2 - p1 + 1); RTSP_DBG("simple_parse_range: offset=%s range=%s\n", str, range); return atoi(str);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -