pthread_t get_socket_thread(int s_id) { sockets *ss = get_sockets(s_id); if (!ss) LOG_AND_RETURN(0, "get_socket_thread: socket is NULL for s_id %d", s_id); return ss->tid; }
int get_socket_rport(int s_id) { sockets *ss = get_sockets(s_id); if (!ss) return 0; return ntohs(ss->sa.sin_port); }
void set_socket_pos(int sock, int pos) { sockets *ss = get_sockets(sock); if (!ss) return; ss->rlen = pos; }
void set_socket_thread(int s_id, pthread_t tid) { sockets *ss = get_sockets(s_id); if (!ss) return; LOG("set_socket_thread: thread %x for sockets %i", tid, s_id); ss->tid = tid; }
char *get_socket_rhost(int s_id, char *dest, int ld) { sockets *ss = get_sockets(s_id); dest[0] = 0; if (!ss) return dest; inet_ntop(AF_INET, &(ss->sa.sin_addr), dest, ld); return dest; }
void sockets_setbuf(int i, char *buf, int len) { sockets *ss = get_sockets(i); if (ss) { ss->buf = (unsigned char *) buf; ss->lbuf = len; } }
void set_socket_buffer(int sid, unsigned char *buf, int len) { sockets *ss = get_sockets(sid); if (!ss) return; ss->buf = buf; ss->lbuf = len; }
void set_sock_lock(int i, SMutex *m) { sockets *ss = get_sockets(i); if (ss) { ss->lock = m; LOG("%s: sock_id %d locks also mutex %p", __FUNCTION__, i, m); } }
int temp11(int argc, char *argv[]) { int o; int sock; while ((o = getopt(argc, argv, "dstS")) != -1) { switch (o) { case 'S': do_sleep = 1; break; case 'd': do_debug = 1; break; case 's': do_stdin = 1; break; case 't': do_thread = 1; break; } } if (do_stdin) { struct sockets s; s.local = 1; s.in = stdin; s.out = stdout; if (do_thread) { pthread_t p; pthread_create(&p, NULL, roll_dice, (void *) &s); } else { roll_dice(&s); exit(0); } } sock = socket_setup(); while (1) { struct sockets *s = get_sockets(sock); if (s) { if (do_thread) { pthread_t p; pthread_create(&p, NULL, roll_dice, (void *) s); } else { roll_dice(s); exit(0); } } } return 0; }
int sockets_del_for_sid(int sid) { int i; sockets *ss; if (sid < 0) return 0; for (i = 0; i < MAX_SOCKS; i++) if ((ss = get_sockets(i)) && ss->sid >= 0 && ss->type == TYPE_RTSP && ss->sid == sid) { ss->timeout_ms = 1; //trigger close of the socket after this operation ends, otherwise we might close an socket on which we run action ss->sid = -1;// make sure the stream is not closed in the future to prevent closing the stream created by another socket } return 0; }
void set_sockets_rtime(int i, int r) { sockets *ss = get_sockets(i); if (ss) ss->rtime = r; }
void sockets_timeout(int i, int t) { sockets *ss = get_sockets(i); if (ss) ss->timeout_ms = t; }
void sockets_setread(int i, void *r) { sockets *ss = get_sockets(i); if (ss) ss->read = (read_action) r; }
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; }