blob: 54b549b0003e5789e45678aa642295cd6b639d1e [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001#include <stdio.h>
2#include <string.h>
3#include <stdlib.h>
4#include <unistd.h>
5#include <sys/stat.h>
6#include <sys/socket.h>
7#include <netinet/in.h>
8#include <arpa/inet.h>
9#include <netdb.h>
10#include <openssl/ssl.h>
11#include <openssl/bio.h>
12
13#include "lpa_inner.h"
14
15
16
17// http ÇëÇóÍ·ÐÅÏ¢
18static char https_header[] =
19 "GET %s HTTP/1.1\r\n"
20 "Host: %s:%d\r\n"
21 "Connection: Close\r\n"
22 "Accept: */*\r\n"
23 "\r\n";
24 /*
25 HTTP POST /gsma/rsp2/es9plus/initiateAuthentication HTTP/1.1
26 Host: smdp.gsma.com
27 User-Agent: gsma-rsp-lpad
28 X-Admin-Protocol: gsma/rsp/v2.2.0
29 Content-Type: application/json
30 Content-Length: XXX
31
32 {
33 "euiccChallenge" : "ZVVpY2NDaGFsbGVuZ2VFeGFtcGxlQmFzZTY0oUFZuQnNZVE5D",
34 "euiccInfo1" : "RmVHRnRjR3hsUW1GelpUWTBvVUZadVFuTlpWRTU",
35 "smdpAddress" : "smdp.gsma.com"
36 }
37 */
38
39static int create_request_socket(const char* host,const int port)
40{
41 int sockfd;
42 struct hostent *server;
43 struct sockaddr_in serv_addr;
44 struct timeval tv;
45
46 sockfd = socket(AF_INET, SOCK_STREAM, 0);
47 if (sockfd < 0)
48 {
49 printf("[http] create_request_socket create socket fail.\n");
50 return -1;
51 }
52
53 tv.tv_sec = 90;
54 tv.tv_usec = 0;
55 if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
56 printf("[http] socket option SO_RCVTIMEO fail\n");
57 close(sockfd);
58 return -1;
59 }
60
61 /* lookup the ip address */
62 server = gethostbyname(host);
63 if(server == NULL)
64 {
65 printf("[http] create_request_socket gethostbyname--%s--fail.\n", host);
66 close(sockfd);
67 return -1;
68 }
69
70 memset(&serv_addr,0,sizeof(serv_addr));
71 serv_addr.sin_family = AF_INET;
72 serv_addr.sin_port = htons(port);
73 memcpy(&serv_addr.sin_addr.s_addr,server->h_addr,server->h_length);
74
75 if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
76 {
77 printf("[http] create_request_socket connect fail.\n");
78 close(sockfd);
79 return -1;
80 }
81 return sockfd;
82}
83
84/**
85 * @brief https_parser_url ½âÎö³öhttps ÖеÄÓòÃû¡¢¶Ë¿ÚºÍ·¾¶
86 * @param url ÐèÒª½âÎöµÄurl
87 * @param host ½âÎö³öÀ´µÄÓòÃû»òÕßip
88 * @param port ¶Ë¿Ú£¬Ã»ÓÐʱĬÈÏ·µ»Ø443
89 * @param path ·¾¶£¬Ö¸µÄÊÇÓòÃûºóÃæµÄλÖÃ
90 * @return
91 */
92int https_parser_url(const char* url,char **host,int *port,char **path)
93{
94 if(url == NULL || strlen(url) < 9 || host == NULL || path == NULL)
95 {
96 printf("url or host or path is null.\n");
97 return -1;
98 }
99
100 //ÅжÏÊDz»ÊÇ https://
101 int i = 0;
102 char https_prefix[] = "https://";
103 for(i=0;i<8;i++)
104 {
105 if(url[i] != https_prefix[i])
106 {
107 printf("illegal url = %s.\n",url);
108 return -1;
109 }
110 }
111
112 const char *temp = url+i;
113 while(*temp != '/') //next /
114 {
115 if(*temp == '\0') //
116 {
117 printf("illegal url = %s.\n",url);
118 return -1;
119 }
120 temp++;
121 }
122
123 const char *host_port = url+i;
124 while(*host_port != ':' && *host_port != '/') //ÕÒµ½ :»òÕß / ½áÊø
125 {
126 host_port ++;
127 }
128
129 int host_len = host_port-url-i; //¼õµôhttps://
130 int path_len = strlen(temp);
131 char *host_temp = (char *)malloc(host_len + 1); //¶àÒ»¸ö×Ö·û´®½áÊø±êʶ \0
132 if(host_temp == NULL)
133 {
134 printf("malloc host fail.\n");
135 return -1;
136 }
137 if(*host_port++ == ':') //url ÖÐÓж˿Ú
138 {
139 *port = 0;
140 while(*host_port !='/' && *host_port !='\0') //Ê®½øÖÆ×Ö·û´®×ª³ÉÊý×Ö
141 {
142 *port *= 10;
143 *port += (*host_port - '0');
144 host_port ++;
145 }
146 }
147 else
148 {
149 *port = 443;
150 }
151
152 char *path_temp = (char *)malloc(path_len + 1); //¶àÒ»¸ö×Ö·û´®½áÊø±êʶ \0
153 if(path_temp == NULL)
154 {
155 printf("malloc path fail.\n");
156 free(host_temp);
157 return -1;
158 }
159 memcpy(host_temp,url+i,host_len);
160 memcpy(path_temp,temp,path_len);
161 host_temp[host_len] = '\0';
162 path_temp[path_len] = '\0';
163 *host = host_temp;
164 *path = path_temp;
165 return 0;
166}
167
168int https_init(https_context_t *context)
169{
170 int ret = 0;
171 if(context == NULL)
172 {
173 printf("init https_context_t is null.\n");
174 return -1;
175 }
176 /*
177 if(https_parser_url(url,&(context->host),&(context->port),&(context->path)))
178 {
179 printf("https_parser_url fail.\n");
180 return -1;
181 }
182 */
183 context->sock_fd = create_request_socket(context->host,context->port);
184 printf("create_request_socket %d.\n",context->sock_fd);
185 if(context->sock_fd < 0)
186 {
187 goto https_init_fail;
188 }
189
190 context->ssl_ct = SSL_CTX_new(SSLv23_method());
191 printf("SSL_CTX_new %p.\n",context->ssl_ct); //cov m
192 if(context->ssl_ct == NULL)
193 {
194 goto https_init_fail;
195 }
196
197 context->ssl = SSL_new(context->ssl_ct);
198 printf("SSL_new %p.\n",context->ssl); //cov m
199 if(context->ssl == NULL)
200 {
201 goto https_init_fail;
202 }
203 ret = SSL_set_fd(context->ssl,context->sock_fd);
204 printf("SSL_set_fd ret %d \n",ret);
205 ret = SSL_connect(context->ssl);
206 printf("SSL_connect ret %d \n",ret);
207 if(ret == -1)
208 {
209 goto https_init_fail;
210 }
211 return 0;
212https_init_fail:
213 https_uninit(context);
214 return -1;
215}
216
217int https_read(https_context_t *context,void* buff,int len)
218{
219 if(context == NULL || context->ssl == NULL)
220 {
221 printf("read https_context_t or ssl is null.\n");
222 return -1;
223 }
224 return SSL_read(context->ssl,buff,len);
225}
226
227int https_write(https_context_t *context,const void* buff,int len)
228{
229 if(context == NULL || context->ssl == NULL)
230 {
231 printf("write https_context_t or ssl is null.\n");
232 return -1;
233 }
234 return SSL_write(context->ssl,buff,len);
235}
236
237int https_get_status_code(https_context_t *context, int *content_len)
238{
239 int ret;
240 int flag =0;
241 int recv_len = 0;
242 char res_header[1024] = {0};
243
244 if(context == NULL || context->ssl == NULL)
245 {
246 printf("get status https_context_t or ssl is null.\n");
247 return -1;
248 }
249
250 while(recv_len < (sizeof(res_header)-1))
251 {
252 ret = SSL_read(context->ssl, res_header+recv_len, 1);
253 if(ret<1) // recv fail
254 {
255 break;
256 }
257 //ÕÒµ½ÏìӦͷµÄÍ·²¿ÐÅÏ¢, Á½¸ö"\r\n"Ϊ·Ö¸îµã
258 if((res_header[recv_len]=='\r'&&(flag==0||flag==2))||(res_header[recv_len]=='\n'&&(flag==1||flag==3)))
259 {
260 flag++;
261 }
262 else
263 {
264 flag = 0;
265 }
266 recv_len+=ret;
267 if(flag==4)
268 {
269 break;
270 }
271 }
272 //printf("[http] recv_len=%d res_header = %s.\n",recv_len,res_header);
273 /*»ñÈ¡ÏìӦͷµÄÐÅÏ¢*/
274 int status_code = -1;
275 char *pos = strstr(res_header, "HTTP/");
276 if(pos)
277 {
278 sscanf(pos, "%*s %d", &status_code);//·µ»Ø×´Ì¬Âë
279 }
280
281 int cont_len = 0;
282 pos = strstr(res_header, "Content-Length:");
283 if(pos)
284 {
285 sscanf(pos, "%*s %d", &cont_len);//·µ»Ø×´Ì¬Âë
286 }
287 pos = strstr(res_header, "chunked");
288 if(pos)//Transfer-Encoding: chunked
289 {
290 cont_len = HTTP_CHUNKED_FLAG;
291 }
292 *content_len = cont_len;
293
294 printf("res_head##%s##\n", res_header);
295 printf("status_code:%d, Content-Length:%d\n", status_code, cont_len);
296
297 return status_code;
298}
299
300int https_read_content(https_context_t *context,char *resp_contet,int max_len)
301{
302 if(context == NULL || context->ssl == NULL)
303 {
304 printf("read content https_context_t or ssl is null.\n");
305 return -1;
306 }
307 int ret ;
308 int recv_size = 0;
309 while(recv_size < max_len)
310 {
311 ret = SSL_read(context->ssl,resp_contet + recv_size,max_len-recv_size);
312 if(ret < 1)
313 {
314 break;
315 }
316 recv_size += ret;
317 }
318 return recv_size;
319}
320//[Chunk´óС][»Ø³µ][ChunkÊý¾ÝÌå][»Ø³µ][Chunk´óС][»Ø³µ][ChunkÊý¾ÝÌå][»Ø³µ][0][»Ø³µ][footerÄÚÈÝ£¨Óеϰ£©][»Ø³µ]
321//×¢Òâchunk-sizeÊÇÒÔÊ®Áù½øÖƵÄASCIIÂë±íʾµÄ£¬±ÈÈç86AE£¨Êµ¼ÊµÄÊ®Áù½øÖÆÓ¦¸ÃÊÇ£º38366165£©£¬¼ÆËã³É³¤¶ÈÓ¦¸ÃÊÇ£º34478£¬±íʾ´Ó»Ø³µÖ®ºóÓÐÁ¬ÐøµÄ34478×Ö½ÚµÄÊý¾Ý
322int https_read_chunked_content(https_context_t *context,char **resp_contet,int max_len)
323{
324 int ret = 0;
325 int flag = 0;
326 int recv_size = 0;
327
328 int recv_len = 0;
329 char chunk_header[1024] = {0};
330
331 int read_flag = 0;
332 int read_len = 1;
333
334 if(context == NULL || context->ssl == NULL)
335 {
336 printf("read content https_context_t or ssl is null.\n");
337 return -1;
338 }
339
340 while(recv_size < max_len)
341 {
342 if (read_flag == 0) {
343 ret = SSL_read(context->ssl, chunk_header+recv_len, read_len);
344 if(ret < 1) // recv fail
345 {
346 break;
347 }
348 printf("chunk_header##%s##\n", chunk_header+recv_len);
349 //Ò»¸ö"\r\n"Ϊ·Ö¸îµã
350 if((chunk_header[recv_len]=='\r'&&flag==0)||(chunk_header[recv_len]=='\n'&&flag==1))
351 {
352 flag++;
353 }
354 else
355 {
356 flag = 0;
357 }
358 recv_len += ret;
359 if(flag == 2)
360 {
361 if (strlen(chunk_header) > 2) {
362 //Ìø¹ý·Ç0~9£¬A~F???
363 errno = 0;
364 int size =strtol(chunk_header, NULL, 16);
365 if (errno == ERANGE)// kw ERRNO.NOT_CHECKED
366 {
367 printf("strtol errno %d: %s\n", errno, strerror(errno));
368 }
369 //sscanf(pos, "%X", &cont_len);//X???
370 if (size <= 0 || size >= max_len) {
371 read_flag = 2;
372 read_len = sizeof(chunk_header)-1;
373 }
374 else {
375 read_flag = 1;
376 read_len = size;
377 }
378 }
379 memset(chunk_header, 0, sizeof(chunk_header));
380 recv_len = 0;
381 }
382 if (recv_len >= (sizeof(chunk_header)-1))
383 break;
384 }
385 else if(read_flag == 1) {
386 if(recv_size == 0) {
387 char *resp_tmp = malloc(read_len + 1);;
388 if (resp_tmp == NULL) {
389 printf("resp_tmp is null\n");
390 return -1;
391 }
392 memset(resp_tmp, 0, read_len + 1);
393 *resp_contet = resp_tmp;
394 }
395 else {
396 char *resp_tmp = NULL;
397 resp_tmp = realloc(*resp_contet, recv_size + read_len + 1);
398 if (resp_tmp == NULL) {
399 free(*resp_contet);
400 printf("resp_tmp realloc null\n");
401 return -1;
402 }
403 *resp_contet = resp_tmp;
404 }
405 //read Ö±µ½³¤¶È
406 ret = https_read_content(context, (*resp_contet)+recv_size, read_len);
407 if(ret<1) // recv fail
408 {
409 break;
410 }
411 read_len = 1;
412 read_flag = 0;
413 recv_size += ret;
414 }
415 else {
416 ret = SSL_read(context->ssl, chunk_header, read_len);
417 printf("chunk_header##%s##\n", chunk_header);
418 break;
419 }
420
421 }
422 return recv_size;
423}
424
425
426int https_uninit(https_context_t *context)
427{
428 if(context == NULL)
429 {
430 printf("uninit https_context_t is null.\n");
431 return -1;
432 }
433
434 if(context->host != NULL)
435 {
436 //free(context->host);
437 context->host = NULL;
438 }
439
440 if(context->path != NULL)
441 {
442 //free(context->path);
443 context->path = NULL;
444 }
445
446 if(context->ssl != NULL)
447 {
448 SSL_shutdown(context->ssl);
449 //SSl_free(context->ssl);
450 context->ssl = NULL;
451 }
452 if(context->ssl_ct != NULL)
453 {
454 SSL_CTX_free(context->ssl_ct);
455 context->ssl_ct = NULL;
456 }
457 if(context->sock_fd > 0)
458 {
459 close(context->sock_fd);
460 context->sock_fd = -1;
461 }
462 return 0;
463}
464