Example #1
0
int32_t rtmp_server_handshake_done(rtmp_session_t *session)
{
    rtmp_log(RTMP_LOG_INFO,"[%d]handshake done!",session->sid);
    session->in_chain = rtmp_core_alloc_chain(session,session->c->pool,
        session->in_chunk_size);

    if (session->in_chain == NULL) {
        rtmp_session_destroy(session);
        return RTMP_FAILED;
    }

    return rtmp_core_cycle(session);
}
Example #2
0
void *SWITCH_THREAD_FUNC rtmp_io_tcp_thread(switch_thread_t *thread, void *obj)
{
	rtmp_io_tcp_t *io = (rtmp_io_tcp_t*)obj;
	io->base.running = 1;
	
	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s: I/O Thread starting\n", io->base.profile->name);
	
	
	while(io->base.running) {
		const switch_pollfd_t *fds;
		int32_t numfds;
		int32_t i;
		switch_status_t status;
		
		switch_mutex_lock(io->mutex);
		status = switch_pollset_poll(io->pollset, 500000, &numfds, &fds);
		switch_mutex_unlock(io->mutex);
		
		if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_TIMEOUT) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "pollset_poll failed\n");
			continue;
		} else if (status == SWITCH_STATUS_TIMEOUT) {
			switch_cond_next();
		}
		
		for (i = 0; i < numfds; i++) {
			if (!fds[i].client_data) { 
				switch_socket_t *newsocket;
				if (switch_socket_accept(&newsocket, io->listen_socket, io->base.pool) != SWITCH_STATUS_SUCCESS) {
					if (io->base.running) {
						/* Don't spam the logs if we are shutting down */
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Error [%s]\n", strerror(errno));	
					} else {
						return NULL;
					}
				} else {
					rtmp_session_t *rsession;
					
					if (switch_socket_opt_set(newsocket, SWITCH_SO_NONBLOCK, TRUE)) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't set socket as non-blocking\n");
					}

					if (switch_socket_opt_set(newsocket, SWITCH_SO_TCP_NODELAY, 1)) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't disable Nagle.\n");
					}
					
					if (rtmp_session_request(io->base.profile, &rsession) != SWITCH_STATUS_SUCCESS) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "RTMP session request failed\n");
						switch_socket_close(newsocket);
					} else {
						switch_sockaddr_t *addr = NULL;
						char ipbuf[200];
						
						/* Create out private data and attach it to the rtmp session structure */
						rtmp_tcp_io_private_t *pvt = switch_core_alloc(rsession->pool, sizeof(*pvt));
						rsession->io_private = pvt;
						pvt->socket = newsocket;
						switch_socket_create_pollfd(&pvt->pollfd, newsocket, SWITCH_POLLIN | SWITCH_POLLERR, rsession, rsession->pool);
						switch_pollset_add(io->pollset, pvt->pollfd);
						switch_buffer_create_dynamic(&pvt->sendq, 512, 1024, 0);
						
						/* Get the remote address/port info */
						switch_socket_addr_get(&addr, SWITCH_TRUE, newsocket);
						switch_get_addr(ipbuf, sizeof(ipbuf), addr);
						rsession->remote_address = switch_core_strdup(rsession->pool, ipbuf);
						rsession->remote_port = switch_sockaddr_get_port(addr);
						switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_INFO, "Rtmp connection from %s:%i\n",
										  rsession->remote_address, rsession->remote_port);
					}
				}
			} else {
				rtmp_session_t *rsession = (rtmp_session_t*)fds[i].client_data;
				rtmp_tcp_io_private_t *io_pvt = (rtmp_tcp_io_private_t*)rsession->io_private;
				
				if (fds[i].rtnevents & SWITCH_POLLOUT && switch_buffer_inuse(io_pvt->sendq) > 0) {
					/* Send as much remaining data as possible */
					switch_size_t sendlen;
					const void *ptr;
					sendlen = switch_buffer_peek_zerocopy(io_pvt->sendq, &ptr);
					switch_socket_send_nonblock(io_pvt->socket, ptr, &sendlen);
					switch_buffer_toss(io_pvt->sendq, sendlen);
					if (switch_buffer_inuse(io_pvt->sendq) == 0) {
						/* Remove our fd from OUT polling */
						rtmp_tcp_alter_pollfd(rsession, SWITCH_FALSE);
					}
				} else 	if (fds[i].rtnevents & SWITCH_POLLIN && rtmp_handle_data(rsession) != SWITCH_STATUS_SUCCESS) {
					switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_DEBUG, "Closing socket\n");
					
					switch_mutex_lock(io->mutex);
					switch_pollset_remove(io->pollset, io_pvt->pollfd);
					switch_mutex_unlock(io->mutex);
					
					switch_socket_close(io_pvt->socket);
					io_pvt->socket = NULL;
					
					rtmp_session_destroy(&rsession);
				}
			}
		}
	}
	
	io->base.running = -1;
	switch_socket_close(io->listen_socket);
	
	return NULL;
}
Example #3
0
void rtmp_chain_send(rtmp_event_t *ev)
{
    rtmp_connection_t   *conn;
    rtmp_session_t      *session;
    mem_buf_t           *sbuf,wbuf;
    int32_t              rc;
    uint32_t             out_rear,out_front;
    mem_buf_chain_t     *chain;
    rtmp_message_t      *msg;

    conn = ev->data;
    session = conn->data;

    if (ev->timeout) {
        rtmp_log(RTMP_LOG_WARNING,"[%d]send timeout!",conn->fd);
        rtmp_session_destroy(session);
        return;
    }

    if (ev->timer_set) {
        rtmp_event_del_timer(ev);
    }

    if (ev->active) {
        rtmp_event_delete(ev,EVENT_WRITE);
    }

    while (1) {
        out_rear = session->out_rear;
        out_front = session->out_front;

        if (session->out_chunk == NULL) {
            if (out_rear == out_front) {
                return ;
            }

            msg = & session->out_message[out_rear];
            rc = rtmp_send_buf(conn->fd,&msg->head,NULL);

            if (rc == SOCK_ERROR) {
                rtmp_log(RTMP_LOG_ERR,"[%d]send error:%p,%d",session->sid,rc);

                return;
            }

            if (rc == SOCK_EAGAIN) {
                rtmp_log(RTMP_LOG_DEBUG,"[%d]send again:%d",session->sid,rc);

                if (!ev->active) {
                    rtmp_event_add(ev,EVENT_WRITE);
                }
                rtmp_event_add_timer(ev,6000);

                return ;
            }

            session->out_chunk = msg->chain;
            if (session->out_chunk == NULL) {

                rtmp_log(RTMP_LOG_WARNING,"[%d]pick null message",
                    session->sid);

                session->out_rear = (out_rear + 1) % session->out_queue;

                continue;
            }

            session->out_last = session->out_chunk->chunk.last;
        }

        while (session->out_chunk) {
            sbuf = & session->out_chunk->chunk;

            if ((session->out_last < sbuf->last)
             || (session->out_last >= sbuf->end))
            {
                rtmp_log(RTMP_LOG_WARNING,"[%d]send error chunk",session->sid);
                session->out_last = sbuf->last;
            }

            wbuf.buf = sbuf->buf;
            wbuf.last = session->out_last;
            wbuf.end = sbuf->end;

            rtmp_log(RTMP_LOG_DEBUG,"[%d]send (%p,%d) bytes",session->sid,
                session->out_last,wbuf.end - wbuf.last);

            rc = rtmp_send_buf(conn->fd,&wbuf,NULL);

            if (rc == SOCK_ERROR) {
                rtmp_log(RTMP_LOG_ERR,"[%d]send error:%p,%d",session->sid,rc);

                return;
            }

            if (rc == SOCK_EAGAIN) {
                rtmp_log(RTMP_LOG_DEBUG,"[%d]send again:%d",session->sid,rc);

                session->out_last = wbuf.last;

                if (!ev->active) {
                    rtmp_event_add(ev,EVENT_WRITE);
                }
                rtmp_event_add_timer(ev,6000);

                return ;
            }

            session->ping_sent = 0;

            chain = session->out_chunk->next;
            session->out_chunk = chain;

            if (chain) {
                session->out_last = chain->chunk.last;
            }
        }

        chain = session->out_message[out_rear].chain;

        rtmp_log(RTMP_LOG_INFO,"[%d]send a message",session->sid);

        rtmp_core_free_chain(session,session->chunk_pool,chain);

        session->out_message[out_rear].chain = NULL;
        session->out_last = NULL;

        session->out_rear = (out_rear + 1) % session->out_queue;
    }

    return ;
}
Example #4
0
void rtmp_core_chunk_recv(rtmp_event_t *ev)
{
    rtmp_connection_t   *conn;
    rtmp_session_t      *session;
    int32_t              rc,hr,n;

    conn = ev->data;
    session = conn->data;

    if (ev->timer_set) {
        rtmp_event_del_timer(ev);
    }

    if (ev->timeout) {

        if (session->ping_sent == 1) {
            rtmp_log(RTMP_LOG_INFO,"[%d]recv timeout!",session->sid);
            rtmp_session_destroy(session);
            return;
        }

        session->ping_sent = 1;

        rtmp_send_ping_request(session);
        rtmp_event_add_timer(ev,session->ping_timeout);

        return;
    }

    for (;;) {
        rc = rtmp_recv_buf(conn->fd,&session->in_chain->chunk,&n);
        if (rc == SOCK_ERROR) {
            rtmp_log(RTMP_LOG_ERR,"[%d]recv error[%d]!",
                session->sid,sock_errno);
            rtmp_session_destroy(session);
            return ;
        }

        session->ping_sent = 0;

        hr = rtmp_core_update_inbytes(session,NULL,(uint32_t)n);
        if(hr != RTMP_OK) {
            rtmp_session_destroy(session);
            return ;
        }

        /*rtmp_core_handle_recv*/
        hr = rtmp_core_handle_recv(session);
        if (hr != RTMP_OK) {
            rtmp_session_destroy(session);
            return ;
        }

        if(rc == SOCK_EAGAIN) {
            if (!ev->active) {
                rtmp_event_add(conn->read,EVENT_READ);
            }
            rtmp_event_add_timer(ev,session->ping_timeout);
            break;
        }
    }
}