-static void handle_connection(int client_socket) {
- int server_socket;
- FILE *client_fd, *server_fd;
-
- char buffer[MAX_REQUEST_LINE];
- char host[MAX_REQUEST_LINE];
- char port[5 + 1];
-
- int version_minor;
- int result;
-
- client_fd = fdopen(client_socket, "a+");
- if (NULL == client_fd) {
- perror("fdopen()");
- close(client_socket);
- return;
- }
-
-#ifdef DEBUG
- printf("New connection:\n");
-#endif
-
- /* Read request line (CONNECT ..) and headers (they are discarded). */
- result = read_http_request(client_fd, buffer, sizeof(buffer));
- if (result == -1) {
- /* Read error. */
- return;
- } else if (result == -2) {
- /* EOF */
- send_close_bad_request(client_fd);
- return;
- }
-
-#ifdef DEBUG
- printf(" request: %s", buffer);
-#endif
-
- if (0 != parse_request(buffer, host, port, &version_minor)) {
- send_close_bad_request(client_fd);
-#ifdef DEBUG
- printf(" bad request\n");
-#endif
- return;
- }
-
-#ifdef DEBUG
- printf(" %s:%s (HTTP 1.%d)\n", host, port, version_minor);
-#endif
-
- /* Connect to proxy server or directly to server. */
- if (NULL != use_proxy_host && NULL != use_proxy_port) {
- server_socket = connect_to_host(use_proxy_host, use_proxy_port);
- } else {
- server_socket = connect_to_host(host, port);
- }
-
- if (-1 == server_socket) {
- send_close_forwarding_failure(client_fd);
- return;
- }
- server_fd = fdopen(server_socket, "a+");
- if (NULL == server_fd) {
- send_close_forwarding_failure(client_fd);
- return;
- }
-
- /* Connect to proxy if requested (command line option). */
- if (NULL != use_proxy_host && NULL != use_proxy_port) {
- fprintf(server_fd, "CONNECT %s:%s HTTP/1.0\r\n", host, port);
- fprintf(server_fd, "\r\n");
-
- /* Read response line from proxy server. */
- result = read_http_request(server_fd, buffer, sizeof(buffer));
- if (result == -1) {
- /* Read error. */
- send_close_forwarding_failure(client_fd);
- return;
- } else if (result == -2) {
- /* EOF */
- fclose(server_fd);
- send_close_forwarding_failure(client_fd);
- return;
- }
-
- /* Check response of proxy server. */
- if (0 != strncmp(buffer, "HTTP/1.0 200", 12)) {
-#ifdef DEBUG
- printf(" bad proxy response\n");
-#endif
- fclose(server_fd);
- send_close_forwarding_failure(client_fd);
- return;
- }
- }
-
-#ifdef DEBUG
- printf(" connection to server established\n");
-#endif
-
- /* We've established a connection, tell the client. */
- fprintf(client_fd, "HTTP/1.0 200 Connection established\r\n");
- fprintf(client_fd, "\r\n");
- fflush(client_fd);
-
- /* And transfer all data between client and server transparently. */
- transfer_data(client_socket, server_socket);
-
- fclose(client_fd);
- fclose(server_fd);
-}
-
-/* Read HTTP request line and headers (ignored).
- *
- * On success 0 is returned, -1 on client error (we close client descriptor in
- * this case), -2 on unexpected EOF.
- */
-static int read_http_request(FILE *client_fd, char *request, size_t length) {
- char buffer[MAX_REQUEST_LINE];
-
- if (NULL == fgets(request, (int)length, client_fd)) {
- if (ferror(client_fd)) {
- perror("fgets(), request");
- fclose(client_fd);
- return -1;
- }
-
- return -2;
- }
-
- while (NULL != fgets(buffer, MAX_REQUEST_LINE, client_fd)) {
- /* End of header. */
- if (0 == strcmp(buffer, "\n") || 0 == strcmp(buffer, "\r\n")) {
- break;
- }
- }
- if (ferror(client_fd)) {
- perror("fgets(), header");
- fclose(client_fd);
- return -1;
- }
-
- return 0;
-}
-
-static void send_close_bad_request(FILE *client_fd) {
- fprintf(client_fd, "HTTP/1.0 400 Bad Request\r\n");
- fprintf(client_fd, "\r\n");
- fclose(client_fd);
-}
-static void send_close_forwarding_failure(FILE *client_fd) {
- fprintf(client_fd, "HTTP/1.0 503 Forwarding failure\r\n");
- fprintf(client_fd, "\r\n");
- fclose(client_fd);
-}
-
-
-/* Transfer data between client and server sockets until one closes the
- * connection. */
-static void transfer_data(int client, int server) {
- struct pollfd fds[2];
- fds[0].fd = client;
- fds[0].events = POLLIN | POLLPRI | POLLHUP | POLLERR;
- fds[0].revents = 0;
- fds[1].fd = server;
- fds[1].events = POLLIN | POLLPRI | POLLHUP | POLLERR;
- fds[1].revents = 0;