forked from georgesofianosgr/HTTP-Web-Server
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhttpserver.cpp
142 lines (121 loc) · 3.22 KB
/
httpserver.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#include "httpserver.h"
#include <iostream>
#include <sstream>
#include <thread>
#include "httprequest.h"
#include "httpresponse.h"
using namespace web;
// Global Functions
std::string ToString(int data)
{
std::stringstream buffer;
buffer << data;
return buffer.str();
}
// Constructor
HttpServer::HttpServer(int port)
: _logging([] (const std::string& message) { std::cout << message << std::endl; })
{
// Socket Settings
ZeroMemory(&_hints, sizeof(_hints));
_hints.ai_family = AF_INET;
_hints.ai_flags = AI_PASSIVE;
_hints.ai_socktype = SOCK_STREAM;
_hints.ai_protocol = IPPROTO_TCP;
// Initialize Data
_maxConnections = 50;
_listeningSocket = INVALID_SOCKET;
_socketVersion = MAKEWORD(2,2);
_port = port;
}
void HttpServer::SetLogging(std::function<void(const std::string&)> logging)
{
this->_logging = logging;
}
int HttpServer::Port() const
{
return _port;
}
void HttpServer::SetPort(int port)
{
_port = port;
}
std::string HttpServer::LocalUrl() const
{
std::stringstream ss;
ss << "http://localhost:" << _port << "/";
return ss.str();
}
// Main Functions
bool HttpServer::Init()
{
// Start Winsocket
auto resultCode = WSAStartup(_socketVersion, &_wsaData);
if(0 != resultCode)
{
this->_logging("Initialize Failed \nError Code : " + ToString(resultCode));
return false;
}
return true;
}
bool HttpServer::Start()
{
std::string port = ToString(_port);
// Resolve Local Address And Port
auto resultCode = getaddrinfo(NULL, port.c_str(), &_hints, &_result);
if (0 != resultCode)
{
this->_logging("Resolving Address And Port Failed \nError Code: " + ToString(resultCode));
return false;
}
// Create Socket
_listeningSocket = socket(_hints.ai_family, _hints.ai_socktype, _hints.ai_protocol);
if (INVALID_SOCKET == _listeningSocket)
{
this->_logging("Could't Create Socket");
return false;
}
// Bind
resultCode = bind(_listeningSocket, _result->ai_addr, (int)_result->ai_addrlen);
if (SOCKET_ERROR == resultCode)
{
this->_logging("Bind Socket Failed");
return false;
}
// Listen
resultCode = listen(_listeningSocket, _maxConnections);
if (SOCKET_ERROR == resultCode)
{
this->_logging("Listening On Port " + ToString(_port) + " Failed");
return false;
}
else
{
this->_logging("-Server Is Up And Running.\n--Listening On Port " + ToString(_port) + "...");
}
return true;
}
void HttpServer::WaitForRequests(std::function<int (const Request &, Response &)> onConnection)
{
while (true)
{
sockaddr_in clientInfo;
int clientInfoSize = sizeof(clientInfo);
auto socket = accept(_listeningSocket, (sockaddr*)&clientInfo, &clientInfoSize);
if (INVALID_SOCKET == socket)
{
this->_logging("Accepting Connection Failed");
}
else
{
this->_logging("Spinning thread to handle request");
std::thread t(Request::handleRequest, onConnection, Request(socket, clientInfo));
t.detach();
}
}
}
void HttpServer::Stop()
{
closesocket(_listeningSocket);
WSACleanup();
}