void log_idi_cb(FILE *fp, void * buf) { ENTITY *e = buf; fprintf(fp, "%s %04x.%04x ", e->Rc ? " rc" : "ind", e->user[0] & 0xffff, e->user[1] & 0xffff); display_id(fp, (int) e->Id & 0xff); if ((e->Rc) && (e->Ind)) { fprintf(fp, "ERRROR - both Rc (%02x) and Ind (%02x) set !\n", e->Rc & 0xff, e->Ind & 0xff); } else { if (e->Rc) { fprintf(fp, "%s\n", map_int((int) e->Rc & 0xff, rc_name)); } if (e->Ind) { fprintf(fp, "IND: %02x\n", e->Ind & 0xff); } } return; }
void mark_pids_deleted(int aid, int sid, char *pids) //pids==NULL -> delete all pids { int i, la, pid; adapter *ad; char *arg[MAX_PIDS]; ad = get_adapter(aid); if (!ad) return; LOG("deleting pids on adapter %d, sid %d, pids=%s", aid, sid, pids ? pids : "NULL"); if (pids) { la = split(arg, pids, MAX_PIDS, ','); for (i = 0; i < la; i++) { pid = map_int(arg[i], NULL); mark_pid_deleted(aid, sid, pid, NULL); } return; } for (i = 0; i < MAX_PIDS; i++) mark_pid_deleted(aid, sid, ad->pids[i].pid, &ad->pids[i]); // if(sid == -1) // reset_pids_type(aid); dump_pids(aid); }
char *describe_streams (sockets *s, char *req, char *sbuf, int size) { char *str, *stream_id; int i, sidf, do_play = 0, streams_enabled = 0; streams *sid; int do_all = 1; if (s->sid == -1 && strchr(req, '?')) setup_stream(req, s); sidf = get_session_id(s->sid); sid = get_sid(s->sid); if(sid) do_play = sid->do_play; // else LOG_AND_RETURN(NULL, "No session associated with sock_id %d", s->sock_id); snprintf(sbuf,size-1,"v=0\r\no=- %010d %010d IN IP4 %s\r\ns=SatIPServer:1 %d %d %d\r\nt=0 0\r\n", sidf, sidf, get_sock_host(s->sock), getS2Adapters(), getTAdapters(), getCAdapters() ); if(strchr(req, '?')) do_all = 0; if((stream_id = strstr(req, "stream="))) { do_all = 0; sid = get_sid(map_int(stream_id + 7, NULL) - 1); if(sid == NULL) return NULL; } if(do_all) { for( i=0; i<MAX_STREAMS; i++) if(st[i].enabled) { int slen=strlen(sbuf); streams_enabled ++; snprintf(sbuf + slen, size - slen - 1, "m=video %d RTP/AVP 33\r\nc=IN IP4 0.0.0.0\r\na=control:stream=%d\r\na=fmtp:33 %s\r\na=%s\r\n", ntohs (st[i].sa.sin_port), i+1, describe_adapter(i, st[i].adapter), st[i].do_play?"sendonly":"inactive"); if( size - slen < 10)LOG_AND_RETURN(sbuf, "DESCRIBE BUFFER is full"); } }else{ int slen = strlen(sbuf); snprintf(sbuf + slen, size - slen - 1, "m=video 0 RTP/AVP 33\r\nc=IN IP4 0.0.0.0\r\na=control:stream=%d\r\na=fmtp:33 %s\r\nb=AS:5000\r\na=%s\r\n", sid->sid + 1, describe_adapter(sid->sid, sid->adapter), do_play?"sendonly":"inactive"); } return sbuf; }
static void display_id(FILE *fp, int id) { char *s; s = map_int(id, global_id_name); if (*s != '?') { fprintf(fp, "%s ", s); } else { fprintf(fp, " %02x ", id); } return; }
int read_rtsp (sockets * s) { char *arg[50]; int cseq, la, i, rlen; char *proto, *transport = NULL, *useragent = NULL; int sess_id = 0; char buf[2000]; streams *sid = get_sid(s->sid); if(s->buf[0]==0x24 && s->buf[1]<2) { if(sid) sid->rtime = s->rtime; int rtsp_len = s->buf[2]*256+s->buf[3]; LOG("Received RTSP over tcp packet (sock_id %d, stream %d, rlen %d) packet len: %d, type %02X %02X discarding %s...", s->id, s->sid, s->rlen, rtsp_len , s->buf[4], s->buf[5], (s->rlen == rtsp_len+4)?"complete":"fragment" ); if(s->rlen == rtsp_len+4){ // we did not receive the entire packet s->rlen = 0; return 0; } } if (s->rlen < 4 || !end_of_header(s->buf + s->rlen - 4)) { if( s->rlen > RBUF - 10 ) { LOG("Discarding %d bytes from the socket buffer, request > %d, consider increasing RBUF", s->rlen, RBUF); s->rlen = 0; } LOG("read_rtsp: read %d bytes from handle %d, sock_id %d, flags %d not ending with \\r\\n\\r\\n", s->rlen, s->sock, s->id, s->flags); if ( s->flags & 1 ) return 0; unsigned char *new_alloc = malloc1 (RBUF); memcpy(new_alloc, s->buf, s->rlen); s->buf = new_alloc; s->flags = s->flags | 1; return 0; } rlen = s->rlen; s->rlen = 0; LOG ("read RTSP (from handle %d sock_id %d, len: %d, sid %d):\n%s", s->sock, s->id, s->rlen, s->sid, s->buf); if( (s->type != TYPE_HTTP ) && (strncasecmp(s->buf, "GET", 3) == 0)) { http_response (s , 404, NULL, NULL, 0, 0); return 0; } la = split (arg, s->buf, 50, ' '); cseq = 0; if (la<2) LOG_AND_RETURN(0, "Most likely not an RTSP packet sock_id: %d sid: %d rlen: %d, dropping ....", s->id, s->sid, rlen); if(s->sid<0) for (i = 0; i < la; i++) if (strncasecmp ("Session:", arg[i], 8) == 0) { sess_id = map_int(header_parameter(arg, i), NULL); s->sid = find_session_id(sess_id); } if(strstr(arg[1], "freq") || strstr(arg[1], "pids")) { int old_sid = s->sid; sid = (streams *) setup_stream (arg[1], s); } sid = get_sid(s->sid); if(sid) sid->rtime = s->rtime; if (sess_id) set_session_id(s->sid, sess_id); for (i = 0; i < la; i++) if (strncasecmp ("CSeq:", arg[i], 5) == 0) cseq = map_int (header_parameter(arg, i), NULL); else if (strncasecmp ("Transport:", arg[i], 9) == 0){ transport = header_parameter(arg, i); if( -1 == decode_transport (s, transport, opts.rrtp, opts.start_rtp)) { http_response (s, 400, NULL, NULL, cseq, 0); return 0; } } else if (strstr (arg[i], "LIVE555")) { if(sid) sid->timeout = 0; } else if (strstr (arg[i], "Lavf")) { if(sid) sid->timeout = 0; } else if (strncasecmp ("User-Agent:", arg[i], 10) == 0) useragent = header_parameter(arg, i); if((strncasecmp (arg[0], "PLAY", 4) == 0) || (strncasecmp (arg[0], "GET", 3) == 0) || (strncasecmp (arg[0], "SETUP", 5) == 0)) { char ra[100]; int rv; if (!( sid = get_sid(s->sid))) { http_response (s, 454, NULL, NULL, cseq, 0); return 0; } if (useragent) strncpy(sid->useragent, useragent, 127); if ((strncasecmp (arg[0], "PLAY", 3) == 0) || (strncasecmp (arg[0], "GET", 3) == 0)) if ((rv = start_play (sid, s)) < 0) { http_response (s, -rv , NULL, NULL, cseq, 0); return 0; } strcpy(ra, inet_ntoa (sid->sa.sin_addr)); buf[0] = 0; if(transport) { int s_timeout = (sid->timeout ? sid->timeout : opts.timeout_sec) / 1000; switch (sid->type) { case STREAM_RTSP_UDP: if (atoi (ra) < 239) snprintf (buf, sizeof(buf), "Transport: RTP/AVP;unicast;destination=%s;source=%s;client_port=%d-%d;server_port=%d-%d\r\nSession: %010d;timeout=%d\r\ncom.ses.streamID: %d", ra, get_sock_host (s->sock), ntohs (sid->sa.sin_port), ntohs (sid->sa.sin_port) + 1, // opts.start_rtp, opts.start_rtp + 1, get_sock_port(sid->rsock), get_sock_port(sid->rtcp), get_session_id (s->sid), s_timeout, sid->sid + 1); else snprintf (buf, sizeof(buf), "Transport: RTP/AVP;multicast;destination=%s;port=%d-%d\r\nSession: %010d;timeout=%d\r\ncom.ses.streamID: %d", ra, ntohs (sid->sa.sin_port), ntohs (sid->sa.sin_port) + 1, get_session_id (s->sid), s_timeout , sid->sid + 1); break; case STREAM_RTSP_TCP: snprintf(buf, sizeof(buf), "Transport: RTP/AVP/TCP;interleaved=0-1\r\nSession: %010d;timeout=%d\r\ncom.ses.streamID: %d", get_session_id (s->sid), s_timeout, sid->sid + 1); break; } } if (strncasecmp(arg[0], "PLAY", 4) == 0) { char *qm = strchr(arg[1], '?'); if(qm) *qm = 0; if(buf[0]) strcat(buf, "\r\n"); snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf) - 1, "RTP-Info: url=%s;seq=%d;rtptime=%lld\r\nRange: npt=0.000-", arg[1], getTick(),(long long int)(getTickUs()/1000000)); } if(buf[0]==0 && sid->type == STREAM_HTTP) snprintf(buf, sizeof(buf), "Content-Type: video/mp2t"); http_response (s, 200, buf, NULL, cseq, 0); } else if (strncmp (arg[0], "TEARDOWN", 8) == 0) { streams *sid; buf[0] = 0; if(get_sid(s->sid)) sprintf(buf, "Session: %010d", get_session_id(s->sid)); close_stream (s->sid); http_response (s, 200, buf, NULL, cseq, 0); } else { if (strncmp (arg[0], "DESCRIBE", 8) == 0) { char sbuf[1000]; char *rv = NULL; rv = describe_streams(s, arg[1], sbuf, sizeof(sbuf)); if (! rv) { http_response (s, 404, NULL, NULL, cseq, 0); return 0; } snprintf(buf, sizeof(buf), "Content-type: application/sdp\r\nContent-Base: rtsp://%s/", get_sock_host(s->sock)); http_response (s, 200, buf, sbuf, cseq, 0); } else if (strncmp (arg[0], "OPTIONS", 8) == 0) { http_response (s, 200, public, NULL, cseq, 0); } }
void set_options (int argc, char *argv[]) { int opt; int sethost = 0; int index; char *lip; opts.log = 1; opts.rrtp = NULL; opts.disc_host = "239.255.255.250"; opts.start_rtp = 5500; opts.http_port = 8080; opts.http_host = NULL; opts.log = 0; opts.timeout_sec = 30000; opts.force_sadapter = 0; opts.force_tadapter = 0; opts.force_cadapter = 0; opts.mac[0] = 0; opts.daemon = 1; opts.bw = 0; opts.device_id = 0; opts.bootid = 0; opts.force_scan = 0; opts.dvr_buffer = DVR_BUFFER; opts.adapter_buffer = ADAPTER_BUFFER; opts.file_line = 0; opts.dvbapi_port = 0; opts.dvbapi_host = NULL; opts.drop_encrypted = 1; opts.rtsp_port = 554; opts.clean_psi = 0; opts.satip_addpids = 0; opts.output_buffer = 512*1024; opts.satip_servers[0] = 0; memset(opts.playlist, sizeof(opts.playlist), 0); while ((opt = getopt_long (argc, argv, "flr:a:td:w:p:s:hc:b:m:p:e:x:u:j:o:gy:zi:D:V", long_options, NULL)) != -1) { // printf("options %d %c %s\n",opt,opt,optarg); switch (opt) { case FOREGROUND_OPT: { opts.daemon = 0; break; } case MAC_OPT: { strncpy (opts.mac, optarg, 12); opts.mac[12] = 0; break; } case RRTP_OPT: { opts.rrtp = optarg; break; } case DEVICEID_OPT: { opts.device_id = atoi (optarg); break; } case HTTPSERVER_OPT: { // int i=0; opts.http_host = optarg; sethost = 1; break; } case LOG_OPT: { opts.log++; break; } case SYSLOG_OPT: { opts.slog++; break; } case HELP_OPT: { usage (); exit (0); } case VERSION_OPT: { LOGL(0, "minisatip version %s, compiled with s2api version: %04X",VERSION, DVBAPIVERSION); exit (0); } case HTTPPORT_OPT: { opts.http_port = atoi (optarg); break; } case BW_OPT: { opts.bw = atoi (optarg) * 1024; break; } case DVRBUFFER_OPT: { sscanf(optarg,"%d:%d", &opts.adapter_buffer, &opts.dvr_buffer) ; opts.adapter_buffer = (opts.adapter_buffer/188) * 188; if(opts.adapter_buffer < ADAPTER_BUFFER) opts.adapter_buffer = ADAPTER_BUFFER; if(opts.dvr_buffer == 0 ) opts.dvr_buffer = DVR_BUFFER; break; } case DVBS2_ADAPTERS_OPT: { sscanf(optarg,"%d:%d:%d", &opts.force_sadapter, &opts.force_tadapter, &opts.force_cadapter) ; break; } case CLEANPSI_OPT: { opts.clean_psi = 1; break; } case SCAN_OPT: { opts.force_scan = 1; break; } case PLAYLIST_OPT: { snprintf(opts.playlist, sizeof(opts.playlist), "<satip:X_SATIPM3U xmlns:satip=\"urn:ses-com:satip\">%s</satip:X_SATIPM3U>\r\n",optarg); break; } case ENABLE_ADAPTERS_OPT: { enable_adapters(optarg); break; } case UNICABLE_OPT: { set_unicable_adapters(optarg, SWITCH_UNICABLE); break; } case JESS_OPT: { set_unicable_adapters(optarg, SWITCH_JESS); break; } case DISEQC_OPT: { set_diseqc_adapters(optarg); } case DVBAPI_OPT: { char* sep1 = strchr(optarg, ':'); if ( sep1 != NULL) { *sep1 = 0; opts.dvbapi_host = optarg; opts.dvbapi_port = map_int(sep1 + 1, NULL ); } break; } case RTSPPORT_OPT: { opts.rtsp_port = atoi (optarg); break; } case SATIPCLIENT_OPT: if(strlen(optarg) + strlen(opts.satip_servers) > sizeof(opts.satip_servers)) break; if(opts.satip_servers[0]) sprintf(opts.satip_servers + strlen(opts.satip_servers), ",%s", optarg ); else sprintf(opts.satip_servers, "%s", optarg ); break; case PRIORITY_OPT: if(nice(map_int(optarg, NULL)) == -1) LOG("Failed to set priority %s", strerror(errno)); break; } } if(opts.bw && (opts.bw < opts.adapter_buffer)) opts.adapter_buffer = (opts.bw / 188) * 188; lip = getlocalip (); if (!opts.http_host) { opts.http_host = (char *) malloc (MAX_HOST); sprintf (opts.http_host, "%s:%d", lip, opts.http_port); } }
int satipc_reply(sockets * s) { int rlen = s->rlen; adapter *ad; char *arg[50], *sess, *es, *sid; int la, i, rc; s->rlen = 0; LOG("satipc_reply (sock %d) handle %d, adapter %d:\n%s", s->id, s->sock, s->sid, s->buf); if (!(ad = get_adapter(s->sid))) return 0; sess = strstr(s->buf, "Session:"); la = split(arg, (char *) s->buf, 50, ' '); rc = map_int(arg[1], NULL); if (ad->last_cmd == RTSP_OPTIONS && !sess && ad->session[0]) rc = 454; if (rc == 454 || rc == 503 || rc == 405) { ad->sent_transport = 0; ad->want_tune = 1; ad->want_commit = 1; ad->force_commit = 1; } else if (rc != 200) ad->err = 1; sid = NULL; if (rc == 200 && !ad->want_tune) ad->ignore_packets = 0; sess = NULL; for (i = 0; i < la; i++) if (strncasecmp("Session:", arg[i], 8) == 0) sess = header_parameter(arg, i); else if (strncasecmp("com.ses.streamID:", arg[i], 17) == 0) sid = header_parameter(arg, i); else if (strncasecmp("Server:", arg[i], 7) == 0) { char *ua = header_parameter(arg, i); if (!strncmp(ua, app_name, strlen(app_name))) { ad->satip_addpids = 1; ad->satip_setup_pids = 1; } } if (!ad->err && !ad->session[0] && sess) { if ((es = strchr(sess, ';'))) *es = 0; strncpy(ad->session, sess, sizeof(ad->session)); ad->session[sizeof(ad->session) - 1] = 0; LOG("satipc: session set for adapter %d to %s", ad->id, ad->session); if (sid && ad->stream_id == -1) ad->stream_id = map_int(sid, NULL); ad->expect_reply = 0; ad->force_commit = 1; // http_request(ad, NULL, "PLAY"); satipc_commit(ad); return 0; } if (ad->wp >= ad->qp) ad->expect_reply = 0; else { char *np = (char *) getItem(MAKE_ITEM(ad->id, ad->wp)); if (np) { int len = strlen(np); if (ad->session[0] && !strstr(np, "Session:")) sprintf(np + len - 2, "Session: %s\r\n\r\n", ad->session); LOG("satipc_reply: sending next packet:\n%s", np); write(s->sock, np, strlen(np)); delItem(MAKE_ITEM(ad->id, ad->wp++)); } } if (!ad->expect_reply && (ad->wp >= ad->qp) && (ad->want_commit || ad->force_commit)) // we do not expect reply and no other events in the queue, we commit a { satipc_commit(ad); } return 0; }