Example #1
0
static switch_status_t handle_node_api_event_stream(ei_event_stream_t *event_stream, switch_stream_handle_t *stream) {
	ei_event_binding_t *binding;
	int column = 0;
	
	switch_mutex_lock(event_stream->socket_mutex);
	if (event_stream->connected == SWITCH_FALSE) {
		switch_sockaddr_t *sa;
		uint16_t port;
		char ipbuf[25] = {0};
		const char *ip_addr;
		
		switch_socket_addr_get(&sa, SWITCH_TRUE, event_stream->acceptor);
		port = switch_sockaddr_get_port(sa);
		ip_addr = switch_get_addr(ipbuf, sizeof (ipbuf), sa);
		
		if (zstr(ip_addr)) {
			ip_addr = globals.ip;
		}
		
		stream->write_function(stream, "%s:%d -> disconnected\n"
							   ,ip_addr, port);
	} else {
		stream->write_function(stream, "%s:%d -> %s:%d\n"
							   ,event_stream->local_ip, event_stream->local_port
							   ,event_stream->remote_ip, event_stream->remote_port);
	}
	
	binding = event_stream->bindings;
	while(binding != NULL) {
		if (binding->type == SWITCH_EVENT_CUSTOM) {
			stream->write_function(stream, "CUSTOM %-43s", binding->subclass_name);
		} else {
			stream->write_function(stream, "%-50s", switch_event_name(binding->type));
		}
		
		if (++column > 2) {
			stream->write_function(stream, "\n");
			column = 0;
		}
		
		binding = binding->next;
	}
	switch_mutex_unlock(event_stream->socket_mutex);
	
	if (!column) {
		stream->write_function(stream, "\n");
	} else {
		stream->write_function(stream, "\n\n");
	}
	
	return SWITCH_STATUS_SUCCESS;
}
Example #2
0
static switch_status_t api_erlang_status(switch_stream_handle_t *stream) {
	switch_sockaddr_t *sa;
	uint16_t port;
	char ipbuf[25];
	const char *ip_addr;
	ei_node_t *ei_node;
	
	switch_socket_addr_get(&sa, SWITCH_FALSE, globals.acceptor);
	
	port = switch_sockaddr_get_port(sa);
	ip_addr = switch_get_addr(ipbuf, sizeof (ipbuf), sa);
	
	stream->write_function(stream, "Running %s\n", VERSION);
	stream->write_function(stream, "Listening for new Erlang connections on %s:%u with cookie %s\n", ip_addr, port, globals.ei_cookie);
	stream->write_function(stream, "Registered as Erlang node %s, visible as %s\n", globals.ei_cnode.thisnodename, globals.ei_cnode.thisalivename);
	
	if (globals.ei_compat_rel) {
		stream->write_function(stream, "Using Erlang compatibility mode: %d\n", globals.ei_compat_rel);
	}

	switch_thread_rwlock_rdlock(globals.ei_nodes_lock);
	ei_node = globals.ei_nodes;
	if (!ei_node) {
		stream->write_function(stream, "No erlang nodes connected\n");
	} else {
		stream->write_function(stream, "Connected to:\n");
		while(ei_node != NULL) {
			unsigned int year, day, hour, min, sec, delta;
			
			delta = (switch_micro_time_now() - ei_node->created_time) / 1000000;
			sec = delta % 60;
			min = delta / 60 % 60;
			hour = delta / 3600 % 24;
			day = delta / 86400 % 7;
			year = delta / 31556926 % 12;
			stream->write_function(stream, "  %s (%s:%d) up %d years, %d days, %d hours, %d minutes, %d seconds\n"
								   ,ei_node->peer_nodename, ei_node->remote_ip, ei_node->remote_port, year, day, hour, min, sec);
			ei_node = ei_node->next;
		}
	}
	switch_thread_rwlock_unlock(globals.ei_nodes_lock);
	
	return SWITCH_STATUS_SUCCESS;
}
Example #3
0
static switch_status_t create_acceptor() {
	switch_sockaddr_t *sa;
	uint16_t port;
    char ipbuf[25];
    const char *ip_addr;
	
	/* if the config has specified an erlang release compatibility then pass that along to the erlang interface */
	if (globals.ei_compat_rel) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Compatability with OTP R%d requested\n", globals.ei_compat_rel);
		ei_set_compat_rel(globals.ei_compat_rel);
	}
	
	if (!(globals.acceptor = create_socket_with_port(globals.pool, globals.port))) {
		return SWITCH_STATUS_SOCKERR;
	}
	
	switch_socket_addr_get(&sa, SWITCH_FALSE, globals.acceptor);
	
	port = switch_sockaddr_get_port(sa);
	ip_addr = switch_get_addr(ipbuf, sizeof (ipbuf), sa);
	
	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Erlang connection acceptor listening on %s:%u\n", ip_addr, port);
	
	/* try to initialize the erlang interface */
	if (create_ei_cnode(ip_addr, globals.ei_nodename, &globals.ei_cnode) != SWITCH_STATUS_SUCCESS) {
		return SWITCH_STATUS_SOCKERR;
	}
	
	/* tell the erlang port manager where we can be reached.  this returns a file descriptor pointing to epmd or -1 */
	if ((globals.epmdfd = ei_publish(&globals.ei_cnode, port)) == -1) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
						  "Failed to publish port to epmd. Try starting it yourself or run an erl shell with the -sname or -name option.\n");
		return SWITCH_STATUS_SOCKERR;
	}
	
	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connected to epmd and published erlang cnode name %s at port %d\n", globals.ei_cnode.thisnodename, port);
	
	return SWITCH_STATUS_SUCCESS;
}
Example #4
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;
}