zte's code,first commit

Change-Id: I9a04da59e459a9bc0d67f101f700d9d7dc8d681b
diff --git a/ap/lib/liblpa/lpa_https.c b/ap/lib/liblpa/lpa_https.c
new file mode 100755
index 0000000..54b549b
--- /dev/null
+++ b/ap/lib/liblpa/lpa_https.c
@@ -0,0 +1,464 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <openssl/ssl.h>
+#include <openssl/bio.h>
+
+#include "lpa_inner.h"
+
+
+ 
+// http ÇëÇóÍ·ÐÅÏ¢
+static char https_header[] =
+    "GET %s HTTP/1.1\r\n"
+    "Host: %s:%d\r\n"
+    "Connection: Close\r\n"
+    "Accept: */*\r\n"
+    "\r\n";
+ /*
+ HTTP POST /gsma/rsp2/es9plus/initiateAuthentication HTTP/1.1
+ Host: smdp.gsma.com
+ User-Agent: gsma-rsp-lpad
+ X-Admin-Protocol: gsma/rsp/v2.2.0
+ Content-Type: application/json
+ Content-Length: XXX
+ 
+ {
+	 "euiccChallenge" : "ZVVpY2NDaGFsbGVuZ2VFeGFtcGxlQmFzZTY0oUFZuQnNZVE5D",
+	 "euiccInfo1" : "RmVHRnRjR3hsUW1GelpUWTBvVUZadVFuTlpWRTU",
+	 "smdpAddress" : "smdp.gsma.com"
+ }
+ */
+
+static int create_request_socket(const char* host,const int port)
+{
+    int sockfd;
+    struct hostent *server;
+    struct sockaddr_in serv_addr;
+	struct timeval tv;
+ 
+    sockfd = socket(AF_INET, SOCK_STREAM, 0);
+    if (sockfd < 0)
+    {
+        printf("[http] create_request_socket create socket fail.\n");
+        return -1;
+    }
+	
+	tv.tv_sec = 90;
+	tv.tv_usec = 0;
+	if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
+		printf("[http] socket option  SO_RCVTIMEO fail\n");
+		close(sockfd);
+        return -1;
+	}
+ 
+    /* lookup the ip address */
+    server = gethostbyname(host);
+    if(server == NULL)
+    {
+        printf("[http] create_request_socket gethostbyname--%s--fail.\n", host);
+        close(sockfd);
+        return -1;
+    }
+ 
+    memset(&serv_addr,0,sizeof(serv_addr));
+    serv_addr.sin_family = AF_INET;
+    serv_addr.sin_port = htons(port);
+    memcpy(&serv_addr.sin_addr.s_addr,server->h_addr,server->h_length);
+ 
+    if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
+    {
+        printf("[http] create_request_socket connect fail.\n");
+        close(sockfd);
+        return -1;
+    }
+    return sockfd;
+}
+ 
+/**
+ * @brief https_parser_url  ½âÎö³öhttps ÖеÄÓòÃû¡¢¶Ë¿ÚºÍ·¾¶
+ * @param url   ÐèÒª½âÎöµÄurl
+ * @param host  ½âÎö³öÀ´µÄÓòÃû»òÕßip
+ * @param port  ¶Ë¿Ú£¬Ã»ÓÐʱĬÈÏ·µ»Ø443
+ * @param path  ·¾¶£¬Ö¸µÄÊÇÓòÃûºóÃæµÄλÖÃ
+ * @return
+ */
+int https_parser_url(const char* url,char **host,int *port,char **path)
+{
+    if(url == NULL || strlen(url) < 9 || host == NULL || path == NULL)
+    {
+         printf("url or host or path is null.\n");
+         return -1;
+    }
+ 
+    //ÅжÏÊDz»ÊÇ https://
+    int i = 0;
+    char https_prefix[] = "https://";
+    for(i=0;i<8;i++)
+    {
+        if(url[i] != https_prefix[i])
+        {
+            printf("illegal url = %s.\n",url);
+            return -1;
+        }
+    }
+ 
+    const char *temp = url+i;
+    while(*temp != '/')  //next /
+    {
+        if(*temp == '\0')  //
+        {
+            printf("illegal url = %s.\n",url);
+            return -1;
+        }
+        temp++;
+    }
+ 
+    const char *host_port = url+i;
+    while(*host_port != ':' && *host_port != '/')  //ÕÒµ½ :»òÕß / ½áÊø
+    {
+        host_port ++;
+    }
+ 
+    int host_len = host_port-url-i;  //¼õµôhttps://
+    int path_len = strlen(temp);
+    char *host_temp = (char *)malloc(host_len + 1);  //¶àÒ»¸ö×Ö·û´®½áÊø±êʶ \0
+    if(host_temp == NULL)
+    {
+        printf("malloc host fail.\n");
+        return -1;
+    }
+    if(*host_port++ == ':')  //url ÖÐÓж˿Ú
+    {
+        *port = 0;
+        while(*host_port !='/' && *host_port !='\0')  //Ê®½øÖÆ×Ö·û´®×ª³ÉÊý×Ö
+        {
+            *port *= 10;
+            *port += (*host_port - '0');
+            host_port ++;
+        }
+    }
+    else
+    {
+        *port = 443;
+    }
+ 
+    char *path_temp = (char *)malloc(path_len + 1);  //¶àÒ»¸ö×Ö·û´®½áÊø±êʶ \0
+    if(path_temp == NULL)
+    {
+        printf("malloc path fail.\n");
+        free(host_temp);
+        return -1;
+    }
+    memcpy(host_temp,url+i,host_len);
+    memcpy(path_temp,temp,path_len);
+    host_temp[host_len] = '\0';
+    path_temp[path_len] = '\0';
+    *host = host_temp;
+    *path = path_temp;
+    return 0;
+}
+ 
+int https_init(https_context_t *context)
+{
+	int ret = 0;
+    if(context == NULL)
+    {
+        printf("init https_context_t is null.\n");
+        return -1;
+    }
+ /*
+    if(https_parser_url(url,&(context->host),&(context->port),&(context->path)))
+    {
+        printf("https_parser_url fail.\n");
+        return -1;
+    }
+ */
+    context->sock_fd = create_request_socket(context->host,context->port);
+	printf("create_request_socket %d.\n",context->sock_fd);
+    if(context->sock_fd < 0)
+    {
+        goto https_init_fail;
+    }
+ 
+    context->ssl_ct = SSL_CTX_new(SSLv23_method());
+	printf("SSL_CTX_new %p.\n",context->ssl_ct); //cov m
+    if(context->ssl_ct == NULL)
+    {
+        goto https_init_fail;
+    }
+ 
+    context->ssl = SSL_new(context->ssl_ct);
+	printf("SSL_new %p.\n",context->ssl); //cov m
+    if(context->ssl == NULL)
+    {
+        goto https_init_fail;
+    }
+ 	ret = SSL_set_fd(context->ssl,context->sock_fd);
+	printf("SSL_set_fd ret %d \n",ret);
+ 	ret = SSL_connect(context->ssl);
+	printf("SSL_connect ret %d \n",ret);
+    if(ret == -1)
+    {
+        goto https_init_fail;
+    }
+    return 0;
+https_init_fail:
+    https_uninit(context);
+    return -1;
+}
+ 
+int https_read(https_context_t *context,void* buff,int len)
+{
+    if(context == NULL || context->ssl == NULL)
+    {
+        printf("read https_context_t or ssl is null.\n");
+        return -1;
+    }
+    return SSL_read(context->ssl,buff,len);
+}
+ 
+int https_write(https_context_t *context,const void* buff,int len)
+{
+    if(context == NULL || context->ssl == NULL)
+    {
+        printf("write https_context_t or ssl is null.\n");
+        return -1;
+    }
+    return SSL_write(context->ssl,buff,len);
+}
+ 
+int https_get_status_code(https_context_t *context, int *content_len)
+{
+    int ret;
+    int flag =0;
+    int recv_len = 0;
+    char res_header[1024] = {0};
+	
+	if(context == NULL || context->ssl == NULL)
+    {
+        printf("get status https_context_t or ssl is null.\n");
+        return -1;
+    }
+	
+    while(recv_len < (sizeof(res_header)-1))
+    {
+        ret = SSL_read(context->ssl, res_header+recv_len, 1);
+        if(ret<1)  // recv fail
+        {
+            break;
+        }
+        //ÕÒµ½ÏìӦͷµÄÍ·²¿ÐÅÏ¢, Á½¸ö"\r\n"Ϊ·Ö¸îµã
+        if((res_header[recv_len]=='\r'&&(flag==0||flag==2))||(res_header[recv_len]=='\n'&&(flag==1||flag==3)))
+        {
+            flag++;
+        }
+        else
+        {
+            flag = 0;
+        }
+        recv_len+=ret;
+        if(flag==4)
+        {
+            break;
+        }
+    }
+    //printf("[http] recv_len=%d res_header = %s.\n",recv_len,res_header);
+    /*»ñÈ¡ÏìӦͷµÄÐÅÏ¢*/
+    int status_code = -1;
+    char *pos = strstr(res_header, "HTTP/");
+    if(pos)
+    {
+        sscanf(pos, "%*s %d", &status_code);//·µ»Ø×´Ì¬Âë
+    }
+
+	int cont_len = 0; 
+	pos = strstr(res_header, "Content-Length:");
+    if(pos)
+    {
+        sscanf(pos, "%*s %d", &cont_len);//·µ»Ø×´Ì¬Âë
+    }
+	pos = strstr(res_header, "chunked");
+	if(pos)//Transfer-Encoding: chunked
+	{
+		cont_len = HTTP_CHUNKED_FLAG;
+	}
+	*content_len = cont_len;
+	
+	printf("res_head##%s##\n", res_header);
+	printf("status_code:%d, Content-Length:%d\n", status_code, cont_len);
+
+    return status_code;
+}
+ 
+int https_read_content(https_context_t *context,char *resp_contet,int max_len)
+{
+    if(context == NULL || context->ssl == NULL)
+    {
+        printf("read content https_context_t or ssl is null.\n");
+        return -1;
+    }
+    int ret ;
+    int recv_size = 0;
+    while(recv_size < max_len)
+    {
+       ret = SSL_read(context->ssl,resp_contet + recv_size,max_len-recv_size);
+	   if(ret < 1)
+       {
+           break;
+       }
+       recv_size += ret;
+    }
+    return recv_size;
+}
+//[Chunk´óС][»Ø³µ][ChunkÊý¾ÝÌå][»Ø³µ][Chunk´óС][»Ø³µ][ChunkÊý¾ÝÌå][»Ø³µ][0][»Ø³µ][footerÄÚÈÝ£¨Óеϰ£©][»Ø³µ]
+//×¢Òâchunk-sizeÊÇÒÔÊ®Áù½øÖƵÄASCIIÂë±íʾµÄ£¬±ÈÈç86AE£¨Êµ¼ÊµÄÊ®Áù½øÖÆÓ¦¸ÃÊÇ£º38366165£©£¬¼ÆËã³É³¤¶ÈÓ¦¸ÃÊÇ£º34478£¬±íʾ´Ó»Ø³µÖ®ºóÓÐÁ¬ÐøµÄ34478×Ö½ÚµÄÊý¾Ý
+int https_read_chunked_content(https_context_t *context,char **resp_contet,int max_len)
+{   
+    int ret = 0;
+	int flag = 0;
+    int recv_size = 0;
+	
+	int recv_len = 0;
+    char chunk_header[1024] = {0};
+	
+	int read_flag = 0;
+	int read_len = 1;
+		
+	if(context == NULL || context->ssl == NULL)
+    {
+        printf("read content https_context_t or ssl is null.\n");
+        return -1;
+    }
+	
+    while(recv_size < max_len)
+    {		
+		if (read_flag == 0) {
+			ret = SSL_read(context->ssl, chunk_header+recv_len, read_len);
+			if(ret < 1)  // recv fail
+			{
+				break;
+			}
+			printf("chunk_header##%s##\n", chunk_header+recv_len);
+			//Ò»¸ö"\r\n"Ϊ·Ö¸îµã
+			if((chunk_header[recv_len]=='\r'&&flag==0)||(chunk_header[recv_len]=='\n'&&flag==1))
+			{
+				flag++;
+			}
+			else
+			{
+				flag = 0;
+			}
+			recv_len += ret;
+			if(flag == 2)
+			{
+				if (strlen(chunk_header) > 2) {
+					//Ìø¹ý·Ç0~9£¬A~F???
+					errno = 0;
+					int size =strtol(chunk_header, NULL, 16);
+					if (errno == ERANGE)// kw ERRNO.NOT_CHECKED
+					{
+						printf("strtol errno %d: %s\n", errno, strerror(errno));
+					}
+					//sscanf(pos, "%X", &cont_len);//X???
+					if (size <= 0 || size >= max_len) {
+						read_flag = 2;
+						read_len = sizeof(chunk_header)-1;
+					}
+					else {
+						read_flag = 1;
+						read_len = size;
+					}
+				}
+				memset(chunk_header, 0, sizeof(chunk_header));
+				recv_len = 0;
+			}
+			if (recv_len >= (sizeof(chunk_header)-1))
+				break;
+		} 
+		else if(read_flag == 1) {
+			if(recv_size == 0) {
+				char *resp_tmp = malloc(read_len + 1);;
+				if (resp_tmp == NULL) {
+					printf("resp_tmp is null\n");
+					return -1;
+				}
+				memset(resp_tmp, 0, read_len + 1);
+				*resp_contet = resp_tmp;
+			}
+			else {
+				char *resp_tmp = NULL;
+				resp_tmp = realloc(*resp_contet, recv_size + read_len + 1);
+				if (resp_tmp == NULL) {
+					free(*resp_contet);
+					printf("resp_tmp realloc null\n");
+					return -1;
+				}
+				*resp_contet = resp_tmp;
+			}
+			//read Ö±µ½³¤¶È
+			ret = https_read_content(context, (*resp_contet)+recv_size, read_len);
+			if(ret<1)  // recv fail
+			{
+				break;
+			}
+			read_len = 1;
+			read_flag = 0;
+			recv_size += ret;
+		} 
+		else {
+			ret = SSL_read(context->ssl, chunk_header, read_len);
+			printf("chunk_header##%s##\n", chunk_header);
+			break;
+		}
+
+    }
+    return recv_size;
+}
+
+ 
+int https_uninit(https_context_t *context)
+{
+    if(context == NULL)
+    {
+        printf("uninit https_context_t is null.\n");
+        return -1;
+    }
+
+    if(context->host != NULL)
+    {
+        //free(context->host);
+        context->host = NULL;
+    }
+	
+    if(context->path != NULL)
+    {
+        //free(context->path);
+        context->path = NULL;
+    }
+
+    if(context->ssl != NULL)
+    {
+        SSL_shutdown(context->ssl);
+        //SSl_free(context->ssl);
+        context->ssl = NULL;
+    }
+    if(context->ssl_ct != NULL)
+    {
+        SSL_CTX_free(context->ssl_ct);
+        context->ssl_ct = NULL;
+    }
+    if(context->sock_fd > 0)
+    {
+        close(context->sock_fd);
+        context->sock_fd = -1;
+    }
+    return 0;
+}
+