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

📄 http_fetcher.cpp

📁 mysee网络直播源代码Mysee Lite是Mysee独立研发的网络视频流媒体播放系统。在应有了P2P技术和一系列先进流媒体技术之后
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* http_fetcher.c - HTTP handling functions

	HTTP Fetcher 
	Copyright (C) 2001, 2003, 2004 Lyle Hanson (lhanson@users.sourceforge.net)

	This library is free software; you can redistribute it and/or
	modify it under the terms of the GNU Library General Public
	License as published by the Free Software Foundation; either
	version 2 of the License, or (at your option) any later version.

	This library is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
	Library General Public License for more details.

	See LICENSE file for details

 */

#include "stdafx.h"
#include "http_fetcher.h"

HttpFetcher::HttpFetcher() : DEFAULT_VERSION("1.1"), HTTP_VERSION("HTTP/1.0"), DEFAULT_USER_AGENT("Chaos Client")
	{
	errorSource = 0;
	http_errno = 0;
	errorInt = 0;			/* When the error message has a %d in it,
							*	this variable is inserted */
	/* Note that '%d' cannot be escaped at this time */
	http_errlist[HF_SUCCESS] ="成功";
	http_errlist[HF_METAERROR] ="内部错误.";
	http_errlist[HF_NULLURL] ="无内容的URL";
	http_errlist[HF_HEADTIMEOUT] ="超时; %d秒钟内没有收到HTTP头";
	http_errlist[HF_DATATIMEOUT] ="超时; %d秒钟内没有收到数据";
	http_errlist[HF_FRETURNCODE] ="无返回代码";
	http_errlist[HF_CRETURNCODE] ="无效的返回代码";
	http_errlist[HF_STATUSCODE] ="状态代码是: %d. \r\n401:需要认证, 403:无法访问, 404:没有找到, 500:服务器出错";
	http_errlist[HF_CONTENTLEN] ="无效的内容长度(Content-Length)";
	http_errlist[HF_HERROR] ="网络错误 (description unavailable)";
	http_errlist[HF_CANTREDIRECT] ="状态代码是: %d,但是没有\"Location\"项";
	http_errlist[HF_MAXREDIRECTS] ="已经达到最大重定向次数(%d)";
	}

	/* 
	 * Actually downloads the url to localFile.
	 * Returns size of download on success, -1 on error is set, 
	 */
int HttpFetcher::http_fetch(const char *url_tmp, HANDLE localFile, UINT& fileSize, UINT& downloadedSize, double limitSpeed)
	{
	fd_set rfds;
	struct timeval tv;
	char headerBuf[HEADER_BUF_SIZE];
	char *tmp, *url, *requestBuf = NULL, *host, *charIndex;
	int sock, bufsize = REQUEST_BUF_SIZE;
	int i,
		ret = -1,
		tempSize,
		selectRet,
		found = 0,	/* For redirects */
		redirectsFollowed = 0;
	downloadedSize = 0;
	fileSize = -1;


	if(url_tmp == NULL)
		{
		errorSource = FETCHER_ERROR;
		http_errno = HF_NULLURL;
		return -1;
		}

	/* Copy the url passed in into a buffer we can work with, change, etc. */
	url = (char*)malloc(strlen(url_tmp)+1);
	if(url == NULL)
		{
		errorSource = ERRNO;
		return -1;
		}
	strncpy(url, url_tmp, strlen(url_tmp) + 1);
	
	/* This loop allows us to follow redirects if need be.  An afterthought,
	 * added to provide this basic functionality.  Will hopefully be designed
	 * better in 2.x.x ;) */
	do {
		/* Seek to the file path portion of the url */
		charIndex = strstr(url, "://");
		if(charIndex != NULL)
			{
			/* url contains a protocol field */
			charIndex += strlen("://");
			host = charIndex;
			charIndex = strchr(charIndex, '/');
			}
		else
			{
			host = (char *)url;
			charIndex = strchr(url, '/');
			}

		/* Compose a request string */
		requestBuf = (char*)malloc(bufsize);
		if(requestBuf == NULL)
			{
			free(url);
			errorSource = ERRNO;
			return -1;
			}
		requestBuf[0] = 0;

		if(charIndex == NULL)
			{
			/* The url has no '/' in it, assume the user is making a root-level
			 *	request */ 
			tempSize = strlen("GET /") + strlen(HTTP_VERSION) + 2;
			if(_checkBufSize(&requestBuf, &bufsize, tempSize) ||
				_snprintf(requestBuf, bufsize, "GET / %s\r\n", HTTP_VERSION) < 0)
				{
				free(url);
				free(requestBuf);
				errorSource = ERRNO;
				return -1;
				}
			}
		else
			{
			tempSize = strlen("GET ") + strlen(charIndex) +
  	          strlen(HTTP_VERSION) + 4;
		 	/* + 4 is for ' ', '\r', '\n', and NULL */
                                    
			if(_checkBufSize(&requestBuf, &bufsize, tempSize) ||
					_snprintf(requestBuf, bufsize, "GET %s %s\r\n",
					charIndex, HTTP_VERSION) < 0)
				{
				free(url);
				free(requestBuf);
				errorSource = ERRNO;
				return -1;
				}
			}

		/* Null out the end of the hostname if need be */
		if(charIndex != NULL)
			*charIndex = 0;

		/* Use Host: even though 1.0 doesn't specify it.  Some servers
		 *	won't play nice if we don't send Host, and it shouldn't
		 *	hurt anything */
		ret = bufsize - strlen(requestBuf); /* Space left in buffer */
		tempSize = (int)strlen("Host: ") + (int)strlen(host) + 3;
        /* +3 for "\r\n\0" */
		if(_checkBufSize(&requestBuf, &bufsize, tempSize + 128))
			{
			free(url);
			free(requestBuf);
			errorSource = ERRNO;
			return -1;
			}
		strcat(requestBuf, "Host: ");
		strcat(requestBuf, host);
		strcat(requestBuf, "\r\n");

		tempSize = (int)strlen("User-Agent: ") +
			(int)strlen(DEFAULT_USER_AGENT) + (int)strlen(DEFAULT_VERSION) + 4;
   	    /* + 4 is for '\', '\r', '\n', and NULL */
		if(_checkBufSize(&requestBuf, &bufsize, tempSize))
			{
			free(url);
			free(requestBuf);
			errorSource = ERRNO;
			return -1;
			}
		strcat(requestBuf, "User-Agent: ");
		strcat(requestBuf, DEFAULT_USER_AGENT);
		strcat(requestBuf, "/");
		strcat(requestBuf, DEFAULT_VERSION);
		strcat(requestBuf, "\r\n");

		tempSize = (int)strlen("Connection: Close\r\n\r\n");
		if(_checkBufSize(&requestBuf, &bufsize, tempSize))
			{
			free(url);
			free(requestBuf);
			errorSource = ERRNO;
			return -1;
			}
		strcat(requestBuf, "Connection: Close\r\n\r\n");

		/* Now free any excess memory allocated to the buffer */
		tmp = (char*)realloc(requestBuf, strlen(requestBuf) + 1);
		if(tmp == NULL)
			{
			free(url);
			free(requestBuf);
			errorSource = ERRNO;
			return -1;
			}
		requestBuf = tmp;

 		sock = makeSocket(host);		/* errorSource set within makeSocket */
		if(sock == -1) { free(url); free(requestBuf); return -1;}

		free(url);
        url = NULL;

		if(send(sock, requestBuf, strlen(requestBuf), 0) == -1) // added by jarjar
		//if(write(sock, requestBuf, strlen(requestBuf)) == -1) // removed by jarjar
			{
			closesocket(sock); // added by jarjar
			//close(sock);  // removed by jarjar
			free(requestBuf);
			errorSource = ERRNO;
			return -1;
			}

		free(requestBuf);
        requestBuf = NULL;

		/* Grab enough of the response to get the metadata */
		ret = _http_read_header(sock, headerBuf);	/* errorSource set within */
		if(ret < 0) 
			{ 
			closesocket(sock); // added by jarjar
			//close(sock);  // removed by jarjar
			return -1; 
			}

		/* Get the return code */
		charIndex = strstr(headerBuf, "HTTP/");
		if(charIndex == NULL)
			{
			closesocket(sock); // added by jarjar
			//close(sock);  // removed by jarjar
			errorSource = FETCHER_ERROR;
			http_errno = HF_FRETURNCODE;
			return -1;
			}
		while(*charIndex != ' ')
			charIndex++;
		charIndex++;

		ret = sscanf(charIndex, "%d", &i);
		if(ret != 1)
			{
			closesocket(sock); // added by jarjar
			//close(sock);  // removed by jarjar
			errorSource = FETCHER_ERROR;
			http_errno = HF_CRETURNCODE;
			return -1;
			}
		if(i<200 || i>307)
			{
			closesocket(sock); // added by jarjar
			//close(sock);  // removed by jarjar
			errorInt = i;	/* Status code, to be inserted in error string */
			errorSource = FETCHER_ERROR;
			http_errno = HF_STATUSCODE;
			return -1;
			}

		/* If a redirect, repeat operation until final URL is found or we
		 *  redirect DEFAULT_REDIRECTS times.  Note the case sensitive "Location",
		 *  should probably be made more robust in the future (without relying
		 *  on the non-standard strcasecmp()).
		 * This bit mostly by Dean Wilder, tweaked by me */
		if(i >= 300)
			{
		    redirectsFollowed++;

			/* Pick up redirect URL, allocate new url, and repeat process */
			charIndex = strstr(headerBuf, "Location:");
			if(!charIndex)
				{
				closesocket(sock); // added by jarjar
				//close(sock);  // removed by jarjar
				errorInt = i; /* Status code, to be inserted in error string */
				errorSource = FETCHER_ERROR;
				http_errno = HF_CANTREDIRECT;
				return -1;
				}
			charIndex += strlen("Location:");
            /* Skip any whitespace... */
            while(*charIndex != '\0' && isspace(*charIndex))
                charIndex++;
            if(*charIndex == '\0')
                {
				closesocket(sock); // added by jarjar
				//close(sock);  // removed by jarjar
				errorInt = i; /* Status code, to be inserted in error string */
				errorSource = FETCHER_ERROR;
				http_errno = HF_CANTREDIRECT;
				return -1;
                }

			i = strcspn(charIndex, " \r\n");
			if(i > 0)
				{
				url = (char *)malloc(i + 1);
				strncpy(url, charIndex, i);
				url[i] = '\0';

⌨️ 快捷键说明

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