[T106][ZXW-22]7520V3SCV2.01.01.02P42U09_VEC_V0.8_AP_VEC origin source commit
Change-Id: Ic6e05d89ecd62fc34f82b23dcf306c93764aec4b
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;
+}
+