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