⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 http_util.c

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 C
字号:
/*
 * The contents of this file are subject to the Mozilla Public
 * License Version 1.1 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of
 * the License at http://www.mozilla.org/MPL/
 * 
 * Software distributed under the License is distributed on an "AS
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * rights and limitations under the License.
 * 
 * The Original Code is MPEG4IP.
 * 
 * The Initial Developer of the Original Code is Cisco Systems Inc.
 * Portions created by Cisco Systems Inc. are
 * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
 * 
 * Contributor(s): 
 *              Bill May        wmay@cisco.com
 */
/*
 * http_util.c - http utilities.
 */
#include "systems.h"
#include <time.h>
#include "http_private.h"

/*
 * http_disect_url
 * Carve URL up into portions that we can use - store them in the
 * client structure.  url points after http:://
 * We're looking for m_host (destination name), m_port (destination port)
 * and m_resource (location of file on m_host - also called path)
 */
static int http_dissect_url (const char *name,
			    http_client_t *cptr)
{
  // Assume name points at host name
  const char *uptr = name;
  const char *nextslash, *nextcolon, *rightbracket;
  char *host;
  size_t hostlen;

  // skip ahead after host
  rightbracket = NULL;
  if (*uptr == '[') {
    rightbracket = strchr(uptr, ']');
    if (rightbracket != NULL) {
      uptr++;
      // literal IPv6 address
      if (rightbracket[1] == ':') {
	nextcolon = rightbracket + 1;
      } else
	nextcolon = NULL;
      nextslash = strchr(rightbracket, '/');
    } else {
      return -1;
    }
  } else {
    nextslash = strchr(uptr, '/');
    nextcolon = strchr(uptr, ':');
  }

  cptr->m_port = 80;
  if (nextslash != NULL || nextcolon != NULL) {
    if (nextcolon != NULL &&
	(nextcolon < nextslash || nextslash == NULL)) {
      hostlen = nextcolon - uptr;
      // have a port number
      nextcolon++;
      cptr->m_port = 0;
      while (isdigit(*nextcolon)) {
	cptr->m_port *= 10;
	cptr->m_port += *nextcolon - '0';
	nextcolon++;
      }
      if (cptr->m_port == 0 || (*nextcolon != '/' && *nextcolon != '\0')) {
	return (-1);
      }
    } else {
      // no port number
      hostlen = nextslash - uptr;
	
    }
    if (hostlen == 0) {
      return (-1);
    }
    FREE_CHECK(cptr, m_host);
    if (rightbracket != NULL) hostlen--;
    host = malloc(hostlen + 1);
    if (host == NULL) {
      return (-1);
    }
    memcpy(host, uptr, hostlen);
    host[hostlen] = '\0';
    cptr->m_host = host;
  } else {
    if (*uptr == '\0') {
      return (EINVAL);
    }
    FREE_CHECK(cptr, m_host);
    host = strdup(uptr);
    if (rightbracket != NULL) {
       host[strlen(host) - 1] = '\0';
    }
    cptr->m_host = host;
  }
  
  FREE_CHECK(cptr, m_resource);
  if (nextslash != NULL) {
    cptr->m_resource = strdup(nextslash);
  } else {
    cptr->m_resource = strdup("/");
  }
  return (0);
}
  
/*
 * http_decode_and_connect_url
 * decode the url, and connect it.  If we were already connected,
 * disconnect the socket and move forward
 */
int http_decode_and_connect_url (const char *name,
				 http_client_t *cptr)
{
  int check_open;
  uint16_t port;
  const char *old_host;
  struct hostent *host;
  struct sockaddr_in sockaddr;
  int result;
  
  if (strncasecmp(name, "http://", strlen("http://")) != 0) {
    return (-1);
  }
  name += strlen("http://");

  check_open = 0;
  port = 80;
  old_host = NULL;
  if (cptr->m_state == HTTP_STATE_CONNECTED) {
    check_open = 1;
    port = cptr->m_port;
    old_host = cptr->m_host;
    cptr->m_host = NULL; // don't inadvertantly free it
  }

  if (http_dissect_url(name, cptr) < 0) {
    // If there's an error - nothing's changed
    return (-1);
  }

  if (check_open) {
    // See if the existing host matches the new one
    int match = 0;
    // Compare strings, first
    if (strcasecmp(old_host, cptr->m_host) == 0) {
      // match
      if (port == cptr->m_port) {
	match = 1;
      }
    } else {
      // Might be same - resolve new address and compare
      host = gethostbyname(cptr->m_host);
      if (host == NULL) {
#ifdef _WIN32
		  return -1;
#else
	if (h_errno > 0) h_errno = 0 - h_errno;
	return (h_errno);
#endif
      }
      if (memcmp(host->h_addr,
		 &cptr->m_server_addr,
		 sizeof(struct in_addr)) == 0 &&
	  (port == cptr->m_port)) {
	match = 1;
      } else {
	cptr->m_server_addr = *(struct in_addr *)host->h_addr;
      }
    }
    free((void *)old_host); // free off the old one we saved
    if (match == 0) {
      cptr->m_state = HTTP_STATE_CLOSED;
      closesocket(cptr->m_server_socket);
      cptr->m_server_socket = -1;
    } else {
      // keep using the same socket...
      return 0;
    }
    
  } else {
    // No existing connection - get the new address.
    host = gethostbyname(cptr->m_host);
    if (host == NULL) {
#ifdef _WIN32
		return -1;
#else
      if (h_errno > 0) h_errno = 0 - h_errno;
      return (h_errno);
#endif
    }
    cptr->m_server_addr = *(struct in_addr *)host->h_addr;
  }

  // Create and connect the socket
  cptr->m_server_socket = socket(AF_INET, SOCK_STREAM, 0);
  if (cptr->m_server_socket == -1) {
    return (-1);
  }
  sockaddr.sin_family = AF_INET;
  sockaddr.sin_port = htons(cptr->m_port);
  sockaddr.sin_addr = cptr->m_server_addr;

  result = connect(cptr->m_server_socket,
		   (struct sockaddr *)&sockaddr,
		   sizeof(sockaddr));

  if (result == -1) {
    return (-1);
  }
  cptr->m_state = HTTP_STATE_CONNECTED;
  return (0);
}

static const char *user_agent = "Mpeg4ip http library 0.1";

/*
 * http_build_header - create a header string
 * Will eventually want to expand this if we want to specify
 * content type, etc.
 */
int http_build_header (char *buffer,
		       uint32_t maxlen,
		       uint32_t *at,
		       http_client_t *cptr,
		       const char *method)
{
  int ret;
#define SNPRINTF_CHECK(fmt, value) \
  ret = snprintf(buffer + *at, maxlen - *at, (fmt), (value)); \
  if (ret == -1) { \
    return (-1); \
  }\
  *at += ret;

  ret = snprintf(buffer,
		 maxlen,
		 "%s %s HTTP/1.1\r\nHost: %s\r\n",
		 method,
		 cptr->m_resource,
		 cptr->m_host);
  if (ret == -1) return -1;
  *at += ret;
  SNPRINTF_CHECK("User-Agent: %s\r\n", user_agent);
  SNPRINTF_CHECK("%s", "\r\n");
#undef SNPRINTF_CHECK
  return (ret);
}

/*
 * Logging code
 */
static int http_debug_level = LOG_ERR;
static error_msg_func_t error_msg_func = NULL;

void http_set_loglevel (int loglevel)
{
  http_debug_level = loglevel;
}

void http_set_error_func (error_msg_func_t func)
{
  error_msg_func = func;
}

void http_debug (int loglevel, const char *fmt, ...)
{
  va_list ap;
  if (loglevel <= http_debug_level) {
    va_start(ap, fmt);
    if (error_msg_func != NULL) {
      (error_msg_func)(loglevel, "libhttp", fmt, ap);
    } else {
 #if _WIN32 && _DEBUG
	  char msg[1024];

      _vsnprintf(msg, 1024, fmt, ap);
      OutputDebugString(msg);
      OutputDebugString("\n");
#else
      struct timeval thistime;
      char buffer[80];
      time_t secs;

      gettimeofday(&thistime, NULL);
      // To add date, add %a %b %d to strftime
      secs = thistime.tv_sec;
      strftime(buffer, sizeof(buffer), "%X", localtime(&secs));
      printf("%s.%03ld-libhttp-%d: ",
	     buffer, (unsigned long)thistime.tv_usec / 1000, loglevel);
      vprintf(fmt, ap);
      printf("\n");
#endif
    }
    va_end(ap);
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -