Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
SAT>IP client: add RTSP/TCP support, fixes #3092
  • Loading branch information
perexg committed Oct 7, 2015
1 parent cad3842 commit 443c287
Show file tree
Hide file tree
Showing 8 changed files with 317 additions and 102 deletions.
5 changes: 5 additions & 0 deletions src/http.h
Expand Up @@ -302,6 +302,7 @@ struct http_client {
int hc_reconnected:1;
int hc_keepalive:1;
int hc_in_data:1;
int hc_in_rtp_data:1;
int hc_chunked:1;
int hc_chunk_trails:1;
int hc_running:1;
Expand All @@ -319,6 +320,8 @@ struct http_client {
char *hc_rtp_dest;
int hc_rtp_port;
int hc_rtpc_port;
int hc_rtp_tcp;
int hc_rtcp_tcp;
int hc_rtcp_server_port;
int hc_rtp_multicast:1;
long hc_rtsp_stream_id;
Expand All @@ -334,6 +337,8 @@ struct http_client {
int (*hc_hdr_received) (http_client_t *hc);
int (*hc_data_received)(http_client_t *hc, void *buf, size_t len);
int (*hc_data_complete)(http_client_t *hc);
int (*hc_rtp_data_received)(http_client_t *hc, void *buf, size_t len);
int (*hc_rtp_data_complete)(http_client_t *hc);
void (*hc_conn_closed) (http_client_t *hc, int err);
};

Expand Down
79 changes: 66 additions & 13 deletions src/httpc.c
Expand Up @@ -209,6 +209,7 @@ http_client_flush( http_client_t *hc, int result )
if (result < 0)
http_client_shutdown(hc, 0, 0);
hc->hc_in_data = 0;
hc->hc_in_rtp_data = 0;
hc->hc_hsize = 0;
hc->hc_csize = 0;
hc->hc_rpos = 0;
Expand Down Expand Up @@ -642,7 +643,11 @@ http_client_finish( http_client_t *hc )
tvhtrace("httpc", "%04X: received %s data", shortid(hc), http_ver2str(hc->hc_version));
tvhlog_hexdump("httpc", hc->hc_data, hc->hc_csize);
}
if (hc->hc_data_complete) {
if (hc->hc_in_rtp_data && hc->hc_rtp_data_complete) {
res = hc->hc_rtp_data_complete(hc);
if (res < 0)
return http_client_flush(hc, res);
} else if (hc->hc_data_complete) {
res = hc->hc_data_complete(hc);
if (res < 0)
return http_client_flush(hc, res);
Expand Down Expand Up @@ -863,7 +868,7 @@ http_client_run( http_client_t *hc )
char *buf, *saveptr, *argv[3], *d, *p;
int ver, res, delimsize = 4;
ssize_t r;
size_t len;
size_t len, limit;

if (hc == NULL)
return 0;
Expand Down Expand Up @@ -891,9 +896,10 @@ http_client_run( http_client_t *hc )
}

buf = alloca(hc->hc_io_size);

if (!hc->hc_in_data && hc->hc_rpos > 3) {
if ((d = strstr(hc->hc_rbuf, "\r\n\r\n")) != NULL)
if (!hc->hc_in_data && !hc->hc_in_rtp_data && hc->hc_rpos > 3) {
if (hc->hc_version == RTSP_VERSION_1_0 && hc->hc_rbuf[0] == '$')
goto rtsp_data;
else if ((d = strstr(hc->hc_rbuf, "\r\n\r\n")) != NULL)
goto header;
if ((d = strstr(hc->hc_rbuf, "\n\n")) != NULL) {
delimsize = 2;
Expand All @@ -906,7 +912,6 @@ http_client_run( http_client_t *hc )
r = http_client_ssl_recv(hc, buf, hc->hc_io_size);
else
r = recv(hc->hc_fd, buf, hc->hc_io_size, MSG_DONTWAIT);
tvhtrace("httpc", "%04X: recv %zi", shortid(hc), r);
if (r == 0) {
if (hc->hc_in_data && !hc->hc_keepalive)
return http_client_finish(hc);
Expand All @@ -920,11 +925,12 @@ http_client_run( http_client_t *hc )
return http_client_flush(hc, -errno);
}
if (r > 0 && tvhtrace_enabled()) {
tvhtrace("httpc", "%04X: received %s answer", shortid(hc), http_ver2str(hc->hc_version));
tvhlog_hexdump("httpc", buf, r);
tvhtrace("httpc", "%04X: received %s answer (len = %zd)", shortid(hc), http_ver2str(hc->hc_version), r);
tvhlog_hexdump("httpc", buf, MIN(64, r));
}

if (hc->hc_in_data) {
limit = hc->hc_version == RTSP_VERSION_1_0 ? hc->hc_io_size * 2 : 16*1024;
if (hc->hc_in_data && !hc->hc_in_rtp_data) {
res = http_client_data_received(hc, buf, r, 0);
if (res < 0)
return http_client_flush(hc, res);
Expand All @@ -936,7 +942,7 @@ http_client_run( http_client_t *hc )
}

if (hc->hc_rsize < r + hc->hc_rpos) {
if (hc->hc_rsize + r > 16*1024)
if (hc->hc_rsize + r > limit)
return http_client_flush(hc, -EMSGSIZE);
hc->hc_rsize += r;
hc->hc_rbuf = realloc(hc->hc_rbuf, hc->hc_rsize + 1);
Expand All @@ -948,6 +954,8 @@ http_client_run( http_client_t *hc )
next_header:
if (hc->hc_rpos < 3)
return HTTP_CON_RECEIVING;
if (hc->hc_version == RTSP_VERSION_1_0 && hc->hc_rbuf[0] == '$')
goto rtsp_data;
if ((d = strstr(hc->hc_rbuf, "\r\n\r\n")) == NULL) {
delimsize = 2;
if ((d = strstr(hc->hc_rbuf, "\n\n")) == NULL)
Expand Down Expand Up @@ -983,6 +991,7 @@ http_client_run( http_client_t *hc )
if (res < 0)
return http_client_flush(hc, -EINVAL);
}
tvhtrace("httpc", "header parse1");
p = http_arg_get(&hc->hc_args, "Content-Length");
if (p) {
hc->hc_csize = atoll(p);
Expand Down Expand Up @@ -1011,16 +1020,19 @@ http_client_run( http_client_t *hc )
if (res < 0)
return http_client_flush(hc, res);
}
hc->hc_rpos -= hc->hc_hsize;
len = hc->hc_rpos;
len = hc->hc_rpos - hc->hc_hsize;
hc->hc_rpos = 0;
if (hc->hc_code == HTTP_STATUS_CONTINUE) {
memmove(hc->hc_rbuf, hc->hc_rbuf + hc->hc_hsize, len);
hc->hc_rpos = len;
goto next_header;
}
hc->hc_rpos = 0;
if (hc->hc_version == RTSP_VERSION_1_0 && !hc->hc_csize) {
hc->hc_csize = -1;
hc->hc_in_data = 0;
memmove(hc->hc_rbuf, hc->hc_rbuf + hc->hc_hsize, len);
hc->hc_rpos = len;
return http_client_finish(hc);
} else {
hc->hc_in_data = 1;
}
Expand All @@ -1030,6 +1042,47 @@ http_client_run( http_client_t *hc )
if (res > 0)
return http_client_finish(hc);
goto retry;

rtsp_data:
/* RTSP embedded data */
r = 0;
res = HTTP_CON_RECEIVING;
hc->hc_in_data = 0;
hc->hc_in_rtp_data = 0;
while (hc->hc_rpos > r + 3) {
hc->hc_csize = 4 + ((hc->hc_rbuf[r+2] << 8) | hc->hc_rbuf[r+3]);
hc->hc_chunked = 0;
if (r + hc->hc_csize > hc->hc_rpos) {
memmove(hc->hc_rbuf, hc->hc_rbuf + r, hc->hc_rpos - r);
hc->hc_rpos -= r;
hc->hc_in_rtp_data = 1;
if (r == 0)
goto retry;
return HTTP_CON_RECEIVING;
}
if (hc->hc_rtp_data_received) {
res = hc->hc_rtp_data_received(hc, hc->hc_rbuf + r, hc->hc_csize);
if (res < 0)
return res;
} else {
res = 0;
}
r += hc->hc_csize;
if (res < 0)
return http_client_flush(hc, res);
hc->hc_in_rtp_data = 1;
res = http_client_finish(hc);
hc->hc_in_rtp_data = 0;
if (res < 0)
return http_client_flush(hc, res);
res = HTTP_CON_RECEIVING;
if (hc->hc_rpos < r + 4 || hc->hc_rbuf[r] != '$') {
memcpy(hc->hc_rbuf, hc->hc_rbuf + r, hc->hc_rpos - r);
hc->hc_rpos -= r;
goto next_header;
}
}
return res;
}

/*
Expand Down
2 changes: 1 addition & 1 deletion src/input/mpegts.h
Expand Up @@ -906,7 +906,7 @@ static inline void
tsdebug_write(mpegts_mux_t *mm, uint8_t *buf, size_t len)
{
#if ENABLE_TSDEBUG
if (mm->mm_tsdebug_fd2 >= 0)
if (mm && mm->mm_tsdebug_fd2 >= 0)
if (write(mm->mm_tsdebug_fd2, buf, len) != len)
tvherror("tsdebug", "unable to write input data (%i)", errno);
#endif
Expand Down
7 changes: 7 additions & 0 deletions src/input/mpegts/satip/satip.c
Expand Up @@ -206,6 +206,13 @@ const idclass_t satip_device_class =
.notify = satip_device_class_tunercfg_notify,
.def.s = "Auto"
},
{
.type = PT_BOOL,
.id = "tcp_mode",
.name = N_("RTSP/TCP (embedded data)"),
.opts = PO_ADVANCED,
.off = offsetof(satip_device_t, sd_tcp_mode),
},
{
.type = PT_BOOL,
.id = "fast_switch",
Expand Down

0 comments on commit 443c287

Please sign in to comment.