-
Notifications
You must be signed in to change notification settings - Fork 34
Expand file tree
/
Copy pathHTTPServer.h
More file actions
executable file
·98 lines (77 loc) · 3.64 KB
/
HTTPServer.h
File metadata and controls
executable file
·98 lines (77 loc) · 3.64 KB
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
/**
httpserver
HTTPServer.h
Copyright 2011-2025 Ramsey Kant
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef _HTTPSERVER_H_
#define _HTTPSERVER_H_
#include "Client.h"
#include "HTTPRequest.h"
#include "HTTPResponse.h"
#include "ResourceHost.h"
#include <array>
#include <memory>
#include <unordered_map>
#include <vector>
#include <string>
#include <sys/time.h>
#ifdef __linux__
#include <kqueue/sys/event.h> // libkqueue Linux - only works if libkqueue is compiled from Github sources
#else
#include <sys/event.h> // kqueue BSD / OS X
#endif
constexpr int32_t INVALID_SOCKET = -1;
constexpr uint32_t QUEUE_SIZE = 1024;
constexpr uint32_t MAX_CLIENTS = 1024;
class HTTPServer {
// Server Socket
int32_t listenPort;
int32_t listenSocket = INVALID_SOCKET; // Descriptor for the listening socket
struct sockaddr_in serverAddr; // Structure for the server address
int32_t dropUid; // setuid to this after bind()
int32_t dropGid; // setgid to this after bind()
// Kqueue
struct timespec kqTimeout = {2, 0}; // Block for 2 seconds and 0ns at the most
int32_t kqfd = -1; // kqueue descriptor
std::array<struct kevent, QUEUE_SIZE> evList = {}; // Events that have triggered a filter in the kqueue (max QUEUE_SIZE at a time)
// Client map, maps Socket descriptor to Client object
std::unordered_map<int, std::shared_ptr<Client>> clientMap;
// Resources / File System
std::vector<std::shared_ptr<ResourceHost>> hostList; // Contains all ResourceHosts
std::unordered_map<std::string, std::shared_ptr<ResourceHost>, std::hash<std::string>, std::equal_to<>> vhosts; // Virtual hosts. Maps a host string to a ResourceHost to service the request
// Connection processing
void updateEvent(int32_t ident, int16_t filter, uint16_t flags, uint32_t fflags, int32_t data, void* udata);
void acceptConnection();
std::shared_ptr<Client> getClient(int32_t clfd);
void disconnectClient(std::shared_ptr<Client> cl, bool mapErase = true);
void readClient(std::shared_ptr<Client> cl, int32_t data_len); // Client read event
bool writeClient(std::shared_ptr<Client> cl, int32_t avail_bytes); // Client write event
std::shared_ptr<ResourceHost> getResourceHostForRequest(const std::shared_ptr<HTTPRequest> req);
// Request handling
void handleRequest(std::shared_ptr<Client> cl, std::shared_ptr<HTTPRequest> req);
void handleGet(std::shared_ptr<Client> cl, const std::shared_ptr<HTTPRequest> req);
void handleOptions(std::shared_ptr<Client> cl, const std::shared_ptr<HTTPRequest> req);
void handleTrace(std::shared_ptr<Client> cl, std::shared_ptr<HTTPRequest> req);
// Response
void sendStatusResponse(std::shared_ptr<Client> cl, int32_t status, std::string const& msg = "");
void sendResponse(std::shared_ptr<Client> cl, std::unique_ptr<HTTPResponse> resp, bool disconnect);
public:
volatile bool canRun = false;
public:
HTTPServer(std::vector<std::string> const& vhost_aliases, int32_t port, std::string const& diskpath, int32_t drop_uid=0, int32_t drop_gid=0);
~HTTPServer();
bool start();
void stop();
// Main event loop
void process();
};
#endif