/modules/http/request.c
C | 1408 lines | 1046 code | 252 blank | 110 comment | 192 complexity | b5cf72be8c2047e981052f05b00ec9a4 MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0
1/*
2 * Astra Module: HTTP Request
3 * http://cesbo.com/astra
4 *
5 * Copyright (C) 2012-2015, Andrey Dyldin <and@cesbo.com>
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21/*
22 * Module Name:
23 * http_request
24 *
25 * Module Options:
26 * host - string, server hostname or IP address
27 * port - number, server port (default: 80)
28 * path - string, request path
29 * method - string, method (default: "GET")
30 * version - string, HTTP version (default: "HTTP/1.1")
31 * headers - table, list of the request headers
32 * content - string, request content
33 * stream - boolean, true to read MPEG-TS stream
34 * sync - boolean or number, enable stream synchronization
35 * sctp - boolean, use sctp instead of tcp
36 * timeout - number, request timeout
37 * callback - function,
38 * upstream - object, stream instance returned by module_instance:stream()
39 */
40
41#include "http.h"
42
43#define MSG(_msg) \
44 "[http_request %s:%d%s] " _msg, mod->config.host \
45 , mod->config.port \
46 , mod->config.path
47
48struct module_data_t
49{
50 MODULE_STREAM_DATA();
51
52 struct
53 {
54 const char *host;
55 int port;
56 const char *path;
57 bool sync;
58 } config;
59
60 int timeout_ms;
61 bool is_stream;
62
63 int idx_self;
64
65 asc_socket_t *sock;
66 asc_timer_t *timeout;
67
68 bool is_socket_busy;
69
70 // request
71 struct
72 {
73 int status; // 1 - connected, 2 - request done
74
75 const char *buffer;
76 size_t skip;
77 size_t size;
78
79 int idx_body;
80 } request;
81
82 bool is_head;
83 bool is_connection_close;
84 bool is_connection_keep_alive;
85
86 // response
87 char buffer[HTTP_BUFFER_SIZE];
88 size_t buffer_skip;
89 size_t chunk_left;
90
91 int idx_response;
92 int status_code;
93
94 int status; // 1 - empty line is found, 2 - request ready, 3 - release
95
96 int idx_content;
97 bool is_chunked;
98 bool is_content_length;
99 string_buffer_t *content;
100
101 bool is_active;
102
103 // receiver
104 struct
105 {
106 void *arg;
107 union
108 {
109 void (*fn)(void *, void *, size_t);
110 void *ptr;
111 } callback;
112 } receiver;
113
114 // stream
115 bool is_thread_started;
116 asc_thread_t *thread;
117 asc_thread_buffer_t *thread_output;
118
119 struct
120 {
121 uint8_t *buffer;
122 size_t buffer_size;
123 size_t buffer_count;
124 size_t buffer_read;
125 size_t buffer_write;
126 size_t buffer_fill;
127 } sync;
128
129 uint64_t pcr;
130};
131
132static const char __path[] = "path";
133static const char __method[] = "method";
134static const char __version[] = "version";
135static const char __headers[] = "headers";
136static const char __content[] = "content";
137static const char __callback[] = "callback";
138static const char __stream[] = "stream";
139static const char __code[] = "code";
140static const char __message[] = "message";
141
142static const char __default_method[] = "GET";
143static const char __default_path[] = "/";
144static const char __default_version[] = "HTTP/1.1";
145
146static const char __connection[] = "Connection: ";
147static const char __close[] = "close";
148static const char __keep_alive[] = "keep-alive";
149
150static void on_close(void *);
151
152static void callback(module_data_t *mod)
153{
154 const int response = lua_gettop(lua);
155 lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_self);
156 lua_getfield(lua, -1, "__options");
157 lua_getfield(lua, -1, "callback");
158 lua_pushvalue(lua, -3);
159 lua_pushvalue(lua, response);
160 lua_call(lua, 2, 0);
161 lua_pop(lua, 3); // self + options + response
162}
163
164static void call_error(module_data_t *mod, const char *msg)
165{
166 lua_newtable(lua);
167 lua_pushnumber(lua, 0);
168 lua_setfield(lua, -2, __code);
169 lua_pushstring(lua, msg);
170 lua_setfield(lua, -2, __message);
171 callback(mod);
172}
173
174void timeout_callback(void *arg)
175{
176 module_data_t *mod = (module_data_t *)arg;
177
178 asc_timer_destroy(mod->timeout);
179 mod->timeout = NULL;
180
181 if(mod->request.status == 0)
182 {
183 mod->status = -1;
184 mod->request.status = -1;
185 call_error(mod, "connection timeout");
186 }
187 else
188 {
189 mod->status = -1;
190 mod->request.status = -1;
191 call_error(mod, "response timeout");
192 }
193
194 on_close(mod);
195}
196
197static void on_thread_close(void *arg);
198
199static void on_close(void *arg)
200{
201 module_data_t *mod = (module_data_t *)arg;
202
203 if(mod->thread)
204 on_thread_close(mod);
205
206 if(!mod->sock)
207 return;
208
209 if(mod->receiver.callback.ptr)
210 {
211 mod->receiver.callback.fn(mod->receiver.arg, NULL, 0);
212
213 mod->receiver.arg = NULL;
214 mod->receiver.callback.ptr = NULL;
215 }
216
217 asc_socket_close(mod->sock);
218 mod->sock = NULL;
219
220 if(mod->timeout)
221 {
222 asc_timer_destroy(mod->timeout);
223 mod->timeout = NULL;
224 }
225
226 if(mod->request.buffer)
227 {
228 if(mod->request.status == 1)
229 free((void *)mod->request.buffer);
230 mod->request.buffer = NULL;
231 }
232
233 if(mod->request.idx_body)
234 {
235 luaL_unref(lua, LUA_REGISTRYINDEX, mod->request.idx_body);
236 mod->request.idx_body = 0;
237 }
238
239 if(mod->request.status == 0)
240 {
241 mod->request.status = -1;
242 call_error(mod, "connection failed");
243 }
244 else if(mod->status == 0)
245 {
246 mod->request.status = -1;
247 call_error(mod, "failed to parse response");
248 }
249
250 if(mod->status == 2)
251 {
252 mod->status = 3;
253
254 lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_response);
255 callback(mod);
256 }
257
258 if(mod->__stream.self)
259 {
260 module_stream_destroy(mod);
261
262 if(mod->status == 3)
263 {
264 /* stream on_close */
265 mod->status = -1;
266 mod->request.status = -1;
267
268 lua_pushnil(lua);
269 callback(mod);
270 }
271 }
272
273 if(mod->sync.buffer)
274 {
275 free(mod->sync.buffer);
276 mod->sync.buffer = NULL;
277 }
278
279 if(mod->idx_response)
280 {
281 luaL_unref(lua, LUA_REGISTRYINDEX, mod->idx_response);
282 mod->idx_response = 0;
283 }
284
285 if(mod->idx_content)
286 {
287 luaL_unref(lua, LUA_REGISTRYINDEX, mod->idx_content);
288 mod->idx_content = 0;
289 }
290
291 if(mod->idx_self)
292 {
293 luaL_unref(lua, LUA_REGISTRYINDEX, mod->idx_self);
294 mod->idx_self = 0;
295 }
296
297 if(mod->content)
298 {
299 string_buffer_free(mod->content);
300 mod->content = NULL;
301 }
302}
303
304/*
305 * oooooooo8 ooooooooooo oooooooooo ooooooooooo o oooo oooo
306 * 888 88 888 88 888 888 888 88 888 8888o 888
307 * 888oooooo 888 888oooo88 888ooo8 8 88 88 888o8 88
308 * 888 888 888 88o 888 oo 8oooo88 88 888 88
309 * o88oooo888 o888o o888o 88o8 o888ooo8888 o88o o888o o88o 8 o88o
310 *
311 */
312
313static bool seek_pcr( module_data_t *mod
314 , size_t *block_size, size_t *next_block
315 , uint64_t *pcr)
316{
317 size_t count;
318
319 while(1)
320 {
321 if(mod->sync.buffer_count < 2 * TS_PACKET_SIZE)
322 return false;
323
324 count = mod->sync.buffer_read + TS_PACKET_SIZE;
325 if(count >= mod->sync.buffer_size)
326 count -= mod->sync.buffer_size;
327
328 if( mod->sync.buffer[mod->sync.buffer_read] == 0x47
329 && mod->sync.buffer[count] == 0x47)
330 {
331 break;
332 }
333
334 ++mod->sync.buffer_read;
335 if(mod->sync.buffer_read >= mod->sync.buffer_size)
336 mod->sync.buffer_read = 0;
337
338 --mod->sync.buffer_count;
339 }
340
341 uint8_t *ptr, ts[TS_PACKET_SIZE];
342
343 size_t next_skip, skip = mod->sync.buffer_read + TS_PACKET_SIZE;
344 if(skip >= mod->sync.buffer_size)
345 skip -= mod->sync.buffer_size;
346
347 for( count = TS_PACKET_SIZE
348 ; count < mod->sync.buffer_count
349 ; count += TS_PACKET_SIZE)
350 {
351 ptr = &mod->sync.buffer[skip];
352
353 next_skip = skip + TS_PACKET_SIZE;
354 if(next_skip > mod->sync.buffer_size)
355 {
356 const size_t packet_head = mod->sync.buffer_size - skip;
357 memcpy(ts, ptr, packet_head);
358 next_skip -= mod->sync.buffer_size;
359 memcpy(&ts[packet_head], mod->sync.buffer, next_skip);
360 ptr = ts;
361 }
362
363 if(TS_IS_PCR(ptr))
364 {
365 *block_size = count;
366 *next_block = skip;
367 *pcr = TS_GET_PCR(ptr);
368
369 return true;
370 }
371
372 skip = (next_skip == mod->sync.buffer_size) ? 0 : next_skip;
373 }
374
375 return false;
376}
377
378static void on_thread_close(void *arg)
379{
380 module_data_t *mod = (module_data_t *)arg;
381
382 mod->is_thread_started = false;
383
384 if(mod->thread)
385 {
386 asc_thread_destroy(mod->thread);
387 mod->thread = NULL;
388 }
389
390 if(mod->thread_output)
391 {
392 asc_thread_buffer_destroy(mod->thread_output);
393 mod->thread_output = NULL;
394 }
395
396 on_close(mod);
397}
398
399static void on_thread_read(void *arg)
400{
401 module_data_t *mod = (module_data_t *)arg;
402
403 uint8_t ts[TS_PACKET_SIZE];
404 const ssize_t r = asc_thread_buffer_read(mod->thread_output, ts, sizeof(ts));
405 if(r == sizeof(ts))
406 module_stream_send(mod, ts);
407}
408
409static void thread_loop(void *arg)
410{
411 module_data_t *mod = (module_data_t *)arg;
412
413 uint8_t *ptr, ts[TS_PACKET_SIZE];
414
415 mod->is_thread_started = true;
416
417 while(mod->is_thread_started)
418 {
419 // block sync
420 uint64_t pcr
421 , system_time, system_time_check
422 , block_time, block_time_total = 0;
423 size_t block_size = 0, next_block;
424
425 bool reset = true;
426
427 asc_log_info(MSG("buffering..."));
428
429 // flush
430 mod->sync.buffer_count = 0;
431 mod->sync.buffer_write = 0;
432 mod->sync.buffer_read = 0;
433
434 // check timeout
435 system_time_check = asc_utime();
436
437 while( mod->is_thread_started
438 && mod->sync.buffer_write < mod->sync.buffer_size)
439 {
440 system_time = asc_utime();
441
442 const ssize_t size = asc_socket_recv( mod->sock
443 , &mod->sync.buffer[mod->sync.buffer_write]
444 , mod->sync.buffer_size - mod->sync.buffer_write);
445 if(size > 0)
446 {
447 system_time_check = system_time;
448 mod->sync.buffer_write += size;
449 }
450 else
451 {
452 if(system_time - system_time_check >= (uint32_t)mod->timeout_ms * 1000)
453 {
454 asc_log_error(MSG("receiving timeout"));
455 return;
456 }
457 asc_usleep(1000);
458 }
459 }
460 mod->sync.buffer_count = mod->sync.buffer_write;
461 if(mod->sync.buffer_write == mod->sync.buffer_size)
462 mod->sync.buffer_write = 0;
463
464 if(!seek_pcr(mod, &block_size, &next_block, &mod->pcr))
465 {
466 asc_log_error(MSG("first PCR is not found"));
467 return;
468 }
469
470 mod->sync.buffer_count -= block_size;
471 mod->sync.buffer_read = next_block;
472
473 reset = true;
474
475 while(mod->is_thread_started)
476 {
477 if(reset)
478 {
479 reset = false;
480 block_time_total = asc_utime();
481 }
482
483 if( mod->is_thread_started
484 && mod->sync.buffer_count < mod->sync.buffer_size)
485 {
486 const size_t tail = (mod->sync.buffer_read > mod->sync.buffer_write)
487 ? (mod->sync.buffer_read - mod->sync.buffer_write)
488 : (mod->sync.buffer_size - mod->sync.buffer_write);
489
490 const ssize_t l = asc_socket_recv( mod->sock
491 , &mod->sync.buffer[mod->sync.buffer_write]
492 , tail);
493 if(l > 0)
494 {
495 mod->sync.buffer_write += l;
496 if(mod->sync.buffer_write >= mod->sync.buffer_size)
497 mod->sync.buffer_write = 0;
498 mod->sync.buffer_count += l;
499 }
500 }
501
502 // get PCR
503 if(!seek_pcr(mod, &block_size, &next_block, &pcr))
504 {
505 asc_log_error(MSG("next PCR is not found"));
506 break;
507 }
508 block_time = mpegts_pcr_block_us(&mod->pcr, &pcr);
509 mod->pcr = pcr;
510 if(block_time == 0 || block_time > 500000)
511 {
512 asc_log_debug( MSG("block time out of range: %"PRIu64"ms block_size:%lu")
513 , (uint64_t)(block_time / 1000), block_size);
514
515 mod->sync.buffer_count -= block_size;
516 mod->sync.buffer_read = next_block;
517
518 reset = true;
519 continue;
520 }
521
522 system_time = asc_utime();
523 if(block_time_total > system_time + 100)
524 asc_usleep(block_time_total - system_time);
525
526 const uint32_t ts_count = block_size / TS_PACKET_SIZE;
527 const uint32_t ts_sync = block_time / ts_count;
528 const uint32_t block_time_tail = block_time % ts_count;
529
530 system_time_check = asc_utime();
531
532 while(mod->is_thread_started && mod->sync.buffer_read != next_block)
533 {
534 // sending
535 ptr = &mod->sync.buffer[mod->sync.buffer_read];
536 size_t next_packet = mod->sync.buffer_read + TS_PACKET_SIZE;
537 if(next_packet < mod->sync.buffer_size)
538 {
539 mod->sync.buffer_read = next_packet;
540 }
541 else if(next_packet > mod->sync.buffer_size)
542 {
543 const size_t packet_head = mod->sync.buffer_size - mod->sync.buffer_read;
544 memcpy(ts, ptr, packet_head);
545 mod->sync.buffer_read = next_packet - mod->sync.buffer_size;
546 memcpy(&ts[packet_head], mod->sync.buffer, mod->sync.buffer_read);
547 ptr = ts;
548 }
549 else /* next_packet == mod->sync.buffer_size */
550 {
551 mod->sync.buffer_read = 0;
552 }
553
554 const ssize_t write_size = asc_thread_buffer_write( mod->thread_output
555 , ptr
556 , TS_PACKET_SIZE);
557 if(write_size != TS_PACKET_SIZE)
558 {
559 // overflow
560 }
561
562 system_time = asc_utime();
563 block_time_total += ts_sync;
564
565 if( (system_time < system_time_check) /* <-0s */
566 ||(system_time > system_time_check + 1000000)) /* >+1s */
567 {
568 asc_log_warning(MSG("system time changed"));
569
570 mod->sync.buffer_read = next_block;
571
572 reset = true;
573 break;
574 }
575 system_time_check = system_time;
576
577 if(block_time_total > system_time + 100)
578 asc_usleep(block_time_total - system_time);
579 }
580 mod->sync.buffer_count -= block_size;
581
582 if(reset)
583 continue;
584
585 system_time = asc_utime();
586 if(system_time > block_time_total + 100000)
587 {
588 asc_log_warning( MSG("wrong syncing time. -%"PRIu64"ms")
589 , (system_time - block_time_total) / 1000);
590 reset = true;
591 }
592
593 block_time_total += block_time_tail;
594 }
595 }
596}
597
598static void check_is_active(void *arg)
599{
600 module_data_t *mod = (module_data_t *)arg;
601
602 if(mod->is_active)
603 {
604 mod->is_active = false;
605 return;
606 }
607
608 asc_log_error(MSG("receiving timeout"));
609 on_close(mod);
610}
611
612static void on_ts_read(void *arg)
613{
614 module_data_t *mod = (module_data_t *)arg;
615
616 ssize_t size = asc_socket_recv( mod->sock
617 , &mod->sync.buffer[mod->sync.buffer_write]
618 , mod->sync.buffer_size - mod->sync.buffer_write);
619 if(size <= 0)
620 {
621 on_close(mod);
622 return;
623 }
624
625 mod->is_active = true;
626 mod->sync.buffer_write += size;
627 mod->sync.buffer_read = 0;
628
629 while(1)
630 {
631 while(mod->sync.buffer[mod->sync.buffer_read] != 0x47)
632 {
633 ++mod->sync.buffer_read;
634 if(mod->sync.buffer_read >= mod->sync.buffer_write)
635 {
636 mod->sync.buffer_write = 0;
637 return;
638 }
639 }
640
641 const size_t next = mod->sync.buffer_read + TS_PACKET_SIZE;
642 if(next > mod->sync.buffer_write)
643 {
644 const size_t tail = mod->sync.buffer_write - mod->sync.buffer_read;
645 if(tail > 0)
646 memmove(mod->sync.buffer, &mod->sync.buffer[mod->sync.buffer_read], tail);
647 mod->sync.buffer_write = tail;
648 return;
649 }
650
651 module_stream_send(mod, &mod->sync.buffer[mod->sync.buffer_read]);
652 mod->sync.buffer_read += TS_PACKET_SIZE;
653 }
654}
655
656/*
657 * oooooooooo ooooooooooo o ooooooooo
658 * 888 888 888 88 888 888 88o
659 * 888oooo88 888ooo8 8 88 888 888
660 * 888 88o 888 oo 8oooo88 888 888
661 * o888o 88o8 o888ooo8888 o88o o888o o888ooo88
662 *
663 */
664
665static void on_read(void *arg)
666{
667 module_data_t *mod = (module_data_t *)arg;
668
669 if(mod->timeout)
670 {
671 asc_timer_destroy(mod->timeout);
672 mod->timeout = NULL;
673 }
674
675 ssize_t size = asc_socket_recv( mod->sock
676 , &mod->buffer[mod->buffer_skip]
677 , HTTP_BUFFER_SIZE - mod->buffer_skip);
678 if(size <= 0)
679 {
680 on_close(mod);
681 return;
682 }
683
684 if(mod->receiver.callback.ptr)
685 {
686 mod->receiver.callback.fn(mod->receiver.arg, &mod->buffer[mod->buffer_skip], size);
687 return;
688 }
689
690 if(mod->status == 3)
691 {
692 asc_log_warning(MSG("received data after response"));
693 return;
694 }
695
696 size_t eoh = 0; // end of headers
697 size_t skip = 0;
698 mod->buffer_skip += size;
699
700 if(mod->status == 0)
701 {
702 // check empty line
703 while(skip < mod->buffer_skip)
704 {
705 if( skip + 1 < mod->buffer_skip
706 && mod->buffer[skip + 0] == '\n' && mod->buffer[skip + 1] == '\n')
707 {
708 eoh = skip + 2;
709 mod->status = 1;
710 break;
711 }
712 else if( skip + 3 < mod->buffer_skip
713 && mod->buffer[skip + 0] == '\r' && mod->buffer[skip + 1] == '\n'
714 && mod->buffer[skip + 2] == '\r' && mod->buffer[skip + 3] == '\n')
715 {
716 eoh = skip + 4;
717 mod->status = 1;
718 break;
719 }
720 ++skip;
721 }
722
723 if(mod->status != 1)
724 return;
725 }
726
727 if(mod->status == 1)
728 {
729 parse_match_t m[4];
730
731 skip = 0;
732
733/*
734 * oooooooooo ooooooooooo oooooooo8 oooooooooo
735 * 888 888 888 88 888 888 888
736 * 888oooo88 888ooo8 888oooooo 888oooo88
737 * ooo 888 88o 888 oo 888 888
738 * 888 o888o 88o8 o888ooo8888 o88oooo888 o888o
739 *
740 */
741
742 if(!http_parse_response(mod->buffer, eoh, m))
743 {
744 call_error(mod, "failed to parse response line");
745 on_close(mod);
746 return;
747 }
748
749 lua_newtable(lua);
750 const int response = lua_gettop(lua);
751
752 lua_pushvalue(lua, -1);
753 if(mod->idx_response)
754 luaL_unref(lua, LUA_REGISTRYINDEX, mod->idx_response);
755 mod->idx_response = luaL_ref(lua, LUA_REGISTRYINDEX);
756
757 lua_pushlstring(lua, &mod->buffer[m[1].so], m[1].eo - m[1].so);
758 lua_setfield(lua, response, __version);
759
760 mod->status_code = atoi(&mod->buffer[m[2].so]);
761 lua_pushnumber(lua, mod->status_code);
762 lua_setfield(lua, response, __code);
763
764 lua_pushlstring(lua, &mod->buffer[m[3].so], m[3].eo - m[3].so);
765 lua_setfield(lua, response, __message);
766
767 skip += m[0].eo;
768
769/*
770 * ooooo ooooo ooooooooooo o ooooooooo ooooooooooo oooooooooo oooooooo8
771 * 888 888 888 88 888 888 88o 888 88 888 888 888
772 * 888ooo888 888ooo8 8 88 888 888 888ooo8 888oooo88 888oooooo
773 * ooo 888 888 888 oo 8oooo88 888 888 888 oo 888 88o 888
774 * 888 o888o o888o o888ooo8888 o88o o888o o888ooo88 o888ooo8888 o888o 88o8 o88oooo888
775 *
776 */
777
778 lua_newtable(lua);
779 lua_pushvalue(lua, -1);
780 lua_setfield(lua, response, __headers);
781 const int headers = lua_gettop(lua);
782
783 while(skip < eoh)
784 {
785 if(!http_parse_header(&mod->buffer[skip], eoh - skip, m))
786 {
787 call_error(mod, "failed to parse response headers");
788 on_close(mod);
789 return;
790 }
791
792 if(m[1].eo == 0)
793 { /* empty line */
794 skip += m[0].eo;
795 mod->status = 2;
796 break;
797 }
798
799 lua_string_to_lower(&mod->buffer[skip], m[1].eo);
800 lua_pushlstring(lua, &mod->buffer[skip + m[2].so], m[2].eo - m[2].so);
801 lua_settable(lua, headers);
802
803 skip += m[0].eo;
804 }
805
806 mod->chunk_left = 0;
807 mod->is_content_length = false;
808
809 if(mod->content)
810 {
811 free(mod->content);
812 mod->content = NULL;
813 }
814
815 lua_getfield(lua, headers, "content-length");
816 if(lua_isnumber(lua, -1))
817 {
818 mod->chunk_left = lua_tonumber(lua, -1);
819 if(mod->chunk_left > 0)
820 {
821 mod->is_content_length = true;
822 }
823 }
824 lua_pop(lua, 1); // content-length
825
826 lua_getfield(lua, headers, "transfer-encoding");
827 if(lua_isstring(lua, -1))
828 {
829 const char *encoding = lua_tostring(lua, -1);
830 mod->is_chunked = (strcmp(encoding, "chunked") == 0);
831 }
832 lua_pop(lua, 1); // transfer-encoding
833
834 if(mod->is_content_length || mod->is_chunked)
835 mod->content = string_buffer_alloc();
836
837 lua_pop(lua, 2); // headers + response
838
839 if( (mod->is_head)
840 || (mod->status_code >= 100 && mod->status_code < 200)
841 || (mod->status_code == 204)
842 || (mod->status_code == 304))
843 {
844 mod->status = 3;
845
846 lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_response);
847 callback(mod);
848
849 if(mod->is_connection_close)
850 on_close(mod);
851
852 mod->buffer_skip = 0;
853 return;
854 }
855
856 if(mod->is_stream && mod->status_code == 200)
857 {
858 mod->status = 3;
859
860 lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_response);
861 lua_pushboolean(lua, mod->is_stream);
862 lua_setfield(lua, -2, __stream);
863 callback(mod);
864
865 mod->sync.buffer = (uint8_t *)malloc(mod->sync.buffer_size);
866
867 if(!mod->config.sync)
868 {
869 mod->timeout = asc_timer_init(mod->timeout_ms, check_is_active, mod);
870
871 asc_socket_set_on_read(mod->sock, on_ts_read);
872 asc_socket_set_on_ready(mod->sock, NULL);
873 }
874 else
875 {
876 asc_socket_set_on_read(mod->sock, NULL);
877 asc_socket_set_on_ready(mod->sock, NULL);
878 asc_socket_set_on_close(mod->sock, NULL);
879
880 mod->thread = asc_thread_init(mod);
881 mod->thread_output = asc_thread_buffer_init(mod->sync.buffer_size);
882 asc_thread_start( mod->thread
883 , thread_loop
884 , on_thread_read, mod->thread_output
885 , on_thread_close);
886 }
887
888 mod->buffer_skip = 0;
889 return;
890 }
891
892 if(!mod->content)
893 {
894 mod->status = 3;
895
896 lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_response);
897 callback(mod);
898
899 if(mod->is_connection_close)
900 on_close(mod);
901
902 mod->buffer_skip = 0;
903 return;
904 }
905 }
906
907/*
908 * oooooooo8 ooooooo oooo oooo ooooooooooo ooooooooooo oooo oooo ooooooooooo
909 * o888 88 o888 888o 8888o 88 88 888 88 888 88 8888o 88 88 888 88
910 * 888 888 888 88 888o88 888 888ooo8 88 888o88 888
911 * ooo 888o oo 888o o888 88 8888 888 888 oo 88 8888 888
912 * 888 888oooo88 88ooo88 o88o 88 o888o o888ooo8888 o88o 88 o888o
913 *
914 */
915
916 // Transfer-Encoding: chunked
917 if(mod->is_chunked)
918 {
919 parse_match_t m[2];
920
921 while(skip < mod->buffer_skip)
922 {
923 if(!mod->chunk_left)
924 {
925 if(!http_parse_chunk(&mod->buffer[skip], mod->buffer_skip - skip, m))
926 {
927 call_error(mod, "invalid chunk");
928 on_close(mod);
929 return;
930 }
931
932 mod->chunk_left = 0;
933 for(size_t i = m[1].so; i < m[1].eo; ++i)
934 {
935 char c = mod->buffer[skip + i];
936 if(c >= '0' && c <= '9')
937 mod->chunk_left = (mod->chunk_left << 4) | (c - '0');
938 else if(c >= 'a' && c <= 'f')
939 mod->chunk_left = (mod->chunk_left << 4) | (c - 'a' + 0x0A);
940 else if(c >= 'A' && c <= 'F')
941 mod->chunk_left = (mod->chunk_left << 4) | (c - 'A' + 0x0A);
942 }
943 skip += m[0].eo;
944
945 if(!mod->chunk_left)
946 {
947 lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_response);
948 string_buffer_push(lua, mod->content);
949 mod->content = NULL;
950 lua_setfield(lua, -2, __content);
951 mod->status = 3;
952 callback(mod);
953
954 if(mod->is_connection_close)
955 {
956 on_close(mod);
957 return;
958 }
959
960 break;
961 }
962
963 mod->chunk_left += 2;
964 }
965
966 const size_t tail = size - skip;
967 if(mod->chunk_left <= tail)
968 {
969 string_buffer_addlstring(mod->content, &mod->buffer[skip], mod->chunk_left - 2);
970
971 skip += mod->chunk_left;
972 mod->chunk_left = 0;
973 }
974 else
975 {
976 string_buffer_addlstring(mod->content, &mod->buffer[skip], tail);
977 mod->chunk_left -= tail;
978 break;
979 }
980 }
981
982 mod->buffer_skip = 0;
983 return;
984 }
985
986 // Content-Length: *
987 if(mod->is_content_length)
988 {
989 const size_t tail = mod->buffer_skip - skip;
990
991 if(mod->chunk_left > tail)
992 {
993 string_buffer_addlstring(mod->content, &mod->buffer[skip], tail);
994 mod->chunk_left -= tail;
995 }
996 else
997 {
998 string_buffer_addlstring(mod->content, &mod->buffer[skip], mod->chunk_left);
999 mod->chunk_left = 0;
1000
1001 lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_response);
1002 string_buffer_push(lua, mod->content);
1003 mod->content = NULL;
1004 lua_setfield(lua, -2, __content);
1005 mod->status = 3;
1006 callback(mod);
1007
1008 if(mod->is_connection_close)
1009 {
1010 on_close(mod);
1011 return;
1012 }
1013 }
1014
1015 mod->buffer_skip = 0;
1016 return;
1017 }
1018}
1019
1020/*
1021 * oooooooo8 ooooooooooo oooo oooo ooooooooo
1022 * 888 888 88 8888o 88 888 88o
1023 * 888oooooo 888ooo8 88 888o88 888 888
1024 * 888 888 oo 88 8888 888 888
1025 * o88oooo888 o888ooo8888 o88o 88 o888ooo88
1026 *
1027 */
1028
1029static void on_ready_send_content(void *arg)
1030{
1031 module_data_t *mod = (module_data_t *)arg;
1032
1033 asc_assert(mod->request.size > 0, MSG("invalid content size"));
1034
1035 const size_t rem = mod->request.size - mod->request.skip;
1036 const size_t cap = (rem > HTTP_BUFFER_SIZE) ? HTTP_BUFFER_SIZE : rem;
1037
1038 const ssize_t send_size = asc_socket_send( mod->sock
1039 , &mod->request.buffer[mod->request.skip]
1040 , cap);
1041 if(send_size == -1)
1042 {
1043 asc_log_error(MSG("failed to send content [%s]"), asc_socket_error());
1044 on_close(mod);
1045 return;
1046 }
1047 mod->request.skip += send_size;
1048
1049 if(mod->request.skip >= mod->request.size)
1050 {
1051 mod->request.buffer = NULL;
1052
1053 luaL_unref(lua, LUA_REGISTRYINDEX, mod->request.idx_body);
1054 mod->request.idx_body = 0;
1055
1056 mod->request.status = 3;
1057
1058 asc_socket_set_on_ready(mod->sock, NULL);
1059 }
1060}
1061
1062static void on_ready_send_request(void *arg)
1063{
1064 module_data_t *mod = (module_data_t *)arg;
1065
1066 asc_assert(mod->request.size > 0, MSG("invalid request size"));
1067
1068 const size_t rem = mod->request.size - mod->request.skip;
1069 const size_t cap = (rem > HTTP_BUFFER_SIZE) ? HTTP_BUFFER_SIZE : rem;
1070
1071 const ssize_t send_size = asc_socket_send( mod->sock
1072 , &mod->request.buffer[mod->request.skip]
1073 , cap);
1074 if(send_size == -1)
1075 {
1076 asc_log_error(MSG("failed to send response [%s]"), asc_socket_error());
1077 on_close(mod);
1078 return;
1079 }
1080 mod->request.skip += send_size;
1081
1082 if(mod->request.skip >= mod->request.size)
1083 {
1084 free((void *)mod->request.buffer);
1085 mod->request.buffer = NULL;
1086
1087 if(mod->request.idx_body)
1088 {
1089 lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->request.idx_body);
1090 mod->request.buffer = lua_tostring(lua, -1);
1091 mod->request.size = luaL_len(lua, -1);
1092 mod->request.skip = 0;
1093 lua_pop(lua, 1);
1094
1095 mod->request.status = 2;
1096
1097 asc_socket_set_on_ready(mod->sock, on_ready_send_content);
1098 }
1099 else
1100 {
1101 mod->request.status = 3;
1102
1103 asc_socket_set_on_ready(mod->sock, NULL);
1104 }
1105 }
1106}
1107
1108static void lua_make_request(module_data_t *mod)
1109{
1110 lua_getfield(lua, -1, __method);
1111 const char *method = lua_isstring(lua, -1) ? lua_tostring(lua, -1) : __default_method;
1112 lua_pop(lua, 1);
1113
1114 mod->is_head = (strcmp(method, "HEAD") == 0);
1115
1116 lua_getfield(lua, -1, __path);
1117 mod->config.path = lua_isstring(lua, -1) ? lua_tostring(lua, -1) : __default_path;
1118 lua_pop(lua, 1);
1119
1120 lua_getfield(lua, -1, __version);
1121 const char *version = lua_isstring(lua, -1) ? lua_tostring(lua, -1) : __default_version;
1122 lua_pop(lua, 1);
1123
1124 string_buffer_t *buffer = string_buffer_alloc();
1125
1126 string_buffer_addfstring(buffer, "%s %s %s\r\n", method, mod->config.path, version);
1127
1128 lua_getfield(lua, -1, __headers);
1129 if(lua_istable(lua, -1))
1130 {
1131 for(lua_pushnil(lua); lua_next(lua, -2); lua_pop(lua, 1))
1132 {
1133 const char *h = lua_tostring(lua, -1);
1134
1135 if(!strncasecmp(h, __connection, sizeof(__connection) - 1))
1136 {
1137 const char *hp = &h[sizeof(__connection) - 1];
1138 if(!strncasecmp(hp, __close, sizeof(__close) - 1))
1139 mod->is_connection_close = true;
1140 else if(!strncasecmp(hp, __keep_alive, sizeof(__keep_alive) - 1))
1141 mod->is_connection_keep_alive = true;
1142 }
1143
1144 string_buffer_addfstring(buffer, "%s\r\n", h);
1145 }
1146 }
1147 lua_pop(lua, 1); // headers
1148
1149 string_buffer_addlstring(buffer, "\r\n", 2);
1150
1151 mod->request.buffer = string_buffer_release(buffer, &mod->request.size);
1152 mod->request.skip = 0;
1153
1154 if(mod->request.idx_body)
1155 {
1156 luaL_unref(lua, LUA_REGISTRYINDEX, mod->request.idx_body);
1157 mod->request.idx_body = 0;
1158 }
1159
1160 lua_getfield(lua, -1, __content);
1161 if(lua_isstring(lua, -1))
1162 mod->request.idx_body = luaL_ref(lua, LUA_REGISTRYINDEX);
1163 else
1164 lua_pop(lua, 1);
1165}
1166
1167static void on_connect(void *arg)
1168{
1169 module_data_t *mod = (module_data_t *)arg;
1170
1171 mod->request.status = 1;
1172
1173 asc_timer_destroy(mod->timeout);
1174 mod->timeout = asc_timer_init(mod->timeout_ms, timeout_callback, mod);
1175
1176 lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_self);
1177 lua_getfield(lua, -1, "__options");
1178 lua_make_request(mod);
1179 lua_pop(lua, 2); // self + __options
1180
1181 asc_socket_set_on_read(mod->sock, on_read);
1182 asc_socket_set_on_ready(mod->sock, on_ready_send_request);
1183}
1184
1185static void on_upstream_ready(void *arg)
1186{
1187 module_data_t *mod = (module_data_t *)arg;
1188
1189 if(mod->sync.buffer_count > 0)
1190 {
1191 size_t block_size = (mod->sync.buffer_write > mod->sync.buffer_read)
1192 ? (mod->sync.buffer_write - mod->sync.buffer_read)
1193 : (mod->sync.buffer_size - mod->sync.buffer_read);
1194
1195 if(block_size > mod->sync.buffer_count)
1196 block_size = mod->sync.buffer_count;
1197
1198 const ssize_t send_size = asc_socket_send( mod->sock
1199 , &mod->sync.buffer[mod->sync.buffer_read]
1200 , block_size);
1201
1202 if(send_size > 0)
1203 {
1204 mod->sync.buffer_count -= send_size;
1205 mod->sync.buffer_read += send_size;
1206 if(mod->sync.buffer_read >= mod->sync.buffer_size)
1207 mod->sync.buffer_read = 0;
1208 }
1209 else if(send_size == -1)
1210 {
1211 asc_log_error( MSG("failed to send ts (%lu bytes) [%s]")
1212 , block_size, asc_socket_error());
1213 on_close(mod);
1214 return;
1215 }
1216 }
1217
1218 if(mod->sync.buffer_count == 0)
1219 {
1220 asc_socket_set_on_ready(mod->sock, NULL);
1221 mod->is_socket_busy = false;
1222 }
1223}
1224
1225static void on_ts(module_data_t *mod, const uint8_t *ts)
1226{
1227 if(mod->status != 3 || mod->status_code != 200)
1228 return;
1229
1230 if(mod->sync.buffer_count + TS_PACKET_SIZE >= mod->sync.buffer_size)
1231 {
1232 // overflow
1233 mod->sync.buffer_count = 0;
1234 mod->sync.buffer_read = 0;
1235 mod->sync.buffer_write = 0;
1236 if(mod->is_socket_busy)
1237 {
1238 asc_socket_set_on_ready(mod->sock, NULL);
1239 mod->is_socket_busy = false;
1240 }
1241 return;
1242 }
1243
1244 const size_t buffer_write = mod->sync.buffer_write + TS_PACKET_SIZE;
1245 if(buffer_write < mod->sync.buffer_size)
1246 {
1247 memcpy(&mod->sync.buffer[mod->sync.buffer_write], ts, TS_PACKET_SIZE);
1248 mod->sync.buffer_write = buffer_write;
1249 }
1250 else if(buffer_write > mod->sync.buffer_size)
1251 {
1252 const size_t ts_head = mod->sync.buffer_size - mod->sync.buffer_write;
1253 memcpy(&mod->sync.buffer[mod->sync.buffer_write], ts, ts_head);
1254 mod->sync.buffer_write = TS_PACKET_SIZE - ts_head;
1255 memcpy(mod->sync.buffer, &ts[ts_head], mod->sync.buffer_write);
1256 }
1257 else
1258 {
1259 memcpy(&mod->sync.buffer[mod->sync.buffer_write], ts, TS_PACKET_SIZE);
1260 mod->sync.buffer_write = 0;
1261 }
1262 mod->sync.buffer_count += TS_PACKET_SIZE;
1263
1264 if( mod->is_socket_busy == false
1265 && mod->sync.buffer_count >= mod->sync.buffer_fill)
1266 {
1267 asc_socket_set_on_ready(mod->sock, on_upstream_ready);
1268 mod->is_socket_busy = true;
1269 }
1270}
1271
1272/*
1273 * oooo oooo ooooooo ooooooooo ooooo oooo ooooo ooooooooooo
1274 * 8888o 888 o888 888o 888 88o 888 88 888 888 88
1275 * 88 888o8 88 888 888 888 888 888 88 888 888ooo8
1276 * 88 888 88 888o o888 888 888 888 88 888 o 888 oo
1277 * o88o 8 o88o 88ooo88 o888ooo88 888oo88 o888ooooo88 o888ooo8888
1278 *
1279 */
1280
1281static int method_set_receiver(module_data_t *mod)
1282{
1283 if(lua_isnil(lua, -1))
1284 {
1285 mod->receiver.arg = NULL;
1286 mod->receiver.callback.ptr = NULL;
1287 }
1288 else
1289 {
1290 mod->receiver.arg = lua_touserdata(lua, -2);
1291 mod->receiver.callback.ptr = lua_touserdata(lua, -1);
1292 }
1293 return 0;
1294}
1295
1296static int method_send(module_data_t *mod)
1297{
1298 mod->status = 0;
1299
1300 if(mod->timeout)
1301 asc_timer_destroy(mod->timeout);
1302 mod->timeout = asc_timer_init(mod->timeout_ms, timeout_callback, mod);
1303
1304 asc_assert(lua_istable(lua, 2), MSG(":send() table required"));
1305 lua_pushvalue(lua, 2);
1306 lua_make_request(mod);
1307 lua_pop(lua, 2); // :send() options
1308
1309 asc_socket_set_on_read(mod->sock, on_read);
1310 asc_socket_set_on_ready(mod->sock, on_ready_send_request);
1311
1312 return 0;
1313}
1314
1315static int method_close(module_data_t *mod)
1316{
1317 mod->status = -1;
1318 mod->request.status = -1;
1319 on_close(mod);
1320
1321 return 0;
1322}
1323
1324static void module_init(module_data_t *mod)
1325{
1326 module_option_string("host", &mod->config.host, NULL);
1327 asc_assert(mod->config.host != NULL, MSG("option 'host' is required"));
1328
1329 mod->config.port = 80;
1330 module_option_number("port", &mod->config.port);
1331
1332 mod->config.path = __default_path;
1333 module_option_string(__path, &mod->config.path, NULL);
1334
1335 lua_getfield(lua, 2, __callback);
1336 asc_assert(lua_isfunction(lua, -1), MSG("option 'callback' is required"));
1337 lua_pop(lua, 1); // callback
1338
1339 // store self in registry
1340 lua_pushvalue(lua, 3);
1341 mod->idx_self = luaL_ref(lua, LUA_REGISTRYINDEX);
1342
1343 module_option_boolean(__stream, &mod->is_stream);
1344 if(mod->is_stream)
1345 {
1346 module_stream_init(mod, NULL);
1347
1348 int value = 0;
1349 module_option_number("sync", &value);
1350 if(value > 0)
1351 mod->config.sync = true;
1352 else
1353 value = 1;
1354
1355 mod->sync.buffer_size = value * 1024 * 1024;
1356 }
1357
1358 lua_getfield(lua, MODULE_OPTIONS_IDX, "upstream");
1359 if(lua_type(lua, -1) == LUA_TLIGHTUSERDATA)
1360 {
1361 asc_assert(mod->is_stream != true, MSG("option 'upstream' is not allowed in stream mode"));
1362
1363 module_stream_init(mod, on_ts);
1364
1365 int value = 1024;
1366 module_option_number("buffer_size", &value);
1367 mod->sync.buffer_size = value * 1024;
1368 mod->sync.buffer = (uint8_t *)malloc(mod->sync.buffer_size);
1369
1370 value = 128;
1371 module_option_number("buffer_fill", &value);
1372 mod->sync.buffer_fill = value * 1024;
1373 }
1374 lua_pop(lua, 1);
1375
1376 mod->timeout_ms = 10;
1377 module_option_number("timeout", &mod->timeout_ms);
1378 mod->timeout_ms *= 1000;
1379 mod->timeout = asc_timer_init(mod->timeout_ms, timeout_callback, mod);
1380
1381 bool sctp = false;
1382 module_option_boolean("sctp", &sctp);
1383 if(sctp == true)
1384 mod->sock = asc_socket_open_sctp4(mod);
1385 else
1386 mod->sock = asc_socket_open_tcp4(mod);
1387
1388 asc_socket_connect(mod->sock, mod->config.host, mod->config.port, on_connect, on_close);
1389}
1390
1391static void module_destroy(module_data_t *mod)
1392{
1393 mod->status = -1;
1394 mod->request.status = -1;
1395
1396 on_close(mod);
1397}
1398
1399MODULE_STREAM_METHODS()
1400MODULE_LUA_METHODS()
1401{
1402 MODULE_STREAM_METHODS_REF(),
1403 { "send", method_send },
1404 { "close", method_close },
1405 { "set_receiver", method_set_receiver },
1406};
1407
1408MODULE_LUA_REGISTER(http_request)