use github repo as central
This commit is contained in:
118
test/httpserver/HTTPServer.cpp
Normal file
118
test/httpserver/HTTPServer.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
#include "HTTPServer.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// the terminator logic, run in a separate thread
|
||||
|
||||
void *tfunc(void* obj) {
|
||||
((HTTPServer*) obj)->RunTerminator();
|
||||
}
|
||||
|
||||
void* sfunc(void* obj) {
|
||||
((HTTPServer*) obj)->RunServer();
|
||||
}
|
||||
|
||||
void error(string msg) {
|
||||
cerr << msg << endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void msg(string msg) {
|
||||
cout << msg << endl;
|
||||
}
|
||||
|
||||
HTTPServer::HTTPServer(int port) {
|
||||
this->portno = port;
|
||||
}
|
||||
|
||||
HTTPServer::~HTTPServer() {
|
||||
}
|
||||
|
||||
void HTTPServer::StartServer() {
|
||||
// socket(int domain, int type, int protocol)
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sockfd < 0)
|
||||
error("Opening socket");
|
||||
|
||||
// clear the struct's memory
|
||||
bzero((char *) &serv_addr, sizeof (serv_addr));
|
||||
|
||||
// setup the host_addr structure
|
||||
serv_addr.sin_family = AF_INET;
|
||||
|
||||
// automatically be filled with current host's IP address which is localhost
|
||||
serv_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
// convert short to network port order
|
||||
serv_addr.sin_port = htons(portno);
|
||||
|
||||
// to avoid waiting for limbo connection when debugging
|
||||
int en = 1;
|
||||
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &en, sizeof (int));
|
||||
|
||||
// bind(int fd, struct sockaddr *local_addr, socklen_t addr_length)
|
||||
// This bind() call will bind the socket to the current IP address on our port
|
||||
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0)
|
||||
error("On binding");
|
||||
// This listen() function will start filling the backlog queue with clients
|
||||
// The maximum size for the backlog queue to 1
|
||||
listen(sockfd, 1);
|
||||
|
||||
clilen = sizeof (cli_addr);
|
||||
|
||||
// create the server thread
|
||||
pthread_create(&server, NULL, sfunc, this);
|
||||
}
|
||||
|
||||
void HTTPServer::StartTerminator() {
|
||||
// create the terminator thread
|
||||
pthread_create(&terminator, NULL, tfunc, this);
|
||||
}
|
||||
|
||||
void HTTPServer::RunServer() {
|
||||
msg("Server is online!");
|
||||
while (true) {
|
||||
// The accept() function blocks untill the backlog has elements
|
||||
// It then stores the info of the client socket in newsockfd
|
||||
int csockn = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
|
||||
if (csockn < 0)
|
||||
msg("Failed on accept.");
|
||||
|
||||
printf("Incoming connection from %s port %ho\n",
|
||||
inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));
|
||||
ServerThread* clt = new ServerThread(csockn);
|
||||
clt->Serve();
|
||||
aclients.push_front(clt);
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPServer::RunTerminator() {
|
||||
while (true) {
|
||||
sleep(0.01);
|
||||
time_t now = time(NULL);
|
||||
int nc = aclients.size();
|
||||
int ttl = 1 / (double) (nc > 0 ? nc : 1); //in seconds
|
||||
for (list<ServerThread*>::iterator list_iter = aclients.begin(); list_iter != aclients.end();) {
|
||||
ServerThread* st = *list_iter;
|
||||
int runningtime = difftime(now, st->GetStartTime());
|
||||
if (st->IsMarked() || (runningtime >= ttl && st->Terminate(false))) {
|
||||
if (st->IsMarked())
|
||||
cout << "Client on socket " << st->GetSocket() << " self terminated" << endl;
|
||||
else
|
||||
cout << "Terminated client on socket " << st->GetSocket() << endl;
|
||||
delete st;
|
||||
list_iter = aclients.erase(list_iter);
|
||||
} else {
|
||||
list_iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPServer::Stop() {
|
||||
close(sockfd);
|
||||
if (server)
|
||||
pthread_cancel(server);
|
||||
if (terminator)
|
||||
pthread_cancel(terminator);
|
||||
}
|
||||
Reference in New Issue
Block a user