static void frag_fu_a(uint8_t *nal, int fragsize, int mtu, Track *tr) { int start = 1, fraglen; uint8_t fu_header, buf[mtu]; fnc_log(FNC_LOG_VERBOSE, "[h264] frags"); // p = data + index; buf[0] = (nal[0] & 0xe0) | 28; // fu_indicator fu_header = nal[0] & 0x1f; nal++; fragsize--; while(fragsize>0) { buf[1] = fu_header; if (start) { start = 0; buf[1] = fu_header | (1<<7); } fraglen = MIN(mtu-2, fragsize); if (fraglen == fragsize) { buf[1] = fu_header | (1<<6); } memcpy(buf + 2, nal, fraglen); fnc_log(FNC_LOG_VERBOSE, "[h264] Frag %d %d",buf[0], buf[1]); mparser_buffer_write(tr, tr->properties.pts, tr->properties.dts, tr->properties.frame_duration, (fragsize<=fraglen), buf, fraglen + 2); fragsize -= fraglen; nal += fraglen; } }
gint unix_sock_bind(const gchar *host, gint port, L4_Proto l4) { struct sockaddr_in sin; gint sock, err; sock = socket(AF_INET, l4 == L4_TCP ? SOCK_STREAM : SOCK_DGRAM, 0); if (sock < 0) { err = -errno; fnc_log(FNC_LOG_ERR, "[FC] Create socket failed."); return err; } memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(port); sin.sin_addr.s_addr = host ? inet_addr(host) : INADDR_ANY; if (bind(sock, (struct sockaddr*)&sin, sizeof(sin))) { err = -errno; fnc_log(FNC_LOG_ERR, "[FC] Bind socket failed on port '%d'.", port); close(sock); return err; } return sock; }
tsocket tcp_connect(unsigned short port, char *addr) { tsocket f; int on=1; int one = 1;/*used to set SO_KEEPALIVE*/ struct sockaddr_in s; int v = 1; if ((f = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))<0) { fnc_log(FNC_LOG_ERR,"socket() error in tcp_connect.\n" ); return ERR_GENERIC; } setsockopt(f, SOL_SOCKET, SO_REUSEADDR, (char *) &v, sizeof(int)); s.sin_family = AF_INET; s.sin_addr.s_addr = inet_addr(addr);//htonl(addr); s.sin_port = htons(port); // set to non-blocking if (ioctl(f, FIONBIO, &on) < 0) { fnc_log(FNC_LOG_ERR,"ioctl() error in tcp_connect.\n" ); return ERR_GENERIC; } if (connect(f,(struct sockaddr*)&s, sizeof(s)) < 0) { fnc_log(FNC_LOG_ERR,"connect() error in tcp_connect.\n" ); return ERR_GENERIC; } if(setsockopt(f, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one))<0){ fnc_log(FNC_LOG_ERR,"setsockopt() SO_KEEPALIVE error in tcp_connect.\n" ); return ERR_GENERIC; } return f; }
static int simple_parse(Track *tr, uint8_t *data, size_t len) { int32_t offset = 0, rem = len; if (DEFAULT_MTU >= len) { mparser_buffer_write(tr, tr->properties.pts, tr->properties.dts, tr->properties.frame_duration, 1, data, len); fnc_log(FNC_LOG_VERBOSE, "[simple] no frags"); } else { do { offset = len - rem; mparser_buffer_write(tr, tr->properties.pts, tr->properties.dts, tr->properties.frame_duration, (rem <= DEFAULT_MTU), data + offset, MIN(rem, DEFAULT_MTU)); rem -= DEFAULT_MTU; fnc_log(FNC_LOG_VERBOSE, "[simple] frags"); } while (rem >= 0); } fnc_log(FNC_LOG_VERBOSE, "[simple] Frame completed"); return ERR_NOERROR; }
int udp_open(unsigned short port,struct sockaddr *s_addr, tsocket *fd) { struct sockaddr_in s; int on = 1; //,v=1; if (!*fd) { if ((*fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { fnc_log(FNC_LOG_ERR,"socket() error in udp_open.\n" ); return ERR_GENERIC; } // set to non-blocking if (ioctl(*fd, FIONBIO, &on) < 0) { fnc_log(FNC_LOG_ERR,"ioctl() error in udp_open.\n" ); return ERR_GENERIC; } } s.sin_family = AF_INET; s.sin_addr.s_addr = htonl(INADDR_ANY); s.sin_port = htons(port); if (bind (*fd, (struct sockaddr *)&s, sizeof (s))) { fnc_log(FNC_LOG_ERR,"bind() error in udp_open.\n" ); return ERR_GENERIC; } *s_addr=*((struct sockaddr*)&s); return ERR_NOERROR; }
/** * Drop privileges to the configured user * * This function takes care of changing the running group and user to * those defined in @ref feng_srv::groupname and @ref * feng_srv::username, defaulting to feng:feng. * * We do not drop privileges if we're running as non-root, as in that * case we assume we have been given already only the limited set of * privileges we need. */ static void feng_drop_privs() { const char *const wanted_group = feng_srv.groupname; const char *const wanted_user = feng_srv.username; if ( getuid() != 0 ) /* only if root */ return; errno = 0; if ( wanted_group != NULL ) { struct group *gr = getgrnam(wanted_group); if ( errno != 0 ) fnc_perror("getgrnam"); else if ( gr == NULL ) fnc_log(FNC_LOG_ERR, "%s: group %s not found", __func__, wanted_group); else if ( setgid(gr->gr_gid) < 0 ) fnc_perror("setgid"); } errno = 0; if ( wanted_user != NULL ) { struct passwd *pw = getpwnam(wanted_user); if ( errno != 0 ) fnc_perror("getpwnam"); else if ( pw == NULL ) fnc_log(FNC_LOG_ERR, "%s: user %s not found", __func__, wanted_user); else if ( setuid(pw->pw_uid) < 0 ) fnc_perror("setuid"); } }
gint set_fd_flags(gint fd, gint flgs) { gint old_flgs, err; old_flgs = fcntl(fd, F_GETFL, 0); if (G_UNLIKELY(old_flgs < 0)) { err = -errno; fnc_log(FNC_LOG_ERR, "set_fd_flags()->fcntl(fd, F_GETFL, 0)" ); return err; } old_flgs |= flgs; if (fcntl(fd, F_SETFL, old_flgs) < 0) { err = -errno; fnc_log(FNC_LOG_ERR, "set_fd_flags()->fcntl(fd, F_SETFL, 0)" ); return err; } return 0; }
/** * @brief Read data from a resource (unlocked) * * @param resouce The resource to read from * * @return The same return value as read_packet */ int r_read(Resource *resource) { int ret = RESOURCE_EOF; g_mutex_lock(resource->lock); if (!resource->eor) switch( (ret = resource->demuxer->read_packet(resource)) ) { case RESOURCE_OK: break; case RESOURCE_EOF: fnc_log(FNC_LOG_INFO, "r_read_unlocked: %s read_packet() end of file.", resource->info->mrl); resource->eor = true; break; default: fnc_log(FNC_LOG_FATAL, "r_read_unlocked: %s read_packet() error.", resource->info->mrl); break; } g_mutex_unlock(resource->lock); return ret; }
static char *encode_avc1_header(uint8_t *p, unsigned int len, int packet_mode) { int i, cnt, nalsize; uint8_t *q = p; char *sprop = NULL; cnt = *(p+5) & 0x1f; // Number of sps p += 6; for (i = 0; i < cnt; i++) { if (p > q + len) goto err_alloc; nalsize = RB16(p); //buf_size p += 2; fnc_log(FNC_LOG_VERBOSE, "[h264] nalsize %d", nalsize); if (i == 0) { gchar *out = g_strdup_printf("profile-level-id=%02x%02x%02x; " "packetization-mode=%d; ", p[0], p[1], p[2], packet_mode); gchar *buf = g_base64_encode(p, nalsize); sprop = g_strdup_printf("%ssprop-parameter-sets=%s", out, buf); g_free(buf); g_free(out); } else { gchar *buf = g_base64_encode(p, nalsize); gchar *out = g_strdup_printf("%s,%s", sprop, buf); g_free(sprop); g_free(buf); sprop = out; } p += nalsize; } // Decode pps from avcC cnt = *(p++); // Number of pps fnc_log(FNC_LOG_VERBOSE, "[h264] pps %d", cnt); for (i = 0; i < cnt; i++) { gchar *out, *buf; if (p > q + len) goto err_alloc; nalsize = RB16(p); p += 2; fnc_log(FNC_LOG_VERBOSE, "[h264] nalsize %d", nalsize); buf = g_base64_encode(p, nalsize); out = g_strdup_printf("%s,%s",sprop, buf); g_free(sprop); g_free(buf); sprop = out; p += nalsize; } return sprop; err_alloc: if (sprop) g_free(sprop); return NULL; }
static void check_if_any_rtp_session_timedout(gpointer element, gpointer user_data) { RTP_session *session = (RTP_session *)element; time_t *last_packet_send_time = (time_t *)user_data; time_t now = time(NULL); /* Jmkn: get the last packet send time in all the session*/ if( last_packet_send_time != NULL && (session->last_packet_send_time > *last_packet_send_time)){ *last_packet_send_time = session->last_packet_send_time; } #if 0 /* Check if we didn't send any data for more then STREAM_BYE_TIMEOUT seconds * this will happen if we are not receiving any more from live producer or * if the stored stream ended. */ if ((session->track->properties.media_source == MS_live) && (now - session->last_packet_send_time) >= LIVE_STREAM_BYE_TIMEOUT) { fnc_log(FNC_LOG_INFO, "[client] Soft stream timeout"); rtcp_send_sr(session, BYE); } /* If we were not able to serve any packet and the client ignored our BYE * kick it by closing everything */ if (session->isBye != 0 && (now - session->last_packet_send_time) >= STREAM_TIMEOUT) { fnc_log(FNC_LOG_INFO, "[client] Stream Timeout, client kicked off!"); ev_async_send(session->srv->loop, &session->client->ev_sig_disconnect); }else{ #endif /* send RTCP SDE */ rtcp_send_sr(session, SDES); /* If we do not read RTCP report in 12 seconds .we will deal it as the client lost connection,and end the child process. */ if(session->srv->srvconf.rtcp_heartbeat != 0 && session->last_rtcp_read_time != 0 && (now - session->last_rtcp_read_time)>=60) { fnc_log(FNC_LOG_INFO, "[client] Client Lost Connection\n"); ev_async_send(session->srv->loop, &session->client->ev_sig_disconnect); } #if 0 } #endif }
static __inline__ gboolean rtsp_recv_rtp_packets(RTSP_client_session *rtsp_s, RTP_Session *rtp_s, GEvent *ev) { gchar rtp_pkt[RTP_BUFFER_LEN]; gint rtp_size, err; for (;;) { rtp_size = recvfrom(g_event_fd(ev), rtp_pkt, RTP_BUFFER_LEN, MSG_DONTWAIT, NULL, NULL); if (rtp_size > 0) { RTP_Frame fr; err = rtp_parse_frame(rtp_s, rtp_pkt, rtp_size, &fr); if (err == RTP_PKT_OK || err == RTP_PKT_AGAIN) { if (err == RTP_PKT_OK) { INVOKE_DAT_HOOK_FRA(rtsp_s, &fr, NULL); } continue; } fnc_log(FNC_LOG_ERR, "[FC] Rtp parse failed, rtsp_s '%p', stop.", rtsp_s ); g_event_remove_events_sync(ev, EV_READ|EV_WRITE); break; } else { err = -errno; if (err != -EAGAIN && err != -EINTR) { fnc_log(FNC_LOG_ERR, "[FC] Rtp recv failed, rtsp_s '%p', err:'%d', stop.", rtsp_s, err ); g_event_remove_events_sync(ev, EV_READ|EV_WRITE); } break; } } return TRUE; }
Track *add_track(Resource *r, char *name, MediaProperties *prop_hints) { Track *t; t = g_slice_new0(Track); t->lock = g_mutex_new(); t->parent = r; t->name = name; t->sdp_description = g_string_new(""); g_string_append_printf(t->sdp_description, "a=control:%s\r\n", name); memcpy(&t->properties, prop_hints, sizeof(MediaProperties)); switch (t->properties.media_source) { case STORED_SOURCE: if ( !(t->parser = mparser_find(t->properties.encoding_name)) ) { fnc_log(FNC_LOG_FATAL, "Could not find a valid parser\n"); goto error; } t->properties.media_type = t->parser->media_type; break; case LIVE_SOURCE: break; default: g_assert_not_reached(); break; } if (t->parser && t->parser->init && t->parser->init(t) != 0) { fnc_log(FNC_LOG_FATAL, "Could not initialize parser for %s\n", t->properties.encoding_name); goto error; } r->tracks = g_list_append(r->tracks, t); return t; error: free_track(t, NULL); return NULL; }
char *alloc_path_name(char *base_path, char *file_path) { char *PathName; char *p; int len; len = strlen(base_path); PathName = malloc(len + strlen(file_path) + 2); if (PathName==NULL) { fnc_log(FNC_LOG_FATAL,"Out of memory in alloc_path_name()\n"); exit(-1); } p = base_path + len ; if (len) p--; if ((*p == '/') && (*file_path == '/')) sprintf(PathName, "%s%s", base_path, file_path + 1); else if ((*p != '/') && (*file_path != '/')) sprintf(PathName, "%s/%s", base_path, file_path); else sprintf(PathName, "%s%s", base_path, file_path); return (PathName); }
static __inline__ gint get_new_udp_sock(gint *port) { struct sockaddr_in sin; socklen_t len = sizeof(sin); gint sock, err; sock = unix_sock_bind(NULL, *port, L4_UDP); if (sock < 0) return sock; if (!*port) { if (getsockname(sock, (struct sockaddr*)&sin, &len)) { err = -errno; fnc_log(FNC_LOG_ERR, "[FC] getsockname() failed."); close(sock); return err; } *port = ntohs(sin.sin_port); } return sock; }
static void interleaved_read_tcp_cb( struct ev_loop *loop, ev_io *w, int revents) { GByteArray *pkt; uint16_t ne_n; char buffer[RTSP_BUFFERSIZE + 1]; RTSP_interleaved_channel *intlvd = w->data; RTSP_Client *rtsp = intlvd->local->data; int n; if ((n = Sock_read(intlvd->local, buffer, RTSP_BUFFERSIZE, NULL, MSG_DONTWAIT)) < 0) { fnc_log(FNC_LOG_WARN, "Error reading from local socket\n"); return; } ne_n = htons((uint16_t)n); pkt = g_byte_array_sized_new(n+4); g_byte_array_set_size(pkt, n+4); pkt->data[0] = '$'; pkt->data[1] = (uint8_t)intlvd->channel; memcpy(&pkt->data[2], &ne_n, sizeof(ne_n)); memcpy(&pkt->data[4], buffer, n); g_queue_push_head(rtsp->out_queue, pkt); ev_io_start(rtsp->srv->loop, &rtsp->ev_io_write); }
/** * @brief Resume (or start) an RTP session * * @param session_gen The session to resume or start * @param range_gen Pointer tp @ref RTSP_Range to start with * * @todo This function should probably take care of starting eventual * libev events when the scheduler is replaced. * * This function is used by the PLAY method of RTSP to start or resume * a session; since a newly-created session starts as paused, this is * the only method available. * * The use of a pointer to double rather than a double itself is to * make it possible to pass this function straight to foreach * functions from glib. * * @internal This function should only be called from g_slist_foreach. */ static void rtp_session_resume(gpointer session_gen, gpointer range_gen) { RTP_session *session = (RTP_session*)session_gen; RTSP_Range *range = (RTSP_Range*)range_gen; fnc_log(FNC_LOG_VERBOSE, "Resuming session %p\n", session); session->range = range; session->start_seq = 1 + session->seq_no; session->start_rtptime = g_random_int(); session->send_time = 0.0; session->last_packet_send_time = time(NULL); /* Create the new thread pool for the read requests */ session->fill_pool = g_thread_pool_new(rtp_session_fill_cb, session, 1, true, NULL); /* Prefetch frames */ rtp_session_fill(session); ev_periodic_set(&session->transport.rtp_writer, range->playback_time - 0.05, 0, NULL); ev_periodic_start(session->srv->loop, &session->transport.rtp_writer); ev_io_start(session->srv->loop, &session->transport.rtcp_reader); }
static void rtsp_client_free(RTSP_Client *client) { GString *outbuf = NULL; close(client->sd); g_free(client->local_host); g_free(client->remote_host); rtsp_session_free(client->session); if ( client->channels ) g_hash_table_destroy(client->channels); /* Remove the output queue */ if ( client->out_queue ) { while( (outbuf = g_queue_pop_tail(client->out_queue)) ) g_string_free(outbuf, TRUE); g_queue_free(client->out_queue); } if ( client->input ) /* not present on SCTP or HTTP transports */ g_byte_array_free(client->input, true); g_slice_free(RFC822_Request, client->pending_request); g_slice_free1(client->sa_len, client->peer_sa); g_slice_free1(client->sa_len, client->local_sa); g_slice_free(RTSP_Client, client); fnc_log(FNC_LOG_INFO, "[client] Client removed"); }
/** * @brief Send an interleaved RTCP packet down to the RTCP handler * * @param rtsp The RTSP client where the handler can be found * @param channel The channel index where the package arrived * @param data The pointer to the data to send * @param len The length of the data to send * * This function is used to send data down to the actual RTCP handler * after it has been received from an interleaved transport (TCP or * SCTP alike). */ void interleaved_rtcp_send(RTSP_Client *rtsp, int channel, void *data, size_t len) { RTSP_interleaved *intlvd = NULL; GSList *intlvd_iter = g_slist_find_custom(rtsp->interleaved, GINT_TO_POINTER(channel), interleaved_rtcp_find_compare); /* We have to check if the value returned by g_slist_find_custom * is valid before derefencing it. */ if ( intlvd_iter == NULL ) { fnc_log(FNC_LOG_DEBUG, "Interleaved RTCP packet arrived for unknown channel (%d)... discarding.\n", channel); return; } intlvd = (RTSP_interleaved *)intlvd_iter->data; /* We should be pretty sure this is not NULL */ g_assert(intlvd != NULL); /* Write the actual data */ Sock_write(intlvd->rtcp.local, data, len, NULL, MSG_DONTWAIT | MSG_EOR); }
static __inline__ RTP_Session * rtp_session_new(RTSP_client_session *rtsp_s) { RTP_Session *rtp_s; gint err; rtp_s = g_new0(RTP_Session, 1); rtp_s->ref_count = 1; if (!rtsp_s->rtp_over_rtsp) { err = rtp_session_sock_init(rtp_s); if (err) { fnc_log(FNC_LOG_ERR, "[FC] Init RTP sock failed, err:%d", err); g_free(rtp_s); return NULL; } } else { rtp_s->interleaved = 1; rtp_s->rtp_port = rtsp_session_get_interleaved(rtsp_s); #ifdef CONFIG_RTCP_SUPPORT rtp_s->rtcp_port = rtsp_session_get_interleaved(rtsp_s); #endif } return rtp_s; }
static void child_terminate_cb (struct ev_loop *loop, ev_child *w, int revents) { client_port_pair *client=NULL; pid_t pid; feng *srv=w->data; //ev_child_stop (EV_A_ w); //printf ("child process %d exited with status %x\n", w->rpid, w->rstatus); pid = w->rpid; client=get_client_list_item(pid); if(client) { fnc_log(FNC_LOG_INFO, "The child process (pid:%d) for rtsp connection (%s:%hu) terminated with status %x\n", w->rpid, client->host, client->port, w->rstatus); reduce_client_list(client); srv->connection_count--; free_child_port(client); } }
gboolean interleaved_setup_transport(RTSP_Client *rtsp, RTP_transport *transport, int rtp_ch, int rtcp_ch) { RTSP_interleaved *intlvd = NULL; Sock *sock_pair[2][2]; //unsigned buffer_size = 0; // RTP local sockpair if ( Sock_socketpair(sock_pair[0]) < 0) { fnc_log(FNC_LOG_ERR, "Cannot create AF_LOCAL socketpair for rtp\n"); return false; } // RTCP local sockpair if ( Sock_socketpair(sock_pair[1]) < 0) { fnc_log(FNC_LOG_ERR, "Cannot create AF_LOCAL socketpair for rtcp\n"); Sock_close(sock_pair[0][0]); Sock_close(sock_pair[0][1]); return false; } intlvd = g_slice_new0(RTSP_interleaved); transport->rtp_sock = sock_pair[0][0]; intlvd->rtp.local = sock_pair[0][1]; /* Jmkn: Not necessary to increase the buffer for socketpair, * because we send a 1.4 Kbytes packet each time */ /* buffer_size = increase_sock_buffer_to(transport->rtp_sock, SO_SNDBUF, RTP_BUF_SIZE); fnc_log(FNC_LOG_VERBOSE,"[rtsp] Set rtp data socket send buffer size to %u", buffer_size); */ transport->rtcp_sock = sock_pair[1][0]; intlvd->rtcp.local = sock_pair[1][1]; // copy stream number in rtp_transport struct transport->rtp_ch = intlvd->rtp.channel = rtp_ch; transport->rtcp_ch = intlvd->rtcp.channel = rtcp_ch; interleaved_setup_callbacks(rtsp, intlvd); rtsp->interleaved = g_slist_prepend(rtsp->interleaved, intlvd); return true; }
int h264_parse(Track *tr, uint8_t *data, ssize_t len) { // double nal_time; // see page 9 and 7.4.1.2 size_t nalsize = 0, index = 0; uint8_t *p, *q; if (tr->h264.is_avc) { const size_t nal_length_size = tr->h264.nal_length_size; while (1) { unsigned int i; if(index >= len) break; //get the nal size nalsize = 0; for(i = 0; i < nal_length_size; i++) nalsize = (nalsize << 8) | data[index++]; if(nalsize <= 1 || nalsize > len) { if(nalsize == 1) { index++; continue; } else { fnc_log(FNC_LOG_VERBOSE, "[h264] AVC: nal size %d", nalsize); break; } } if (DEFAULT_MTU >= nalsize) { struct MParserBuffer *buffer = g_slice_new0(struct MParserBuffer); buffer->timestamp = tr->pts; buffer->delivery = tr->dts; buffer->duration = tr->frame_duration; buffer->marker = true; buffer->data_size = nalsize; buffer->data = g_memdup(data + index, buffer->data_size); track_write(tr, buffer); fnc_log(FNC_LOG_VERBOSE, "[h264] single NAL"); } else { // single NAL, to be fragmented, FU-A; frag_fu_a(data + index, nalsize, tr); } index += nalsize; } } else {
void rtsp_interleaved_receive(RTSP_Client *rtsp, int channel, uint8_t *data, size_t len) { RTP_session *rtp = NULL; if ( (rtp = g_hash_table_lookup(rtsp->channels, GINT_TO_POINTER(channel))) == NULL ) fnc_log(FNC_LOG_INFO, "Received interleaved message for unknown channel %d", channel); else /* we currently only support inbound RTCP; find a solution before supporting inbound RTP */ rtcp_handle(rtp, data, len); }
static void frag_fu_a(uint8_t *nal, int fragsize, Track *tr) { int start = 1; const uint8_t fu_indicator = (nal[0] & 0xe0) | 28; const uint8_t fu_header = nal[0] & 0x1f; fnc_log(FNC_LOG_VERBOSE, "[h264] frags"); nal++; fragsize--; while(fragsize>0) { const size_t fraglen = MIN(DEFAULT_MTU-2, fragsize); struct MParserBuffer *buffer = g_slice_new0(struct MParserBuffer); buffer->timestamp = tr->pts; buffer->delivery = tr->dts; buffer->duration = tr->frame_duration; buffer->data_size = fraglen + 2; buffer->data = g_malloc(buffer->data_size); buffer->data[0] = fu_indicator; buffer->data[1] = fu_header; if ( start ) { buffer->data[1] |= (1<<7); start = 0; } if (fraglen == fragsize) { buffer->marker = true; buffer->data[1] |= (1<<6); } memcpy(buffer->data + 2, nal, fraglen); fnc_log(FNC_LOG_VERBOSE, "[h264] Frag %02x%02x", buffer->data[0], buffer->data[1]); track_write(tr, buffer); fragsize -= fraglen; nal += fraglen; } }
/** * @brief parse incoming RTCP packets */ static void rtcp_read_cb(ATTR_UNUSED struct ev_loop *loop, ev_io *w, ATTR_UNUSED int revents) { char buffer[RTP_DEFAULT_MTU*2] = { 0, }; //FIXME just a quick hack... RTP_session *session = w->data; int n = Sock_read(session->transport.rtcp_sock, buffer, RTP_DEFAULT_MTU*2, NULL, 0); fnc_log(FNC_LOG_INFO, "[RTCP] Read %d byte", n); }
int send_reply(int err, char *addon, RTSP_buffer * rtsp) { unsigned int len; char *b; char *p; int res; char method[32]; char object[256]; char ver[32]; if (addon != NULL) { len = 256 + strlen(addon); } else { len = 256; } b = (char *) malloc(len); if (b == NULL) { fnc_log(FNC_LOG_ERR,"send_reply(): memory allocation error.\n"); return ERR_ALLOC; } memset(b, 0, sizeof(b)); sprintf(b, "%s %d %s"RTSP_EL"CSeq: %d"RTSP_EL, RTSP_VER, err, get_stat(err), rtsp->rtsp_cseq); //---patch coerenza con rfc in caso di errore // strcat(b, "\r\n"); strcat(b, RTSP_EL); res = bwrite(b, (unsigned short) strlen(b), rtsp); free(b); sscanf(rtsp->in_buffer, " %31s %255s %31s ", method, object, ver); fnc_log(FNC_LOG_ERR,"%s %s %s %d - - ", method, object, ver, err); if ((p=strstr(rtsp->in_buffer, HDR_USER_AGENT))!=NULL) { char cut[strlen(p)]; strcpy(cut,p); cut[strlen(cut)-1]='\0'; fnc_log(FNC_LOG_CLIENT,"%s",cut); } return res; }
static __inline__ void rtp_session_destroy_ssrc(RTP_Session *rtp_s) { if (rtp_s->ssrc != &rtp_s->rtp_ssrc_init) { fnc_log(FNC_LOG_ERR, "[FC] rtp ssrc sanity check failed!"); BUG(); } return; }
int send_options_reply(RTSP_buffer * rtsp, long cseq) { char r[1024]; sprintf(r, "%s %d %s"RTSP_EL"CSeq: %ld"RTSP_EL, RTSP_VER, 200, get_stat(200), cseq); strcat(r, "Public: OPTIONS,DESCRIBE,SETUP,PLAY,PAUSE,TEARDOWN"RTSP_EL); strcat(r, RTSP_EL); bwrite(r, (unsigned short) strlen(r), rtsp); fnc_log(FNC_LOG_CLIENT,"200 - - "); return ERR_NOERROR; }
static void rtp_packet_send(RTP_session *session, MParserBuffer *buffer, time_t time_now) { gsize packet_size = sizeof(RTP_packet) + buffer->data_size; RTP_packet *packet = g_malloc0(packet_size); Track *tr = session->track; guint32 timestamp = RTP_calc_rtptime(session, tr->properties.clock_rate, buffer); packet->version = 2; packet->padding = 0; packet->extension = 0; packet->csrc_len = 0; packet->marker = buffer->marker & 0x1; packet->payload = tr->properties.payload_type & 0x7f; packet->seq_no = htons(++session->seq_no); packet->timestamp = htonl(timestamp); packet->ssrc = htonl(session->ssrc); fnc_log(FNC_LOG_VERBOSE, "[RTP] Timestamp: %u", ntohl(timestamp)); memcpy(packet->data, buffer->data, buffer->data_size); if (__rtp_pkt_send(session, &session->transport, packet, packet_size) < 0) { fnc_log(FNC_LOG_DEBUG, "RTP Packet Lost\n"); } else { session->last_timestamp = buffer->timestamp; session->pkt_count++; session->octet_count += buffer->data_size; session->last_packet_send_time = time_now;//time(NULL); } g_free(packet); }
static void command_environment(int argc, char **argv) { #ifndef CLEANUP_DESTRUCTOR gchar *progname; #endif gchar *config_file = NULL; gboolean quiet = FALSE, verbose = FALSE, lint = FALSE; GOptionEntry optionsTable[] = { { "config", 'f', 0, G_OPTION_ARG_STRING, &config_file, "specify configuration file", NULL }, { "quiet", 'q', 0, G_OPTION_ARG_NONE, &quiet, "show as little output as possible", NULL }, { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "output to standard error (debug)", NULL }, { "version", 'V', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, show_version, "print version information and exit", NULL }, { "lint", 'l', 0, G_OPTION_ARG_NONE, &lint, "check the configuration file for errors, then exit", NULL }, { NULL, 0, 0, 0, NULL, NULL, NULL } }; GError *error = NULL; GOptionContext *context = g_option_context_new(""); g_option_context_add_main_entries(context, optionsTable, PACKAGE_TARNAME); g_option_context_parse(context, &argc, &argv, &error); g_option_context_free(context); if ( error != NULL ) { fnc_log(FNC_LOG_FATAL, "%s", error->message); exit(1); } if (!quiet && !lint) fncheader(); config_file_parse(config_file, lint); g_free(config_file); /* if we're doing a verbose run, make sure to output everything directly on standard error. */ if ( verbose ) { feng_srv.log_level = FNC_LOG_INFO; feng_srv.error_log = "stderr"; } progname = g_path_get_basename(argv[0]); fnc_log_init(progname); }