static void interleaved_setup_callbacks(RTSP_Client *rtsp, RTSP_interleaved *intlvd) { void (*cb)(EV_P_ struct ev_io *w, int revents); ev_io *io; switch (Sock_type(rtsp->sock)) { case TCP: cb = interleaved_read_tcp_cb; break; default: // Shouldn't be possible return; } intlvd->rtp.local->data = rtsp; io = &intlvd->rtp.ev_io_listen; io->data = &intlvd->rtp; ev_io_init(io, cb, Sock_fd(intlvd->rtp.local), EV_READ); ev_io_start(rtsp->srv->loop, io); intlvd->rtcp.local->data = rtsp; io = &intlvd->rtcp.ev_io_listen; io->data = &intlvd->rtcp; ev_io_init(io, cb, Sock_fd(intlvd->rtcp.local), EV_READ); ev_io_start(rtsp->srv->loop, io); }
void rtp_over_tcp_prepare(RTP_transport *transport) { transport->passby = (GEvent*)rtp_watch_new(Sock_fd(transport->rtp_sock), 0); g_event_set_callback((GEvent*)transport->passby, rtp_over_tcp_rw_cb, transport, rtp_watch_finalize); g_scheduler_add((GEvent*)transport->passby, LOOP_WEIGHT_VIDEO); }
/** * @brief Create a new RTP session object. * * @param rtsp The buffer for which to generate the session * @param rtsp_s The RTSP session * @param uri The URI for the current RTP session * @param transport The transport used by the session * @param tr The track that will be sent over the session * * @return A pointer to a newly-allocated RTP_session, that needs to * be freed with @ref rtp_session_free. * * @see rtp_session_free */ RTP_session *rtp_session_new(RTSP_Client *rtsp, RTSP_session *rtsp_s, RTP_transport *transport, const char *uri, Track *tr) { feng *srv = rtsp->srv; RTP_session *rtp_s = g_slice_new0(RTP_session); ev_io *io = &rtp_s->transport.rtcp_reader; ev_periodic *periodic = &rtp_s->transport.rtp_writer; /* Make sure we start paused since we have to wait for parameters * given by @ref rtp_session_resume. */ rtp_s->uri = g_strdup(uri); memcpy(&rtp_s->transport, transport, sizeof(RTP_transport)); rtp_s->start_rtptime = g_random_int(); rtp_s->start_seq = g_random_int_range(0, G_MAXUINT16); rtp_s->seq_no = rtp_s->start_seq - 1; /* Set up the track selector and get a consumer for the track */ rtp_s->track = tr; rtp_s->consumer = bq_consumer_new(tr->producer); rtp_s->srv = srv; rtp_s->ssrc = g_random_int(); rtp_s->client = rtsp; #ifdef HAVE_METADATA rtp_s->metadata = rtsp_s->resource->metadata; #endif periodic->data = rtp_s; ev_periodic_init(periodic, rtp_write_cb, 0, 0, NULL); io->data = rtp_s; ev_io_init(io, rtcp_read_cb, Sock_fd(rtp_s->transport.rtcp_sock), EV_READ); // Setup the RTP session rtsp_s->rtp_sessions = g_slist_append(rtsp_s->rtp_sessions, rtp_s); return rtp_s; }
/** * @brief Handle an incoming RTSP connection * * @param loop The event loop where the incoming connection was triggered * @param w The watcher that triggered the incoming connection * @param revents Unused * * This function takes care of all the handling of an incoming RTSP * client connection: * * @li accept the new socket; * * @li checks that there is space for new connections for the current * fork; * * @li creates and sets up the @ref RTSP_Client object. * * The newly created instance is deleted by @ref * client_ev_disconnect_handler. * * @internal This function should be used as callback for an ev_io * listener. */ void rtsp_client_incoming_cb(struct ev_loop *loop, ev_io *w, int revents) { Sock *sock = w->data; feng *srv = sock->data; Sock *client_sock = NULL; ev_io *io; ev_async *async; ev_timer *timer; RTSP_Client *rtsp; client_port_pair *clients=NULL; pid_t pid; if ( (client_sock = Sock_accept(sock, NULL)) == NULL ) return; if (srv->connection_count >= ONE_FORK_MAX_CONNECTION) { Sock_close(client_sock); return; } if(!( clients = new_child_port(srv, get_remote_host(client_sock), get_remote_port(client_sock)))){ Sock_close(client_sock); return; } pid = fork(); if(pid==0){ /*clean the context of parent*/ clients->pid = getpid(); current_client = clients; //free_child_port(clients); feng_ports_cleanup(srv); feng_stop_child_watcher(srv); demuxer_stsw_global_init(); //void fnc_log_change_child(); if(srv->srvconf.log_type == FNC_LOG_FILE){ //child process can't write to parent log file fnc_log_uninit(); } rtsp = g_slice_new0(RTSP_Client); rtsp->sock = client_sock; rtsp->input = g_byte_array_new(); rtsp->out_queue = g_queue_new(); rtsp->srv = srv; rtsp->cached_resource = NULL; srv->connection_count++; client_sock->data = srv; /*install read handler*/ io = &rtsp->ev_io_read; io->data = rtsp; ev_io_init(io, rtsp_read_cb, Sock_fd(client_sock), EV_READ); ev_io_start(srv->loop, io); /* configure the write handler*/ /* to be started/stopped when necessary */ io = &rtsp->ev_io_write; io->data = rtsp; ev_io_init(io, rtsp_write_cb, Sock_fd(client_sock), EV_WRITE); fnc_log(FNC_LOG_INFO, "Incoming RTSP connection accepted on socket: %d\n", Sock_fd(client_sock)); /* install async event handler for destroy */ async = &rtsp->ev_sig_disconnect; async->data = rtsp; ev_async_init(async, client_ev_disconnect_handler); ev_async_start(srv->loop, async); /* configure a check timer, * After play, this timer would be started */ timer = &rtsp->ev_timeout; timer->data = rtsp; ev_init(timer, client_ev_timeout); timer->repeat = STREAM_TIMEOUT; }else if(pid > 0){ Sock_close(client_sock); srv->connection_count++; clients->pid = pid; fnc_log(FNC_LOG_INFO, "The child process (pid:%d) for rtsp connection (%s:%hu) is created\n", pid, clients->host, clients->port); fnc_log(FNC_LOG_INFO, "Connection reached: %d\n", srv->connection_count); add_client_list(clients); return; }else{ Sock_close(client_sock); free_child_port(clients); fnc_log(FNC_LOG_ERR, "fork faild\n"); return; } }