void close_socket(switch_socket_t ** sock) { if (*sock) { switch_socket_shutdown(*sock, SWITCH_SHUTDOWN_READWRITE); switch_socket_close(*sock); *sock = NULL; } }
switch_status_t init_nat_monitor(switch_memory_pool_t *pool) { char *addr = NULL; switch_port_t port = 0; if (nat_globals.nat_type == SWITCH_NAT_TYPE_UPNP) { addr = "239.255.255.250"; port = 1900; } else if (nat_globals.nat_type == SWITCH_NAT_TYPE_PMP) { addr = "224.0.0.1"; port = 5350; } if (switch_sockaddr_info_get(&nat_globals_perm.maddress, addr, SWITCH_UNSPEC, port, 0, pool) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find address\n"); return SWITCH_STATUS_TERM; } if (switch_socket_create(&nat_globals_perm.msocket, AF_INET, SOCK_DGRAM, 0, pool) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Error\n"); return SWITCH_STATUS_TERM; } if (switch_socket_opt_set(nat_globals_perm.msocket, SWITCH_SO_REUSEADDR, 1) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Option Error\n"); switch_socket_close(nat_globals_perm.msocket); return SWITCH_STATUS_TERM; } if (switch_mcast_join(nat_globals_perm.msocket, nat_globals_perm.maddress, NULL, NULL) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Multicast Error\n"); switch_socket_close(nat_globals_perm.msocket); return SWITCH_STATUS_TERM; } if (switch_socket_bind(nat_globals_perm.msocket, nat_globals_perm.maddress) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Bind Error\n"); switch_socket_close(nat_globals_perm.msocket); return SWITCH_STATUS_TERM; } switch_socket_opt_set(nat_globals_perm.msocket, SWITCH_SO_NONBLOCK, TRUE); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "NAT thread configured\n"); return SWITCH_STATUS_SUCCESS; }
/** * Thread that delivers logs to graylog2 server * @param thread this thread * @param obj unused * @return NULL */ static void *SWITCH_THREAD_FUNC deliver_graylog2_thread(switch_thread_t *thread, void *obj) { switch_socket_t *graylog2_sock = NULL; char *log; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "graylog2 delivery thread started\n"); switch_thread_rwlock_rdlock(globals.shutdown_rwlock); graylog2_sock = open_graylog2_socket(globals.server_host, globals.server_port, globals.pool); if (graylog2_sock) { while (!globals.shutdown) { if (switch_queue_pop(globals.log_queue, (void *)&log) == SWITCH_STATUS_SUCCESS) { if (!zstr(log)) { switch_size_t len = strlen(log); switch_size_t max_len = globals.send_uncompressed_header ? MAX_GELF_LOG_LEN - UNCOMPRESSED_MAGIC_LEN : MAX_GELF_LOG_LEN; if (len <= max_len) { if (globals.send_uncompressed_header) { char buf[MAX_GELF_LOG_LEN]; memcpy(buf, UNCOMPRESSED_MAGIC, UNCOMPRESSED_MAGIC_LEN); memcpy(buf + UNCOMPRESSED_MAGIC_LEN, log, len); len += UNCOMPRESSED_MAGIC_LEN; switch_socket_send_nonblock(graylog2_sock, (void *)buf, &len); } else { switch_socket_send_nonblock(graylog2_sock, (void *)log, &len); } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Skipping large log\n"); } } switch_safe_free(log); } } } globals.shutdown = 1; /* clean up remaining logs */ while(switch_queue_trypop(globals.log_queue, (void *)&log) == SWITCH_STATUS_SUCCESS) { switch_safe_free(log); } if (graylog2_sock) { switch_socket_close(graylog2_sock); } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "graylog2 delivery thread finished\n"); switch_thread_rwlock_unlock(globals.shutdown_rwlock); return NULL; }
static void socket_destroy(JSContext * cx, JSObject * obj) { js_socket_obj_t *socket = JS_GetPrivate(cx, obj); if (socket == NULL) return; if (socket->socket != 0) { socket->saveDepth = JS_SuspendRequest(cx); switch_socket_shutdown(socket->socket, SWITCH_SHUTDOWN_READWRITE); switch_socket_close(socket->socket); switch_core_destroy_memory_pool(&socket->pool); JS_ResumeRequest(cx, socket->saveDepth); } }
static JSBool socket_close(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval) { js_socket_obj_t *socket = JS_GetPrivate(cx, obj); if (socket == NULL) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to find js object.\n"); return JS_FALSE; } socket->saveDepth = JS_SuspendRequest(cx); switch_socket_shutdown(socket->socket, SWITCH_SHUTDOWN_READWRITE); switch_socket_close(socket->socket); socket->socket = NULL; JS_ResumeRequest(cx, socket->saveDepth); return JS_TRUE; }
static switch_status_t rtmp_tcp_close(rtmp_session_t *rsession) { rtmp_io_tcp_t *io = (rtmp_io_tcp_t*)rsession->profile->io; rtmp_tcp_io_private_t *io_pvt = rsession->io_private; if (io_pvt->socket) { 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; } return SWITCH_STATUS_SUCCESS; }
/** * Open connection to graylog2 server */ static switch_socket_t *open_graylog2_socket(const char *host, switch_port_t port, switch_memory_pool_t *pool) { switch_sockaddr_t *graylog2_addr = NULL; switch_socket_t *graylog2_sock = NULL; if (switch_sockaddr_info_get(&graylog2_addr, host, SWITCH_UNSPEC, port, 0, pool) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Bad address: %s:%d\n", host, port); return NULL; } if (switch_socket_create(&graylog2_sock, switch_sockaddr_get_family(graylog2_addr), SOCK_DGRAM, 0, pool) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to open UDP socket\n"); return NULL; } if (switch_socket_connect(graylog2_sock, graylog2_addr) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to connect to: %s:%d\n", host, port); switch_socket_close(graylog2_sock); return NULL; } return graylog2_sock; }
switch_status_t rtmp_tcp_init(rtmp_profile_t *profile, const char *bindaddr, rtmp_io_t **new_io, switch_memory_pool_t *pool) { char *szport; switch_sockaddr_t *sa; switch_threadattr_t *thd_attr = NULL; rtmp_io_tcp_t *io_tcp; io_tcp = (rtmp_io_tcp_t*)switch_core_alloc(pool, sizeof(rtmp_io_tcp_t)); io_tcp->base.pool = pool; io_tcp->ip = switch_core_strdup(pool, bindaddr); *new_io = (rtmp_io_t*)io_tcp; io_tcp->base.profile = profile; io_tcp->base.read = rtmp_tcp_read; io_tcp->base.write = rtmp_tcp_write; io_tcp->base.close = rtmp_tcp_close; io_tcp->base.name = "tcp"; io_tcp->base.address = switch_core_strdup(pool, io_tcp->ip); if ((szport = strchr(io_tcp->ip, ':'))) { *szport++ = '\0'; io_tcp->port = atoi(szport); } else { io_tcp->port = RTMP_DEFAULT_PORT; } if (switch_sockaddr_info_get(&sa, io_tcp->ip, SWITCH_INET, io_tcp->port, 0, pool)) { goto fail; } if (switch_socket_create(&io_tcp->listen_socket, switch_sockaddr_get_family(sa), SOCK_STREAM, SWITCH_PROTO_TCP, pool)) { goto fail; } if (switch_socket_opt_set(io_tcp->listen_socket, SWITCH_SO_REUSEADDR, 1)) { goto fail; } if (switch_socket_opt_set(io_tcp->listen_socket, SWITCH_SO_TCP_NODELAY, 1)) { goto fail; } if (switch_socket_bind(io_tcp->listen_socket, sa)) { goto fail; } if (switch_socket_listen(io_tcp->listen_socket, 10)) { goto fail; } if (switch_socket_opt_set(io_tcp->listen_socket, SWITCH_SO_NONBLOCK, TRUE)) { goto fail; } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Listening on %s:%u (tcp)\n", io_tcp->ip, io_tcp->port); io_tcp->base.running = 1; if (switch_pollset_create(&io_tcp->pollset, 1000 /* max poll fds */, pool, 0) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "pollset_create failed\n"); goto fail; } switch_socket_create_pollfd(&(io_tcp->listen_pollfd), io_tcp->listen_socket, SWITCH_POLLIN | SWITCH_POLLERR, NULL, pool); if (switch_pollset_add(io_tcp->pollset, io_tcp->listen_pollfd) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "pollset_add failed\n"); goto fail; } switch_mutex_init(&io_tcp->mutex, SWITCH_MUTEX_NESTED, pool); switch_threadattr_create(&thd_attr, pool); switch_threadattr_detach_set(thd_attr, 1); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); switch_thread_create(&io_tcp->thread, thd_attr, rtmp_io_tcp_thread, *new_io, pool); return SWITCH_STATUS_SUCCESS; fail: if (io_tcp->listen_socket) { switch_socket_close(io_tcp->listen_socket); } *new_io = NULL; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Socket error. Couldn't listen on %s:%u\n", io_tcp->ip, io_tcp->port); return SWITCH_STATUS_FALSE; }
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; }