Skip to content

Commit 404b5c3

Browse files
author
lh5053
committed
Merge branch 'temp'
2 parents 5f1a1b1 + f1e85ee commit 404b5c3

File tree

11 files changed

+200
-84
lines changed

11 files changed

+200
-84
lines changed

config

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ port=8000
22
log_path=./log
33
queue_size=10
44
config_test=Config Loaded, hello from server.cpp!
5-
start_full_server=false
5+
start_full_server=true
66
;
77

88
Config manual:

hackttp.archive

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ echo "OK"
66
echo -n "Creating archive..."
77
zip -r HackTTP.zip hackttp/ -x '*/.git/*'
88
rm -Rf hackttp
9-
echo "HackTTP.zip ready"
9+
echo "etap_$1.zip ready"

src/Logger.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ Logger::Logger(std::string path, std::string name) : LoggerBase(path) {
4040
logFileDescriptor = open(log_path.c_str(), O_WRONLY | O_APPEND);
4141

4242
if(logFileDescriptor < 0){
43-
loggerStatus = "[" + this->class_name + "]" + "Error opening logfile, disabling logging to file\nError: " + strerror(errno);
43+
loggerStatus = "[" + this->class_name + "]" + " Error opening logfile, disabling logging to file\nError: " + strerror(errno) + "\n";
4444
cLoggerStatus = loggerStatus.c_str();
4545
write(2, cLoggerStatus, strlen(cLoggerStatus));
4646
isLoggingToFileEnabled = false;
@@ -72,8 +72,8 @@ void Logger::_log(std::string msg, int level) {
7272

7373
write(1, cFullMessage, strlen(cFullMessage));
7474
if (isLoggingToFileEnabled) {
75-
write(logFileDescriptor, cFullMessage, strlen(cFullMessage));
76-
}
75+
write(logFileDescriptor, cFullMessage, strlen(cFullMessage));
76+
}
7777
mutex.unlock();
7878
}
7979
}

src/Logger.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ enum LogLevel { QUIET, WARNINGS, INFO, DEBUG };
66

77
class LoggerBase {
88
protected:
9-
int current_log_level = INFO;
9+
// TODO: should be loaded from Config
10+
int current_log_level = DEBUG;
1011
public:
1112
LoggerBase() {}
1213
LoggerBase(std::string path);

src/Manager.cpp

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,50 @@
1-
#include "Manager.h"
1+
#include <stdio.h>
2+
#include <pthread.h>
3+
#include <stdlib.h>
4+
#include <stdio.h>
5+
#include <cstring>
6+
#include <pthread.h>
27

8+
#include "Manager.h"
9+
#include "Worker.h"
310
/*
411
* manager - keeps track of workers, their current status, should handle zombies (number of workers comes from config)
512
*/
613

714
Manager::Manager() {
8-
// TODO Auto-generated constructor stub
9-
15+
this->logger = Logger("Manager");
16+
// TODO Move to config file and fetch directly from there
17+
int worker_count = 10;
18+
this->pool = (pthread_t*) calloc(worker_count, sizeof(pthread_t));
1019
}
1120

1221
Manager::~Manager() {
13-
// TODO Auto-generated destructor stub
22+
free(this->pool);
1423
}
1524

25+
void *worker_runner(void *socket_fd);
26+
27+
void Manager::handle_request(int socket_fd) {
28+
this->logger.debug("Handling request via socket: " + std::to_string(socket_fd));
29+
30+
// get worker, if available
31+
pthread_t worker_t = this->get_free_worker();
32+
33+
// handle the requst in a new thread
34+
pthread_create(&worker_t, NULL, worker_runner, (void *) &socket_fd);
35+
36+
return;
37+
}
38+
39+
int Manager::get_free_worker() {
40+
// TODO look for a free worker
41+
return this->pool[0];
42+
}
43+
44+
void *worker_runner(void *socket_fd) {
45+
int *socket = (int *) socket_fd;
46+
Worker worker(*socket);
47+
worker.handle_request();
48+
49+
return NULL;
50+
}

src/Manager.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
11
#ifndef SRC_MANAGER_H_
22
#define SRC_MANAGER_H_
33

4+
#include "Logger.h"
5+
#include "Worker.h"
6+
47
class Manager {
8+
private:
9+
pthread_t * pool; // keeps a pool of available workers
10+
Logger logger;
11+
int get_free_worker();
12+
513
public:
614
Manager();
715
virtual ~Manager();
16+
void handle_request(int socket_fd);
817
};
918

1019
#endif /* SRC_MANAGER_H_ */

src/Router.cpp

Lines changed: 71 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,104 @@
1-
#include <cstring>
2-
#include <string.h>
31
#include <sys/types.h>
42
#include <sys/socket.h>
3+
#include <errno.h>
54
#include <netdb.h>
65
#include <unistd.h>
7-
#include <stdio.h>
8-
#include <pthread.h>
6+
#include <thread>
7+
#include <chrono>
8+
#include <cstring>
9+
#include <netinet/in.h>
10+
#include <arpa/inet.h>
911

1012
#include "Router.h"
13+
#include "Manager.h"
1114

1215
/*
1316
* router - watches the designated port and for launches a new worker for every connection
1417
* (when all workers are busy, waits some time before returning an error - "how long" should be kept in the config)
1518
* Handles *some* of the HTTP errors
1619
*/
1720

18-
Router::Router(int qsize) {
21+
Router::Router(int qsize, std::string port) {
1922
this->queue_size = qsize;
2023
this->logger = Logger("Router");
24+
this->port = port;
25+
// initialize the socket
26+
this->listening_socket_fd = this->init_socket();
2127
}
2228

2329
Router::~Router() {
24-
// TODO Auto-generated destructor stub
30+
// close our socket
31+
close(this->listening_socket_fd);
32+
// free the address
33+
freeaddrinfo(addr);
34+
}
35+
36+
void *get_in_addr(struct sockaddr *sa) {
37+
if (sa->sa_family == AF_INET) {
38+
return &(((struct sockaddr_in*)sa)->sin_addr);
39+
}
40+
41+
return &(((struct sockaddr_in6*)sa)->sin6_addr);
2542
}
2643

27-
void *newSocketFunction(void *socket_fd);
28-
void Router::watch(std::string port) {
29-
this->logger.debug("starting with port" + port);
44+
void Router::watch() {
45+
socklen_t addr_size;
46+
struct sockaddr_storage client;
47+
int handling_socket;
48+
49+
this->logger.debug("watching port: " + this->port);
50+
51+
// create a manager object to handle different threads
52+
Manager manager;
53+
54+
// we work until we're told to stop working
55+
while (true) {
56+
// listen for new connections
57+
listen(this->listening_socket_fd, this->queue_size);
58+
59+
addr_size = sizeof client;
60+
handling_socket = accept(this->listening_socket_fd, (struct sockaddr *) &client, &addr_size);
61+
if (handling_socket < 0) {
62+
char * err = std::strerror(errno);
63+
throw RouterException("Error when accepting connection: " + std::string(err ? err : "unknown error"));
64+
}
65+
66+
struct sockaddr_in *sin = (struct sockaddr_in *)&client;
67+
char client_addr[INET6_ADDRSTRLEN];
68+
inet_ntop(AF_INET, &sin->sin_addr, client_addr, sizeof client_addr);
69+
this->logger.info("Handling incoming connection from: " + std::string(client_addr));
70+
// this will create a new worker to work with
71+
// TODO: add try/catch and handle too many workers exception
72+
manager.handle_request(handling_socket);
73+
}
74+
}
3075

31-
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;
76+
int Router::init_socket() {
77+
struct addrinfo listening_socket_description;
3578

3679
// first, load up address structs with getaddrinfo():
80+
// TODO error handling (what if there's no memory available)
3781
memset(&listening_socket_description, 0, sizeof listening_socket_description);
3882

3983
listening_socket_description.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever
4084
listening_socket_description.ai_socktype = SOCK_STREAM;
4185
listening_socket_description.ai_flags = AI_PASSIVE; // fill in my IP for me
42-
getaddrinfo(NULL, port.c_str(), &listening_socket_description, &results);
86+
getaddrinfo(NULL, this->port.c_str(), &listening_socket_description, &this->addr);
4387

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);
47-
48-
listen(listening_socket_fd, this->queue_size);
49-
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");
53-
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);
58-
59-
this->logger.debug("closing connection");
60-
freeaddrinfo(results);
61-
close(listening_socket_fd);
62-
close(new_socket_fd);
63-
64-
this->logger.debug("done");
65-
}
88+
// TODO error handling (what if we cannot open the socket)
89+
int listening_socket = socket(this->addr->ai_family, this->addr->ai_socktype, this->addr->ai_protocol);
90+
if (listening_socket < 0) {
91+
char * err = std::strerror(errno);
92+
throw RouterException("Error opening socket: " + std::string(err ? err : "unknown error"));
93+
}
6694

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();
95+
// TODO error handling (what if we can't bind)
96+
int check = bind(listening_socket, this->addr->ai_addr, this->addr->ai_addrlen);
97+
if (check < 0) {
98+
char * err = std::strerror(errno);
99+
throw RouterException("Error binding socket: " + std::string(err ? err : "unknown error"));
90100
}
91101

92-
return NULL;
102+
this->logger.debug("Got socket: " + std::to_string(listening_socket));
103+
return listening_socket;
93104
}

src/Router.h

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,38 @@
11
#ifndef SRC_ROUTER_H_
22
#define SRC_ROUTER_H_
3-
3+
#include <cstring>
44
#include <iostream>
5+
56
#include "Logger.h"
67

78
class Router {
89
private:
910
int queue_size;
11+
int listening_socket_fd;
12+
std::string port;
13+
struct addrinfo *addr;
1014
Logger logger;
15+
int init_socket();
16+
1117
public:
12-
Router(int qsize);
18+
Router(int qsize, std::string port);
1319
virtual ~Router();
14-
void watch(std::string port);
20+
void watch();
21+
};
22+
23+
using namespace std;
24+
// Possibly we could also add a stack trace here:
25+
// http://stackoverflow.com/questions/353180/how-do-i-find-the-name-of-the-calling-function
26+
class RouterException: public exception {
27+
std::string reason;
28+
29+
public:
30+
RouterException(std::string msg = "Unknown exception") {
31+
reason = msg;
32+
}
33+
virtual const char* what() const throw() {
34+
return reason.c_str();
35+
}
1536
};
1637

1738
#endif /* SRC_ROUTER_H_ */

src/Worker.cpp

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,48 @@
1+
#include <sys/types.h>
2+
#include <sys/socket.h>
3+
#include <netdb.h>
4+
#include <unistd.h>
5+
#include <stdlib.h>
6+
#include <cstring>
7+
#include <string.h>
8+
19
#include "Worker.h"
210
#include "BasicHTTP.h"
311

412
/*
513
* worker - uses an appropriate handler to serve the request
614
*/
715

8-
Worker::Worker() {
9-
// TODO Auto-generated constructor stub
10-
16+
Worker::Worker(int socket_fd) {
17+
this->logger = Logger("Worker");
18+
this->socket_fd = socket_fd;
1119
}
1220

1321
Worker::~Worker() {
14-
// TODO Auto-generated destructor stub
22+
// make sure to close the socket when we finish
23+
close(this->socket_fd);
1524
}
1625

26+
void Worker::handle_request() {
27+
char reply[100], *msg;
28+
29+
this->logger.info("Handling request via socket: " + std::to_string(this->socket_fd));
30+
// Send welcome message
31+
std::string string = "Welcome to HACKttp: " + std::to_string(this->socket_fd) + "\nYour message: ";
32+
msg = (char *) string.c_str();
33+
send(this->socket_fd, msg, strlen(msg), 0);
34+
35+
std::string response;
36+
while(1){
37+
memset(&reply, 0, sizeof reply);
38+
if(recv(this->socket_fd, reply, 100, 0) <= 0) break;
39+
response.append("HackTTP echo: ");
40+
response.append(reply);
41+
response.append("\nYour message: ");
42+
msg = (char *)response.c_str();
43+
send(this->socket_fd, msg, strlen(msg), 0);
44+
//reply[99] = '\0';
45+
printf("Sent back: %s", response.c_str());
46+
response.clear();
47+
}
48+
}

0 commit comments

Comments
 (0)