Ejemplo n.º 1
0
void
rtp_transport_close(RTP_transport *transport)
{
	port_pair pair;

	switch (transport->trans_mode)
	{
	case RTP_OVER_TCP:
		g_event_remove((GEvent*)transport->passby);
		g_event_unref((GEvent*)transport->passby);
		/* fall through */
	case RTP_OVER_UDP:
	    pair.RTP = get_local_port(transport->rtp_sock);
	    pair.RTCP = get_local_port(transport->rtcp_sock);		
		put_port_pair(NULL, &pair);
		Sock_close(transport->rtp_sock);
		Sock_close(transport->rtcp_sock);
		break;

	case RTP_OVER_RTSP:
		g_event_unref((GEvent*)transport->passby);
		break;

	default:
		break;
	}
}
Ejemplo n.º 2
0
/**
 * @brief Free a RTSP_interleaved instance
 *
 * @param element Instance to destroy and free
 * @param user_data The loop to stop libev I/O
 *
 * @internal This function should only be called through
 *           g_slist_foreach() by @ref interleaved_free_list.
 *
 * @see interleaved_setup_transport
 */
static void interleaved_free(gpointer element, gpointer user_data)
{
    struct ev_loop *loop = (struct ev_loop *)user_data;
    RTSP_interleaved *intlvd = (RTSP_interleaved *)element;

    Sock_close(intlvd->rtp.local);
    ev_io_stop(loop, &intlvd->rtp.ev_io_listen);

    Sock_close(intlvd->rtcp.local);
    ev_io_stop(loop, &intlvd->rtcp.ev_io_listen);

    g_slice_free(RTSP_interleaved, element);
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
/**
 * Closes a transport linked to a session
 * @param session the RTP session for which to close the transport
 */
static void rtp_transport_close(RTP_session * session)
{
    port_pair pair;
    pair.RTP = get_local_port(session->transport.rtp_sock);
    pair.RTCP = get_local_port(session->transport.rtcp_sock);

    ev_periodic_stop(session->srv->loop, &session->transport.rtp_writer);
    ev_io_stop(session->srv->loop, &session->transport.rtcp_reader);

    switch (session->transport.rtp_sock->socktype) {
    case UDP:
        RTP_release_port_pair(session->srv, &pair);
    default:
        break;
    }
    Sock_close(session->transport.rtp_sock);
    Sock_close(session->transport.rtcp_sock);
}
Ejemplo n.º 5
0
static int close_sock(int fd)
{
    perr.error = 0;
    int res = Sock_close(fd, &perr);
    if (res == -1) {
	REprintf("socket error: %s\n", strerror(perr.error));
	return -1;
    }
    return 0;
}
Ejemplo n.º 6
0
/**
 * @brief Handle client disconnection and free resources
 *
 * @param loop The event loop where the event was issued
 * @param w The async event object
 * @param revents Unused
 *
 * This event is triggered when a client disconnects or is forcefully
 * disconnected. It stops the other events from running, and frees all
 * the remaining resources for the client itself.
 */
static void client_ev_disconnect_handler(struct ev_loop *loop,
                                         ev_async *w,
                                         int revents)
{
    RTSP_Client *rtsp = (RTSP_Client*)w->data;
    GString *outbuf = NULL;
    feng *srv = rtsp->srv;

    ev_io_stop(srv->loop, &rtsp->ev_io_read);
    ev_io_stop(srv->loop, &rtsp->ev_io_write);
    ev_async_stop(srv->loop, &rtsp->ev_sig_disconnect);
    ev_timer_stop(srv->loop, &rtsp->ev_timeout);

    Sock_close(rtsp->sock);
    srv->connection_count--;

    rtsp_session_free(rtsp->session);
    
    r_close(rtsp->cached_resource);

    interleaved_free_list(rtsp);

    /* Remove the output queue */
    while( (outbuf = g_queue_pop_tail(rtsp->out_queue)) )
        g_string_free(outbuf, TRUE);

    g_queue_free(rtsp->out_queue);

    g_byte_array_free(rtsp->input, true);

    g_slice_free(RTSP_Client, rtsp);

    fnc_log(FNC_LOG_INFO, "[client] Client removed");

    demuxer_stsw_global_uninit();
    
	sleep(1);
	exit(0);

}
Ejemplo n.º 7
0
Sock * Sock_connect(char *host, char *port, Sock *binded, sock_type socktype, sock_flags ssl_flag)
{
    Sock *s;
    char remote_host[128]; /*Unix Domain is largest*/
    char local_host[128]; /*Unix Domain is largest*/
    int sockfd = -1;
    struct sockaddr *sa_p = NULL;
    socklen_t sa_len = 0;
    int32_t local_port;
    int32_t remote_port;
#if HAVE_SSL
    SSL *ssl_con;
#endif

    if(binded) {
        sockfd = binded->fd;
    }

    if (sock_connect(host, port, &sockfd, socktype)) {
            net_log(NET_LOG_ERR, "Sock_connect() failure.\n");
            return NULL;
    }

#if HAVE_SSL
    if(ssl_flag & IS_SSL) {
        if (sock_SSL_connect(&ssl_con))
            net_log (NET_LOG_ERR, "Sock_connect() failure in SSL init.\n");
            sock_close(sockfd);
            return NULL;
    }
    else
#endif


    if (binded) {
        s = binded;
        free(s->local_host);
        s->local_host = NULL;
        free(s->remote_host);
        s->remote_host = NULL;
    } else if (!(s = calloc(1, sizeof(Sock)))) {
        net_log(NET_LOG_FATAL, "Unable to allocate a Sock struct in Sock_connect().\n");
#if HAVE_SSL
        if(ssl_flag & IS_SSL) 
            sock_SSL_close(ssl_con);
#endif
        sock_close (sockfd);
        return NULL;
    }

    s->fd = sockfd;
    s->socktype = socktype;
#if HAVE_SSL
    if(ssl_flag & IS_SSL) 
        s->ssl = ssl_con;
#endif
    s->flags = ssl_flag;

    sa_p = (struct sockaddr *) &(s->local_stg);
    sa_len = sizeof(struct sockaddr_storage);

    if(getsockname(s->fd, sa_p, &sa_len))
    {
        net_log(NET_LOG_ERR, "Unable to get remote port in Sock_connect().\n");
        Sock_close(s);
        return NULL;
    }

    if(!sock_ntop_host(sa_p, local_host, sizeof(local_host)))
        memset(local_host, 0, sizeof(local_host));

    if (!(s->local_host = strdup(local_host))) {
        net_log(NET_LOG_FATAL, "Unable to allocate local host in Sock_connect().\n");
        Sock_close(s);
        return NULL;
    }

    local_port = sock_get_port(sa_p);

    if(local_port < 0) {
        net_log(NET_LOG_ERR, "Unable to get local port in Sock_connect().\n");
        Sock_close(s);
        return NULL;
    } else
        s->local_port = ntohs(local_port);

    sa_p = (struct sockaddr *) &(s->remote_stg);
    sa_len = sizeof(struct sockaddr_storage);

    if(getpeername(s->fd, sa_p, &sa_len))
    {
        net_log(NET_LOG_ERR, "Unable to get remote address in Sock_connect().\n");
        Sock_close(s);
        return NULL;
    }

    if(!sock_ntop_host(sa_p, remote_host, sizeof(remote_host)))
        memset(remote_host, 0, sizeof(remote_host));
    
    if (!(s->remote_host = strdup(remote_host))) {
        net_log(NET_LOG_FATAL, "Unable to allocate remote host in Sock_connect().\n");
        Sock_close(s);
        return NULL;
    }

    remote_port = sock_get_port(sa_p);
    if(remote_port < 0) {
        net_log(NET_LOG_ERR, "Unable to get remote port in Sock_connect().\n");
        Sock_close(s);
        return NULL;
    } else
        s->remote_port = ntohs(remote_port);

    net_log(NET_LOG_DEBUG, "Socket connected between local=\"%s\":%u and "
        "remote=\"%s\":%u.\n", s->local_host, s->local_port, s->remote_host,
        s->remote_port);

    if(is_multicast_address(sa_p, s->remote_stg.ss_family)) {
        //fprintf(stderr,"IS MULTICAST\n");
        if(mcast_join(s->fd, sa_p, NULL, 0, &(s->addr))!=0) {
            Sock_close(s);
            return NULL;
        }
        s->flags |= IS_MULTICAST;
    }

    return s;
}
Ejemplo n.º 8
0
/**
 * @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;
    }

}
Ejemplo n.º 9
0
/**
 * Create a new socket accepting a new connection from a listening socket.
 * @param main Listening socket.
 * @param octx optional ssl global context
 * @return the newly allocated Sock
 */
Sock * Sock_accept(Sock *s, void * octx)
{
    int res = -1;
    char remote_host[128]; /*Unix Domain is largest*/
    char local_host[128]; /*Unix Domain is largest*/
    int remote_port = -1;
    int local_port = -1;
    Sock *new_s = NULL;
    struct sockaddr *sa_p = NULL;
    socklen_t sa_len = 0;

#if ENABLE_SSL
    SSL_CTX * ctx = octx;
    SSL *ssl_con = NULL;
#endif

    if (!s)
        return NULL;

    if ((res = sock_accept(s->fd)) < 0) {
        net_log(NET_LOG_ERR, "System error in sock_accept().\n");
        return NULL;
    }

#if ENABLE_SSL
    if(ctx) {
        if( !(ssl_con = SSL_sock_accept(res, ctx)) ) {
            net_log(NET_LOG_ERR, "Unable to accept SSL connection.\n");
            sock_close(res);
            return NULL;
        }
    }
#endif

    if (!(new_s = calloc(1, sizeof(Sock)))) {
        net_log(NET_LOG_FATAL,
                "Unable to allocate a Sock struct in Sock_accept().\n");
#if ENABLE_SSL
        if(ctx)
            SSL_close_connection(ssl_con, res);
#endif
        sock_close(res);
        return NULL;
    }

    new_s->fd = res;
    new_s->socktype = s->socktype;
    new_s->flags = s->flags;

#if ENABLE_SSL
    if(ctx)
        new_s->ssl = ssl_con;
#endif

    sa_p = (struct sockaddr *) &(new_s->remote_stg);
    sa_len = sizeof(struct sockaddr_storage);

    if(getpeername(res, sa_p, &sa_len))
    {
        net_log(NET_LOG_ERR,
                "Unable to get remote address in Sock_accept().\n");
        Sock_close(new_s);
        return NULL;
    }

    if(!sock_ntop_host(sa_p, remote_host, sizeof(remote_host)))
        memset(remote_host, 0, sizeof(remote_host));

    if (!(new_s->remote_host = strdup(remote_host))) {
        net_log(NET_LOG_FATAL,
                "Unable to allocate remote host in Sock_accept().\n");
        Sock_close(new_s);
        return NULL;
    }

    remote_port = sock_get_port(sa_p);
    if(remote_port < 0) {
        net_log(NET_LOG_ERR, "Unable to get remote port in Sock_accept().\n");
        Sock_close(new_s);
        return NULL;
    }
    else
        new_s->remote_port = ntohs(remote_port);

    sa_p = (struct sockaddr *) &(new_s->remote_stg);
    sa_len = sizeof(struct sockaddr_storage);

    if(getsockname(res, sa_p, &sa_len))
    {
        net_log(NET_LOG_ERR, "Unable to get remote port in Sock_accept().\n");
        Sock_close(new_s);
        return NULL;
    }

    if(!sock_ntop_host(sa_p, local_host, sizeof(local_host)))
        memset(local_host, 0, sizeof(local_host));

    if (!(new_s->local_host = strdup(local_host))) {
        net_log(NET_LOG_FATAL,
                "Unable to allocate local host in Sock_accept().\n");
        Sock_close(new_s);
        return NULL;
    }

    local_port = sock_get_port(sa_p);
    if(local_port < 0) {
        net_log(NET_LOG_ERR, "Unable to get local port in Sock_accept().\n");
        Sock_close(new_s);
        return NULL;
    }
    else
        new_s->local_port = ntohs(local_port);

    net_log(NET_LOG_DEBUG, "Socket accepted between local=\"%s\":%u and "
        "remote=\"%s\":%u.\n", new_s->local_host, new_s->local_port,
        new_s->remote_host, new_s->remote_port);

    return new_s;
}
Ejemplo n.º 10
0
Sock * Sock_bind(char const *host, char const *port, Sock *sock,
                 sock_type socktype, void * octx)
{

    Sock *s = NULL;
    int sockfd = -1;
    struct sockaddr *sa_p;
    socklen_t sa_len;
    char local_host[128];
    int local_port;

#if ENABLE_SSL
    if ((octx)) {
        if(socktype != TCP) {
            net_log(NET_LOG_ERR, "SSL can't work on this protocol.\n");
            return NULL;
        }
    }
#endif

    if(sock) {
        sockfd = sock->fd;
    }

    if (sock_bind(host, port, &sockfd, socktype)) {
        net_log(NET_LOG_ERR, "Error in low level sock_bind().\n");
        return NULL;
    }

    if (!(s = calloc(1, sizeof(Sock)))) {
        net_log(NET_LOG_FATAL,
                "Unable to allocate a Sock struct in Sock_bind().\n");
        sock_close(sockfd);
        return NULL;
    }

    s->fd = sockfd;
    s->socktype = socktype;
    s->flags = 0;

    sa_p = (struct sockaddr *)&(s->local_stg);
    sa_len = sizeof(struct sockaddr_storage);

    if(getsockname(s->fd, sa_p, &sa_len) < 0) {
        Sock_close(s);
        return NULL;
    }

    if(!sock_ntop_host(sa_p, local_host, sizeof(local_host)))
        memset(local_host, 0, sizeof(local_host));

    if (!(s->local_host = strdup(local_host))) {
        net_log(NET_LOG_FATAL,
                "Unable to allocate local host in Sock_bind().\n");
        Sock_close(s);
        return NULL;
    }

    local_port = sock_get_port(sa_p);

    if(local_port < 0) {
        net_log(NET_LOG_ERR, "Unable to get local port in Sock_bind().\n");
        Sock_close(s);
        return NULL;
    } else
        s->local_port = ntohs(local_port);

    net_log(NET_LOG_DEBUG,
            "Socket bound with addr=\"%s\" and port=\"%u\".\n",
            s->local_host, s->local_port);

    if(is_multicast_address(sa_p, s->local_stg.ss_family)) {
        if(mcast_join(s->fd, sa_p)) {
            Sock_close(s);
            return NULL;
        }
        s->flags |= IS_MULTICAST;
    }

    return s;
}