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

📄 http_fetcher.cpp

📁 mysee网络直播源代码Mysee Lite是Mysee独立研发的网络视频流媒体播放系统。在应有了P2P技术和一系列先进流媒体技术之后
💻 CPP
📖 第 1 页 / 共 2 页
字号:
				}
			else
                /* Found 'Location:' but contains no URL!  We'll handle it as
                 * 'found', hopefully the resulting document will give the user
                 * a hint as to what happened. */
                found = 1;
            }
		else
			found = 1;
	    } while(!found && redirectsFollowed <= DEFAULT_REDIRECTS);

    if(url) /* Redirection code may malloc this, then exceed DEFAULT_REDIRECTS */
        {
        free(url);
        url = NULL;
        }
    
    if(redirectsFollowed >= DEFAULT_REDIRECTS && !found)
        {
		closesocket(sock); // added by jarjar
		//close(sock);  // removed by jarjar
    	errorInt = DEFAULT_REDIRECTS; /* To be inserted in error string */
    	errorSource = FETCHER_ERROR;
    	http_errno = HF_MAXREDIRECTS;
	    return -1;
        }
	
	/*
	 * Parse out about how big the data segment is.
	 *	Note that under current HTTP standards (1.1 and prior), the
	 *	Content-Length field is not guaranteed to be accurate or even present. 
	 *	I just use it here so I can allocate a ballpark amount of memory.
	 *
	 * Note that some servers use different capitalization
	 */
	charIndex = strstr(headerBuf, "Content-Length:");
	if(charIndex == NULL)
		charIndex = strstr(headerBuf, "Content-length:");

	if(charIndex != NULL)
		{
		ret = sscanf(charIndex + strlen("content-length: "), "%d",
			&fileSize);
		if(ret < 1)
			{
			closesocket(sock); // added by jarjar
			//close(sock);  // removed by jarjar
			errorSource = FETCHER_ERROR;
			http_errno = HF_CONTENTLEN;
			return -1;
			}
		}

	char tmpReadBuf[BLOCK_SIZE];
	DWORD tmpWriteBytes = 0;
	tv.tv_sec = DEFAULT_READ_TIMEOUT; 
	tv.tv_usec = 0;
	DWORD dwStartTicks = GetTickCount();
	/* Begin reading the body of the file */
	while(ret > 0 && (fileSize == -1 || downloadedSize < fileSize) && localFile != INVALID_HANDLE_VALUE)
		{
		FD_ZERO(&rfds);
		FD_SET((SOCKET)sock, &rfds);

		selectRet = select(sock+1, &rfds, NULL, NULL, &tv);

		if(selectRet == 0)
			{
			// timeout means nothing
			continue;
			/*
			errorSource = FETCHER_ERROR;
			http_errno = HF_DATATIMEOUT;
			errorInt = DEFAULT_READ_TIMEOUT;
			closesocket(sock); // added by jarjar
			//close(sock);  // removed by jarjar
			return -1;
			*/
			}
		else if(selectRet == -1)
			{
			closesocket(sock); // added by jarjar
			//close(sock);  // removed by jarjar
			errorSource = ERRNO;
			return -1;
			}

		ret = recv(sock, tmpReadBuf, BLOCK_SIZE, 0); // added by jarjar 
		if(ret == -1)
			{
			closesocket(sock); // added by jarjar
			//close(sock);  // removed by jarjar
			errorSource = ERRNO;
			return -1;
			}

		if(INVALID_SET_FILE_POINTER == SetFilePointer(localFile, downloadedSize, 0, FILE_BEGIN))
			{
			int xxx = GetLastError();
			closesocket(sock); // added by jarjar
			//close(sock);  // removed by jarjar
			errorSource = ERRNO;
			return -1;
			}

		downloadedSize += ret;

		if(!WriteFile(localFile, tmpReadBuf, ret, &tmpWriteBytes, NULL) || tmpWriteBytes != ret)
			{
			int xxx = GetLastError();
			closesocket(sock); // added by jarjar
			//close(sock);  // removed by jarjar
			errorSource = ERRNO;
			return -1;
			}

        // For bandwidth throttling
		if (limitSpeed > 0.0f) 
			{
			double t = (double)(GetTickCount() - dwStartTicks);
			double q = (double)((double)downloadedSize / t);
			
			if (q > limitSpeed)	
				Sleep((DWORD)((((q*t)/limitSpeed)-t)));
			}
		}
	
	::FlushFileBuffers(localFile);
	closesocket(sock); // added by jarjar
	//close(sock);  // removed by jarjar
	return downloadedSize;
	}


	/* 
	 * Returns a pointer to the current error description message. The
	 *	message pointed to is only good until the next call to http_strerror(),
	 *	so if you need to hold on to the message for a while you should make
	 *	a copy of it
	 */
const char* HttpFetcher::http_strerror()
	{
	int errno;
	
	if(errorSource == ERRNO)
		return strerror(errno);
	else if(errorSource == FETCHER_ERROR)
		{
		if(strstr(http_errlist[http_errno], "%d") == NULL)
			return http_errlist[http_errno];
		else
			{
			/* The error string has a %d in it, we need to insert errorInt.
			 *	convertedError[128] has been declared for that purpose */
			char *stringIndex, *originalError;
		
			originalError = (char *)http_errlist[http_errno];
			convertedError[0] = 0;		/* Start off with NULL */
			stringIndex = strstr(originalError, "%d");
			strncat(convertedError, originalError,		/* Copy up to %d */
				abs(stringIndex - originalError));
			sprintf(&convertedError[strlen(convertedError)],"%d",errorInt);
			stringIndex += 2;		/* Skip past the %d */
			strcat(convertedError, stringIndex);

			return convertedError;
			}
		}
		
	return http_errlist[HF_METAERROR];	/* Should NEVER happen */
	}

	
	/*
	 * Reads the metadata of an HTTP response.
	 * Perhaps a little inefficient, as it reads 1 byte at a time, but
	 *	I don't think it's that much of a loss (most headers aren't HUGE).
	 * Returns:
	 *	# of bytes read on success, or
	 *	-1 on error
	 */
int HttpFetcher::_http_read_header(int sock, char *headerPtr)
	{
	fd_set rfds;
	struct timeval tv;
	int bytesRead = 0, newlines = 0, ret, selectRet;

	while(newlines != 2 && bytesRead != HEADER_BUF_SIZE)
		{
		FD_ZERO(&rfds);
		FD_SET((SOCKET)sock, &rfds);
		tv.tv_sec = DEFAULT_READ_TIMEOUT; 
		tv.tv_usec = 0;

		selectRet = select(sock+1, &rfds, NULL, NULL, &tv);
		
		if(selectRet == 0)
			{
			errorSource = FETCHER_ERROR;
			http_errno = HF_HEADTIMEOUT;
			errorInt = DEFAULT_READ_TIMEOUT;
			return -1;
			}
		else if(selectRet == -1) { errorSource = ERRNO; return -1; }

		ret = recv(sock, headerPtr, 1, 0);
		//ret = read(sock, headerPtr, 1);  //removed by jarjar
		if(ret == -1) { errorSource = ERRNO; return -1; }
		bytesRead++;

		if(*headerPtr == '\r')			/* Ignore CR */
			{
			/* Basically do nothing special, just don't set newlines
			 *	to 0 */
			headerPtr++;
			continue;
			}
		else if(*headerPtr == '\n')		/* LF is the separator */
			newlines++;
		else
			newlines = 0;

		headerPtr++;
		}

	headerPtr -= 3;		/* Snip the trailing LF's */
	*headerPtr = '\0';
	return bytesRead;
	}



	/*
	 * Opens a TCP socket and returns the descriptor
	 * Returns:
	 *	socket descriptor, or
	 *	-1 on error
	 */
int HttpFetcher::makeSocket(const char *host)
	{
	int sock;										/* Socket descriptor */
	struct sockaddr_in sa;							/* Socket address */
	struct hostent *hp;								/* Host entity */
	int ret;
	u_short port; // added by jarjar
    //int port; // removed by jarjar
    char *p;
	
    /* Check for port number specified in URL */
    p = strchr(host, ':');
    if(p)
        {
        port = atoi(p + 1);
        *p = '\0';
        }
    else
        port = PORT_NUMBER;

	hp = gethostbyname(host);
	if(hp == NULL) { errorSource = ERRNO; return -1; }
		
	/* Copy host address from hostent to (server) socket address */
	memcpy((char *)&sa.sin_addr, (char *)hp->h_addr, hp->h_length);
	sa.sin_family = hp->h_addrtype;		/* Set service sin_family to PF_INET */
	sa.sin_port = htons(port);      	/* Put portnum into sockaddr */

	sock = socket(hp->h_addrtype, SOCK_STREAM, 0);
	if(sock == -1) { errorSource = ERRNO; return -1; }

	ret = connect(sock, (struct sockaddr *)&sa, sizeof(sa));
	if(ret == -1) { errorSource = ERRNO; return -1; }

	return sock;
	}



	/*
	 * Determines if the given NULL-terminated buffer is large enough to
	 * 	concatenate the given number of characters.  If not, it attempts to
	 * 	grow the buffer to fit.
	 * Returns:
	 *	0 on success, or
	 *	-1 on error (original buffer is unchanged).
	 */
int HttpFetcher::_checkBufSize(char **buf, int *bufsize, int more)
	{
	char *tmp;
	int roomLeft = *bufsize - (strlen(*buf) + 1);
	if(roomLeft > more)
		return 0;
	tmp = (char*)realloc(*buf, *bufsize + more + 1);
	if(tmp == NULL)
		return -1;
	*buf = tmp;
	*bufsize += more + 1;
	return 0;
	}

⌨️ 快捷键说明

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