|
1 | | -#include <cstring> |
2 | | -#include <string.h> |
3 | 1 | #include <sys/types.h> |
4 | 2 | #include <sys/socket.h> |
5 | 3 | #include <netdb.h> |
6 | 4 | #include <unistd.h> |
7 | | -#include <stdio.h> |
8 | | -#include <pthread.h> |
| 5 | +#include <thread> |
| 6 | +#include <chrono> |
9 | 7 |
|
10 | 8 | #include "Router.h" |
| 9 | +#include "Manager.h" |
11 | 10 |
|
12 | 11 | /* |
13 | 12 | * router - watches the designated port and for launches a new worker for every connection |
14 | 13 | * (when all workers are busy, waits some time before returning an error - "how long" should be kept in the config) |
15 | 14 | * Handles *some* of the HTTP errors |
16 | 15 | */ |
17 | 16 |
|
18 | | -Router::Router(int qsize) { |
| 17 | +Router::Router(int qsize, std::string port) { |
19 | 18 | this->queue_size = qsize; |
20 | 19 | this->logger = Logger("Router"); |
| 20 | + this->port = port; |
| 21 | + // initialize the socket |
| 22 | + this->init_socket(); |
21 | 23 | } |
22 | 24 |
|
23 | 25 | Router::~Router() { |
24 | | - // TODO Auto-generated destructor stub |
| 26 | + // close our socket |
| 27 | + close(this->listening_socket_fd); |
| 28 | + // free the address |
| 29 | + freeaddrinfo(addr); |
25 | 30 | } |
26 | 31 |
|
27 | | -void *newSocketFunction(void *socket_fd); |
28 | | -void Router::watch(std::string port) { |
29 | | - this->logger.debug("starting with port" + port); |
30 | | - |
| 32 | +void Router::watch() { |
| 33 | + socklen_t addr_size; |
31 | 34 | struct sockaddr_storage incoming_connection_info; |
32 | | - socklen_t addr_size; |
33 | | - struct addrinfo listening_socket_description, *results; |
34 | | - int listening_socket_fd, new_socket_fd; |
| 35 | + int handling_socket; |
35 | 36 |
|
36 | | - // first, load up address structs with getaddrinfo(): |
37 | | - memset(&listening_socket_description, 0, sizeof listening_socket_description); |
| 37 | + this->logger.debug("watching port: " + this->port); |
38 | 38 |
|
39 | | - listening_socket_description.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever |
40 | | - listening_socket_description.ai_socktype = SOCK_STREAM; |
41 | | - listening_socket_description.ai_flags = AI_PASSIVE; // fill in my IP for me |
42 | | - getaddrinfo(NULL, port.c_str(), &listening_socket_description, &results); |
| 39 | + // create a manager object to handle different threads |
| 40 | + Manager manager; |
43 | 41 |
|
44 | | - // make a socket, bind it, and listen on it: |
45 | | - listening_socket_fd = socket(results->ai_family, results->ai_socktype, results->ai_protocol); |
46 | | - bind(listening_socket_fd, results->ai_addr, results->ai_addrlen); |
| 42 | + // we work until we're told to stop working |
| 43 | + while (true) { |
| 44 | + // listen for new connections |
| 45 | + listen(this->listening_socket_fd, this->queue_size); |
47 | 46 |
|
48 | | - listen(listening_socket_fd, this->queue_size); |
| 47 | + addr_size = sizeof incoming_connection_info; |
| 48 | + handling_socket = accept(listening_socket_fd, (struct sockaddr *) &incoming_connection_info, &addr_size); |
| 49 | + this->logger.info("Handling incoming connection from: "); |
| 50 | + // this will create a new worker to work with |
| 51 | + // TODO: handle too many workers exception |
| 52 | + manager.handle_request(handling_socket); |
| 53 | + |
| 54 | + // sleep a little |
| 55 | + std::this_thread::sleep_for (std::chrono::seconds(1)); |
| 56 | + } |
| 57 | +} |
49 | 58 |
|
50 | | - addr_size = sizeof incoming_connection_info; |
51 | | - new_socket_fd = accept(listening_socket_fd, (struct sockaddr *) &incoming_connection_info, &addr_size); |
52 | | - this->logger.info("handling connection"); |
| 59 | +int Router::init_socket() { |
| 60 | + struct addrinfo listening_socket_description; |
53 | 61 |
|
54 | | - pthread_t t1; |
55 | | - this->logger.debug("creating new thread"); |
56 | | - pthread_create(&t1, NULL, newSocketFunction, (void *) &new_socket_fd); |
57 | | - pthread_join(t1, NULL); |
| 62 | + // first, load up address structs with getaddrinfo(): |
| 63 | + // TODO error handling (what if there's no memory available) |
| 64 | + memset(&listening_socket_description, 0, sizeof listening_socket_description); |
58 | 65 |
|
59 | | - this->logger.debug("closing connection"); |
60 | | - freeaddrinfo(results); |
61 | | - close(listening_socket_fd); |
62 | | - close(new_socket_fd); |
| 66 | + listening_socket_description.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever |
| 67 | + listening_socket_description.ai_socktype = SOCK_STREAM; |
| 68 | + listening_socket_description.ai_flags = AI_PASSIVE; // fill in my IP for me |
| 69 | + getaddrinfo(NULL, this->port.c_str(), &listening_socket_description, &this->addr); |
63 | 70 |
|
64 | | - this->logger.debug("done"); |
65 | | -} |
| 71 | + // TODO error handling (what if we cannot open the socket) |
| 72 | + int listening_socket = socket(this->addr->ai_family, this->addr->ai_socktype, this->addr->ai_protocol); |
66 | 73 |
|
67 | | -// Possibly this code will be moved and divided to manager/worker |
68 | | -// that's why I'm leaving this out of the Router:: class |
69 | | -void *newSocketFunction(void *socket_fd_ptr){ |
70 | | - int *socket_fd = (int *)socket_fd_ptr; |
71 | | - char reply[100], *msg; |
72 | | - |
73 | | - std::string string = "Welcome to HACKttp: " + std::to_string(*socket_fd) + "\nYour message: "; |
74 | | - //msg = "Welcome to HACKttp " + (char) socket_fd; |
75 | | - msg = (char *) string.c_str(); |
76 | | - send(*socket_fd, msg, strlen(msg), 0); |
77 | | - |
78 | | - std::string response; |
79 | | - while(1){ |
80 | | - memset(&reply, 0, sizeof reply); |
81 | | - if(recv(*socket_fd, reply, 100, 0) <= 0) break; |
82 | | - response.append("HackTTP echo: "); |
83 | | - response.append(reply); |
84 | | - response.append("\nYour message: "); |
85 | | - msg = (char *)response.c_str(); |
86 | | - send(*socket_fd, msg, strlen(msg), 0); |
87 | | - //reply[99] = '\0'; |
88 | | - printf("Sent back: %s", response.c_str()); |
89 | | - response.clear(); |
90 | | - } |
| 74 | + // TODO error handling (what if we can't bind) |
| 75 | + bind(listening_socket, this->addr->ai_addr, this->addr->ai_addrlen); |
91 | 76 |
|
92 | | - return NULL; |
| 77 | + return listening_socket; |
93 | 78 | } |
0 commit comments