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; }
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; }
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; }
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; }