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

流媒体/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_comm.c - contains communication routines.
  23.  */
  24. #include "rtsp_private.h"
  25. #ifdef HAVE_POLL
  26. #include <sys/poll.h>
  27. #endif
  28. #if !defined(HAVE_ST_ADDRINFO) && !defined(_WIN32)
  29. #include "addrinfo.h"
  30. #endif
  31. /*
  32.  * rtsp_create_socket()
  33.  * creates and connects socket to server.  Requires rtsp_info_t fields
  34.  * port, server_addr, server_name be set.
  35.  * returns 0 for success, -1 for failure
  36.  */
  37. static int rtsp_get_server_address (rtsp_client_t *info)
  38. {
  39. #ifdef HAVE_IPv6
  40.   struct addrinfo hints;
  41.   char port[32];
  42.   int error;
  43.   
  44.   snprintf(port, sizeof(port), "%d", info->port);
  45.   memset(&hints, 0, sizeof(hints));
  46.   hints.ai_family = PF_UNSPEC;
  47.   hints.ai_socktype = SOCK_STREAM;
  48.   error = getaddrinfo(info->server_name, port, &hints, &info->addr_info);
  49.   if (error) {
  50.     rtsp_debug(LOG_CRIT, "Can't get server address info %s - error %d", 
  51.        info->server_name, h_errno);
  52.     return h_errno;
  53.   }
  54. #else
  55.   struct hostent *host;
  56. #if defined(_WIN32) || !defined(HAVE_INET_NTOA)
  57.   info->server_addr.s_addr = inet_addr(info->server_name);
  58.   if (info->server_addr.s_addr != INADDR_NONE) return 0;
  59. #else
  60.   if (inet_aton(info->server_name, &info->server_addr) != 0) return 0;
  61. #endif
  62.   
  63.   host = gethostbyname(info->server_name);
  64.   if (host == NULL) {
  65.     rtsp_debug(LOG_CRIT, "Can't get server host name %s", info->server_name);
  66.     return (h_errno);
  67.   }
  68.   info->server_addr = *(struct in_addr *)host->h_addr;
  69. #endif
  70.   return 0;
  71. }
  72. int rtsp_create_socket (rtsp_client_t *info)
  73. {
  74. #ifndef HAVE_IPv6
  75.   struct sockaddr_in sockaddr;
  76. #endif
  77.   int result;
  78.   // Do we have a socket already - if so, go ahead
  79.   if (info->server_socket != -1) {
  80.     return (0);
  81.   }
  82.   
  83.   if (info->server_name == NULL) {
  84.     rtsp_debug(LOG_CRIT, "No server name in create socket");
  85.     return (-1);
  86.   }
  87.   result = rtsp_get_server_address(info);
  88.   if (result != 0) return -1;
  89.   
  90. #ifndef _WIN32
  91. #ifdef HAVE_IPv6
  92.   info->server_socket = socket(info->addr_info->ai_family,
  93.        info->addr_info->ai_socktype,
  94.        info->addr_info->ai_protocol);
  95. #else
  96.   info->server_socket = socket(AF_INET, SOCK_STREAM, 0);
  97. #endif
  98. #else
  99.   info->server_socket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, 0);
  100. #endif
  101.   if (info->server_socket == -1) {
  102.     rtsp_debug(LOG_CRIT, "Couldn't create socket");
  103.     return (-1);
  104.   }
  105.   
  106. #ifndef HAVE_IPv6  
  107.   sockaddr.sin_family = AF_INET;
  108.   sockaddr.sin_port = htons(info->port);
  109.   sockaddr.sin_addr = info->server_addr;
  110. #endif
  111. #ifndef _WIN32
  112.   result = connect(info->server_socket,
  113. #ifndef HAVE_IPv6
  114.    (struct sockaddr *)&sockaddr,
  115.    sizeof(sockaddr)
  116. #else
  117.    info->addr_info->ai_addr,
  118.    info->addr_info->ai_addrlen
  119. #endif
  120.    );
  121.   if (result < 0)
  122. #else
  123.   result = WSAConnect(info->server_socket, 
  124.                   (struct sockaddr *)&sockaddr,
  125.   sizeof(sockaddr), 
  126.   NULL, 
  127.   NULL, 
  128.   NULL, 
  129.   NULL);
  130.   if (result != 0)
  131. #endif
  132.   {
  133.     rtsp_debug(LOG_CRIT, "Couldn't connect socket - error %s",
  134.        strerror(errno)
  135.        );
  136.     return (-1);
  137.   }
  138.   if (info->thread != NULL) {
  139. #ifndef _WIN32
  140.     result = fcntl(info->server_socket, F_GETFL);
  141.     result = fcntl(info->server_socket, F_SETFL, result | O_NONBLOCK);
  142.     if (result < 0) {
  143.       rtsp_debug(LOG_ERR, "Couldn't create nonblocking %s", 
  144.  strerror(errno)
  145.  );
  146.     }
  147. #else
  148. rtsp_thread_set_nonblocking(info);
  149. #endif
  150.   }
  151.   return (0);
  152. }
  153. /*
  154.  * rtsp_send()
  155.  * Sends a buffer over connected socket.  If socket isn't connected,
  156.  * tries that first.
  157.  * Buffer must be formatted to RTSP spec.
  158.  * Inputs:
  159.  *   info - pointer to rtsp_client_t for client session
  160.  *   buff - pointer to buffer
  161.  *   len  - length of buffer
  162.  * Outputs:
  163.  *   0 - success, -1 failure
  164.  */
  165. int rtsp_send (rtsp_client_t *info, const char *buff, uint32_t len)
  166. {
  167.   int ret;
  168.   if (info->server_socket == -1) {
  169.     if (rtsp_create_socket(info) != 0)
  170.       return (-1);
  171.   }
  172.   ret = send(info->server_socket, buff, len, 0);
  173.   return (ret);
  174. }
  175. /*
  176.  * rtsp_receive()
  177.  * Receives a response from server with a timeout.  If recv returns a
  178.  * full buffer, and the last character is not r or n, will make a
  179.  * bigger buffer and try to receive.
  180.  *
  181.  * Will set fields in rtsp_client_t.  Relevent fields are:
  182.  *   recv_buff - pointer to receive buffer (malloc'ed so we can always add
  183.  *            at end).
  184.  *   recv_buff_len - max size of receive buffer.
  185.  *   recv_buff_used - number of bytes received.
  186.  *   recv_buff_parsed - used by above routine in case we got more than
  187.  *      1 response at a time.
  188.  */
  189. int rtsp_receive_socket (rtsp_client_t *info, char *buffer, uint32_t len,
  190.  uint32_t msec_timeout, int wait)
  191. {
  192.   int ret;
  193. #ifdef HAVE_POLL
  194.   struct pollfd pollit;
  195. #else
  196.   fd_set read_set;
  197.   struct timeval timeout;
  198. #endif
  199.   if (msec_timeout != 0 && wait != 0) {
  200. #ifdef HAVE_POLL
  201.     pollit.fd = info->server_socket;
  202.     pollit.events = POLLIN | POLLPRI;
  203.     pollit.revents = 0;
  204.     ret = poll(&pollit, 1, msec_timeout);
  205. #else
  206.     FD_ZERO(&read_set);
  207.     FD_SET(info->server_socket, &read_set);
  208.     timeout.tv_sec = msec_timeout / 1000;
  209.     timeout.tv_usec = (msec_timeout % 1000) * 1000;
  210.     ret = select(info->server_socket + 1, &read_set, NULL, NULL, &timeout);
  211. #endif
  212.     if (ret <= 0) {
  213.       rtsp_debug(LOG_ERR, "Response timed out %d %d", msec_timeout, ret);
  214.       if (ret == -1) {
  215. rtsp_debug(LOG_ERR, "Error is %s", 
  216.    strerror(errno));
  217.       }
  218.       return (-1);
  219.     }
  220.   }
  221.   //rtsp_debug(LOG_DEBUG, "Calling recv");
  222. #ifndef _WIN32
  223.   ret = recv(info->server_socket, buffer, len, 0);
  224. #else 
  225.   {
  226.   WSABUF foo;
  227.   int val;
  228.   DWORD flag = 0;
  229.   DWORD bytes;
  230.   foo.buf = buffer;
  231.   foo.len = len;
  232.   val = WSARecv(info->server_socket, &foo, 1, &bytes, &flag, NULL, NULL);
  233.   if (val != 0) {
  234.   //rtsp_debug(LOG_DEBUG, "error is %d", WSAGetLastError());
  235.   return -1;
  236.   }
  237.   ret = bytes;
  238.   //rtsp_debug(LOG_DEBUG, "recvd %d bytes", ret);
  239.   }
  240. #endif
  241.   return (ret);
  242. }
  243. /*
  244.  * rtsp_close_socket
  245.  * closes the socket.  Duh.
  246.  */
  247. void rtsp_close_socket (rtsp_client_t *info)
  248. {
  249.   if (info->server_socket != -1)
  250.     closesocket(info->server_socket);
  251.   info->server_socket = -1;
  252. #ifdef HAVE_ST_ADDRINFO
  253.   CHECK_AND_FREE(info,addr_info);
  254. #endif
  255. }