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

流媒体/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. 2001.  All Rights Reserved.
  17.  * 
  18.  * Contributor(s): 
  19.  *              Bill May        wmay@cisco.com
  20.  */
  21. /*
  22.  * http_util.c - http utilities.
  23.  */
  24. #include "systems.h"
  25. #include <time.h>
  26. #include "http_private.h"
  27. /*
  28.  * http_disect_url
  29.  * Carve URL up into portions that we can use - store them in the
  30.  * client structure.  url points after http:://
  31.  * We're looking for m_host (destination name), m_port (destination port)
  32.  * and m_resource (location of file on m_host - also called path)
  33.  */
  34. static int http_dissect_url (const char *name,
  35.     http_client_t *cptr)
  36. {
  37.   // Assume name points at host name
  38.   const char *uptr = name;
  39.   const char *nextslash, *nextcolon, *rightbracket;
  40.   char *host;
  41.   size_t hostlen;
  42.   // skip ahead after host
  43.   rightbracket = NULL;
  44.   if (*uptr == '[') {
  45.     rightbracket = strchr(uptr, ']');
  46.     if (rightbracket != NULL) {
  47.       uptr++;
  48.       // literal IPv6 address
  49.       if (rightbracket[1] == ':') {
  50. nextcolon = rightbracket + 1;
  51.       } else
  52. nextcolon = NULL;
  53.       nextslash = strchr(rightbracket, '/');
  54.     } else {
  55.       return -1;
  56.     }
  57.   } else {
  58.     nextslash = strchr(uptr, '/');
  59.     nextcolon = strchr(uptr, ':');
  60.   }
  61.   cptr->m_port = 80;
  62.   if (nextslash != NULL || nextcolon != NULL) {
  63.     if (nextcolon != NULL &&
  64. (nextcolon < nextslash || nextslash == NULL)) {
  65.       hostlen = nextcolon - uptr;
  66.       // have a port number
  67.       nextcolon++;
  68.       cptr->m_port = 0;
  69.       while (isdigit(*nextcolon)) {
  70. cptr->m_port *= 10;
  71. cptr->m_port += *nextcolon - '0';
  72. nextcolon++;
  73.       }
  74.       if (cptr->m_port == 0 || (*nextcolon != '/' && *nextcolon != '')) {
  75. return (-1);
  76.       }
  77.     } else {
  78.       // no port number
  79.       hostlen = nextslash - uptr;
  80.     }
  81.     if (hostlen == 0) {
  82.       return (-1);
  83.     }
  84.     FREE_CHECK(cptr, m_host);
  85.     if (rightbracket != NULL) hostlen--;
  86.     host = malloc(hostlen + 1);
  87.     if (host == NULL) {
  88.       return (-1);
  89.     }
  90.     memcpy(host, uptr, hostlen);
  91.     host[hostlen] = '';
  92.     cptr->m_host = host;
  93.   } else {
  94.     if (*uptr == '') {
  95.       return (EINVAL);
  96.     }
  97.     FREE_CHECK(cptr, m_host);
  98.     host = strdup(uptr);
  99.     if (rightbracket != NULL) {
  100.        host[strlen(host) - 1] = '';
  101.     }
  102.     cptr->m_host = host;
  103.   }
  104.   
  105.   FREE_CHECK(cptr, m_resource);
  106.   if (nextslash != NULL) {
  107.     cptr->m_resource = strdup(nextslash);
  108.   } else {
  109.     cptr->m_resource = strdup("/");
  110.   }
  111.   return (0);
  112. }
  113.   
  114. /*
  115.  * http_decode_and_connect_url
  116.  * decode the url, and connect it.  If we were already connected,
  117.  * disconnect the socket and move forward
  118.  */
  119. int http_decode_and_connect_url (const char *name,
  120.  http_client_t *cptr)
  121. {
  122.   int check_open;
  123.   uint16_t port;
  124.   const char *old_host;
  125.   struct hostent *host;
  126.   struct sockaddr_in sockaddr;
  127.   int result;
  128.   
  129.   if (strncasecmp(name, "http://", strlen("http://")) != 0) {
  130.     return (-1);
  131.   }
  132.   name += strlen("http://");
  133.   check_open = 0;
  134.   port = 80;
  135.   old_host = NULL;
  136.   if (cptr->m_state == HTTP_STATE_CONNECTED) {
  137.     check_open = 1;
  138.     port = cptr->m_port;
  139.     old_host = cptr->m_host;
  140.     cptr->m_host = NULL; // don't inadvertantly free it
  141.   }
  142.   if (http_dissect_url(name, cptr) < 0) {
  143.     // If there's an error - nothing's changed
  144.     return (-1);
  145.   }
  146.   if (check_open) {
  147.     // See if the existing host matches the new one
  148.     int match = 0;
  149.     // Compare strings, first
  150.     if (strcasecmp(old_host, cptr->m_host) == 0) {
  151.       // match
  152.       if (port == cptr->m_port) {
  153. match = 1;
  154.       }
  155.     } else {
  156.       // Might be same - resolve new address and compare
  157.       host = gethostbyname(cptr->m_host);
  158.       if (host == NULL) {
  159. #ifdef _WIN32
  160.   return -1;
  161. #else
  162. if (h_errno > 0) h_errno = 0 - h_errno;
  163. return (h_errno);
  164. #endif
  165.       }
  166.       if (memcmp(host->h_addr,
  167.  &cptr->m_server_addr,
  168.  sizeof(struct in_addr)) == 0 &&
  169.   (port == cptr->m_port)) {
  170. match = 1;
  171.       } else {
  172. cptr->m_server_addr = *(struct in_addr *)host->h_addr;
  173.       }
  174.     }
  175.     free((void *)old_host); // free off the old one we saved
  176.     if (match == 0) {
  177.       cptr->m_state = HTTP_STATE_CLOSED;
  178.       closesocket(cptr->m_server_socket);
  179.       cptr->m_server_socket = -1;
  180.     } else {
  181.       // keep using the same socket...
  182.       return 0;
  183.     }
  184.     
  185.   } else {
  186.     // No existing connection - get the new address.
  187.     host = gethostbyname(cptr->m_host);
  188.     if (host == NULL) {
  189. #ifdef _WIN32
  190. return -1;
  191. #else
  192.       if (h_errno > 0) h_errno = 0 - h_errno;
  193.       return (h_errno);
  194. #endif
  195.     }
  196.     cptr->m_server_addr = *(struct in_addr *)host->h_addr;
  197.   }
  198.   // Create and connect the socket
  199.   cptr->m_server_socket = socket(AF_INET, SOCK_STREAM, 0);
  200.   if (cptr->m_server_socket == -1) {
  201.     return (-1);
  202.   }
  203.   sockaddr.sin_family = AF_INET;
  204.   sockaddr.sin_port = htons(cptr->m_port);
  205.   sockaddr.sin_addr = cptr->m_server_addr;
  206.   result = connect(cptr->m_server_socket,
  207.    (struct sockaddr *)&sockaddr,
  208.    sizeof(sockaddr));
  209.   if (result == -1) {
  210.     return (-1);
  211.   }
  212.   cptr->m_state = HTTP_STATE_CONNECTED;
  213.   return (0);
  214. }
  215. static const char *user_agent = "Mpeg4ip http library 0.1";
  216. /*
  217.  * http_build_header - create a header string
  218.  * Will eventually want to expand this if we want to specify
  219.  * content type, etc.
  220.  */
  221. int http_build_header (char *buffer,
  222.        uint32_t maxlen,
  223.        uint32_t *at,
  224.        http_client_t *cptr,
  225.        const char *method)
  226. {
  227.   int ret;
  228. #define SNPRINTF_CHECK(fmt, value) 
  229.   ret = snprintf(buffer + *at, maxlen - *at, (fmt), (value)); 
  230.   if (ret == -1) { 
  231.     return (-1); 
  232.   }
  233.   *at += ret;
  234.   ret = snprintf(buffer,
  235.  maxlen,
  236.  "%s %s HTTP/1.1rnHost: %srn",
  237.  method,
  238.  cptr->m_resource,
  239.  cptr->m_host);
  240.   if (ret == -1) return -1;
  241.   *at += ret;
  242.   SNPRINTF_CHECK("User-Agent: %srn", user_agent);
  243.   SNPRINTF_CHECK("%s", "rn");
  244. #undef SNPRINTF_CHECK
  245.   return (ret);
  246. }
  247. /*
  248.  * Logging code
  249.  */
  250. static int http_debug_level = LOG_ERR;
  251. static error_msg_func_t error_msg_func = NULL;
  252. void http_set_loglevel (int loglevel)
  253. {
  254.   http_debug_level = loglevel;
  255. }
  256. void http_set_error_func (error_msg_func_t func)
  257. {
  258.   error_msg_func = func;
  259. }
  260. void http_debug (int loglevel, const char *fmt, ...)
  261. {
  262.   va_list ap;
  263.   if (loglevel <= http_debug_level) {
  264.     va_start(ap, fmt);
  265.     if (error_msg_func != NULL) {
  266.       (error_msg_func)(loglevel, "libhttp", fmt, ap);
  267.     } else {
  268.  #if _WIN32 && _DEBUG
  269.   char msg[1024];
  270.       _vsnprintf(msg, 1024, fmt, ap);
  271.       OutputDebugString(msg);
  272.       OutputDebugString("n");
  273. #else
  274.       struct timeval thistime;
  275.       char buffer[80];
  276.       time_t secs;
  277.       gettimeofday(&thistime, NULL);
  278.       // To add date, add %a %b %d to strftime
  279.       secs = thistime.tv_sec;
  280.       strftime(buffer, sizeof(buffer), "%X", localtime(&secs));
  281.       printf("%s.%03ld-libhttp-%d: ",
  282.      buffer, (unsigned long)thistime.tv_usec / 1000, loglevel);
  283.       vprintf(fmt, ap);
  284.       printf("n");
  285. #endif
  286.     }
  287.     va_end(ap);
  288.   }
  289. }