rtsp_resp.c
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:19k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is MPEG4IP.
  13.  * 
  14.  * The Initial Developer of the Original Code is Cisco Systems Inc.
  15.  * Portions created by Cisco Systems Inc. are
  16.  * Copyright (C) Cisco Systems Inc. 2000, 2001.  All Rights Reserved.
  17.  * 
  18.  * Contributor(s): 
  19.  *              Bill May        wmay@cisco.com
  20.  */
  21. /*
  22.  * rtsp_resp.c - process rtsp response
  23.  */
  24. #include "rtsp_private.h"
  25. static const char *end2 = "nr";
  26. static const char *end1 = "rn";
  27. static const char *end3 = "r";
  28. static const char *end4 = "n";
  29. /*
  30.  * find_end_seperator()
  31.  * Will search through the string pointer to by ptr, and figure out
  32.  * what character is being used as a seperator - either r n, rn
  33.  * or nr.
  34.  *
  35.  * Inputs:
  36.  *    ptr - string to decode
  37.  *    len - pointer to end seperator len
  38.  *
  39.  * Outputs:
  40.  *    pointer to character to use as end seperator.  Dividing the len
  41.  *    by 2, and adding to the return pointer will give the normal
  42.  *    line seperator.
  43.  */
  44. static const char *find_seperator (const char *ptr)
  45. {
  46.   while (*ptr != '') {
  47.     if (*ptr == 'r') {
  48.       if (*(ptr + 1) == 'n') {
  49. return (end1);
  50.       } else {
  51. return (end3);
  52.       }
  53.     } else if (*ptr == 'n') {
  54.       if (*(ptr + 1) == 'r') {
  55. return (end2);
  56.       } else {
  57. return (end4);
  58.       }
  59.     }
  60.     ptr++;
  61.   }
  62.   return (NULL);
  63. }
  64. /************************************************************************
  65.  * Decode rtsp header lines.
  66.  *
  67.  * These routines will decode the various RTSP header lines, setting the
  68.  * correct information in the rtsp_decode_t structure.
  69.  *
  70.  * DEC_DUP_WARN macro will see if the field is already set, and send a warning
  71.  * if it is.  If the cont_line field is set, it will append the next line
  72.  *
  73.  ************************************************************************/
  74. #define RTSP_HEADER_FUNC(a) static void a (const char *lptr, rtsp_decode_t *dec, int cont_line)
  75. static void dec_dup_warn (char **location,
  76.   const char *lptr,
  77.   const char *warn,
  78.   int cont_line)
  79. {
  80.   if (*location == NULL) {
  81.     *location = strdup(lptr);
  82.   } else if (cont_line != 0) {
  83.     uint32_t len = strlen(*location);
  84.     len += strlen(lptr);
  85.     len++;
  86.     *location = realloc(*location, len);
  87.     strcat(*location, lptr);
  88.   } else {
  89.     rtsp_debug(LOG_WARNING, "2nd %s %s", warn, lptr);
  90.   }
  91. }
  92. #define DEC_DUP_WARN(a, b) dec_dup_warn(&dec->a, lptr, b, cont_line)
  93. RTSP_HEADER_FUNC(rtsp_header_allow_public)
  94. {
  95.   DEC_DUP_WARN(allow_public, "allow public");
  96. }
  97. RTSP_HEADER_FUNC(rtsp_header_connection)
  98. {
  99.   if (strncasecmp(lptr, "close", strlen("close")) == 0) {
  100.     dec->close_connection = TRUE;
  101.   }
  102. }
  103. RTSP_HEADER_FUNC(rtsp_header_cookie)
  104. {
  105.   DEC_DUP_WARN(cookie, "cookie");
  106. }
  107. RTSP_HEADER_FUNC(rtsp_header_content_base)
  108. {
  109.   DEC_DUP_WARN(content_base, "Content-Base");
  110. }
  111. RTSP_HEADER_FUNC(rtsp_header_content_length)
  112. {
  113.   dec->content_length = strtoul(lptr, NULL, 10);
  114. }
  115. RTSP_HEADER_FUNC(rtsp_header_content_loc)
  116. {
  117.   DEC_DUP_WARN(content_location, "Content-Location");
  118. }
  119. RTSP_HEADER_FUNC(rtsp_header_content_type)
  120. {
  121.   DEC_DUP_WARN(content_type, "Content-Type");
  122. }
  123. RTSP_HEADER_FUNC(rtsp_header_cseq)
  124. {
  125.   dec->cseq = strtoul(lptr, NULL, 10);
  126. }
  127. RTSP_HEADER_FUNC(rtsp_header_location)
  128. {
  129.   DEC_DUP_WARN(location, "Location");
  130. }
  131. RTSP_HEADER_FUNC(rtsp_header_range)
  132. {
  133.   DEC_DUP_WARN(range, "Range");
  134. }
  135. RTSP_HEADER_FUNC(rtsp_header_retry_after)
  136. {
  137.   // May try strptime if we need to convert
  138.   DEC_DUP_WARN(retry_after, "Retry-After");
  139. }
  140. RTSP_HEADER_FUNC(rtsp_header_rtp)
  141. {
  142.   DEC_DUP_WARN(rtp_info, "RtpInfo");
  143. }
  144. RTSP_HEADER_FUNC(rtsp_header_session)
  145. {
  146.   DEC_DUP_WARN(session, "Session");
  147. }
  148. RTSP_HEADER_FUNC(rtsp_header_speed)
  149. {
  150.   DEC_DUP_WARN(speed, "Speed");
  151. }
  152. RTSP_HEADER_FUNC(rtsp_header_transport)
  153. {
  154.   DEC_DUP_WARN(transport, "Transport");
  155. }
  156. RTSP_HEADER_FUNC(rtsp_header_www)
  157. {
  158.   DEC_DUP_WARN(www_authenticate, "WWW-Authenticate");
  159. }
  160. RTSP_HEADER_FUNC(rtsp_header_accept)
  161. {
  162.   DEC_DUP_WARN(accept, "Accept");
  163. }
  164. RTSP_HEADER_FUNC(rtsp_header_accept_enc)
  165. {
  166.   DEC_DUP_WARN(accept_encoding, "Accept-Encoding");
  167. }
  168. RTSP_HEADER_FUNC(rtsp_header_accept_lang)
  169. {
  170.   DEC_DUP_WARN(accept_language, "Accept-Language");
  171. }
  172. RTSP_HEADER_FUNC(rtsp_header_auth)
  173. {
  174.   DEC_DUP_WARN(authorization, "Authorization");
  175. }
  176. RTSP_HEADER_FUNC(rtsp_header_bandwidth)
  177. {
  178.   DEC_DUP_WARN(bandwidth, "Bandwidth");
  179. }
  180. RTSP_HEADER_FUNC(rtsp_header_blocksize)
  181. {
  182.   DEC_DUP_WARN(blocksize, "blocksize");
  183. }
  184. RTSP_HEADER_FUNC(rtsp_header_cache_control)
  185. {
  186.   DEC_DUP_WARN(cache_control, "Cache-control:");
  187. }
  188. RTSP_HEADER_FUNC(rtsp_header_content_enc)
  189. {
  190.   DEC_DUP_WARN(content_encoding, "Content-Encoding:");
  191. }
  192. RTSP_HEADER_FUNC(rtsp_header_content_lang)
  193. {
  194.   DEC_DUP_WARN(content_language, "Content-Language:");
  195. }
  196. RTSP_HEADER_FUNC(rtsp_header_date)
  197. {
  198.   DEC_DUP_WARN(date, "Date:");
  199. }
  200. RTSP_HEADER_FUNC(rtsp_header_expires)
  201. {
  202.   DEC_DUP_WARN(expires, "Expires:");
  203. }
  204. RTSP_HEADER_FUNC(rtsp_header_from)
  205. {
  206.   DEC_DUP_WARN(from, "From:");
  207. }
  208. RTSP_HEADER_FUNC(rtsp_header_ifmod)
  209. {
  210.   DEC_DUP_WARN(if_modified_since, "If-Modified-Since:");
  211. }
  212. RTSP_HEADER_FUNC(rtsp_header_lastmod)
  213. {
  214.   DEC_DUP_WARN(last_modified, "Last-Modified:");
  215. }
  216. RTSP_HEADER_FUNC(rtsp_header_proxyauth)
  217. {
  218.   DEC_DUP_WARN(proxy_authenticate, "Proxy-Authenticate:");
  219. }
  220. RTSP_HEADER_FUNC(rtsp_header_proxyreq)
  221. {
  222.   DEC_DUP_WARN(proxy_require, "Proxy-Require:");
  223. }
  224. RTSP_HEADER_FUNC(rtsp_header_referer)
  225. {
  226.   DEC_DUP_WARN(referer, "Referer:");
  227. }
  228. RTSP_HEADER_FUNC(rtsp_header_scale)
  229. {
  230.   DEC_DUP_WARN(scale, "Scale:");
  231. }
  232. RTSP_HEADER_FUNC(rtsp_header_server)
  233. {
  234.   DEC_DUP_WARN(server, "Server:");
  235. }
  236. RTSP_HEADER_FUNC(rtsp_header_unsup)
  237. {
  238.   DEC_DUP_WARN(unsupported, "Unsupported:");
  239. }
  240. RTSP_HEADER_FUNC(rtsp_header_uagent)
  241. {
  242.   DEC_DUP_WARN(user_agent, "User-Agent:");
  243. }
  244. RTSP_HEADER_FUNC(rtsp_header_via)
  245. {
  246.   DEC_DUP_WARN(via, "Via:");
  247. }
  248. /*
  249.  * header_types structure will provide a lookup between certain headers
  250.  * in RTSP, and the function routines (above) that deal with actions based
  251.  * on the response
  252.  */
  253. static struct {
  254.   const char *val;
  255.   uint32_t val_length;
  256.   void (*parse_routine)(const char *lptr, rtsp_decode_t *decode, int cont_line);
  257. } header_types[] =
  258. {
  259. #define HEAD_TYPE(a, b) { a, sizeof(a), b }
  260.   HEAD_TYPE("Allow:", rtsp_header_allow_public),
  261.   HEAD_TYPE("Public:", rtsp_header_allow_public),
  262.   HEAD_TYPE("Connection:", rtsp_header_connection),
  263.   HEAD_TYPE("Content-Base:", rtsp_header_content_base),
  264.   HEAD_TYPE("Content-Length:", rtsp_header_content_length),
  265.   HEAD_TYPE("Content-Location:", rtsp_header_content_loc),
  266.   HEAD_TYPE("Content-Type:", rtsp_header_content_type),
  267.   HEAD_TYPE("CSeq:", rtsp_header_cseq),
  268.   HEAD_TYPE("Location:", rtsp_header_location),
  269.   HEAD_TYPE("Range:", rtsp_header_range),
  270.   HEAD_TYPE("Retry-After:", rtsp_header_retry_after),
  271.   HEAD_TYPE("RTP-Info:", rtsp_header_rtp),
  272.   HEAD_TYPE("Session:", rtsp_header_session),
  273.   HEAD_TYPE("Set-Cookie:", rtsp_header_cookie),
  274.   HEAD_TYPE("Speed:", rtsp_header_speed),
  275.   HEAD_TYPE("Transport:", rtsp_header_transport),
  276.   HEAD_TYPE("WWW-Authenticate:", rtsp_header_www),
  277.   // None of these are needed for client, but are included for completion
  278.   HEAD_TYPE("Accept:", rtsp_header_accept),
  279.   HEAD_TYPE("Accept-Encoding:", rtsp_header_accept_enc),
  280.   HEAD_TYPE("Accept-Language:", rtsp_header_accept_lang),
  281.   HEAD_TYPE("Authorization:", rtsp_header_auth),
  282.   HEAD_TYPE("Bandwidth:", rtsp_header_bandwidth),
  283.   HEAD_TYPE("Blocksize:", rtsp_header_blocksize),
  284.   HEAD_TYPE("Cache-Control:", rtsp_header_cache_control),
  285.   HEAD_TYPE("Content-Encoding:", rtsp_header_content_enc),
  286.   HEAD_TYPE("Content-Language:", rtsp_header_content_lang),
  287.   HEAD_TYPE("Date:", rtsp_header_date),
  288.   HEAD_TYPE("Expires:", rtsp_header_expires),
  289.   HEAD_TYPE("From:", rtsp_header_from),
  290.   HEAD_TYPE("If-Modified-Since:", rtsp_header_ifmod),
  291.   HEAD_TYPE("Last-Modified:", rtsp_header_lastmod),
  292.   HEAD_TYPE("Proxy-Authenticate:", rtsp_header_proxyauth),
  293.   HEAD_TYPE("Proxy-Require:", rtsp_header_proxyreq),
  294.   HEAD_TYPE("Referer:", rtsp_header_referer),
  295.   HEAD_TYPE("Scale:", rtsp_header_scale),
  296.   HEAD_TYPE("Server:", rtsp_header_server),
  297.   HEAD_TYPE("Unsupported:", rtsp_header_unsup),
  298.   HEAD_TYPE("User-Agent:", rtsp_header_uagent),
  299.   HEAD_TYPE("Via:", rtsp_header_via),
  300.   { NULL, 0, NULL },
  301. };
  302. // We don't care about the following: Cache-control, date, expires,
  303. // Last-modified, Server, Unsupported, Via
  304. /*
  305.  * rtsp_decode_header - header line pointed to by lptr.  will be  terminated
  306.  * Decode using above table
  307.  */
  308. static void rtsp_decode_header (const char *lptr,
  309. rtsp_client_t *info,
  310. int *last_number)
  311. {
  312.   int ix;
  313.   const char *after;
  314.   ix = 0;
  315.   /*
  316.    * go through above array, looking for a complete match
  317.    */
  318.   while (header_types[ix].val != NULL) {
  319.     if (strncasecmp(lptr,
  320.     header_types[ix].val,
  321.     header_types[ix].val_length - 1) == 0) {
  322.       after = lptr + header_types[ix].val_length;
  323.       ADV_SPACE(after);
  324.       /*
  325.        * Call the correct parsing routine
  326.        */
  327.       (header_types[ix].parse_routine)(after, info->decode_response, 0);
  328.       *last_number = ix;
  329.       return;
  330.     }
  331.     ix++;
  332.   }
  333.   if (last_number >= 0 && isspace(*lptr)) {
  334.     //asdf
  335.     ADV_SPACE(lptr);
  336.     (header_types[*last_number].parse_routine)(lptr, info->decode_response, 1);
  337.   } else 
  338.     rtsp_debug(LOG_DEBUG, "Not processing response header: %s", lptr);
  339. }
  340. static int rtsp_read_into_buffer (rtsp_client_t *cptr,
  341.   uint32_t buffer_offset,
  342.   int wait)
  343. {
  344.   int ret;
  345.   ret = rtsp_receive_socket(cptr,
  346.     cptr->m_resp_buffer + buffer_offset,
  347.     RECV_BUFF_DEFAULT_LEN - buffer_offset,
  348.     cptr->recv_timeout, 
  349.     wait);
  350.   if (ret <= 0) return (ret);
  351.   cptr->m_buffer_len = buffer_offset + ret;
  352.   cptr->m_resp_buffer[cptr->m_buffer_len] = '';
  353.   return ret;
  354. }
  355. int rtsp_bytes_in_buffer (rtsp_client_t *cptr)
  356. {
  357.   return (cptr->m_buffer_len - cptr->m_offset_on);
  358. }
  359. int rtsp_recv (rtsp_client_t *cptr,
  360.        char *buffer,
  361.        uint32_t len)
  362. {
  363.   uint32_t mlen;
  364.   int copied, result;
  365.   copied = 0;
  366.   if (cptr->m_offset_on < cptr->m_buffer_len) {
  367.     mlen =  MIN(len, cptr->m_buffer_len - cptr->m_offset_on);
  368.     memmove(buffer,
  369.     &cptr->m_resp_buffer[cptr->m_offset_on],
  370.     mlen);
  371.     cptr->m_offset_on += mlen;
  372.     len -= mlen;
  373.     copied += mlen;
  374.   }
  375.   if (len > 0) {
  376.     result = rtsp_receive_socket(cptr,
  377.  buffer + copied,
  378.  len,
  379.  0,
  380.  0);
  381.     if (result >= 0) {
  382.       copied += result;
  383.     }
  384.   }
  385.   return copied;
  386. }
  387.     
  388.     
  389. static int rtsp_save_and_read (rtsp_client_t *cptr)
  390. {
  391.   int last_on;
  392.   int ret;
  393.   cptr->m_buffer_len -= cptr->m_offset_on;
  394.   if (cptr->m_buffer_len >= RECV_BUFF_DEFAULT_LEN) {
  395.     return 0;
  396.   } else if (cptr->m_buffer_len != 0) {
  397.     memmove(cptr->m_resp_buffer,
  398.     &cptr->m_resp_buffer[cptr->m_offset_on],
  399.     cptr->m_buffer_len);
  400.     last_on = cptr->m_buffer_len;
  401.   } else {
  402.     last_on = 0;
  403.   }
  404.   
  405.   cptr->m_offset_on = 0;  
  406.   ret = rtsp_read_into_buffer(cptr, cptr->m_buffer_len, 0);
  407.   if (ret > 0) {
  408.     last_on += ret;
  409.   }
  410.   return (last_on);
  411. }
  412. static const char *rtsp_get_next_line (rtsp_client_t *cptr,
  413.        const char *seperator)
  414. {
  415.   int ret;
  416.   int last_on;
  417.   char *sep;
  418.   /*
  419.    * If we don't have any data, try to read a buffer full
  420.    */
  421.   if (cptr->m_buffer_len <= 0) {
  422.     cptr->m_offset_on = 0;
  423.     ret = rtsp_read_into_buffer(cptr, 0, 1);
  424.     if (ret <= 0) {
  425.       return (NULL);
  426.     }
  427.   }
  428.   /*
  429.    * Look for CR/LF in the buffer.  If we find it, NULL terminate at
  430.    * the CR, then set the buffer values to look past the crlf
  431.    */
  432.   sep = strstr(&cptr->m_resp_buffer[cptr->m_offset_on],
  433.        seperator);
  434.   if (sep != NULL) {
  435.     const char *retval = &cptr->m_resp_buffer[cptr->m_offset_on];
  436.     cptr->m_offset_on = sep - cptr->m_resp_buffer;
  437.     cptr->m_offset_on += strlen(seperator);
  438.     *sep = '';
  439.     return (retval);
  440.   }
  441.   if (cptr->m_offset_on == 0) {
  442.     return (NULL);
  443.   }
  444.   /*
  445.    * We don't have a line.  So, move the data down in the buffer, then
  446.    * read into the rest of the buffer
  447.    */
  448.   last_on = rtsp_save_and_read(cptr);
  449.   if (last_on < 0) return (NULL);
  450.   /*
  451.    * Continue searching through the buffer.  If we get this far, we've
  452.    * received like 2K or 4K without a CRLF - most likely a bad response
  453.    */
  454.   sep = strstr(&cptr->m_resp_buffer[last_on],
  455.        seperator);
  456.   if (sep != NULL) {
  457.     const char *retval = &cptr->m_resp_buffer[cptr->m_offset_on];
  458.     cptr->m_offset_on = sep - cptr->m_resp_buffer;
  459.     cptr->m_offset_on += strlen(seperator);
  460.     *sep = '';
  461.     return (retval);
  462.   }
  463.   return (NULL);
  464. }
  465. /*
  466.  * rtsp_parse_response - parse out response headers lines.  Figure out
  467.  * where seperators are, then use them to determine where the body is
  468.  */
  469. static int rtsp_parse_response (rtsp_client_t *info)
  470. {
  471.   const char *seperator;
  472.   const char *lptr, *p;
  473.   rtsp_decode_t *decode;
  474.   int ret, done;
  475.   int last_header = -1;
  476.   uint32_t len;
  477.   decode = info->decode_response;
  478.   
  479.   // Figure out what seperator is being used throughout the response
  480.   ret = rtsp_save_and_read(info);
  481.   if (ret < 0) {
  482.     return (RTSP_RESPONSE_RECV_ERROR);
  483.   }
  484.   seperator = find_seperator(info->m_resp_buffer);
  485.   if (seperator == NULL) {
  486.     rtsp_debug(LOG_INFO, "Could not find seperator in header");
  487.     return RTSP_RESPONSE_MALFORM_HEADER;
  488.   }
  489.   
  490.   //rtsp_debug(LOG_DEBUG, "Response buffer:n%s", info->m_resp_buffer);
  491.   do {
  492.     lptr = rtsp_get_next_line(info, seperator);
  493.     if (lptr == NULL) {
  494.       rtsp_debug(LOG_INFO, "Couldn't get next line");
  495.       return (RTSP_RESPONSE_MALFORM_HEADER);
  496.     }
  497.   } while (*lptr == '');
  498.   rtsp_debug(LOG_DEBUG, lptr);
  499.   if (strncasecmp(lptr, "RTSP/1.0", strlen("RTSP/1.0")) != 0) {
  500.     rtsp_debug(LOG_INFO, "RTSP/1.0 not found");
  501.     return RTSP_RESPONSE_MALFORM_HEADER;
  502.   }
  503.   p = lptr + strlen("RTSP/1.0");
  504.   ADV_SPACE(p);
  505.   memcpy(decode->retcode, p, 3);
  506.   decode->retcode[3] = '';
  507.   switch (*p) {
  508.   case '1':
  509.   case '2':
  510.   case '3':
  511.   case '4':
  512.   case '5':
  513.     break;
  514.   default:
  515.     rtsp_debug(LOG_INFO, "Bad error code %s", p);
  516.     return RTSP_RESPONSE_MALFORM_HEADER;
  517.   }
  518.   p += 3;
  519.   ADV_SPACE(p);
  520.   if (p != '') {
  521.     decode->retresp = strdup(p);
  522.   }
  523.   rtsp_debug(LOG_DEBUG, "Decoded status - code %s %s",
  524.      decode->retcode, decode->retresp);
  525.   done = 0;
  526.   do {
  527.     lptr = rtsp_get_next_line(info, seperator);
  528.     if (lptr == NULL) {
  529.       return (RTSP_RESPONSE_MALFORM_HEADER);
  530.     }
  531.     if (*lptr == '') {
  532.       done = 1;
  533.     } else {
  534.       rtsp_debug(LOG_DEBUG, lptr);
  535.       rtsp_decode_header(lptr, info, &last_header);
  536.     }
  537.   } while (done == 0);
  538.   if (decode->content_length != 0) {
  539.     rtsp_debug(LOG_DEBUG, "reading content length %d", decode->content_length);
  540.     decode->body = malloc(decode->content_length + 1);
  541.     decode->body[decode->content_length] = '';
  542.     len = info->m_buffer_len - info->m_offset_on;
  543.     rtsp_debug(LOG_DEBUG, "Copied %d bytes from buffer", len);
  544.     if (len < decode->content_length) {
  545.       // not enough in memory - need to read
  546.       memcpy(decode->body,
  547.      &info->m_resp_buffer[info->m_offset_on],
  548.      len);
  549.       while (len < decode->content_length) {
  550. int left;
  551. ret = rtsp_read_into_buffer(info, 0, 1);
  552. if (ret <= 0) {
  553.   rtsp_debug(LOG_DEBUG, "Returned from rtsp_read_into_buffer - error %d", 
  554.      ret);
  555.   return (-1);
  556. }
  557. left = decode->content_length - len;
  558. if (left < info->m_buffer_len) {
  559.   // we have more data in the buffer then we need
  560.   memcpy(decode->body + len,
  561.  info->m_resp_buffer,
  562.  left);
  563.   len += left;
  564.   info->m_offset_on = left;
  565. } else {
  566.   // exact or less - we're cool
  567.   memcpy(decode->body + len,
  568.  info->m_resp_buffer,
  569.  info->m_buffer_len);
  570.   len += info->m_buffer_len;
  571.   info->m_offset_on = info->m_buffer_len; // get ready for next...
  572. }
  573.       }
  574.     } else {
  575.       // Plenty in memory - copy it, continue to end...
  576.       memcpy(decode->body,
  577.      &info->m_resp_buffer[info->m_offset_on],
  578.      decode->content_length);
  579.       info->m_offset_on += decode->content_length;
  580.     }
  581.   } else if (decode->close_connection) {
  582.     // No termination - just deal with what we've got...
  583.     len = info->m_buffer_len - info->m_offset_on;
  584.     decode->body = (char *)malloc(len + 1);
  585.     memcpy(decode->body,
  586.    &info->m_resp_buffer[info->m_offset_on],
  587.    len);
  588.     decode->body[len] = '';
  589.   }
  590.   if (decode->body != NULL)
  591.      rtsp_debug(LOG_DEBUG, "%s", decode->body);
  592.   return (0);
  593. }
  594. /*
  595.  * rtsp_get_response - wait for a complete response.  Interesting that
  596.  * it could be in multiple packets, so deal with that.
  597.  */
  598. int rtsp_get_response (rtsp_client_t *info)
  599. {
  600.   int ret;
  601.   rtsp_decode_t *decode;
  602.   int response_okay;
  603.   while (1) {
  604.     // In case we didn't get a response that we wanted.
  605.     if (info->decode_response != NULL) {
  606.       clear_decode_response(info->decode_response);
  607.       decode = info->decode_response;
  608.     } else {
  609.       decode = info->decode_response = malloc(sizeof(rtsp_decode_t));
  610.       if (decode == NULL) {
  611. rtsp_debug(LOG_ALERT, "Couldn't create decode response");
  612. return (RTSP_RESPONSE_RECV_ERROR);
  613.       }
  614.     }
  615.     
  616.     memset(decode, 0, sizeof(rtsp_decode_t));
  617.     do {
  618.       // Parse response.
  619.       ret = rtsp_parse_response(info);
  620.       rtsp_debug(LOG_DEBUG, "parsed response - len %d offset %d",
  621.  info->m_buffer_len, info->m_offset_on);
  622.       if (ret != 0) {
  623. if (info->thread == NULL)
  624.   rtsp_close_socket(info);
  625. rtsp_debug(LOG_ERR, "return code %d from rtsp_parse_response", ret);
  626. return (RTSP_RESPONSE_RECV_ERROR);
  627.       }
  628.       if (decode->close_connection) {
  629. rtsp_debug(LOG_DEBUG, "Response requested connection close");
  630. rtsp_close_socket(info);
  631.       }
  632.   
  633.       response_okay = TRUE;
  634.       // Okay - we have a good response. - check the cseq, and return
  635.       // the correct error code.
  636.       if (info->next_cseq == decode->cseq) {
  637. info->next_cseq++;
  638. if ((decode->retcode[0] == '4') ||
  639.     (decode->retcode[0] == '5')) {
  640.   return (RTSP_RESPONSE_BAD);
  641. }
  642. if (decode->cookie != NULL) {
  643.   // move cookie to rtsp_client
  644.   info->cookie = strdup(decode->cookie);
  645. }
  646. if (decode->retcode[0] == '2') {
  647.   return (RTSP_RESPONSE_GOOD);
  648. }
  649. if (decode->retcode[0] == '3') {
  650.   if (decode->location == NULL) {
  651.     return (RTSP_RESPONSE_BAD);
  652.   }
  653.   if (rtsp_setup_redirect(info) != 0) {
  654.     return (RTSP_RESPONSE_BAD);
  655.   }
  656.   return (RTSP_RESPONSE_REDIRECT);
  657. }
  658.       }
  659. #if 0
  660.       if (info->m_buffer_len != 0) {
  661. // We have more in the buffer - see if it's what
  662. // we need
  663. // clear out last response
  664. clear_decode_response(decode);
  665. memset(decode, 0, sizeof(rtsp_decode_t));
  666.       }
  667. #endif
  668.     } while (info->m_buffer_len != 0);
  669.   } 
  670.   return (RTSP_RESPONSE_RECV_ERROR);
  671. }
  672. /* end file rtsp_resp.c */