📄 http.c
字号:
{ 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 + -