diff --git a/octoserve/boot/fpga_gtl.img b/octoserve/boot/fpga_gtl.img index f815e30..ac56117 100644 Binary files a/octoserve/boot/fpga_gtl.img and b/octoserve/boot/fpga_gtl.img differ diff --git a/octoserve/dvb.c b/octoserve/dvb.c index 119ec86..d1e0049 100644 --- a/octoserve/dvb.c +++ b/octoserve/dvb.c @@ -153,7 +153,7 @@ static int set_fe(int fd, uint32_t fr, uint32_t sr, fe_delivery_system_t ds) struct dtv_properties c; int ret; - printf("ds = %u\n", ds); + dbgprintf(DEBUG_DVB, "ds = %u\n", ds); c.num = 7; c.props = p; @@ -335,9 +335,11 @@ static int tune_sat(struct dvbfe *fe) fe->scif_slot, fe->scif_freq, ds); pthread_mutex_unlock(&fe->os->uni_lock); } else if (fe->scif_type == 2) { + pthread_mutex_lock(&fe->os->uni_lock); set_en50607(fe->fd, freq / 1000, fe->param[PARAM_SR], fe->param[PARAM_SRC] - 1, fe->param[PARAM_POL] - 1, hi, fe->scif_slot, fe->scif_freq, ds); + pthread_mutex_unlock(&fe->os->uni_lock); } else { diseqc(fe->fd, fe->param[PARAM_SRC] - 1, fe->param[PARAM_POL] - 1, hi); set_fe(fe->fd, freq, fe->param[PARAM_SR] * 1000, ds); diff --git a/octoserve/http.c b/octoserve/http.c index e3bf090..99af4b5 100644 --- a/octoserve/http.c +++ b/octoserve/http.c @@ -19,6 +19,8 @@ #include "octoserve.h" +extern uint32_t debug; + char httpxml[] = "HTTP/1.0 200 OK\r\nConnection: close\r\n" "Content-Length: %d\r\nContent-Type: text/xml\r\nMime-Version: 1.0\r\n" @@ -44,22 +46,22 @@ char xmldesc[] = "\r\nimage/png\r\n" "120\r\n120\r\n" - "24\r\nwww/icons/dd-120.png\r\n" + "24\r\n/octoserve/www/icons/dd-120.png\r\n" "\r\n" "\r\nimage/jpg\r\n" "120\r\n120\r\n" - "24\r\nwww/icons/dd-120.jpg\r\n" + "24\r\n/octoserve/www/icons/dd-120.jpg\r\n" "\r\n" "\r\nimage/png\r\n" "48\r\n48\r\n" - "24\r\nwww/icons/dd-48.png\r\n" + "24\r\n/octoserve/www/icons/dd-48.png\r\n" "\r\n" "\r\nimage/jpg\r\n" "48\r\n48\r\n" - "24\r\nwww/icons/dd-48.jpg\r\n" + "24\r\n/octoserve/www/icons/dd-48.jpg\r\n" "\r\n" "\r\n" @@ -363,6 +365,7 @@ void handle_http(struct os_ssdp *ss) send_http_error(ss->csock, 405); break; } + dbgprintf(DEBUG_SSDP, "%s\n", buf); if (!strncasecmp("GET /octonet.xml", buf, 16)) { send_xml(ss); break; diff --git a/octoserve/igmp.c b/octoserve/igmp.c index 05f85ab..98d1661 100644 --- a/octoserve/igmp.c +++ b/octoserve/igmp.c @@ -62,8 +62,10 @@ void proc_igmp(struct octoserve *os, uint8_t *b, int l, uint8_t *macheader) return; if (cs16(p, pl) != ((p[2] << 8) | p[3])) { dbgprintf(DEBUG_IGMP, "IGMP CS error\n"); +#if 0 if (debug & DEBUG_IGMP) dump(b, l); +#endif return; } @@ -84,7 +86,7 @@ void proc_igmp(struct octoserve *os, uint8_t *b, int l, uint8_t *macheader) if (a1 < a2) { /* somebody else with lower IP is already sending queries */ os->igmp_mode = 3; - time(&os->igmp_time); + mtime(&os->igmp_time); os->igmp_tag++; os->igmp_timeout = b[hl + 1] / 10 + 1; dbgprintf(DEBUG_IGMP, "IGMP slave, tag = %u, timeout = %u\n", @@ -212,7 +214,7 @@ void check_igmp(struct octoserve *os) { time_t tdiff, t; - tdiff = time(&t) - os->igmp_time; + tdiff = mtime(&t) - os->igmp_time; switch (os->igmp_mode) { case 0: if (tdiff > 124) { diff --git a/octoserve/ntools.c b/octoserve/ntools.c index f19548b..f4281e7 100644 --- a/octoserve/ntools.c +++ b/octoserve/ntools.c @@ -119,8 +119,10 @@ int sendlen(int sock, char *buf, int len) int done, todo; for (todo = len; todo; todo -= done, buf += done) - if ((done = send(sock, buf, todo, 0)) < 0) + if ((done = send(sock, buf, todo, 0)) < 0) { + printf("sendlen error\n"); return done; + } return len; } @@ -138,3 +140,14 @@ int sendstring(int sock, char *fmt, ...) va_end(args); } +time_t mtime(time_t *t) +{ + struct timespec ts; + + if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts)) + return 0; + if (t) + *t = ts.tv_sec; + return ts.tv_sec; +} + diff --git a/octoserve/octoserve.c b/octoserve/octoserve.c index f1ec33a..3a80452 100644 --- a/octoserve/octoserve.c +++ b/octoserve/octoserve.c @@ -1,5 +1,5 @@ /* - (C) 2012-14 Digital Devices GmbH. + (C) 2012-15 Digital Devices GmbH. This file is part of the octoserve SAT>IP server. @@ -22,6 +22,19 @@ #include uint32_t debug; +uint32_t flags; +uint32_t conform = 0; +#define FLAGS_TRANSPORT 1 + + +uint64_t mtime_nano(void) +{ + struct timespec ts; + + if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts)) + return 0; + return ts.tv_sec * 1000000000 + ts.tv_nsec; +} void dump(const uint8_t *b, int l) { @@ -313,6 +326,40 @@ static struct dvbfe *alloc_fe(struct octoserve *os, int type) return NULL; } +static void release_con(struct oscon *con) +{ + close(con->sock); + con->state = 0; + dbgprintf(DEBUG_SYS, "releasing con %d\n", con->nr); +} + +static void shutdown_con(struct oscon *con) +{ + con->session = 0; + con->state = 3; + con->timeout = mtime(NULL) + 10; + dbgprintf(DEBUG_SYS, "shutdown con %u at %u\n", con->nr, con->timeout); +} + +static void *_release_session(struct ossess *oss) +{ + struct octoserve *os = oss->os; + int i; + + dbgprintf(DEBUG_SYS, "releasing session %d\n", oss->nr); + for (i = 0; i < MAX_CONNECT; i++) { + if (os->con[i].state && + (os->con[i].session == oss)) + shutdown_con(&os->con[i]); + } + if (oss->nsfd >= 0) { + dbgprintf(DEBUG_SYS, "closing netstream of session %d\n", oss->nr); + close(oss->nsfd); + } + oss->playing = 0; + oss->state = 0; +} + static void *release_stream(struct osstrm *str) { struct octoserve *os = str->os; @@ -321,8 +368,8 @@ static void *release_stream(struct osstrm *str) for (i = 0; i < MAX_SESSION; i++) { if (os->session[i].state && - os->session[i].stream == str) - os->session[i].stream = 0; + (os->session[i].stream == str)) + _release_session(&os->session[i]); } str->state = 0; release_fe(os, str->fe); @@ -347,8 +394,7 @@ static struct osstrm *alloc_stream(struct octoserve *os) str->sport2 = 8000 + 2 * i + 1; pthread_mutex_unlock(&os->lock); dbgprintf(DEBUG_SYS, "Allocated stream %d\n", str->nr); - return str; - } + return str;} } pthread_mutex_unlock(&os->lock); return NULL; @@ -362,7 +408,7 @@ static struct osstrm *get_stream(struct octoserve *os, int id) pthread_mutex_lock(&os->lock); for (i = 0; i < MAX_STREAM; i++) { str = &os->stream[i]; - if (str->state && str->nr == id) { + if (str->state && (str->nr == id)) { r = str; break; } @@ -379,21 +425,10 @@ static void *release_session(struct ossess *oss) dbgprintf(DEBUG_SYS, "release session nr %d id %010d\n", oss->nr, oss->id); pthread_mutex_lock(&os->lock); mc_del(oss); - if (oss->stream) { - if (oss->stream->session == oss) - release_stream(oss->stream); - } - for (i = 0; i < MAX_CONNECT; i++) { - if (os->con[i].state && - os->con[i].session == oss) - os->con[i].session = 0; - } - if (oss->nsfd >= 0) { - dbgprintf(DEBUG_SYS, "close NS\n"); - close(oss->nsfd); - } - oss->playing = 0; - oss->state = 0; + if (oss->stream && (oss->stream->session == oss)) // stream owner? + release_stream(oss->stream); + else + _release_session(oss); pthread_mutex_unlock(&os->lock); } @@ -405,7 +440,7 @@ static struct ossess *get_session(struct octoserve *os, uint32_t id) pthread_mutex_lock(&os->lock); for (i = 0; i < MAX_SESSION; i++) { oss = &os->session[i]; - if (oss->state && oss->id == id) { + if (oss->state && (oss->id == id)) { pthread_mutex_unlock(&os->lock); return oss; } @@ -417,11 +452,12 @@ static struct ossess *get_session(struct octoserve *os, uint32_t id) static void check_mccs(struct ossess *sess) { time_t tdiff, t; - + int update = 0; + if (!sess->trans.mcast) return; - tdiff = time(&t) - sess->mcc_time; + tdiff = mtime(&t) - sess->mcc_time; switch (sess->mcc_state) { case 1: if (tdiff >= 1) { @@ -441,21 +477,23 @@ static void check_mccs(struct ossess *sess) } break; case 3: - if (tdiff >= 4) { + if (tdiff >= 2) { sess->mcc_state = 0; sess->mcc_time = t; printf("%u: mcc_state 2 done, tag = %d\n", t, sess->mcc_tag); + update = 1; } break; case 0: + update = 1; break; } - mc_check(sess); + mc_check(sess, update); } void session_timeout(struct ossess *sess) { - time(&sess->timeout); + mtime(&sess->timeout); sess->timeout += sess->timeout_len; dbgprintf(DEBUG_RTSP, "new timeout %d\n", sess->timeout); } @@ -466,14 +504,14 @@ void check_session_timeouts(struct octoserve *os) int i; struct ossess *sess; - time(&t); + mtime(&t); pthread_mutex_lock(&os->lock); for (i = 0; i < MAX_SESSION; i++) { sess = &os->session[i]; check_mccs(sess); if (sess->state && - sess->timeout < t) { + (sess->timeout < t)) { struct oscon *con; int j; @@ -482,7 +520,7 @@ void check_session_timeouts(struct octoserve *os) for (j = 0; j < MAX_CONNECT; j++) { con = &os->con[j]; if (con->state && con->session && - con->session == sess) { + (con->session == sess)) { session_timeout(sess); break; } @@ -503,7 +541,7 @@ static uint32_t get_id(struct octoserve *os) id = random(); for (i = 0; i < MAX_SESSION; i++) { oss = &os->session[i]; - if (oss->state && oss->id == id) + if (oss->state && (oss->id == id)) break; } if (i == MAX_SESSION) @@ -530,7 +568,7 @@ static struct ossess *alloc_session(struct octoserve *os) oss->timeout_len = 60; session_timeout(oss); LIST_INIT(&oss->mccs); - time(&oss->mcc_time); + mtime(&oss->mcc_time); dbgprintf(DEBUG_SYS, "Allocated session nr=%d id=%d\n", oss->nr, oss->id); @@ -542,13 +580,6 @@ static struct ossess *alloc_session(struct octoserve *os) return NULL; } -static void *release_con(struct oscon *con) -{ - close(con->sock); - con->state = 0; - dbgprintf(DEBUG_SYS, "released con %d\n", con->nr); -} - static struct oscon *alloc_con(struct octoserve *os) { int i; @@ -593,7 +624,7 @@ static void send_option(struct oscon *con) "%s" "\r\n", con->seq, opt); - if (len > 0 && len < sizeof(buf)) { + if ((len > 0) && (len < sizeof(buf))) { sendlen(con->sock, buf, len); dbgprintf(DEBUG_RTSP, "Send: %s\n", buf); } @@ -736,7 +767,7 @@ static int send_describe(struct oscon *con, int only) { struct osstrm *str; struct ostrans *t; - uint8_t buf[4096], buf2[1024], buf3[1024]; + uint8_t buf[4096], buf2[4096 + 1024], buf3[1024]; int len, len2, i; int start = 0, end = MAX_STREAM; char *p; @@ -756,24 +787,42 @@ static int send_describe(struct oscon *con, int only) return -404; #endif if (only >= 0) { + if (only >= MAX_STREAM) + return -404; start = only - 1; end = only; + str = &con->os->stream[start]; + if (!str->state) + return -404; } - len = snprintf(buf, sizeof(buf), - "v=0\r\n" - "o=- 5678901234 1 IN %s %s\r\n" - "s=SatIPServer:1 %d,%d,%d\r\n" - "t=0 0\r\n", - con->trans.family == AF_INET ? "IP4" : "IP6", - con->sadr_ip, - con->os->dvbs2num, - con->os->dvbtnum + con->os->dvbt2num, - con->os->dvbcnum + con->os->dvbc2num - ); + if (con->os->dvbtnum + con->os->dvbt2num + con->os->dvbcnum + con->os->dvbc2num) + len = snprintf(buf, sizeof(buf), + "v=0\r\n" + "o=- 5678901234 7890123456 IN %s %s\r\n" + "s=SatIPServer:1 %d,%d,%d\r\n" + "t=0 0\r\n", + con->trans.family == AF_INET ? "IP4" : "IP6", + con->sadr_ip, + con->os->dvbs2num, + con->os->dvbtnum + con->os->dvbt2num, + con->os->dvbcnum + con->os->dvbc2num + ); + else + len = snprintf(buf, sizeof(buf), + "v=0\r\n" + "o=- 5678901234 7890123456 IN %s %s\r\n" + "s=SatIPServer:1 %d\r\n" + "t=0 0\r\n", + con->trans.family == AF_INET ? "IP4" : "IP6", + con->sadr_ip, + con->os->dvbs2num + ); + if (len <= 0 || len >= sizeof(buf)) return -500; for (i = start; i < end; i++) { char *adr = "0.0.0.0", abuf[32]; + int j, sendonly = 0; int alen; str = &con->os->stream[i]; @@ -781,6 +830,12 @@ static int send_describe(struct oscon *con, int only) continue; t = &str->session->trans; + for (j = sendonly = 0; j < MAX_SESSION; j++) { + if (con->os->session[j].state && + con->os->session[j].stream == str && + con->os->session[j].playing) + sendonly = 1; + } session_string(str->session, buf3, sizeof(buf3)); if (t->mcast) { @@ -808,21 +863,29 @@ static int send_describe(struct oscon *con, int only) adr, str->nr, buf3, - str->session->playing ? "sendonly" : "inactive" + sendonly ? "sendonly" : "inactive" ); if (len2 <= 0 || len2 >= sizeof(buf) - len) return -500; len += len2; } - len2=sprintf(buf2, "RTSP/1.0 200 OK\r\nCSeq: %d\r\n" - "Content-Type: application/sdp\r\n" - "Content-Base: rtsp://%s/\r\n" - "Content-Length: %d\r\n" - "\r\n", - con->seq, con->sadr_ip, len); - + len2 = sprintf(buf2, "RTSP/1.0 200 OK\r\nCSeq: %d\r\n" + "Content-Type: application/sdp\r\n" + "Content-Base: rtsp://%s/\r\n" + "Content-Length: %d\r\n" + "\r\n", + con->seq, con->sadr_ip, len); + + /* URGH, some receivers (cough Kathr** cough) cannot handle + split RTSP messages */ +#if 0 sendlen(con->sock, buf2, len2); sendlen(con->sock, buf, len); +#else + memcpy(buf2 + len2, buf, len); + sendlen(con->sock, buf2, len + len2); + //dump(buf2, len + len2); +#endif dbgprintf(DEBUG_RTSP, "Send:\n%s", buf2); dbgprintf(DEBUG_RTSP, "%s\n", buf); return 0; @@ -1279,17 +1342,27 @@ static int setup_nsp(struct ostrans *trans, struct dvb_ns_params *nsp) static int merge_pids(struct dvb_params *op, struct dvb_params *p) { - int i; + int i, r = 0; if (p->set & (1UL << PARAM_PID)) - for (i = 0 ; i < 1024 ; i++) - op->pid[i] = p->pid[i]; - if (p->set & (1UL << PARAM_APID)) - for (i = 0 ; i < 1024 ; i++) - op->pid[i] |= p->pid[i]; + for (i = 0 ; i < 1024 ; i++) + if (op->pid[i] != p->pid[i]) { + r |= 1; + op->pid[i] = p->pid[i]; + } + if (p->set & (1UL << PARAM_APID)) + for (i = 0 ; i < 1024 ; i++) + if (!(op->pid[i] & p->pid[i])) { + r |= 2; + op->pid[i] |= p->pid[i]; + } if (p->set & (1UL << PARAM_DPID)) - for (i = 0 ; i < 1024 ; i++) - op->pid[i] &= ~p->dpid[i]; + for (i = 0 ; i < 1024 ; i++) + if (op->pid[i] & p->dpid[i]) { + r |= 4; + op->pid[i] &= ~p->dpid[i]; + } + return r; } static int merge_params(struct dvb_params *op, struct dvb_params *p) @@ -1318,7 +1391,11 @@ static int setup_session(struct oscon *con, int newtrans) if (!str) return -500; - merge_pids(sp, p); + if (conform) { + if (str->session != sess && merge_pids(sp, p) < 0) + return -455; + } else + merge_pids(sp, p); if (str->session == sess) { /* stream owner */ merge_params(sp, p); @@ -1356,6 +1433,10 @@ static int setup_session(struct oscon *con, int newtrans) newtrans = 1; } if (newtrans) { + if (str->session != sess && + sess->trans.mcast && + conform) + return -455; if (setup_nsp(&sess->trans, &nsp) < 0) return -1; if (set_ns(sess, &nsp) < 0) @@ -1412,8 +1493,7 @@ static int start_session(struct ossess *sess) { if (sess->playing) return 0; - dbgprintf(DEBUG_SYS, "START\n"); - printf("start session %d\n", sess->nr); + dbgprintf(DEBUG_SYS, "start session %d\n", sess->nr); if (sess->stream->ca) { uint8_t canum = sess->stream->ca->nr - 1; if (sess->nsfd >= 0) @@ -1465,7 +1545,7 @@ static struct ossess *match_session(struct octoserve *os, uint8_t *group) return NULL; } -void mc_check(struct ossess *sess) +void mc_check(struct ossess *sess, int update) { struct osmcc *mcc, *next; struct octoserve *os = sess->os; @@ -1485,10 +1565,12 @@ void mc_check(struct ossess *sess) free(mcc); } } - if (os->has_switch) - update_switch_vec(sess); - if (!sess->mccs.lh_first) - stop_session(sess); + if (update) { + if (os->has_switch) + update_switch_vec(sess); + if (!sess->mccs.lh_first) + stop_session(sess); + } pthread_mutex_unlock(&os->lock); } @@ -1575,7 +1657,7 @@ void mc_query(struct ossess *sess) { /* query in group if anybody still there */ if (!sess->mcc_state) { - time(&sess->mcc_time); + mtime(&sess->mcc_time); sess->mcc_state = 1; } } @@ -1617,7 +1699,6 @@ static void send_play(struct oscon *con) uint8_t buf[1024]; int len; - dbgprintf(DEBUG_SYS, "%s\n", __FUNCTION__); len = sprintf(buf, "RTSP/1.0 200 OK\r\n" "CSeq: %d\r\n" @@ -1800,6 +1881,123 @@ static void cpyarg(char *d, char *s) strcpy(d, s); } + +static int cmp_trans(struct ostrans *t, struct ostrans *u) +{ + if (t->mcast != u->mcast) + return 1; + + if (t->cport != u->cport) + return 2; + if (t->cport2 != u->cport2) + return 3; + if (t->flags != u->flags) + return 4; + if (t->ttl != u->ttl) + return 5; + return 0; +} + +static int proc_setup(struct oscon *con) +{ + struct osstrm *str = 0; + int newtrans = 0; + int res; + + if (!con->transport_parsed) { + /* no proper transport params given */ + send_error(con, 400); + return -1; + } + if (con->session_parsed && !con->session) { + /* no session with given ID found */ + send_error(con, 454); + return -1; + } + if (parse_url(con, 0) < 0) { + /* invalid params in URL */ + send_error(con, 400); + return -1; + } + if (con->p.set & (1UL << PARAM_STREAMID)) { + dbgprintf(DEBUG_SYS, "existing stream %d\n", + con->p.param[PARAM_STREAMID]); + str = get_stream(con->os, con->p.param[PARAM_STREAMID]); + if (!str) { + /* no stream with given ID */ + send_error(con, 400); + return -1; + } + if (con->session && con->session != str->session) { + /* if we already have a session ID we + have to be stream owner */ + send_error(con, 400); + return -1; + } + } + if (!con->session) { + /* alloc new session */ + con->session = alloc_session(con->os); + if (!con->session) { + send_error(con, 400); + return -1; + } + con->state = 2; + if (!con->session->stream) { + if (str) { + /* use existing stream and stream params*/ + con->session->stream = str; + if (con->session->stream->session) { + memcpy(&con->session->p, + &con->session->stream->session->p, + sizeof(struct dvb_params)); + } + } else { + con->session->stream = alloc_stream(con->os); + if (!con->session->stream) { + send_error(con, 400); + return -1; + } + con->session->stream->session = con->session; + } + } + newtrans = 1; + } + if (newtrans || cmp_trans(&con->session->trans, &con->trans)) { + con->trans.sport = con->session->stream->sport; + con->trans.sport2 = con->session->stream->sport2; + + /* set transport struct according to session + and transport parameters */ + if (con->trans.mcast && con->trans.cport == 0) { + con->trans.cport = con->trans.sport; + con->trans.cport2 = con->trans.sport2; + } + + if (con->trans.mcast && + !(con->trans.flags & TRANS_ALT_DEST)) { + uint8_t mac[6] = { 0x01, 0x00, 0x5e, + con->os->ssdp.devid & 0x7f, 1, + con->session->stream->nr }; + uint8_t ip[4] = { 239, con->os->ssdp.devid, 1, + con->session->stream->nr }; + + memcpy(con->trans.mcmac, mac, 6); + memcpy(con->trans.mcip, ip, 4); + } + con->session->trans = con->trans; + newtrans = 1; + } + res = setup_session(con, newtrans); + if (res < 0) { + release_session(con->session); + send_error(con, -res); + } else + send_setup(con); + return 0; +} + + static int proc_line(struct oscon *con) { char *line = con->buf; @@ -1858,107 +2056,11 @@ static int proc_line(struct oscon *con) send_error(con, -res); break; } + case M_SETUP: - { - struct osstrm *str = 0; - int newtrans = 0; - - if (!con->transport_parsed) { - /* no proper transport params given */ - send_error(con, 400); - break; - } - if (con->session_parsed && !con->session) { - /* no session with given ID found */ - send_error(con, 454); - break; - } - if (parse_url(con, 0) < 0) { - /* invalid params in URL */ - send_error(con, 400); - break; - } - if (con->p.set & (1UL << PARAM_STREAMID)) { - dbgprintf(DEBUG_SYS, "existing stream %d\n", - con->p.param[PARAM_STREAMID]); - str = get_stream(con->os, con->p.param[PARAM_STREAMID]); - if (!str) { - /* no stream with given ID */ - send_error(con, 400); - break; - } - if (con->session && con->session != str->session) { - /* if we already have a session ID we - have to be stream owner */ - send_error(con, 400); - break; - } - } - if (!con->session) { - /* alloc new session */ - con->session = alloc_session(con->os); - if (!con->session) { - send_error(con, 400); - break; - } - if (!con->session->stream) { - if (str) { - /* use existing stream and stream params*/ - con->session->stream = str; - if (con->session->stream->session) { - memcpy(&con->session->p, - &con->session->stream->session->p, - sizeof(struct dvb_params)); - } - } else { - con->session->stream = alloc_stream(con->os); - if (!con->session->stream) { - send_error(con, 400); - break; - } - con->session->stream->session = con->session; - } - } - newtrans = 1; - } - if (newtrans || - con->session->trans.mcast != con->trans.mcast || - con->session->trans.cport != con->trans.cport || - con->session->trans.cport2 != con->trans.cport2 || - con->session->trans.flags != con->trans.flags || - con->session->trans.ttl != con->trans.ttl) { - con->trans.sport = con->session->stream->sport; - con->trans.sport2 = con->session->stream->sport2; - - /* set transport struct according to session - and transport parameters */ - if (con->trans.mcast && con->trans.cport == 0) { - con->trans.cport = con->trans.sport; - con->trans.cport2 = con->trans.sport2; - } - - if (con->trans.mcast && - !(con->trans.flags & TRANS_ALT_DEST)) { - uint8_t mac[6] = { 0x01, 0x00, 0x5e, - con->os->ssdp.devid & 0x7f, 1, - con->session->stream->nr }; - uint8_t ip[4] = { 239, con->os->ssdp.devid, 1, - con->session->stream->nr }; - - memcpy(con->trans.mcmac, mac, 6); - memcpy(con->trans.mcip, ip, 4); - } - con->session->trans = con->trans; - newtrans = 1; - } - res = setup_session(con, newtrans); - if (res < 0) { - release_session(con->session); - send_error(con, -res); - } else - send_setup(con); + proc_setup(con); break; - } + case M_PLAY: if (!con->session || !con->session->stream) { send_error(con, 400); @@ -1989,7 +2091,6 @@ static int proc_line(struct oscon *con) } send_teardown(con); release_session(con->session); - con->session = 0; break; default: send_error(con, 501); @@ -2019,6 +2120,7 @@ static int proc_line(struct oscon *con) con->session = get_session(con->os, sid); if (con->session) session_timeout(con->session); + con->state = 2; con->session_parsed = 1; } else if (!strncasecmp(line, "User-Agent:", 11)) { char *p = line + 11; @@ -2106,6 +2208,19 @@ static void init_con(struct oscon *con) #endif } + +static void con_check(struct octoserve *os) +{ + int i; + time_t t = mtime(NULL); + + for (i = 0; i < MAX_CONNECT; i++) { + if (os->con[i].state == 3 && + t > os->con[i].timeout) + release_con(&os->con[i]); + } +} + int con_loop(struct oscon *con) { uint8_t buf[1024]; @@ -2119,20 +2234,19 @@ int con_loop(struct oscon *con) goto release; return 0; } - dump(buf, len); + if (debug & DEBUG_RTSP) + dump(buf, len); //printf("received %d bytes\n", len); for (i = 0; i < len; i++) { // FIXME send URI too long if (con->bufp >= 8192) { - release_con(con); - return -1; + goto release; } con->buf[con->bufp++] = buf[i]; if (buf[i] == '\n') { if (con->bufp < 2 || con->buf[con->bufp - 2] != '\r') { - release_con(con); - return -1; + goto release; } con->buf[con->bufp - 2] = 0; if (con->buf[0]) @@ -2146,6 +2260,7 @@ int con_loop(struct oscon *con) } return 0; release: + dbgprintf(DEBUG_SYS, "release\n"); release_con(con); return -1; } @@ -2231,7 +2346,7 @@ static int alloc_igmp_socket(struct octoserve *os) &one, sizeof(one)); setsockopt(os->igmp_sock, IPPROTO_IP, IP_ROUTER_ALERT, &one, sizeof(one)); - time(&os->igmp_time); + mtime(&os->igmp_time); /* first query after 125-94=31 seconds */ os->igmp_mode = 0; os->igmp_time -= 94; @@ -2326,7 +2441,7 @@ static void os_serve(struct octoserve *os) &imr, sizeof(imr)); } #endif - time(&t); + mtime(&t); while (!os->exit) { int csock, ncon; struct sockaddr cadr; @@ -2334,7 +2449,7 @@ static void os_serve(struct octoserve *os) uint8_t buf[2048]; int num, n; - time(&u); + mtime(&u); if (u > t) { t = u; check_session_timeouts(os); @@ -2384,6 +2499,8 @@ static void os_serve(struct octoserve *os) FD_ISSET(os->con[i].sock, &fds)) con_loop(&os->con[i]); #endif + con_check(os); + if (FD_ISSET(os->rtsp_sock, &fds)) { struct oscon *con; @@ -2517,24 +2634,27 @@ static void awrite(char *fn, char *txt) int main(int argc, char **argv) { int nodms = 0, nossdp = 0, nodvbt = 0, vlan = 0, noswitch = 0; - + printf("Octoserve " OCTOSERVE_VERSION ", Copyright (C) 2012-15 Digital Devices GmbH\n"); debug = 0; + flags = 0; while (1) { int option_index = 0; int c; static struct option long_options[] = { {"debug", required_argument, 0, 'd'}, + {"flags", required_argument, 0, 'f'}, {"nossdp", no_argument, 0, 'n'}, {"nodms", no_argument, 0, 'm'}, {"nodvbt", no_argument, 0, 't'}, {"noswitch", no_argument, 0, 's'}, + {"conform", no_argument, 0, 'c'}, {"help", no_argument , 0, 'h'}, {0, 0, 0, 0} }; c = getopt_long(argc, argv, - "d:hnmt", + "d:f:nmtsch", long_options, &option_index); if (c==-1) break; @@ -2543,6 +2663,9 @@ int main(int argc, char **argv) case 'd': debug = strtoul(optarg, NULL, 16); break; + case 'f': + flags = strtoul(optarg, NULL, 16); + break; case 'n': nossdp = 1; break; @@ -2555,6 +2678,9 @@ int main(int argc, char **argv) case 's': noswitch = 1; break; + case 'c': + conform = 1; + break; case 'h': default: break; diff --git a/octoserve/octoserve.h b/octoserve/octoserve.h index a4e5f88..5ed3c59 100644 --- a/octoserve/octoserve.h +++ b/octoserve/octoserve.h @@ -1,5 +1,5 @@ /* - (C) 2012-13 Digital Devices GmbH. + (C) 2012-15 Digital Devices GmbH. This file is part of the octoserve SAT>IP server. @@ -73,9 +73,14 @@ #define DEBUG_IGMP 32 #define DEBUG_SWITCH 64 +#if 0 #define dbgprintf(_mask_, ...) \ do { if (debug & _mask_) fprintf(stderr, __VA_ARGS__); } while (0) - +#else +#define dbgprintf(_mask_, ...) \ + do { if (debug & _mask_) { fprintf(stderr, "[%5u] ", mtime(NULL)); \ + fprintf(stderr, __VA_ARGS__); } } while (0) +#endif #define SYS_DVBC2 19 @@ -305,7 +310,7 @@ struct ossess { uint32_t timeout_len; time_t timeout; - + int nsfd; struct ostrans trans; struct dvb_params p; @@ -339,6 +344,8 @@ struct oscon { int sock; int nr; + time_t timeout; + struct ostrans trans; struct sockaddr cadr; @@ -444,6 +451,7 @@ struct octoserve { int scif_type; int has_feswitch; int do_feswitch; + int strict_satip; int dvbfe_num; struct dvbfe dvbfe[MAX_DVB_FE]; @@ -501,7 +509,7 @@ void dump(const uint8_t *b, int l); void proc_igmp(struct octoserve *os, uint8_t *b, int l, uint8_t *mh); void mc_join(struct octoserve *os, uint8_t *ip, uint8_t *mac, uint8_t *group); void mc_leave(struct octoserve *os, uint8_t *ip, uint8_t *group); -void mc_check(struct ossess *sess); +void mc_check(struct ossess *sess, int update); void mc_del(struct ossess *sess); void send_igmp_query(struct octoserve *os, uint8_t *group, uint8_t timeout); @@ -519,4 +527,6 @@ int set_nonblock(int fd); int sendlen(int sock, char *buf, int len); int sendstring(int sock, char *fmt, ...); +time_t mtime(time_t *t); + #endif diff --git a/octoserve/ssdp.c b/octoserve/ssdp.c index c23f1c4..4a72365 100644 --- a/octoserve/ssdp.c +++ b/octoserve/ssdp.c @@ -26,9 +26,9 @@ extern uint32_t debug; static void ssdp_reset_setup(struct os_ssdp *ss) { ss->setup = 0; - time(&ss->setupt); + mtime(&ss->setupt); ss->setupt += 5; - time(&ss->annt); + mtime(&ss->annt); } static int read_id(char *type, uint32_t *id) @@ -171,7 +171,7 @@ static int ssdp_announce(struct octoserve *os, int alive, int notify) time_t t; if (notify) { - time(&t); + mtime(&t); if (!ss->setup) if (t >= ss->setupt) { ss->setup = 1; @@ -194,7 +194,7 @@ static int ssdp_defend(struct os_ssdp *ss) int s = ss->v6 ? ss->sock6 : ss->sock; sockname(&ss->cadr, host); - printf("defend against HOST:%s\n", host); + dbgprintf(DEBUG_SSDP, "defend against HOST:%s\n", host); len = snprintf(buf, sizeof(buf), "M-SEARCH * HTTP/1.1\r\n" @@ -335,7 +335,7 @@ static void handle_ssdp(struct octoserve *os, char *m, int ml) } for (tl = 0; tl < ll && l[tl] != ':'; tl++); if (tl == ll) - return; + continue; for (as = tl + 1; as < ll && isspace(l[as]); as++); al = ll - as; @@ -344,8 +344,11 @@ static void handle_ssdp(struct octoserve *os, char *m, int ml) if (!strncmp(l + as, "239.255.255.250:1900", al)) htype = 1; - else + else { htype = 2; + if (mx < 0) + mx = 1; + } h = host; p = l + as; while (*p && *p != ':') @@ -389,16 +392,17 @@ static void handle_ssdp(struct octoserve *os, char *m, int ml) } } ss->csport = sport; - dbgprintf(DEBUG_SSDP, "host=%s, hport=%u, type=%d, htype=%d mx=%d\n", host, hport, type, htype, mx); + dbgprintf(DEBUG_SSDP, "host=%s, hport=%u, type=%d, htype=%d mx=%d\n", + host, hport, type, htype, mx); /* M-SEARCH */ if (ss->setup) { if (type == 1 && mx > 0) { + //ssdp_msearch(ss, htype == 2 ? 0 : 1, st); ssdp_msearch(ss, 0, st); } /* NOTIFY */ - if (type == 2 && devid == ss->devid && memcmp(uu, ss->uuid, 16)) { + if (type == 2 && devid == ss->devid && memcmp(uu, ss->uuid, 16)) ssdp_defend(ss); - } } else { if (type == 1 && htype == 2 && ss->devid == devid) { send_reply_msearch(ss, 0, 1, 2); diff --git a/octoserve/switch.c b/octoserve/switch.c index 5a0227d..cf66ba7 100644 --- a/octoserve/switch.c +++ b/octoserve/switch.c @@ -84,7 +84,20 @@ int mdio_wait_switch(int fd, uint8_t adr, uint8_t reg) int mdio_open() { - return open("/dev/ddbridge/card0", O_RDWR); + int i, r; + + for (i = 0; i < 100; i++) { + r = open("/dev/ddbridge/card0", O_RDWR); + if (r >= 0) + return r; + if (r < 0) + if (errno != EBUSY) + return r; + else + usleep(100000); + } + dbgprintf(DEBUG_SWITCH, "MDIO BUSY\n"); + return r; } int mdio_close(int fd) diff --git a/octoserve/version.h b/octoserve/version.h index 7c351f0..fadd901 100644 --- a/octoserve/version.h +++ b/octoserve/version.h @@ -1,5 +1,5 @@ /* - (C) 2012-13 Digital Devices GmbH. + (C) 2012-15 Digital Devices GmbH. This file is part of the octoserve SAT>IP server. @@ -19,5 +19,5 @@ #ifndef _OCTOSERVE_VERSION_ #define _OCTOSERVE_VERSION_ -#define OCTOSERVE_VERSION "1.0.46" +#define OCTOSERVE_VERSION "1.0.52" #endif