static void client_input(struct client *client) { const char *const *args, *error; int ret; if (client->to_pending != NULL) timeout_remove(&client->to_pending); switch (i_stream_read(client->input)) { case -2: i_error("BUG: Stats client sent too much data"); client_destroy(&client); return; case -1: client_destroy(&client); return; } o_stream_cork(client->output); while ((args = client_read_next_line(client)) != NULL) { ret = client_handle_request(client, args, &error); if (ret < 0) { i_error("Stats client input error: %s", error); client_destroy(&client); return; } if (ret == 0) { o_stream_set_flush_pending(client->output, TRUE); io_remove(&client->io); break; } client->cmd_more = NULL; } o_stream_uncork(client->output); }
int main(void) { int s; int i; int ret; fd_set fds; struct clients cli; client_init(&cli); s = socket_setup(SOCK_PATH); cli.self = s; client_add(&cli, s); for (;;) { fds = cli.set; if (select(cli.max + 1, &fds, NULL, NULL, NULL) == -1) { perror("select"); exit(1); } for (i = 0; i <= cli.max; i++) { if (!FD_ISSET(i, &fds)) continue; if (i == cli.self) { client_accept(&cli, s); continue; } client_handle_request(&cli, i); } } return 0; }
static void client_fill_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) { BroadwayClient *client = user_data; gssize res; res = g_buffered_input_stream_fill_finish (client->in, result, NULL); if (res > 0) { guint32 size; gsize count, remaining; guint8 *buffer; buffer = (guint8 *)g_buffered_input_stream_peek_buffer (client->in, &count); remaining = count; while (remaining >= sizeof (guint32)) { memcpy (&size, buffer, sizeof (guint32)); if (size <= remaining) { client_handle_request (client, (BroadwayRequest *)buffer); remaining -= size; buffer += size; } } /* This is guaranteed not to block */ g_input_stream_skip (G_INPUT_STREAM (client->in), count - remaining, NULL, NULL); g_buffered_input_stream_fill_async (client->in, 4*1024, 0, NULL, client_fill_cb, client); } else { client_disconnected (client); } }
static void client_input(struct connection *conn) { struct client *client = (struct client *)conn; struct http_request request; enum http_request_parse_error error_code; const char *error; int ret; while ((ret = http_request_parse_next (client->parser, NULL, &request, &error_code, &error)) > 0) { if (client_handle_request(client, &request) < 0 || request.connection_close) { client_destroy(conn); return; } } if (ret < 0) { i_error("Client sent invalid request: %s", error); client_destroy(conn); } }
static void client_handle_read(void *opaque) { Client *client = opaque; int length; const char *message = NULL; char packet_signature[PACKET_MAX_SIGNATURE_LENGTH]; length = io_read(client->io, (uint8_t *)&client->request + client->request_used, sizeof(Packet) - client->request_used); if (length == 0) { log_info("Client ("CLIENT_SIGNATURE_FORMAT") disconnected by peer", client_expand_signature(client)); client->disconnected = true; return; } if (length < 0) { if (length == IO_CONTINUE) { // no actual data received } else if (errno_interrupted()) { log_debug("Receiving from client ("CLIENT_SIGNATURE_FORMAT") was interrupted, retrying", client_expand_signature(client)); } else if (errno_would_block()) { log_debug("Receiving from client ("CLIENT_SIGNATURE_FORMAT") would block, retrying", client_expand_signature(client)); } else { log_error("Could not receive from client ("CLIENT_SIGNATURE_FORMAT"), disconnecting client: %s (%d)", client_expand_signature(client), get_errno_name(errno), errno); client->disconnected = true; } return; } client->request_used += length; while (!client->disconnected && client->request_used > 0) { if (client->request_used < (int)sizeof(PacketHeader)) { // wait for complete header break; } if (!client->request_header_checked) { if (!packet_header_is_valid_request(&client->request.header, &message)) { // FIXME: include packet_get_content_dump output in the error message log_error("Received invalid request (%s) from client ("CLIENT_SIGNATURE_FORMAT"), disconnecting client: %s", packet_get_request_signature(packet_signature, &client->request), client_expand_signature(client), message); client->disconnected = true; return; } client->request_header_checked = true; } length = client->request.header.length; if (client->request_used < length) { // wait for complete packet break; } if (client->request.header.function_id == FUNCTION_DISCONNECT_PROBE) { log_packet_debug("Received disconnect probe from client ("CLIENT_SIGNATURE_FORMAT"), dropping request", client_expand_signature(client)); } else { log_packet_debug("Received request (%s) from client ("CLIENT_SIGNATURE_FORMAT")", packet_get_request_signature(packet_signature, &client->request), client_expand_signature(client)); client_handle_request(client, &client->request); } memmove(&client->request, (uint8_t *)&client->request + length, client->request_used - length); client->request_used -= length; client->request_header_checked = false; } }