|
@@ -267,7 +267,7 @@ char TS_NULL_FRAME[FRAME_PACKET_SIZE];
|
267
|
267
|
regex_t http_response;
|
268
|
268
|
|
269
|
269
|
void proxy_log(RESTREAMER *r, char *msg, char *info) {
|
270
|
|
- LOGf("%s: %sChan: %s Src: %s Dst: udp://%s:%d SrcIP: %s SrcFD: %i DstFD: %i\n",
|
|
270
|
+ LOGf("%s: %s Chan: %s Src: %s Dst: udp://%s:%d SrcIP: %s SrcFD: %i DstFD: %i\n",
|
271
|
271
|
msg,
|
272
|
272
|
info,
|
273
|
273
|
r->channel->name,
|
|
@@ -412,7 +412,7 @@ report_error:
|
412
|
412
|
}
|
413
|
413
|
|
414
|
414
|
void proxy_close(RESTREAMER *r) {
|
415
|
|
- proxy_log(r, "STOP ","");
|
|
415
|
+ proxy_log(r, "STOP ","-");
|
416
|
416
|
// If there are no clients left, no "Timeout" messages will be logged
|
417
|
417
|
list_del_entry(config.restreamer, r);
|
418
|
418
|
free_restreamer(r);
|
|
@@ -446,8 +446,12 @@ void proxy_close(RESTREAMER *r) {
|
446
|
446
|
1 = retry
|
447
|
447
|
0 = connected ok
|
448
|
448
|
*/
|
449
|
|
-int connect_source(RESTREAMER *r, int retries, int readbuflen, int *http_code) {
|
450
|
|
- CHANSRC *src = init_chansrc(r->channel->source);
|
|
449
|
+int connect_source(RESTREAMER *r, int retries, int readbuflen, int *http_code, char *url, int depth) {
|
|
450
|
+ CHANSRC *src = init_chansrc(url);
|
|
451
|
+ if (depth > 4) {
|
|
452
|
+ LOGf("ERR : Redirect loop detected, depth: %d | Channel: %s Source: %s\n", depth, r->channel->name, url);
|
|
453
|
+ FATAL_ERROR;
|
|
454
|
+ }
|
451
|
455
|
if (!src) {
|
452
|
456
|
LOGf("ERR : Can't parse channel source | Channel: %s Source: %s\n", r->channel->name, r->channel->source);
|
453
|
457
|
FATAL_ERROR;
|
|
@@ -477,7 +481,11 @@ int connect_source(RESTREAMER *r, int retries, int readbuflen, int *http_code) {
|
477
|
481
|
log_perror("play(): Could not create SOCK_STREAM socket.", errno);
|
478
|
482
|
FATAL_ERROR;
|
479
|
483
|
}
|
480
|
|
- proxy_log(r, "NEW ","");
|
|
484
|
+ if (depth == 0) {
|
|
485
|
+ proxy_log(r, "NEW ", "-");
|
|
486
|
+ } else {
|
|
487
|
+ proxy_log(r, "NEW ", url);
|
|
488
|
+ }
|
481
|
489
|
if (do_connect(r->sock, (struct sockaddr *)&(r->src_sockname), sizeof(r->src_sockname), PROXY_CONNECT_TIMEOUT) < 0) {
|
482
|
490
|
LOGf("ERR : Error connecting to %s srv_fd: %i err: %s\n", r->channel->source, r->sock, strerror(errno));
|
483
|
491
|
proxy_set_status(r, "ERROR: Can not connect to source");
|
|
@@ -489,6 +497,8 @@ int connect_source(RESTREAMER *r, int retries, int readbuflen, int *http_code) {
|
489
|
497
|
buf[sizeof(buf)-1] = 0;
|
490
|
498
|
fdwrite(r->sock, buf, strlen(buf));
|
491
|
499
|
|
|
500
|
+ char redirect_to[1024];
|
|
501
|
+ memset(redirect_to, 0, sizeof(redirect_to));
|
492
|
502
|
char xresponse[128];
|
493
|
503
|
memset(xresponse, 0, sizeof(xresponse));
|
494
|
504
|
memset(buf, 0, sizeof(buf));
|
|
@@ -515,6 +525,20 @@ int connect_source(RESTREAMER *r, int retries, int readbuflen, int *http_code) {
|
515
|
525
|
break;
|
516
|
526
|
}
|
517
|
527
|
}
|
|
528
|
+ if (strstr(buf, "Location: ") == buf) {
|
|
529
|
+ // Remove new line
|
|
530
|
+ char *new_line = strchr(buf, '\r');
|
|
531
|
+ if (new_line) *new_line = '\0';
|
|
532
|
+ new_line = strchr(buf, '\n');
|
|
533
|
+ if (new_line) *new_line = '\0';
|
|
534
|
+ snprintf(redirect_to, sizeof(redirect_to)-1, "%s", buf + 10);
|
|
535
|
+ if (strstr(redirect_to, "http://") != redirect_to) {
|
|
536
|
+ // Assume that the redirect is relative, add proto, host and port
|
|
537
|
+ snprintf(redirect_to, sizeof(redirect_to)-1, "http://%s:%d%s",
|
|
538
|
+ src->host, src->port, buf + 10);
|
|
539
|
+ LOGf("DEBUG: Converted relative location to: %s | srv_fd: %i\n", redirect_to, r->sock);
|
|
540
|
+ }
|
|
541
|
+ }
|
518
|
542
|
}
|
519
|
543
|
if (*http_code == 0) { // No valid HTTP response, retry
|
520
|
544
|
LOGf("DEBUG: Server returned not valid HTTP code | srv_fd: %i\n", r->sock);
|
|
@@ -526,7 +550,15 @@ int connect_source(RESTREAMER *r, int retries, int readbuflen, int *http_code) {
|
526
|
550
|
proxy_set_status(r, "ERROR: Source returned no-signal");
|
527
|
551
|
FATAL_ERROR;
|
528
|
552
|
}
|
529
|
|
- if (*http_code > 300) { // Unhandled or error codes, exit
|
|
553
|
+ if (*http_code == 301 || *http_code == 302) { // Handle redirects
|
|
554
|
+ if (redirect_to[0]) {
|
|
555
|
+ LOGf("REDIR: Get code %i for %s from %s on srv_fd: %i, handling redirect to: %s\n", *http_code, r->channel->name, r->channel->source, r->sock, redirect_to);
|
|
556
|
+ free_chansrc(src);
|
|
557
|
+ shutdown_fd(&(r->sock));
|
|
558
|
+ return connect_source(r, retries, readbuflen, http_code, redirect_to, ++depth);
|
|
559
|
+ }
|
|
560
|
+ // Redirect connect is OK, continue
|
|
561
|
+ } else if (*http_code > 300) { // Unhandled or error codes, exit
|
530
|
562
|
LOGf("ERR : Get code %i for %s from %s on srv_fd: %i exiting.\n", *http_code, r->channel->name, r->channel->source, r->sock);
|
531
|
563
|
proxy_set_status(r, "ERROR: Source returned unhandled error code");
|
532
|
564
|
FATAL_ERROR;
|
|
@@ -787,7 +819,7 @@ void * proxy_ts_stream(void *self) {
|
787
|
819
|
r->conn_ts = 0;
|
788
|
820
|
r->read_bytes = 0;
|
789
|
821
|
|
790
|
|
- int result = connect_source(self, 1, FRAME_PACKET_SIZE * 1000, &http_code);
|
|
822
|
+ int result = connect_source(self, 1, FRAME_PACKET_SIZE * 1000, &http_code, r->channel->source, 0);
|
791
|
823
|
if (result > 0)
|
792
|
824
|
goto RECONNECT;
|
793
|
825
|
|