这个过程是解析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; }