📄 http_util.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 + -