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

📄 http.c

📁 linux的多线程下载工具。基于gtk界面。
💻 C
📖 第 1 页 / 共 2 页
字号:
{	if(strnicmp(buf->data, "HTTP/", 5) != 0) return 0;	return atoi(buf->data + 9);}//get HTTP header tag value.     eg: Content-Length: 2032STRING *http_header_get_tag(BUFFER *buf, CHAR *tag){	CHAR t[100];	CHAR *p, *p1;	STRING *value;	value = string_new("");
	sprintf(t, "\r\n%s:", tag);		p = bufstri(buf, NULL, t);	if(!p) return value;			p = p + strlen(t);	p1 = bufstr(buf, p, "\r\n");	if(p1 == NULL) return value;			while(*p == ' ' || *p == '\t') p++;			return string_nappend(value, p, p1 - p);}BOOL http_header_is_finished(BUFFER *buf){	return (bufstr(buf, NULL, "\r\n\r\n") != NULL);}//get the offset of the data from the HTTP headerINT http_header_get_data_offset(BUFFER *buf){	CHAR *p;	p = bufstr(buf, NULL, "\r\n\r\n") + 4;	return (p - buf->data);}





VOID http_taskthread_process_connection(HttpTaskThread *taskthread)
{
	DldTask *task;
	BOOL readable, writeable, error;
	STRING *request = NULL;
	STRING *value;
	INT httpcode;
	INT recvlen = 0;
	INT offset;
	INT ret;
	BOOL blockfinished;
	CHAR recvbuf[SOCKET_BUF_MAX + 1];
	//HttpTaskThread *taskthread;
	
	//taskthread = (HttpTaskThread *)dldtaskthread;

	task = taskthread->parenttask;

	if(!taskthread) return;
	if(taskthread->status != DLD_TASKTHREAD_RUNNING) return;
		
	
	os_socket_tcp_status(taskthread->connsocket, &readable, &writeable, &error);
	
	if(error)
	{
		//network error ....
		http_taskthread_meet_error(taskthread, FALSE);
		return;
	}
	
	if(writeable && taskthread->cmdstatus == HTTP_STATUS_WAITING)
	{
		//try to send request...
		
		//if the filesize is not zero, we can requst some part of the file
		if(task->filesize != 0)
		{
			//taskthread->block shoud be ready in http_taskthread_connect
			if(!taskthread->block) http_taskthread_stop((DldTaskThread *)taskthread);
			request = http_request_make(task, taskthread->block->start, taskthread->block->end);
		}
		else if(dld_taskthread_is_first((DldTaskThread *)taskthread))
		{
			//we haven't get the filesize. try to get it!
			request = http_request_make(task,  0, 0);
		}
		else //filesize == 0 && not first taskthread
		{
			//just do nothing
			request = NULL;
		}
		
		if(request)
		{
			dld_taskthread_add_log((DldTaskThread *)taskthread, _("Connected OK! Sending request ..."));
			os_socket_tcp_send(taskthread->connsocket, request->str, request->len);
			request = string_free(request);
			
			//prepare to recv http responses...
			taskthread->cmdstatus = HTTP_STATUS_WAIT_FOR_HEADER;
			taskthread->buffer = buffer_clear(taskthread->buffer);
		}				
	}

	blockfinished = FALSE;

	if(readable && taskthread->cmdstatus == HTTP_STATUS_WAIT_FOR_HEADER)
	{
		//readable, recv RESPONSE
		recvlen = os_socket_tcp_recv(taskthread->connsocket, recvbuf, SOCKET_BUF_MAX);
		//do
		//{
			if(recvlen > 0)
			{
				dprintf("[http_taskthread_process] %d : response ...\r\n", taskthread);
				
				//save data to buffer
				taskthread->buffer = buffer_append(taskthread->buffer, recvbuf, recvlen);
				
				//clean TIMEOUT tick
				os_tick_clear(taskthread->timeouttick);
			}
			if(http_header_is_finished(taskthread->buffer))
			{
				httpcode = http_header_get_code(taskthread->buffer);
	
				dprintf("[http_taskthread_process] %d : HTTPCODE = %d \r\n", taskthread, httpcode);
				dld_taskthread_add_log((DldTaskThread *)taskthread, _("HTTP header is returned. CODE = %d ."), httpcode);
				
				
				if(httpcode == 200 && task->filesize == 0)
				{
					//the file sizs is returned
					// get the file size
					value = http_header_get_tag(taskthread->buffer, "Content-Length");
					dld_task_set_filesize(task, atoi(value->str));
					value = string_free(value);
	
					if(task->filesize != 0)
					{
						//close the connection . prepare to make a new connection
						os_socket_tcp_close(taskthread->connsocket);
						taskthread->connsocket = 0;
						taskthread->cmdstatus = HTTP_STATUS_WAITING;
		
						dprintf("[http_taskthread_process] %d (First): FILESIZE = %d\r\n", taskthread, task->filesize);
						dld_taskthread_add_log((DldTaskThread *)taskthread, _("Remote file size : %d"), task->filesize);
					}
					else
					{
						//we can't get the file size. stop.
						dld_taskthread_add_log((DldTaskThread *)taskthread, _("Remote file size is unknown. Stop."));
						//http_taskthread_stop((DldTaskThread *)taskthread);
						http_taskthread_meet_error(taskthread, FALSE);
					}
				}
				else if(httpcode == 206 || (httpcode == 200 && taskthread->block->pos == -1))  //some servers return 200 for Bytes-Range: 0 -, amusing...
				{
					// the first part is returned. save it
					offset = http_header_get_data_offset(taskthread->buffer);
					ret = dld_task_save_thread_data((DldTaskThread *)taskthread, ((CHAR *)taskthread->buffer->data + offset), taskthread->buffer->len - offset);
					blockfinished = (ret == DLD_ERR_BLOCK_FINISH);
					taskthread->cmdstatus = HTTP_STATUS_WAIT_FOR_DATA;
					dld_taskthread_add_log((DldTaskThread *)taskthread, _("Start receiving remote file ..."));
				}

				if(httpcode == 302)
				{
					//Object moved
					value = http_header_get_tag(taskthread->buffer, "Location");
					dld_taskthread_add_log((DldTaskThread *)taskthread, _("Object is relocated to %s"), value->str);
					task->status = DLD_TASK_RESET;
					dld_task_set_url(task, value->str, task->allowrename);
					value = string_free(value);
				}
				
				if(httpcode >= 400)
				{
					//meet an server error.
					//dld_taskthread_add_log((DldTaskThread *)taskthread, _("Server returns ERROR! %d"), httpcode);
					http_taskthread_meet_error(taskthread, TRUE);
				}
			
			}
		//}while(recvlen == SOCKET_BUF_MAX);
	}
	
	
	if(readable && taskthread->cmdstatus == HTTP_STATUS_WAIT_FOR_DATA)
	{
		//the following datas come...
		recvlen = os_socket_tcp_recv(taskthread->connsocket, recvbuf, SOCKET_BUF_MAX);
		if(recvlen > 0) 
		{
			//save data to file
			ret = dld_task_save_thread_data((DldTaskThread *)taskthread, recvbuf, recvlen);
			blockfinished = (ret == DLD_ERR_BLOCK_FINISH);
			
			//clear TIMEOUT tick
			os_tick_clear(taskthread->timeouttick);
		}
	}

	if(blockfinished)
	{
		//current block is finished. close the connection , prepare a new connection
		taskthread->block = os_free(taskthread->block);			
		os_socket_tcp_close(taskthread->connsocket);
		taskthread->connsocket = 0;
		taskthread->cmdstatus = HTTP_STATUS_WAITING;
		taskthread->buffer = buffer_clear(taskthread->buffer);
		
		if(task->finishedsize < task->filesize )
			dld_taskthread_add_log((DldTaskThread *)taskthread, _("Current block is finished. Trying to alloc a new block ..."));
		else
			dld_taskthread_add_log((DldTaskThread *)taskthread, _("Task is finished successfully."));
	}
}




VOID http_taskthread_connect(HttpTaskThread *taskthread)
{
	DldTask *task;
	BOOL resolveip = FALSE;
	DldProxy *proxy;
	STRING *ip, *port;
	STRING *host;
	
	task = taskthread->parenttask;

	if(!taskthread) return;
	if(taskthread->status != DLD_TASKTHREAD_RUNNING) return;

	if(taskthread->retries != 0)
	{
		//In retry mode ....
		//make a delay ...
		if(!os_tick_check(taskthread->retrytick))
			return;
	}		

	if(taskthread->block == NULL && task->filesize != 0)
	{
		//try to alloc a block for this thread
		dld_task_alloc_block((DldTaskThread *)taskthread);
		
		if(taskthread->block == NULL)
		{
			//no more blocks need to be alloced.
			//taskthread will finish ...
			dld_taskthread_add_log((DldTaskThread *)taskthread, _("No more blocks. Thread finished successfully."));
			dprintf("[http_taskthread_process] %d : no more blocks\r\n", taskthread);
			http_taskthread_stop((DldTaskThread *)taskthread);
			return;
		}
	}
	
	proxy = dld_proxymgr_get_proxy(task->proxy->str);
	if(dld_proxy_get_protocoltype(proxy) != DLD_PROTOCOL_PROXY_UNKNOWN)
	{
		ip = proxy->ip;
		port = proxy->port;
		host = proxy->host;
	}		
	else
	{
		ip = task->ip;
		port = task->port;
		host = task->host;
	}
	
	//should we resolve the host to ip ?
	if(!ip)resolveip = TRUE;
	if(ip) if(strlen(ip->str) <= 7)resolveip = TRUE;
	if(dld_taskthread_is_first((DldTaskThread *)taskthread) && proxy == NULL)resolveip = TRUE;
		
	if(resolveip)
	{
		ip = string_free(ip);
		dld_taskthread_add_log((DldTaskThread *)taskthread, _("Resolving host %s ..."),  host->str);
		
		//here may block!
		ip = os_socket_getip(host->str);
		
		//save the result
		if(proxy != NULL)
		{
			proxy->ip = ip;
		}
		else
		{
			task->ip = ip;
		}
		//clean TIMEOUT tick
		os_tick_clear(taskthread->timeouttick);
	}
	
	//try to connect to the ip
	dld_taskthread_add_log((DldTaskThread *)taskthread, _("Connecting to %s:%s"),  ip->str, port->str);
	taskthread->connsocket = os_socket_tcp_connect(ip->str, (USHORT)atoi(port->str), TRUE);
	if(taskthread->connsocket != 0) 
	{
		//OK
		taskthread->cmdstatus = HTTP_STATUS_WAITING;
	}
	else
	{
		//fail
		http_taskthread_meet_error(taskthread, FALSE);
	}
}



VOID http_taskthread_process(DldTaskThread *dldtaskthread)
{
	HttpTaskThread *taskthread = (HttpTaskThread *)dldtaskthread;
	DldTask *task;


	task = taskthread->parenttask;

	if(!taskthread) return;
	if(taskthread->status != DLD_TASKTHREAD_RUNNING) return;

	//set TIMEOUT with global config
	os_tick_set_delay(taskthread->timeouttick, g_config.timeout);
	os_tick_set_delay(taskthread->retrytick, g_config.retrydelay);
	
	if(dld_taskthread_is_first((DldTaskThread *)taskthread) || task->filesize != 0)
	{
		if(taskthread->connsocket == 0)
		{
			http_taskthread_connect(taskthread);
		}
		else
		{
			http_taskthread_process_connection(taskthread);
		}
	}
	else
	{
		//clear other taskthreads' timeout tick .
		os_tick_clear(taskthread->timeouttick);		
	}
	
	if(os_tick_check(taskthread->timeouttick) && os_tick_timeout(taskthread->retrytick))
	{
		http_taskthread_meet_error(taskthread, FALSE);
	}	
}

⌨️ 快捷键说明

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