742 lines
15 KiB
C
742 lines
15 KiB
C
#include "mrc_base.h"
|
||
#include "mrc_network.h"
|
||
#include "mrc_network_http.h"
|
||
#include "stdarg.h"//for va_list
|
||
|
||
typedef DWORD HBLOCKHEAP;
|
||
|
||
#ifndef MAX_HOSTNAME_LEN
|
||
#define MAX_HOSTNAME_LEN 112
|
||
#endif
|
||
#define HTTP_RESPONSECODE_OFFSET 9
|
||
|
||
static const char sHttpMethods[][5] =
|
||
{
|
||
"GET",
|
||
"HEAD",
|
||
"POST"
|
||
};
|
||
|
||
typedef struct HttpRequest_T
|
||
{
|
||
HTTPMETHOD method;
|
||
struct HttpRequest_T* next;
|
||
}HTTPREQUEST, *PHTTPREQUEST;
|
||
|
||
typedef struct HttpData
|
||
{
|
||
//http event handler
|
||
FN_SOCKEVENT fnEvent;
|
||
|
||
//available when header responsed
|
||
uint32 responsecode;
|
||
int32 contentLength;
|
||
|
||
//cache the http header
|
||
uint32 hdrsize;
|
||
char header[HTTP_HEADER_SIZE];
|
||
//http request list on this connection
|
||
PHTTPREQUEST requests_head;
|
||
PHTTPREQUEST requests_tail;
|
||
}HTTPDATA, *PHTTPDATA;
|
||
|
||
static HTTPDATA sHttpDataPool[SOCKET_MAX_COUNT];
|
||
static HBLOCKHEAP sHttpDataHeap;
|
||
|
||
|
||
HBLOCKHEAP BlockHeap_Initialize(VOID* buffer, int buffersize, int blocksize);
|
||
VOID BlockHeap_Free(HBLOCKHEAP* pHeap, VOID* pBlock);
|
||
VOID* BlockHeap_Alloc(HBLOCKHEAP* pHeap);
|
||
|
||
static int mrc_i_isNum(uint8 code);
|
||
static int mrc_i_isNumText(char * code);
|
||
static uint32 inet_addr(const char* cp);
|
||
static char* tolower(char* str);
|
||
static PCSTR host(PCSTR url, uint16* port, uint16 def);
|
||
static uint16 get_port(PCSTR url);
|
||
|
||
static char* tolower(char* str)
|
||
{
|
||
int i = 0;
|
||
|
||
for(; str[i]; i++)
|
||
{
|
||
if(str[i] >= 'A' && str[i] <= 'Z')
|
||
str[i] += 'a' - 'A';
|
||
}
|
||
|
||
return str;
|
||
}
|
||
|
||
|
||
static PCSTR host(PCSTR url, uint16* port, uint16 def)
|
||
{
|
||
static char host[MAX_HOSTNAME_LEN];
|
||
int i, j;
|
||
if(port) *port = def;
|
||
|
||
for(i = j = 0; url[i]; i++)
|
||
{
|
||
if(url[i] == ':' && url[i+1] == '/' && url[i+2] == '/')
|
||
{
|
||
i+=3;
|
||
while(url[i] && url[i]!=':' && url[i]!='/')
|
||
{
|
||
host[j++] = url[i++];
|
||
}
|
||
|
||
if(port && url[i] == ':')
|
||
{
|
||
*port = atoi(url+i+1);
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
host[j] = 0;
|
||
return host;
|
||
}
|
||
|
||
|
||
static uint16 get_port(PCSTR url)
|
||
{
|
||
uint16 port = 0;
|
||
char* p = NULL;
|
||
|
||
if( NULL == url )
|
||
{
|
||
return 80;
|
||
}
|
||
|
||
p = mrc_strstr(url,"://");
|
||
if( p )
|
||
{
|
||
p += 3;
|
||
}
|
||
else
|
||
{
|
||
p = (char*)url;
|
||
}
|
||
|
||
p = mrc_strstr(p,":");
|
||
if( p )
|
||
{
|
||
port = atoi(p+1);
|
||
}
|
||
else
|
||
{
|
||
port = 80;
|
||
}
|
||
|
||
if( port == 0 )
|
||
{
|
||
port = 80;
|
||
}
|
||
return port;
|
||
|
||
}
|
||
static int mrc_i_isNum(uint8 code)
|
||
{
|
||
if ((code>47 && code<58) || (code=='.') || (code==':') )
|
||
{
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
static int mrc_i_isNumText(char * code)
|
||
{
|
||
char * tempCode = code;
|
||
|
||
while(*tempCode)
|
||
{
|
||
if( mrc_i_isNum(*tempCode) ==0 )
|
||
{
|
||
return 0;
|
||
}
|
||
tempCode++;
|
||
}
|
||
return 1;
|
||
}
|
||
static uint32 inet_addr(const char* cp)
|
||
{
|
||
uint32 ip = 0;
|
||
int i;
|
||
char ipstr[100];
|
||
mrc_memset(ipstr, 0, 100);
|
||
|
||
for(i = 0; i < 4; i++)
|
||
{
|
||
ip <<= 8;
|
||
ip |= atoi(cp);
|
||
|
||
if(i < 3 && (NULL == (cp = mrc_strchr(cp, '.'))))
|
||
return 0;
|
||
cp++;
|
||
}
|
||
return ip;
|
||
}
|
||
|
||
#ifdef HTTP_HEAD_METHOD_ENABLE
|
||
static BOOL mrc_Http_Request_Add(PHTTPDATA pHttpData, HTTPMETHOD method)
|
||
{
|
||
PHTTPREQUEST request;
|
||
|
||
//append to the request list, must not failed
|
||
if( NULL == (request = (PHTTPREQUEST)malloc(sizeof(HTTPREQUEST))))
|
||
{
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
//add to the request list
|
||
request->method = method;
|
||
request->next = NULL;
|
||
if(pHttpData->requests_head == NULL)
|
||
pHttpData->requests_head = request;
|
||
else
|
||
pHttpData->requests_tail->next = request;
|
||
pHttpData->requests_tail = request;
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
static void mrc_Http_Request_Clear(PHTTPDATA pHttpData)
|
||
{
|
||
PHTTPREQUEST request;
|
||
|
||
while(pHttpData->requests_head)
|
||
{
|
||
request = pHttpData->requests_head;
|
||
pHttpData->requests_head = request->next;
|
||
free(request);
|
||
}
|
||
}
|
||
|
||
|
||
static void mrc_Http_Request_Pop(PHTTPDATA pHttpData)
|
||
{
|
||
PHTTPREQUEST request = pHttpData->requests_head;
|
||
|
||
if(request)
|
||
{
|
||
pHttpData->requests_head = request->next;
|
||
if(pHttpData->requests_head == NULL)
|
||
pHttpData->requests_tail = NULL;
|
||
|
||
free(request);
|
||
}
|
||
}
|
||
#endif
|
||
|
||
|
||
#define FIND_HTTP_HEADER_ENDING(pHttpData) \
|
||
(pHttpData->hdrsize >= 4 \
|
||
&& pHttpData->header[pHttpData->hdrsize - 4] == '\r' \
|
||
&& pHttpData->header[pHttpData->hdrsize - 3] == '\n' \
|
||
&& pHttpData->header[pHttpData->hdrsize - 2] == '\r' \
|
||
&& pHttpData->header[pHttpData->hdrsize -1] == '\n')
|
||
|
||
|
||
#define RESET_HTTP_RESPONSE_INFO(pHttpData) \
|
||
pHttpData->contentLength = 0; \
|
||
pHttpData->hdrsize = 0; \
|
||
pHttpData->responsecode = 0
|
||
|
||
|
||
#ifdef HTTP_HEAD_METHOD_ENABLE
|
||
#define HANDLE_RESPONSE_END(socket, pHttpData) \
|
||
if(pHttpData->fnEvent(socket, HTTPEVT_RESPONSE_END, NULL)) \
|
||
return 1; \
|
||
RESET_HTTP_RESPONSE_INFO(pHttpData); \
|
||
Http_Request_Pop(pHttpData)
|
||
#else
|
||
#define HANDLE_RESPONSE_END(socket, pHttpData) \
|
||
if(pHttpData->fnEvent(socket, HTTPEVT_RESPONSE_END, NULL)) \
|
||
return 1; \
|
||
RESET_HTTP_RESPONSE_INFO(pHttpData)
|
||
#endif
|
||
|
||
|
||
static DWORD mrc_Http_HandleResponseData(PSOCKET socket, PSOCKEVTDATA data)
|
||
{
|
||
int32 i;
|
||
PCSTR len;
|
||
PHTTPDATA pHttpData = (PHTTPDATA)socket->userdata;
|
||
|
||
if(pHttpData->responsecode == 0)
|
||
{
|
||
//receive the http header
|
||
for(i = 0; i < data->size; i++)
|
||
{
|
||
//check the http header buffer, when this happen user should adjust the value of HTTP_HEADER_SIZE
|
||
//todo
|
||
if(pHttpData->hdrsize >= HTTP_HEADER_SIZE)
|
||
{
|
||
mrc_Http_Close(socket, HTTPEVT_ERROR);
|
||
return 1;
|
||
}
|
||
|
||
//copy the byte and continue when not found the http header ending
|
||
pHttpData->header[pHttpData->hdrsize++] = data->buffer[i];
|
||
if(!FIND_HTTP_HEADER_ENDING(pHttpData))
|
||
continue;
|
||
|
||
//find the header
|
||
pHttpData->header[pHttpData->hdrsize] = 0;
|
||
//SGL_LOG("header.txt", pHttpData->header, pHttpData->hdrsize);
|
||
tolower(pHttpData->header);
|
||
|
||
//maybe socket been closed, user do not want to deal the data left
|
||
//Note:changed by huangsunbo 2008-10-20,respond head data
|
||
//todo
|
||
if(pHttpData->fnEvent(socket, HTTPEVT_RESPONSE_HEADER, data))
|
||
return 1;
|
||
|
||
#ifdef HTTP_HEAD_METHOD_ENABLE
|
||
if(pHttpData->requests_head->method == HEAD)
|
||
{
|
||
HANDLE_RESPONSE_END(socket, pHttpData);
|
||
}else{
|
||
#endif
|
||
if(NULL == (len = mrc_Http_GetResponseField(socket, HTTP_FIELD_CONTENTLENGTH)) )
|
||
{
|
||
//can not support the response do not have the field "Content-Length"
|
||
mrc_Http_Close(socket, HTTPEVT_ERROR);
|
||
return 1;
|
||
}
|
||
|
||
pHttpData->contentLength = atoi(len);
|
||
pHttpData->responsecode = mrc_Http_GetResponseCode(socket);
|
||
if(pHttpData->contentLength == 0)
|
||
{
|
||
HANDLE_RESPONSE_END(socket, pHttpData);
|
||
}
|
||
#ifdef HTTP_HEAD_METHOD_ENABLE
|
||
}
|
||
#endif
|
||
|
||
i++; //i is the bytes has been copyed, so should add 1
|
||
break;
|
||
}
|
||
|
||
data->buffer += i;
|
||
data->size -= i;
|
||
}
|
||
|
||
if(data->size > 0)
|
||
{
|
||
int32 notifybytes = MIN(pHttpData->contentLength, data->size);
|
||
int32 remainbytes = data->size - pHttpData->contentLength;
|
||
data->size = notifybytes;
|
||
|
||
//maybe socket been closed, user do not want to deal the data left
|
||
if(pHttpData->fnEvent(socket, HTTPEVT_RESPONSE_DATA, data))
|
||
return 1;
|
||
|
||
pHttpData->contentLength -= notifybytes;
|
||
data->size -= notifybytes;
|
||
data->buffer += notifybytes;
|
||
data->size = remainbytes;
|
||
|
||
if(pHttpData->contentLength == 0)
|
||
{
|
||
HANDLE_RESPONSE_END(socket, pHttpData);
|
||
}
|
||
|
||
if(data->size > 0)
|
||
return mrc_Http_HandleResponseData(socket, data);
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
static void mrc_Http_Destroy(PSOCKET socket)
|
||
{
|
||
PHTTPDATA pHttpData = (PHTTPDATA)socket->userdata;
|
||
|
||
#ifdef HTTP_HEAD_METHOD_ENABLE
|
||
Http_Request_Clear(pHttpData);
|
||
#endif
|
||
BlockHeap_Free(&sHttpDataHeap, pHttpData);
|
||
}
|
||
|
||
|
||
static DWORD mrc_Http_HandleSocketEvents(PSOCKET socket, DWORD evt, PSOCKEVTDATA data)
|
||
{
|
||
PHTTPDATA pHttpData = (PHTTPDATA)socket->userdata;
|
||
FN_SOCKEVENT fnEvent = pHttpData->fnEvent;
|
||
|
||
switch(evt)
|
||
{
|
||
|
||
case SOCKEVT_CONNECTED:
|
||
{
|
||
return fnEvent(socket, evt, data);
|
||
}
|
||
|
||
case SOCKEVT_RECVDATA:
|
||
{
|
||
/*
|
||
* HTTPEVT_RESPONSE_HEADER sent to the user after get the http response header
|
||
* HTTPEVT_RESPONSE_DATA sent to the user when receive the http data,
|
||
* HTTPEVT_RESPONSE_END sent to the user when request finished
|
||
*/
|
||
return mrc_Http_HandleResponseData(socket, data);
|
||
}
|
||
|
||
case SOCKEVT_CONNECTFAILED:
|
||
case SOCKEVT_ERROR:
|
||
case SOCKEVT_CLOSED:
|
||
{
|
||
mrc_Http_Destroy(socket);
|
||
return fnEvent(socket, evt, data);
|
||
}
|
||
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
void mrc_Http_Initialize(void)
|
||
{
|
||
sHttpDataHeap = BlockHeap_Initialize(sHttpDataPool, sizeof(sHttpDataPool), sizeof(HTTPDATA));
|
||
}
|
||
|
||
|
||
void mrc_Http_Terminate(void)
|
||
{
|
||
//DO NOTHING
|
||
}
|
||
|
||
|
||
/*
|
||
֧<EFBFBD><EFBFBD>ֱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ
|
||
<EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD> 2010-03-30
|
||
*/
|
||
PSOCKET mrc_Http_OpenEx(char*ip_string,uint16 port,FN_SOCKEVENT fnEvent)
|
||
{
|
||
PHTTPDATA pHttpData;
|
||
PSOCKET socket;
|
||
|
||
if(!ip_string)
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
if( NULL == (pHttpData = BlockHeap_Alloc(&sHttpDataHeap)))
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
pHttpData->fnEvent = fnEvent;
|
||
pHttpData->contentLength = 0;
|
||
pHttpData->responsecode = 0;
|
||
pHttpData->hdrsize = 0;
|
||
|
||
#ifdef HTTP_HEAD_METHOD_ENABLE
|
||
pHttpData->requests_head = NULL;
|
||
pHttpData->requests_tail = NULL;
|
||
#endif
|
||
|
||
if(NULL == (socket = mrc_Socket_Create(SOCKPROTO_TCP,
|
||
mrc_Http_HandleSocketEvents, (DWORD)pHttpData)))
|
||
{
|
||
BlockHeap_Free(&sHttpDataHeap, pHttpData);
|
||
return NULL;
|
||
}
|
||
|
||
if(mrc_Socket_ConnectNoProxy(socket, ip_string,port,1))
|
||
{
|
||
return socket;
|
||
}
|
||
else
|
||
{
|
||
mrc_Socket_Close(socket,SOCKEVT_CLOSED);
|
||
BlockHeap_Free(&sHttpDataHeap, pHttpData);
|
||
return NULL;
|
||
}
|
||
}
|
||
|
||
|
||
BOOL mrc_Http_Close(PSOCKET socket, DWORD evt)
|
||
{
|
||
return mrc_Socket_Close(socket, evt);
|
||
}
|
||
|
||
|
||
PCSTR mrc_Http_FormatHeader(uint32* size, HTTPMETHOD method, PCSTR url,...)
|
||
{
|
||
static char header[HTTP_HEADER_SIZE];
|
||
uint32 hdrsize;
|
||
PCSTR field, value;
|
||
va_list args;
|
||
va_start(args, url);
|
||
|
||
//format the request header line
|
||
sprintf(header, HTTP_HEADER_FORMAT, sHttpMethods[method], url);
|
||
hdrsize = strlen(header);
|
||
|
||
//parse other fields and values
|
||
while(NULL != (field = va_arg(args, PCSTR)))
|
||
{
|
||
//field name
|
||
strcpy(header + hdrsize, field);
|
||
hdrsize += strlen(field);
|
||
header[hdrsize++] = ':';
|
||
header[hdrsize++] = ' ';//add space by huangsunbo
|
||
|
||
//field value
|
||
value = va_arg(args, PCSTR);
|
||
strcpy(header + hdrsize, value);
|
||
hdrsize += strlen(value);
|
||
|
||
//field ending
|
||
header[hdrsize++] = '\r';
|
||
header[hdrsize++] = '\n';
|
||
}
|
||
|
||
//append the http header ending
|
||
header[hdrsize++] = '\r';
|
||
header[hdrsize++] = '\n';
|
||
|
||
va_end(args);
|
||
*size = hdrsize;
|
||
return header;
|
||
}
|
||
|
||
|
||
BOOL mrc_Http_Send(PSOCKET socket, HTTPMETHOD method, PBYTE buffer, uint32 size)
|
||
{
|
||
#ifdef HTTP_HEAD_METHOD_ENABLE
|
||
PHTTPDATA pHttpData = (PHTTPDATA)socket->userdata;
|
||
#endif
|
||
|
||
|
||
if(!mrc_Socket_Send(socket, buffer, size))
|
||
return FALSE;
|
||
|
||
#ifdef HTTP_HEAD_METHOD_ENABLE
|
||
|
||
//append to the request list, must not failed
|
||
if(!mrc_Http_Request_Add(pHttpData, method))
|
||
{
|
||
mrc_Http_Close(socket, HTTPEVT_ERROR);
|
||
return FALSE;
|
||
}
|
||
|
||
#endif
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOL mrc_Http_GetEx(PSOCKET socket, PCSTR url, uint32 from, uint32 to)
|
||
{
|
||
PCSTR pHeader, pHost;
|
||
uint32 hdrsize;
|
||
uint16 port;
|
||
uint8 host_buf[128] = {0};
|
||
|
||
|
||
pHost = host(url,NULL,80);
|
||
port = get_port(url);
|
||
|
||
//<2F><><EFBFBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD>Ͷ˿<CDB6>
|
||
/*<2A><><EFBFBD><EFBFBD>ע<EFBFBD><D7A2>*/
|
||
sprintf((char*)host_buf,"%s:%d",pHost,port);
|
||
|
||
|
||
//<1>CP<43><50><EFBFBD><EFBFBD><EFBFBD><EFBFBD>http<74><70><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><D6BB>Ҫͨ<D2AA><CDA8>sky<6B><79>proxy<78><79><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>
|
||
//<2F><><EFBFBD><EFBFBD>ֻ<EFBFBD><D6BB>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>sky<6B><79>server<65><72>Ȼ<EFBFBD><C8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>
|
||
//<2F><><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>url
|
||
|
||
|
||
//<2><3E><><EFBFBD><EFBFBD>cmwap<61><70><EFBFBD>ŷ<EFBFBD>ʽ<EFBFBD><CABD>ʱ<EFBFBD><CAB1>,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫͨ<D2AA><CDA8>cmcc<63><63><EFBFBD><EFBFBD><EFBFBD>ؽ<EFBFBD><D8BD><EFBFBD>ת<EFBFBD><D7AA>
|
||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫͨ<D2AA><CDA8>Host<73><74>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͷ˿<CDB6><CBBF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ؽ<EFBFBD><D8BD><EFBFBD>ת<EFBFBD><D7AA>
|
||
|
||
if(from > 0)
|
||
{
|
||
char tmp[24] = {0};
|
||
if(to > from)
|
||
sprintf(tmp, "bytes=%d-%d", from, to);
|
||
else
|
||
sprintf(tmp, "bytes=%d-", from);
|
||
|
||
pHeader = mrc_Http_FormatHeader(&hdrsize, GET, url,
|
||
HTTP_FIELD_HOST, host_buf,
|
||
HTTP_FIELD_UA, HTTP_VALUE_UA,
|
||
HTTP_FIELD_ACCEPT, HTTP_VALUE_ACCEPT,
|
||
HTTP_FIELD_CONTENTTYPE, HTTP_VALUE_CONTENTTYPE,
|
||
HTTP_FIELD_CONNECTION, HTTP_VALUE_CONNECTION_KEEPALIVE,
|
||
HTTP_FIELD_PROXYCONNECTION, HTTP_VALUE_CONNECTION_KEEPALIVE,
|
||
HTTP_FIELD_RANGE, tmp,
|
||
NULL); //do not forget the NULL ending
|
||
}
|
||
else
|
||
{
|
||
/**/
|
||
pHeader = mrc_Http_FormatHeader(&hdrsize, GET, url,
|
||
HTTP_FIELD_HOST, host_buf,
|
||
HTTP_FIELD_UA, HTTP_VALUE_UA,
|
||
HTTP_FIELD_ACCEPT, HTTP_VALUE_ACCEPT,
|
||
HTTP_FIELD_CONTENTTYPE, HTTP_VALUE_CONTENTTYPE,
|
||
HTTP_FIELD_CONNECTION, HTTP_VALUE_CONNECTION_KEEPALIVE,
|
||
HTTP_FIELD_PROXYCONNECTION, HTTP_VALUE_CONNECTION_KEEPALIVE,
|
||
NULL); //do not forget the NULL ending
|
||
|
||
}
|
||
|
||
return mrc_Http_Send(socket, GET, (PBYTE)pHeader, hdrsize);
|
||
}
|
||
|
||
|
||
#ifdef HTTP_HEAD_METHOD_ENABLE
|
||
|
||
BOOL mrc_Http_Head(PSOCKET socket, PCSTR url)
|
||
{
|
||
PCSTR pHeader, pHost;
|
||
uint32 hdrsize;
|
||
|
||
pHost = host(url, NULL, 0);
|
||
pHeader = mrc_Http_FormatHeader(&hdrsize, HEAD, url,
|
||
HTTP_FIELD_HOST, pHost,
|
||
HTTP_FIELD_UA, HTTP_VALUE_UA,
|
||
HTTP_FIELD_ACCEPT, HTTP_VALUE_ACCEPT,
|
||
HTTP_FIELD_CONTENTTYPE, HTTP_VALUE_CONTENTTYPE,
|
||
HTTP_FIELD_CONNECTION, HTTP_VALUE_CONNECTION_KEEPALIVE,
|
||
HTTP_FIELD_PROXYCONNECTION, HTTP_VALUE_CONNECTION_KEEPALIVE,
|
||
NULL); //do not forget the NULL ending
|
||
|
||
return mrc_Http_Send(socket, HEAD, (PBYTE)pHeader, hdrsize);
|
||
}
|
||
|
||
#endif
|
||
BOOL mrc_Http_PostEx(PSOCKET socket, PCSTR url, PCSTR buffer, uint32 size)
|
||
{
|
||
PCSTR pHeader, pHost;
|
||
uint32 hdrsize;
|
||
char tmp[12]={0};
|
||
uint8 host_buf[128] = {0};
|
||
uint16 port;
|
||
|
||
|
||
pHost = host(url,NULL,80);
|
||
port = get_port(url);
|
||
|
||
//<2F><><EFBFBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD>Ͷ˿<CDB6>
|
||
sprintf((char*)host_buf,"%s:%d",pHost,port);
|
||
|
||
sprintf(tmp, "%d", size);
|
||
pHeader = mrc_Http_FormatHeader(&hdrsize, POST, url,
|
||
HTTP_FIELD_HOST, host_buf,
|
||
HTTP_FIELD_UA, HTTP_VALUE_UA,
|
||
HTTP_FIELD_ACCEPT, HTTP_VALUE_ACCEPT,
|
||
HTTP_FIELD_CONTENTTYPE, HTTP_VALUE_CONTENTTYPE,
|
||
HTTP_FIELD_CONNECTION, HTTP_VALUE_CONNECTION_KEEPALIVE,
|
||
HTTP_FIELD_PROXYCONNECTION, HTTP_VALUE_CONNECTION_KEEPALIVE,
|
||
HTTP_FIELD_CONTENTLENGTH, tmp,
|
||
NULL); //do not forget the NULL ending
|
||
|
||
//check that socket have enough buffer
|
||
if(socket->begin + SOCKET_SENDBUFFER_SIZE - socket->end < hdrsize + size)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
//if return false that cause is not about send buffer
|
||
if(!mrc_Http_Send(socket, POST, (PBYTE)pHeader, hdrsize))
|
||
return FALSE;
|
||
|
||
//if return false that cause is not about send buffer
|
||
if(size > 0 && !mrc_Socket_Send(socket, (PBYTE)buffer, size))
|
||
return FALSE;
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
uint32 mrc_Http_GetResponseCode(PSOCKET socket)
|
||
{
|
||
PHTTPDATA pHttpData = (PHTTPDATA) socket->userdata;
|
||
return atoi(pHttpData->header + HTTP_RESPONSECODE_OFFSET);
|
||
}
|
||
|
||
int mrc_Http_GetResponseHead(PSOCKET socket,uint8** buf, uint32* size)
|
||
{
|
||
PHTTPDATA pHttpData = NULL;
|
||
if( NULL == socket || NULL == buf || size == NULL ||
|
||
socket->sd < 0 || socket->protocol != SOCKPROTO_TCP )
|
||
{
|
||
buf = NULL;
|
||
*size = 0;
|
||
return MR_FAILED;
|
||
}
|
||
|
||
pHttpData = (PHTTPDATA) socket->userdata;
|
||
*buf = (uint8*)pHttpData->header;
|
||
*size = pHttpData->hdrsize;
|
||
return MR_SUCCESS;
|
||
}
|
||
|
||
|
||
PCSTR mrc_Http_GetResponseField(PSOCKET socket, PCSTR field)
|
||
{
|
||
static char value[HTTP_FIELDVALUE_SIZE];
|
||
|
||
int32 i = 0;
|
||
PCSTR pTmp;
|
||
PHTTPDATA pHttpData = (PHTTPDATA)socket->userdata;
|
||
|
||
strncpy(value, field, HTTP_FIELDVALUE_SIZE-1);
|
||
value[HTTP_FIELDVALUE_SIZE-1] = 0;
|
||
tolower(value);
|
||
|
||
if( NULL == (pTmp = mrc_strstr(pHttpData->header, value)))
|
||
return NULL;
|
||
|
||
pTmp += mrc_strlen(field);
|
||
while(*pTmp == ' ' || *pTmp == ':')
|
||
pTmp++;
|
||
|
||
while(!(pTmp[i] == '\r' && pTmp[i+1] == '\n'))
|
||
{
|
||
value[i] = pTmp[i];
|
||
i++;
|
||
}
|
||
|
||
value[i] = 0;
|
||
return value;
|
||
}
|
||
|
||
|
||
HBLOCKHEAP BlockHeap_Initialize(VOID* buffer, int buffersize, int blocksize)
|
||
{
|
||
PBYTE pBlock = (PBYTE)buffer;
|
||
|
||
//SGL_ASSERT(0 == MOD(buffersize, blocksize) && 0 == MOD(blocksize, 4));
|
||
|
||
for(buffersize -= blocksize; pBlock - (PBYTE)buffer < buffersize ; pBlock += blocksize)
|
||
*(Uint8**)pBlock = pBlock + blocksize;
|
||
|
||
*(PBYTE*)pBlock = NULL;
|
||
return (HBLOCKHEAP)buffer;
|
||
}
|
||
|
||
|
||
VOID* BlockHeap_Alloc(HBLOCKHEAP* pHeap)
|
||
{
|
||
VOID* pBlock = (VOID*)(*pHeap);
|
||
|
||
if(pBlock)
|
||
*pHeap =(HBLOCKHEAP)( *(PBYTE*)(*pHeap) );
|
||
|
||
return pBlock;
|
||
}
|
||
|
||
|
||
VOID BlockHeap_Free(HBLOCKHEAP* pHeap, VOID* pBlock)
|
||
{
|
||
*(PBYTE*)pBlock = (PBYTE)(*pHeap);
|
||
*pHeap = (HBLOCKHEAP)pBlock;
|
||
} |