Exemplo n.º 1
0
/**
 * 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 switch_status_t rtmp_tcp_write(rtmp_session_t *rsession, const unsigned char *buf, switch_size_t *len)
{
	//rtmp_io_tcp_t *io = (rtmp_io_tcp_t*)rsession->profile->io;
	rtmp_tcp_io_private_t *io_pvt = rsession->io_private;
	switch_status_t status = SWITCH_STATUS_SUCCESS;
	switch_size_t orig_len = *len;
	switch_size_t remaining = *len;
	int sanity = 100;

#ifdef RTMP_DEBUG_IO
	{
		int i;
		fprintf(rsession->io_debug_out,
			"SEND %"SWITCH_SIZE_T_FMT" bytes\n> ", *len);

		for (i = 0; i < *len; i++) {
			fprintf(rsession->io_debug_out, "%02X ", (uint8_t)buf[i]);

			if (i != 0 && i % 32 == 0) {
				fprintf(rsession->io_debug_out, "\n> ");
			}
		}
		fprintf(rsession->io_debug_out, "\n\n ");

		fflush(rsession->io_debug_out);
	}
#endif

	while (remaining > 0) {
		if (rsession->state >= RS_DESTROY) {
			return SWITCH_STATUS_FALSE;
		}

again:
		status = switch_socket_send_nonblock(io_pvt->socket, (char*)buf, len);

		if ((status == 32 || SWITCH_STATUS_IS_BREAK(status)) && sanity-- > 0) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "sending too fast, retrying %d\n", sanity);
			goto again;
		}

		if (status != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "send error %d\n", status);
			break;
		}

		if (*len != orig_len) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "sent %ld of %ld\n", *len, orig_len);
		buf += *len;
		remaining -= *len;
		*len = remaining;
	}

	*len = orig_len;

	return status;
}
Exemplo n.º 3
0
static switch_status_t rtmp_tcp_write(rtmp_session_t *rsession, const unsigned char *buf, switch_size_t *len)
{
	//rtmp_io_tcp_t *io = (rtmp_io_tcp_t*)rsession->profile->io;
	rtmp_tcp_io_private_t *io_pvt = rsession->io_private;
	switch_status_t status;
	switch_size_t orig_len = *len;	
	
#ifdef RTMP_DEBUG_IO
	{
		int i;
		fprintf(rsession->io_debug_out,
			"SEND %"SWITCH_SIZE_T_FMT" bytes\n> ", *len);

		for (i = 0; i < *len; i++) {
			fprintf(rsession->io_debug_out, "%02X ", (uint8_t)buf[i]);
				
			if (i != 0 && i % 32 == 0) {
				fprintf(rsession->io_debug_out, "\n> ");
			}
		}
		fprintf(rsession->io_debug_out, "\n\n ");
		
		fflush(rsession->io_debug_out);
	}
#endif
	
	if (io_pvt->sendq && switch_buffer_inuse(io_pvt->sendq) > 0) {
		/* We already have queued data, append it to the sendq */
		switch_buffer_write(io_pvt->sendq, buf, *len);
		return SWITCH_STATUS_SUCCESS;
	}
	
	status = switch_socket_send_nonblock(io_pvt->socket, (char*)buf, len);
	
	if (*len > 0 && *len < orig_len) {
		
		if (rsession->state >= RS_DESTROY) {
			return SWITCH_STATUS_FALSE;
		}
		
		/* We didnt send it all... add it to the sendq*/		
		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_DEBUG, "%"SWITCH_SIZE_T_FMT" bytes added to sendq.\n", (orig_len - *len));
		
		switch_buffer_write(io_pvt->sendq, (buf + *len), orig_len - *len);

		/* Make sure we poll-write */
		rtmp_tcp_alter_pollfd(rsession, SWITCH_TRUE);
	}
	
	return status;
}
Exemplo n.º 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;
}