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

+ 39
- 7
tomcast.c View File

267
 regex_t http_response;
267
 regex_t http_response;
268
 
268
 
269
 void proxy_log(RESTREAMER *r, char *msg, char *info) {
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
 		msg,
271
 		msg,
272
 		info,
272
 		info,
273
 		r->channel->name,
273
 		r->channel->name,
412
 }
412
 }
413
 
413
 
414
 void proxy_close(RESTREAMER *r) {
414
 void proxy_close(RESTREAMER *r) {
415
-	proxy_log(r, "STOP ","");
415
+	proxy_log(r, "STOP ","-");
416
 	// If there are no clients left, no "Timeout" messages will be logged
416
 	// If there are no clients left, no "Timeout" messages will be logged
417
 	list_del_entry(config.restreamer, r);
417
 	list_del_entry(config.restreamer, r);
418
 	free_restreamer(r);
418
 	free_restreamer(r);
446
 		 1 = retry
446
 		 1 = retry
447
 		 0 = connected ok
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
 	if (!src) {
455
 	if (!src) {
452
 		LOGf("ERR  : Can't parse channel source | Channel: %s Source: %s\n", r->channel->name, r->channel->source);
456
 		LOGf("ERR  : Can't parse channel source | Channel: %s Source: %s\n", r->channel->name, r->channel->source);
453
 		FATAL_ERROR;
457
 		FATAL_ERROR;
477
 			log_perror("play(): Could not create SOCK_STREAM socket.", errno);
481
 			log_perror("play(): Could not create SOCK_STREAM socket.", errno);
478
 			FATAL_ERROR;
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
 		if (do_connect(r->sock, (struct sockaddr *)&(r->src_sockname), sizeof(r->src_sockname), PROXY_CONNECT_TIMEOUT) < 0) {
489
 		if (do_connect(r->sock, (struct sockaddr *)&(r->src_sockname), sizeof(r->src_sockname), PROXY_CONNECT_TIMEOUT) < 0) {
482
 			LOGf("ERR  : Error connecting to %s srv_fd: %i err: %s\n", r->channel->source, r->sock, strerror(errno));
490
 			LOGf("ERR  : Error connecting to %s srv_fd: %i err: %s\n", r->channel->source, r->sock, strerror(errno));
483
 			proxy_set_status(r, "ERROR: Can not connect to source");
491
 			proxy_set_status(r, "ERROR: Can not connect to source");
489
 		buf[sizeof(buf)-1] = 0;
497
 		buf[sizeof(buf)-1] = 0;
490
 		fdwrite(r->sock, buf, strlen(buf));
498
 		fdwrite(r->sock, buf, strlen(buf));
491
 
499
 
500
+		char redirect_to[1024];
501
+		memset(redirect_to, 0, sizeof(redirect_to));
492
 		char xresponse[128];
502
 		char xresponse[128];
493
 		memset(xresponse, 0, sizeof(xresponse));
503
 		memset(xresponse, 0, sizeof(xresponse));
494
 		memset(buf, 0, sizeof(buf));
504
 		memset(buf, 0, sizeof(buf));
515
 					break;
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
 		if (*http_code == 0) { // No valid HTTP response, retry
543
 		if (*http_code == 0) { // No valid HTTP response, retry
520
 			LOGf("DEBUG: Server returned not valid HTTP code | srv_fd: %i\n", r->sock);
544
 			LOGf("DEBUG: Server returned not valid HTTP code | srv_fd: %i\n", r->sock);
526
 			proxy_set_status(r, "ERROR: Source returned no-signal");
550
 			proxy_set_status(r, "ERROR: Source returned no-signal");
527
 			FATAL_ERROR;
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
 			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);
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
 			proxy_set_status(r, "ERROR: Source returned unhandled error code");
563
 			proxy_set_status(r, "ERROR: Source returned unhandled error code");
532
 			FATAL_ERROR;
564
 			FATAL_ERROR;
787
 		r->conn_ts = 0;
819
 		r->conn_ts = 0;
788
 		r->read_bytes = 0;
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
 		if (result > 0)
823
 		if (result > 0)
792
 			goto RECONNECT;
824
 			goto RECONNECT;
793
 
825
 

Loading…
Cancel
Save