/** * The listener thread main function. The listener listens for * connections from clients. */ static void *listener_main(void *arg_p) { struct http_server_t *self_p = arg_p; struct http_server_listener_t *listener_p; struct http_server_connection_t *connection_p; struct inet_addr_t addr; thrd_set_name(self_p->listener_p->thrd.name_p); listener_p = self_p->listener_p; if (socket_open_tcp(&listener_p->socket) != 0) { log_object_print(NULL, LOG_ERROR, FSTR("Failed to open socket.")); return (NULL); } if (inet_aton(listener_p->address_p, &addr.ip) != 0) { return (NULL); } addr.port = listener_p->port; if (socket_bind(&listener_p->socket, &addr) != 0) { log_object_print(NULL, LOG_ERROR, FSTR("Failed to bind socket.")); return (NULL); } if (socket_listen(&listener_p->socket, 3) != 0) { log_object_print(NULL, LOG_ERROR, FSTR("Failed to listen on socket.")); return (NULL); } /* Wait for clients to connect. */ while (1) { /* Allocate a connection. */ connection_p = allocate_connection(self_p); /* Wait for a client to connect. */ socket_accept(&listener_p->socket, &connection_p->socket, &addr); handle_accept(self_p, connection_p); } return (NULL); }
static int read_initial_request_line(struct socket_t *socket_p, char *buf_p, struct http_server_request_t *request_p) { char *action_p = NULL; char *path_p = NULL; char *proto_p = NULL; *buf_p++ = '\0'; action_p = buf_p; while (1) { if (socket_read(socket_p, buf_p, sizeof(*buf_p)) != sizeof(*buf_p)) { return (-EIO); } buf_p++; /* The line ending is "\r\n". */ if ((buf_p[-2] == '\r') && (buf_p[-1] == '\n')) { buf_p[-2] = '\0'; break; } /* Action and path has ' ' as terminator. */ if (buf_p[-1] == ' ') { buf_p[-1] = '\0'; if (path_p == NULL) { path_p = buf_p; } else if (proto_p == NULL) { proto_p = buf_p; } } } /* A path is required. */ if (path_p == NULL) { return (-1); } log_object_print(NULL, LOG_DEBUG, FSTR("%s %s %s\r\n"), action_p, path_p, proto_p); /* Save the action and path in the request struct. */ strcpy(request_p->path, path_p); if (strcmp(action_p, "GET") == 0) { request_p->action = http_server_request_action_get_t; } else if (strcmp(action_p, "POST") == 0) { request_p->action = http_server_request_action_post_t; } else { return (-1); } return (0); }
/** * The connection thread serves a client for the duration of the * socket lifetime. */ static void *connection_main(void *arg_p) { struct http_server_connection_t *connection_p = arg_p; struct http_server_t *self_p = connection_p->self_p; uint32_t mask; /* thrd_init_env(buf, sizeof(buf)); */ /* thrd_set_env("CWD", self_p->root_path_p); */ thrd_set_name(connection_p->thrd.name_p); /* Wait for a connection from the listener. */ while (1) { log_object_print(NULL, LOG_DEBUG, FSTR("Connection thread '%s' waiting for a new connection.\r\n"), thrd_get_name()); mask = 0x1; event_read(&connection_p->events, &mask, sizeof(mask)); if (mask & 0x1) { handle_request(self_p, connection_p); socket_close(&connection_p->socket); /* Add thread to the free list. */ sys_lock(); connection_p->state = http_server_connection_state_free_t; sys_unlock(); mask = 0x1; event_write(&self_p->events, &mask, sizeof(mask)); } } return (NULL); }
static int read_request(struct http_server_t *self_p, struct http_server_connection_t *connection_p, struct http_server_request_t *request_p) { int res; char buf[128]; char *header_p; char *value_p; /* Read the intial line in the request. */ if (read_initial_request_line(&connection_p->socket, buf, request_p) != 0) { return (-EIO); } memset(&request_p->headers, 0, sizeof(request_p->headers)); /* Read the header lines. */ while (1) { res = read_header_line(&connection_p->socket, buf, &header_p, &value_p); if (res == 1) { break; } else if (res < 0) { return (-EIO); } log_object_print(NULL, LOG_DEBUG, FSTR("%s: %s\r\n"), header_p, value_p); /* Save the header field in the request object. */ if (strcmp(header_p, "Sec-WebSocket-Key") == 0) { request_p->headers.sec_websocket_key.present = 1; strncpy(request_p->headers.sec_websocket_key.value, value_p, sizeof(request_p->headers.sec_websocket_key.value)); } else if (strcmp(header_p, "Content-Type") == 0) { request_p->headers.content_type.present = 1; strncpy(request_p->headers.content_type.value, value_p, sizeof(request_p->headers.content_type.value)); } else if (strcmp(header_p, "Content-Length") == 0) { if (std_strtol(value_p, &request_p->headers.content_length.value) != NULL) { request_p->headers.content_length.present = 1; } } else if (strcmp(header_p, "Authorization") == 0) { request_p->headers.authorization.present = 1; strncpy(request_p->headers.authorization.value, value_p, sizeof(request_p->headers.authorization.value)); } } return (0); }
int test_print(struct harness_t *harness_p) { struct log_object_t foo; struct log_object_t bar; /* Initialize the log objects. */ BTASSERT(log_object_init(&foo, "foo", LOG_UPTO(INFO)) == 0); BTASSERT(log_object_init(&bar, "bar", LOG_UPTO(DEBUG)) == 0); /* Write on INFO level. */ BTASSERT(log_object_print(&foo, LOG_INFO, FSTR("x = %d\r\n"), 1) == 1); BTASSERT(log_object_print(&bar, LOG_INFO, FSTR("y = %d\r\n"), 2) == 1); /* Write on DEBUG level. */ BTASSERT(log_object_print(&foo, LOG_DEBUG, FSTR("m = %d\r\n"), 3) == 0); BTASSERT(log_object_print(&bar, LOG_DEBUG, FSTR("n = %d\r\n"), 4) == 1); /* Write using the thread log mask instead of the log object mask. */ BTASSERT(log_object_print(NULL, LOG_DEBUG, FSTR("k = %d\r\n"), 5) == 0); BTASSERT(log_object_print(NULL, LOG_ERROR, FSTR("l = %d\r\n"), 6) == 1); return (0); }
int test_handler(struct harness_t *harness_p) { struct log_object_t foo; struct log_handler_t handler; /* Initialize the log objects. */ BTASSERT(log_object_init(&foo, "foo", LOG_UPTO(INFO)) == 0); BTASSERT(log_handler_init(&handler, sys_get_stdout()) == 0); /* This should be printed once for the default handler. */ BTASSERT(log_object_print(&foo, LOG_INFO, FSTR("one handler\r\n")) == 1); /* Add our handler. */ BTASSERT(log_add_handler(&handler) == 0); /* This should be printed twice, one for the default handler and once for our handler. */ BTASSERT(log_object_print(&foo, LOG_INFO, FSTR("two handlers\r\n")) == 2); /* Remove our handler. */ BTASSERT(log_remove_handler(&handler) == 0); BTASSERT(log_remove_handler(&handler) == 1); /* This should be printed once for the default handler. */ BTASSERT(log_object_print(&foo, LOG_INFO, FSTR("one handler again\r\n")) == 1); return (0); }
int music_player_set_bits_per_sample(struct music_player_t *self_p, int value) { uint16_t mask; value = (12 - value); mask = ~((1 << value) - 1); self_p->down_sampling_mask = (((uint32_t)mask << 16) | mask); log_object_print(NULL, LOG_INFO, FSTR("down_sampling_mask = 0x%lx\r\n"), self_p->down_sampling_mask); return (0); }