int satipc_open_device(adapter *ad) { if (!ad->sip) return 1; int ctime = getTick(); if ((ad->last_connect > 0) && (ctime - ad->last_connect < 30000)) return 3; ad->last_connect = ctime; ad->fe = tcp_connect(ad->sip, ad->sport, NULL, 0); // non-blockin socket if (ad->fe < 0) return 2; LOG("satipc: connected to SAT>IP server %s port %d, handle %d", ad->sip, ad->sport, ad->fe); ad->listen_rtp = opts.start_rtp + 1000 + ad->id * 2; ad->dvr = udp_bind(NULL, ad->listen_rtp); ad->rtcp = udp_bind(NULL, ad->listen_rtp + 1); ad->fe_sock = sockets_add(ad->fe, NULL, ad->id, TYPE_TCP, (socket_action) satipc_reply, (socket_action) satipc_close, (socket_action) satipc_timeout); ad->rtcp_sock = sockets_add(ad->rtcp, NULL, ad->id, TYPE_TCP, (socket_action) satipc_rtcp_reply, (socket_action) satipc_close, NULL); sockets_timeout(ad->fe_sock, 15000); // 15s set_socket_receive_buffer(ad->dvr, opts.output_buffer); if (ad->fe_sock < 0 || ad->dvr < 0 || ad->rtcp < 0 || ad->rtcp_sock < 0) { sockets_del(ad->rtcp_sock); sockets_del(ad->fe_sock); close(ad->rtcp); close(ad->dvr); close(ad->fe); } ad->type = ADAPTER_SATIP; ad->session[0] = 0; lap[ad->id] = 0; ldp[ad->id] = 0; ad->cseq = 1; ad->err = 0; ad->expect_reply = 0; ad->last_connect = 0; ad->sent_transport = 0; ad->session[0] = 0; ad->stream_id = -1; ad->wp = ad->qp = ad->want_commit = 0; ad->rcvp = ad->repno = 0; ad->rtp_miss = ad->rtp_ooo = 0; ad->rtp_seq = 0xFFFF; ad->ignore_packets = 1; ad->force_commit = 0; ad->satip_last_setup = -10000; ad->last_cmd = 0; return 0; }
void free_all() { int i = 0; for (i = MAX_SOCKS - 1; i > 0; i--) if (s[i].sock >= 0) sockets_del(i); free_all_streams(); free_all_adapters(); }
void free_all() { int i = 0; for (i = MAX_SOCKS - 1; i > 0; i--) { if (s[i] && s[i]->enabled) sockets_del(i); if (s[i]) free(s[i]); s[i] = NULL; } free_all_streams(); free_all_adapters(); }
void close_adapter(int na) { adapter *ad; init_complete = 0; ad = get_adapter_nw(na); if (!ad) return; mutex_lock(&ad->mutex); if (!ad->enabled) { mutex_unlock(&ad->mutex); return; } LOG("closing adapter %d -> fe:%d dvr:%d", na, ad->fe, ad->dvr); ad->enabled = 0; if (ad->close) ad->close(ad); //close all streams attached to this adapter // close_streams_for_adapter (na, -1); mark_pids_deleted(na, -1, NULL); update_pids(na); // if(ad->dmx>0)close(ad->dmx); if (ad->fe > 0) close(ad->fe); if (ad->sock > 0) sockets_del(ad->sock); if (ad->ca_mask > 0) tables_close_device(ad); ad->ca_mask = 0; ad->fe = 0; ad->dvr = 0; ad->strength = 0; ad->snr = 0; mutex_unlock(&ad->mutex); mutex_destroy(&ad->mutex); // if(a[na]->buf)free1(a[na]->buf);a[na]->buf=NULL; LOG("done closing adapter %d", na); }
void *select_and_execute(void *arg) { fd_set io; int i, rv, rlen, les, es; unsigned char buf[2001]; int err; struct pollfd pf[MAX_SOCKS]; int64_t lt, c_time; int read_ok; char ra[50]; if (arg) thread_name = (char *) arg; else thread_name = "main"; tid = get_tid(); les = 1; es = 0; lt = getTick(); memset(&pf, -1, sizeof(pf)); LOG("Starting select_and_execute on thread ID %x, thread_name %s", tid, thread_name); while (run_loop) { c_time = getTick(); es = 0; clean_mutexes(); for (i = 0; i < max_sock; i++) if (s[i] && s[i]->enabled && s[i]->tid == tid) { pf[i].fd = s[i]->sock; pf[i].events = s[i]->events; pf[i].revents = 0; s[i]->last_poll = c_time; es++; } else { pf[i].fd = -1; pf[i].events = pf[i].revents = 0; } i = -1; if (les == 0 && es == 0 && tid != main_tid) { LOG("No enabled sockets for Thread ID %lx name %s ... exiting ", tid, thread_name); break; } les = es; // LOG("start select"); if ((rv = poll(pf, max_sock, 100)) < 0) { LOG("select_and_execute: select() error %d: %s", errno, strerror(errno)); continue; } // LOG("select returned %d",rv); if (rv > 0) while (++i < max_sock) if ((pf[i].fd >= 0) && pf[i].revents) { sockets *ss = s[i]; if (!ss) continue; c_time = getTick(); LOGL(6, "event on socket index %d handle %d type %d (poll fd:%d, revents=%d)", i, ss->sock, ss->type, pf[i].fd, pf[i].revents); sockets_lock(ss); if (pf[i].revents & POLLOUT) { ss->events &= ~POLLOUT; } if (!ss->buf || ss->buf == buf) { ss->buf = buf; ss->lbuf = sizeof(buf) - 1; ss->rlen = 0; } if (ss->rlen >= ss->lbuf) { LOG( "Socket buffer full, handle %d, sock_id %d, type %d, lbuf %d, rlen %d, ss->buf = %p, buf %p", ss->sock, i, ss->type, ss->lbuf, ss->rlen, ss->buf, buf); ss->rlen = 0; } rlen = 0; if (opts.bw > 0 && bw > opts.bw && ss->type == TYPE_DVR) { int64_t ms = 1000 - c_time + bwtt; if (bwnotify++ == 0) LOG( "capping %d sock %d for the next %jd ms, sleeping for the next %jd ms", i, ss->sock, ms, ms / 50); if (ms > 50) usleep(ms * 20); sockets_unlock(ss); continue; } read_ok = ss->read(ss->sock, &ss->buf[ss->rlen], ss->lbuf - ss->rlen, ss, &rlen); if (opts.log >= 1) { int64_t now = getTick(); if (now - c_time > 100) LOG( "WARNING: read on socket id %d, handle %d, took %jd ms", ss->id, ss->sock, now - c_time); } err = 0; if (rlen < 0) err = errno; if (rlen > 0) ss->rtime = c_time; if (read_ok && rlen >= 0) ss->rlen += rlen; else ss->rlen = 0; //force 0 at the end of the string if (ss->lbuf >= ss->rlen) ss->buf[ss->rlen] = 0; LOGL(6, "Read %s %d (rlen:%d/total:%d) bytes from %d -> %p - iteration %d action %p", read_ok ? "OK" : "NOK", rlen, ss->rlen, ss->lbuf, ss->sock, ss->buf, it++, ss->action); if (((ss->rlen > 0) || err == EWOULDBLOCK) && ss->action && (ss->type != TYPE_SERVER)) ss->action(ss); sockets_unlock(ss); if (!read_ok && ss->type != TYPE_SERVER) { char *err_str; char *types[] = { "udp", "tcp", "server", "http", "rtsp", "dvr" }; if (rlen == 0) { err = 0; err_str = "Close"; } else if (err == EOVERFLOW) err_str = "EOVERFLOW"; else if (err == EWOULDBLOCK) err_str = "Connected"; else err_str = strerror(err); if (ss->type == TYPE_RTCP || ss->sock == SOCK_TIMEOUT) { LOG( "ignoring error on sock_id %d handle %d type %d error %d : %s", ss->id, ss->sock, ss->type, err, err_str); continue; // do not close the RTCP socket, we might get some errors here but ignore them } LOG( "select_and_execute[%d]: %s on socket %d (sid:%d) from %s:%d - type %s errno %d", i, err_str, ss->sock, ss->sid, get_socket_rhost(ss->id, ra, sizeof(ra)), ntohs(ss->sa.sin_port), types[ss->type], err); if (err == EOVERFLOW || err == EWOULDBLOCK) continue; if (err == EAGAIN) { ss->err++; if (ss->err < 10) continue; } sockets_del(i); LOG("Delete socket %d done: sid %d", i, ss->sid); continue; } // ss->err = 0; } // checking every 60seconds for idle connections - or if select times out c_time = getTick(); if (rv == 0 || (c_time - lt >= 200)) { sockets *ss; lt = c_time; i = -1; while (++i < max_sock) if ((ss = get_sockets(i)) && (ss->tid == tid) && ((ss->timeout_ms > 0 && lt - ss->rtime > ss->timeout_ms) || (ss->timeout_ms == 1))) { if (ss->timeout) { int rv; if (ss->sock == SOCK_TIMEOUT) ss->rtime = getTick(); sockets_lock(ss); rv = ss->timeout(ss); sockets_unlock(ss); if (rv) sockets_del(i); } if (!ss->timeout) sockets_del(i); } } } clean_mutexes(); if (tid == main_tid) LOG("The main loop ended, run_loop = %d", run_loop); add_join_thread(tid); return NULL; }
int select_and_execute() { fd_set io; int i, rv, rlen; unsigned char buf[2001]; int err; run_loop = 1; int lt, read_ok, c_time; char ra[50]; lt = getTick(); while (run_loop) { FD_ZERO(&io); i = -1; // LOG("start select"); if ((rv = poll(pf, max_sock, 100)) < 0) { perror("select_and_execute: select() error"); continue; } c_time = getTick(); // LOG("select returned %d",rv); if (rv > 0) while (++i < max_sock) if (pf[i].revents) { sockets *ss = &s[i]; c_time = getTick(); LOGL(6, "event on socket index %d handle %d type %d (poll fd:%d, revents=%d)", i, ss->sock, ss->type, pf[i].fd, pf[i].revents); if (pf[i].revents & POLLOUT) { pf[i].events &= ~POLLOUT; } if (!ss->buf || ss->buf == buf) { ss->buf = buf; ss->lbuf = sizeof(buf) - 1; ss->rlen = 0; } if (ss->rlen >= ss->lbuf) { LOG( "Socket buffer full, handle %d, sock_id %d, type %d, lbuf %d, rlen %d, ss->buf = %p, buf %p", ss->sock, i, ss->type, ss->lbuf, ss->rlen, ss->buf, buf); ss->rlen = 0; } rlen = 0; if (c_time - bwtt > 1000) { bwtt = c_time; tbw += bw; if (bw > 2000) LOG( "BW %dKB/s, Total BW: %ld MB, ns/read %lld, r: %d, tt: %lld ms, n: %d (s: %d ms, s_cnt %d)", (int ) bw / 1024, tbw / 1024576, nsecs / reads, reads, nsecs / 1000, bwnotify, sleeping / 1000, sleeping_cnt); bw = 0; bwnotify = 0; nsecs = 0; reads = 0; sleeping = sleeping_cnt = 0; } if (opts.bw > 0 && bw > opts.bw && ss->type == TYPE_DVR) { int ms = 1000 - c_time + bwtt; if (bwnotify++ == 0) LOG( "capping %d sock %d for the next %d ms, sleeping for the next %d ms", i, ss->sock, ms, ms / 50); if (ms > 50) usleep(ms * 20); continue; } read_ok = ss->read(ss->sock, &ss->buf[ss->rlen], ss->lbuf - ss->rlen, ss, &rlen); if (opts.log >= 1) { int now = getTick(); if (now - c_time > 100) LOG( "WARNING: read on socket id %d, handle %d, took %d ms", ss->id, ss->sock, now - c_time); } err = 0; if (rlen < 0) err = errno; if (rlen > 0) ss->rtime = c_time; if (read_ok && rlen > 0) ss->rlen += rlen; else ss->rlen = 0; //force 0 at the end of the string if (ss->lbuf >= ss->rlen) ss->buf[ss->rlen] = 0; LOGL(6, "Read %s %d (rlen:%d/total:%d) bytes from %d -> %p - iteration %d action %p", read_ok ? "OK" : "NOK", rlen, ss->rlen, ss->lbuf, ss->sock, ss->buf, it++, ss->action); if (((ss->rlen > 0) || err == EWOULDBLOCK) && ss->action && (ss->type != TYPE_SERVER)) ss->action(ss); // if(s[i].type==TYPE_DVR && (c_time/1000 % 10 == 0))sockets_del(i); // we do this in stream.c in flush_stream* if (!read_ok && ss->type != TYPE_SERVER) { char *err_str; char *types[] = { "udp", "tcp", "server", "http", "rtsp", "dvr" }; if (rlen == 0) { err = 0; err_str = "Close"; } else if (err == EOVERFLOW) err_str = "EOVERFLOW"; else if (err == EWOULDBLOCK) err_str = "Connected"; else err_str = strerror(err); if (ss->type == TYPE_RTCP) continue; // do not close the RTCP socket, we might get some errors here but ignore them LOG( "select_and_execute[%d]: %s on socket %d (sid:%d) from %s:%d - type %s errno %d", i, err_str, ss->sock, ss->sid, get_socket_rhost(ss->id, ra, sizeof(ra)), ntohs(ss->sa.sin_port), types[ss->type], err); if (err == EOVERFLOW || err == EWOULDBLOCK) continue; if (err == EAGAIN) { ss->err++; if (ss->err < 10) continue; } sockets_del(i); LOG("Delete socket %d done: sid %d", i, ss->sid); continue; } // ss->err = 0; } // checking every 60seconds for idle connections - or if select times out if (rv == 0 || c_time - lt >= 200) { lt = c_time; i = -1; while (++i < max_sock) if (( s[i].sock > 0 ) && ((s[i].close_sec > 0 && lt - s[i].rtime > s[i].close_sec) || (s[i].close_sec == 1))) { if (s[i].timeout && s[i].timeout(&s[i])) sockets_del(i); if (!s[i].timeout) sockets_del(i); } stream_timeouts(); } } LOG("The main loop ended, run_loop = %d", run_loop); return 0; }