Browse Source

Add support for handling of HTTP 301/302 redirects

Georgi Chorbadzhiyski 6 years ago
parent
commit
a717fd9c8a
2 changed files with 42 additions and 7 deletions
  1. 3
    0
      ChangeLog
  2. 39
    7
      tomcast.c

+ 3
- 0
ChangeLog View File

@@ -1,3 +1,6 @@
1
+vNEXT | xx xxx xxxx
2
+  * Add support for handling of 301/302 HTTP redirects
3
+
1 4
 v1.30 | 21 Dec 2016
2 5
   * Add web access for monitoring and reconfiguration
3 6
 

+ 39
- 7
tomcast.c View File

@@ -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
 

Loading…
Cancel
Save