这个过程是解析http跟https协议时请求的过程,已经获取数据的过程。
#define HTTP_COMMON_TIMEOUT 15000
BOOL HTTP_DoRequestFunc(char *pcUrl, char *pcRequest,
BOOL (* ParseContent)(char *pcSrc, int iSrcLen, void *pcDst,
void *pvDstLoc, char *pcReserve, int *piReserveLen, int iTimes, int iRequestType),
void *pvDstData, int *psk, E_NET_APP_REQUEST_TYPE eRequestType)
{
BOOL bRet = FALSE;
int iSockFileDescrip = -1;
char *pcLoc;
int iNum;
int iRemainderLen;
char *pcBuff;
char acHostAddr[128] = {0};
char acFileAddr[1024] = {0};
unsigned int uiPort;
int iBuffSize = 16 * 1024;//10 * 1024;
APPLICATION_LAYER_PROTOCOL_TYPE eProtocolType;
int iRequestLen;
unsigned long ulIP = 0;
struct sockaddr_in stServerAddr;
SSL *ssl = NULL;
SSL_CTX *ctx = NULL;
int iSSL_Ret = 0;
eProtocolType = parse_url(pcUrl, acHostAddr, acFileAddr, &uiPort);
if (pcRequest == NULL || eProtocolType == P_INVALID)
{
printf("[%s %d] Invalid request. \n", __FUNCTION__, __LINE__);
return FALSE;
}
iRequestLen = strlen(pcRequest);
ulIP = GSSOCK_host2inetaddr(acHostAddr);
if(ulIP== 0 )
{
printf("[%s %d] gethostbyname error: %s\n", __FUNCTION__, __LINE__, strerror(errno));
return FALSE;
}
if (NULL == (pcBuff = (char *)GSOS_Malloc(iBuffSize)))
{
printf("[%s %d] No enough memory.\n", __FUNCTION__, __LINE__);
return FALSE;
}
if(psk && *psk != -1)
{
iSockFileDescrip = *psk;
}
else
{
if ((iSockFileDescrip = GSSOCK_socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
printf("[%s %d] socket error: %s\n", __FUNCTION__, __LINE__, strerror(errno));
goto EXIT;
}
if (P_HTTPS == eProtocolType)
{
memset(&stServerAddr, 0, sizeof(stServerAddr));
stServerAddr.sin_family = AF_INET;
stServerAddr.sin_port = htons(uiPort);
stServerAddr.sin_addr.s_addr = ulIP;
fd_set fdW;
int inNonBlocking = 0;
int sdret = 0;
int iReturnValue = GS_HTTP_SUCCESS;
int SocketErr = 0;
int len = 0;
int iTimeOut = 0;
bool ConnectComplete = false;
/* set socket to non-blocking mode */
inNonBlocking = 1;
if(ioctl(iSockFileDescrip, FIONBIO, &inNonBlocking) < 0)
return HTTP_SOCKET_ERROR;
struct timeval waitTime = {};
waitTime.tv_sec = 5;
len = sizeof(int);
/* Not connected at first time */
if(connect(iSockFileDescrip, (struct sockaddr*)(&stServerAddr), sizeof(struct sockaddr)) < 0)
{
getsockopt(iSockFileDescrip, SOL_SOCKET, SO_ERROR, &SocketErr, (socklen_t*)&len);
if (SocketErr == EINPROGRESS || SocketErr == ENOERR)
{
do
{
if(ConnectComplete == false)
{
FD_ZERO(&fdW);
FD_SET(iSockFileDescrip, &fdW);
sdret = select(iSockFileDescrip+1, NULL, &fdW, NULL, &waitTime);
printf ("select(), ret = %d\n", sdret);
switch (sdret)
{
case -1:
//error handled by u;
printf("Connect error! %s(%d):%s()\n", __FILE__, __LINE__,__FUNCTION__);
ConnectComplete = true;
iReturnValue = HTTP_SOCKET_ERROR;
break;
case 0:
iTimeOut++;
if(iTimeOut == 6)/*noavtek :wait 30 second is enough*/
{
ConnectComplete = true;
iReturnValue = HTTP_SOCKET_ERROR;
}
break;
default:
ConnectComplete = true;
getsockopt(iSockFileDescrip, SOL_SOCKET, SO_ERROR, &SocketErr, (socklen_t*)&len);
if(SocketErr == 0)
{
iReturnValue = GS_HTTP_SUCCESS;
printf("Connect SUCCESS, SocketErr = %d\n", SocketErr);
}
else
{
iReturnValue = HTTP_SOCKET_ERROR;
printf("Connect FAIL, SocketErr = %d\n", SocketErr);
}
break;
}
}
}while(ConnectComplete == false);
if(ConnectComplete == false)
{
printf("Socket Connecting has been interrupted, %d\n", ConnectComplete);
return HTTP_SOCKET_ERROR;
}
}
else
{
printf("connect failed = %x\n", SocketErr);
return HTTP_SOCKET_ERROR;
}
}
inNonBlocking = 0;
if(ioctl(iSockFileDescrip, FIONBIO, &inNonBlocking) < 0)
{
return HTTP_OTHER_ERROR;
}
}
else
{
struct timeval tv;
tv.tv_sec = HTTP_COMMON_TIMEOUT / 1000;
tv.tv_usec = HTTP_COMMON_TIMEOUT % 1000;
setsockopt(iSockFileDescrip, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(struct timeval));
setsockopt(iSockFileDescrip, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval));
if (-1 == GSSOCK_Connect(iSockFileDescrip, ulIP, uiPort))
{
printf("[%s %d] Connect Error: %s\n", __FUNCTION__, __LINE__, strerror(errno));
goto EXIT;
}
}
}
if (P_HTTPS == eProtocolType)
{
/* SSL initialize */
SSL_library_init();
SSL_load_error_strings();
ctx = SSL_CTX_new(/*TLSv1_method()*/SSLv23_client_method());
if (ctx == NULL)
{
ERR_print_errors_fp(stderr);
goto EXIT;
}
ssl = SSL_new(ctx);
if (ssl == NULL)
{
ERR_print_errors_fp(stderr);
goto EXIT;
}
/* correlate socket with SSL */
iSSL_Ret = SSL_set_fd(ssl, iSockFileDescrip);
if (iSSL_Ret == 0)
{
ERR_print_errors_fp(stderr);
goto EXIT;
}
RAND_poll();
while (RAND_status() == 0)
{
unsigned short rand_ret = rand() % 65536;
RAND_seed(&rand_ret, sizeof(rand_ret));
}
iSSL_Ret = SSL_connect(ssl);
if (iSSL_Ret != 1)
{
int test=SSL_get_error(ssl,iSSL_Ret);
printf("[%s %d] SSL_connect fail. test:%d, %d\n", __FUNCTION__, __LINE__, test, iSSL_Ret);
ERR_print_errors_fp(stderr);
goto EXIT;
}
}
pcLoc = pcRequest;
iRemainderLen = iRequestLen;
if (P_HTTP == eProtocolType)
{
while ((iNum = GSSOCK_send(iSockFileDescrip, (unsigned char *)pcLoc, iRemainderLen, HTTP_COMMON_TIMEOUT)) > 0)
{
pcLoc += iNum;
iRemainderLen -= iNum;
}
}
else if (P_HTTPS == eProtocolType)
{
while ((iNum = GSSSL_send(ssl, iSockFileDescrip, (unsigned char *)pcLoc, iRemainderLen, 3000)) > 0) /* send */
{
pcLoc += iNum;
iRemainderLen -= iNum;
}
}
memset(pcBuff, 0, iBuffSize);
pcLoc = pcBuff;
iRemainderLen = iBuffSize;
if (P_HTTP == eProtocolType)
{
int iTimes = 0;
int iReserveLen = 0;
char *pcReserve = (char *)GSOS_Malloc(HTTP_RESERVE_BUFFER_SIZE + 1);
U32 dst_register = 0;
void *pvDestLoc = &dst_register;
if (pcReserve == NULL)
{
printf("[%s %d] no enough memory. \n", __FUNCTION__, __LINE__);
goto EXIT;
}
while ((iNum = GSSOCK_recv(iSockFileDescrip, (unsigned char *)pcLoc, iRemainderLen, HTTP_COMMON_TIMEOUT)) > 0)
{
if (ParseContent != NULL)
{
memset(pcReserve, 0, HTTP_RESERVE_BUFFER_SIZE + 1);
if (ParseContent(pcBuff, iNum + iReserveLen, pvDstData, pvDestLoc, pcReserve, &iReserveLen, iTimes++, eRequestType))
{
bRet = TRUE;
break;
}
else
{
if (iReserveLen > 0 && iReserveLen <= HTTP_RESERVE_BUFFER_SIZE)
{
memcpy(pcBuff, pcReserve, iReserveLen);
pcLoc = pcBuff + iReserveLen;
iRemainderLen = iBuffSize - iReserveLen;
memset(pcLoc, 0, iBuffSize - iReserveLen);
}
else
{
memset(pcBuff, 0, iBuffSize);
pcLoc = pcBuff;
}
}
}
else
{
iTimes++;
bRet = TRUE;
}
}
GSOS_Free(pcReserve);
}
else if (P_HTTPS == eProtocolType)
{
int iTimes = 0;
int iReserveLen = 0;
char *pcReserve = (char *)GSOS_Malloc(HTTP_RESERVE_BUFFER_SIZE + 1);
U32 dst_register = 0;
void *pvDestLoc = &dst_register;
if (pcReserve == NULL)
{
goto EXIT;
}
while ((iNum = GSSSL_recv(ssl, iSockFileDescrip, (unsigned char *)pcLoc, iRemainderLen, /*3000*/HTTP_COMMON_TIMEOUT)) > 0)
{
if (ParseContent != NULL)
{
memset(pcReserve, 0, HTTP_RESERVE_BUFFER_SIZE + 1);
if (ParseContent(pcBuff, iNum + iReserveLen, pvDstData, pvDestLoc, pcReserve, &iReserveLen, iTimes++, eRequestType))
{
bRet = TRUE;
break;
}
else
{
if (iReserveLen > 0 && iReserveLen <= HTTP_RESERVE_BUFFER_SIZE)
{
memcpy(pcBuff, pcReserve, iReserveLen);
pcLoc = pcBuff + iReserveLen;
iRemainderLen = iBuffSize - iReserveLen;
memset(pcLoc, 0, iBuffSize - iReserveLen);
}
else
{
memset(pcBuff, 0, iBuffSize);
pcLoc = pcBuff;
}
}
}
else
{
iTimes++;
bRet = TRUE;
}
}
GSOS_Free(pcReserve);
}
EXIT:
if (P_HTTPS == eProtocolType)
{
if (ssl != NULL)
{
iSSL_Ret = SSL_shutdown(ssl); //todo: The iSSL_Ret is 0 here. It may be not right.
if (iSSL_Ret != 1)
{
ERR_print_errors_fp(stderr);
}
SSL_free(ssl);
}
if (ctx != NULL)
{
SSL_CTX_free(ctx);
}
ERR_free_strings();
}
if(psk)
{
*psk = iSockFileDescrip;
}
else
{
if (iSockFileDescrip >= 0)
{
close(iSockFileDescrip);
}
}
if (pcBuff != NULL)
{
GSOS_Free(pcBuff);
}
if (bNginxServerFlg)
{
bNginxServerFlg = FALSE;
bRet = TRUE;
}
return bRet;
}
解析url的函数:
APPLICATION_LAYER_PROTOCOL_TYPE parse_url(char *url, char *host, char *file,
unsigned int *port)
{
char *p0, *p1, *p3;
int iIndex = 0;
APPLICATION_LAYER_PROTOCOL_TYPE protocol_type;
if (strncasecmp(url, "http://", 7) == 0)
{
p0 = url + 7;
*port = 80;
protocol_type = P_HTTP;
}
else if (strncasecmp(url, "https://", 8) == 0)
{
p0 = url + 8;
*port = 443;
protocol_type = P_HTTPS;
}
else
{
//It need to be extended here for other protocol if be used.
p0 = strstr(url, "//");
if (p0 != NULL)
{
p0 += 2;
}
else
{
p0 = url;
}
*port = 0;
protocol_type = P_INVALID;
}
p1 = strchr(p0, '/');
if (p1 != NULL)
{
memcpy(host, p0, strlen(p0) - strlen(p1));
p3 = strchr(host, ':');
if (p3 != NULL)
{
*port = atoi(p3 + 1);
host[p3 - host] = '\0';
}
if (*(p1 + 1) != '\0')
{
memcpy(file, p1 + 1, strlen(p1) - 1);
file[strlen(p1) - 1] = 0;
for (iIndex = 0; iIndex < (strlen(p1) -1); iIndex++)//add:fix url is space,get no date.--fix:xie.
{
if (isspace(file[iIndex]))
{
file[iIndex] = '+';
}
}
}
}
else
{
memcpy(host, p0, strlen(p0));
p3 = strchr(host, ':');
if (p3 != NULL)
{
*port = atoi(p3 + 1);
host[p3 - host] = '\0';
}
}
return protocol_type;
}
unsigned long GSSOCK_host2inetaddr(const char *host)
{
unsigned long ulAddr = INADDR_NONE;
if(host)
{
ulAddr = inet_addr(host);
if(ulAddr == INADDR_NONE)
{
struct addrinfo hints, *res = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = AF_INET;
hints.ai_protocol = IPPROTO_TCP;
int err = getaddrinfo(host, NULL, &hints, &res);
if (err != 0 || !res || !res->ai_addr)
{
}
else
{
ulAddr=((struct sockaddr_in *)(res->ai_addr))->sin_addr.s_addr;
}
if (res) freeaddrinfo(res);
}
}
return ulAddr;
}
在解析https数据时,在connect成功后一定要设置一下取消非柱塞模式,
if(ioctl(iSockFileDescrip, FIONBIO, &inNonBlocking) < 0)
{
return HTTP_OTHER_ERROR;
}
要不然,就是失败
SSL_connect:
iSSL_Ret = SSL_connect(ssl);
if (iSSL_Ret != 1)
{
int test=SSL_get_error(ssl,iSSL_Ret);
printf("[%s %d] SSL_connect fail. test:%d, %d\n", __FUNCTION__, __LINE__, test, iSSL_Ret);
ERR_print_errors_fp(stderr);
goto EXIT;
}