struct httpd_client *
httpd_client_new(struct httpd_output *httpd, int fd, bool metadata_supported)
{
	struct httpd_client *client = g_new(struct httpd_client, 1);

	client->httpd = httpd;

	client->channel = g_io_channel_new_socket(fd);

	/* GLib is responsible for closing the file descriptor */
	g_io_channel_set_close_on_unref(client->channel, true);
	/* NULL encoding means the stream is binary safe */
	g_io_channel_set_encoding(client->channel, NULL, NULL);
	/* we prefer to do buffering */
	g_io_channel_set_buffered(client->channel, false);

	client->read_source_id = g_io_add_watch(client->channel,
						G_IO_IN|G_IO_ERR|G_IO_HUP,
						httpd_client_in_event, client);

	client->input = fifo_buffer_new(4096);
	client->state = REQUEST;

	client->metadata_supported = metadata_supported;
	client->metadata_requested = false;
	client->metadata_sent = true;
	client->metaint = 8192; /*TODO: just a std value */
	client->metadata = NULL;
	client->metadata_current_position = 0;
	client->metadata_fill = 0;

	return client;
}
Exemple #2
0
void event_pipe_init(void)
{
	GIOChannel *channel;
	int ret;

	ret = pipe_cloexec_nonblock(event_pipe);
	if (ret < 0)
		MPD_ERROR("Couldn't open pipe: %s", strerror(errno));

	channel = g_io_channel_new_socket(event_pipe[0]);
	g_io_channel_set_encoding(channel, NULL, NULL);
	g_io_channel_set_buffered(channel, false);

	event_pipe_source_id = g_io_add_watch(channel, G_IO_IN,
					      main_notify_event, NULL);

	event_channel = channel;

	event_pipe_mutex = g_mutex_new();
}
Exemple #3
0
static gpointer
tcp_connect_init(gpointer data)
{
	struct tcp_connect *c = data;

	/* create a connect source */
	GIOChannel *channel = g_io_channel_new_socket(c->fd);
	c->source = g_io_create_watch(channel, G_IO_OUT);
	g_io_channel_unref(channel);

	g_source_set_callback(c->source, (GSourceFunc)tcp_connect_event, c,
			      NULL);
	g_source_attach(c->source, io_thread_context());

	/* create a timeout source */
	if (c->timeout_ms > 0)
		c->timeout_source =
			io_thread_timeout_add(c->timeout_ms,
					      tcp_connect_timeout, c);

	return NULL;
}
bool
server_socket_open(struct server_socket *ss, GError **error_r)
{
	struct one_socket *good = NULL, *bad = NULL;
	GError *last_error = NULL;

	for (struct one_socket *s = ss->sockets; s != NULL; s = s->next) {
		assert(s->serial > 0);
		assert(good == NULL || s->serial >= good->serial);
		assert(s->fd < 0);

		if (bad != NULL && s->serial != bad->serial) {
			server_socket_close(ss);
			g_propagate_error(error_r, last_error);
			return false;
		}

		GError *error = NULL;
		s->fd = socket_bind_listen(s->address.sa_family, SOCK_STREAM, 0,
					   &s->address, s->address_length, 5,
					   &error);
		if (s->fd < 0) {
			if (good != NULL && good->serial == s->serial) {
				char *address_string = one_socket_to_string(s);
				char *good_string = one_socket_to_string(good);
				g_warning("bind to '%s' failed: %s "
					  "(continuing anyway, because "
					  "binding to '%s' succeeded)",
					  address_string, error->message,
					  good_string);
				g_free(address_string);
				g_free(good_string);
				g_error_free(error);
			} else if (bad == NULL) {
				bad = s;

				char *address_string = one_socket_to_string(s);
				g_propagate_prefixed_error(&last_error, error,
							   "Failed to bind to '%s': ",
							   address_string);
				g_free(address_string);
			} else
				g_error_free(error);
			continue;
		}

		/* allow everybody to connect */

		if (s->path != NULL)
			chmod(s->path, 0666);

		/* register in the GLib main loop */

		GIOChannel *channel = g_io_channel_new_socket(s->fd);
		s->source_id = g_io_add_watch(channel, G_IO_IN,
					      server_socket_in_event, s);
		g_io_channel_unref(channel);

		/* mark this socket as "good", and clear previous
		   errors */

		good = s;

		if (bad != NULL) {
			bad = NULL;
			g_error_free(last_error);
			last_error = NULL;
		}
	}

	if (bad != NULL) {
		server_socket_close(ss);
		g_propagate_error(error_r, last_error);
		return false;
	}

	return true;
}
Exemple #5
0
void
client_new(struct player_control *player_control,
	   int fd, const struct sockaddr *sa, size_t sa_length, int uid)
{
	static unsigned int next_client_num;
	struct client *client;
	char *remote;

	assert(player_control != NULL);
	assert(fd >= 0);

#ifdef HAVE_LIBWRAP
	if (sa->sa_family != AF_UNIX) {
		char *hostaddr = sockaddr_to_string(sa, sa_length, NULL);
		const char *progname = g_get_prgname();

		struct request_info req;
		request_init(&req, RQ_FILE, fd, RQ_DAEMON, progname, 0);

		fromhost(&req);

		if (!hosts_access(&req)) {
			/* tcp wrappers says no */
			g_log(G_LOG_DOMAIN, LOG_LEVEL_SECURE,
			      "libwrap refused connection (libwrap=%s) from %s",
			      progname, hostaddr);

			g_free(hostaddr);
			close_socket(fd);
			return;
		}

		g_free(hostaddr);
	}
#endif	/* HAVE_WRAP */

	if (client_list_is_full()) {
		g_warning("Max Connections Reached!");
		close_socket(fd);
		return;
	}

	client = g_new0(struct client, 1);
	client->player_control = player_control;

	client->channel = g_io_channel_new_socket(fd);
	/* GLib is responsible for closing the file descriptor */
	g_io_channel_set_close_on_unref(client->channel, true);
	/* NULL encoding means the stream is binary safe; the MPD
	   protocol is UTF-8 only, but we are doing this call anyway
	   to prevent GLib from messing around with the stream */
	g_io_channel_set_encoding(client->channel, NULL, NULL);
	/* we prefer to do buffering */
	g_io_channel_set_buffered(client->channel, false);

	client->source_id = g_io_add_watch(client->channel,
					   G_IO_IN|G_IO_ERR|G_IO_HUP,
					   client_in_event, client);

	client->input = fifo_buffer_new(4096);

	client->permission = getDefaultPermissions();
	client->uid = uid;

	client->last_activity = g_timer_new();

	client->cmd_list = NULL;
	client->cmd_list_OK = -1;
	client->cmd_list_size = 0;

	client->deferred_send = g_queue_new();
	client->deferred_bytes = 0;
	client->num = next_client_num++;

	client->send_buf_used = 0;

	client->subscriptions = NULL;
	client->messages = NULL;
	client->num_messages = 0;

	(void)send(fd, GREETING, sizeof(GREETING) - 1, 0);

	client_list_add(client);

	remote = sockaddr_to_string(sa, sa_length, NULL);
	g_log(G_LOG_DOMAIN, LOG_LEVEL_SECURE,
	      "[%u] opened from %s", client->num, remote);
	g_free(remote);
}