/*--------------------------------------------------------
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';
retu