static void httpd_remove_connection(httpd_t *httpd, http_connection_t *connection) { if (connection->request) { http_request_destroy(connection->request); connection->request = NULL; } httpd->callbacks.conn_destroy(connection->user_data); shutdown(connection->socket_fd, SHUT_WR); closesocket(connection->socket_fd); connection->connected = 0; httpd->open_connections--; }
int test_parse_valid_method() { printf("test_parse_valid_method - running\n"); http_request* req; http_request_init(&req); char* data = "GET http://www.redd.it/hej/ HTTP/1.1\r\n"; http_parse_method(req, data); assert(strcmp(http_methods[req->method], "GET") == 0); assert(req->version == HTTP_VERSION_1_1); assert(strcmp(req->search_path, "http://www.redd.it/hej/") == 0); http_request_destroy(req); printf("test_parse_valid_method - ok\n"); return 0; }
static THREAD_RETVAL httpd_thread(void *arg) { httpd_t *httpd = arg; char buffer[1024]; int i; assert(httpd); while (1) { fd_set rfds; struct timeval tv; int nfds=0; int ret; MUTEX_LOCK(httpd->run_mutex); if (!httpd->running) { MUTEX_UNLOCK(httpd->run_mutex); break; } MUTEX_UNLOCK(httpd->run_mutex); /* Set timeout value to 5ms */ tv.tv_sec = 1; tv.tv_usec = 5000; /* Get the correct nfds value and set rfds */ FD_ZERO(&rfds); if (httpd->open_connections < httpd->max_connections) { FD_SET(httpd->server_fd4, &rfds); nfds = httpd->server_fd4+1; if (httpd->server_fd6 != -1) { FD_SET(httpd->server_fd6, &rfds); if (nfds <= httpd->server_fd6) { nfds = httpd->server_fd6+1; } } } for (i=0; i<httpd->max_connections; i++) { int socket_fd; if (!httpd->connections[i].connected) { continue; } socket_fd = httpd->connections[i].socket_fd; FD_SET(socket_fd, &rfds); if (nfds <= socket_fd) { nfds = socket_fd+1; } } ret = select(nfds, &rfds, NULL, NULL, &tv); if (ret == 0) { /* Timeout happened */ continue; } else if (ret == -1) { /* FIXME: Error happened */ logger_log(httpd->logger, LOGGER_INFO, "Error in select"); break; } if (FD_ISSET(httpd->server_fd4, &rfds)) { ret = httpd_accept_connection(httpd, httpd->server_fd4, 0); if (ret == -1) { break; } else if (ret == 0) { continue; } } if (httpd->server_fd6 != -1 && FD_ISSET(httpd->server_fd6, &rfds)) { ret = httpd_accept_connection(httpd, httpd->server_fd6, 1); if (ret == -1) { break; } else if (ret == 0) { continue; } } for (i=0; i<httpd->max_connections; i++) { http_connection_t *connection = &httpd->connections[i]; if (!connection->connected) { continue; } if (!FD_ISSET(connection->socket_fd, &rfds)) { continue; } /* If not in the middle of request, allocate one */ if (!connection->request) { connection->request = http_request_init(httpd->use_rtsp); assert(connection->request); } logger_log(httpd->logger, LOGGER_DEBUG, "Receiving on socket %d", connection->socket_fd); ret = recv(connection->socket_fd, buffer, sizeof(buffer), 0); if (ret == 0) { logger_log(httpd->logger, LOGGER_INFO, "Connection closed for socket %d", connection->socket_fd); httpd_remove_connection(httpd, connection); continue; } /* Parse HTTP request from data read from connection */ http_request_add_data(connection->request, buffer, ret); if (http_request_has_error(connection->request)) { logger_log(httpd->logger, LOGGER_INFO, "Error in parsing: %s", http_request_get_error_name(connection->request)); httpd_remove_connection(httpd, connection); continue; } /* If request is finished, process and deallocate */ if (http_request_is_complete(connection->request)) { http_response_t *response = NULL; httpd->callbacks.conn_request(connection->user_data, connection->request, &response); http_request_destroy(connection->request); connection->request = NULL; if (response) { const char *data; int datalen; int written; int ret; /* Get response data and datalen */ data = http_response_get_data(response, &datalen); written = 0; while (written < datalen) { ret = send(connection->socket_fd, data+written, datalen-written, 0); if (ret == -1) { /* FIXME: Error happened */ logger_log(httpd->logger, LOGGER_INFO, "Error in sending data"); break; } written += ret; } } else { logger_log(httpd->logger, LOGGER_INFO, "Didn't get response"); } http_response_destroy(response); } } } /* Remove all connections that are still connected */ for (i=0; i<httpd->max_connections; i++) { http_connection_t *connection = &httpd->connections[i]; if (!connection->connected) { continue; } logger_log(httpd->logger, LOGGER_INFO, "Removing connection for socket %d", connection->socket_fd); httpd_remove_connection(httpd, connection); } logger_log(httpd->logger, LOGGER_INFO, "Exiting HTTP thread"); return 0; }
void http_disconnect(http_client_t *http_client) { http_request_destroy(&http_client->request); http_response_destroy(&http_client->response); close_tcp(&http_client->connection); }