-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathHTTP_server.cpp
More file actions
222 lines (187 loc) · 4.61 KB
/
Copy pathHTTP_server.cpp
File metadata and controls
222 lines (187 loc) · 4.61 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
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
/*
Comments in this code written in russian language for students
*/
#include "stdafx.h"
const int LISTEN_PORT = 8080;
#if ! defined(_WIN32)
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#else
#pragma comment(lib,"Ws2_32.lib")
#include <winsock2.h>
#include <WS2tcpip.h>
#include <io.h>
#define write _write
#define close _close
#endif
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
using namespace std;
typedef struct sockaddr_in address_t;
typedef struct sockaddr sockaddr_t;
string programm_path;
string http_root_folder;
extern void serve(int client);
//
// Ôóíêöèÿ âîçâðàùàåò ñòðîêó ñ IP-àäðåñîì WEB-áðàóçåðà, ñîåäèíèâøåãîñÿ ñ ñåðâåðîì.
// IP-àäðåñ "âû÷èñëÿåòñÿ" íà îñíîâå ñîåäèí¸ííîãî ñîåêòà
//
string get_peer_address(int sock, int &port)
{
socklen_t len;
struct sockaddr_storage addr;
char ipstr[INET6_ADDRSTRLEN];
len = sizeof addr;
getpeername(sock, (struct sockaddr*)&addr, &len);
// deal with both IPv4 and IPv6:
if (addr.ss_family == AF_INET) {
struct sockaddr_in *s = (struct sockaddr_in *)&addr;
port = ntohs(s->sin_port);
inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof ipstr);
}
else { // AF_INET6
struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr;
port = ntohs(s->sin6_port);
inet_ntop(AF_INET6, &s->sin6_addr, ipstr, sizeof ipstr);
}
return string(ipstr);
}
// Ïå÷àòü â ôàéë èíôîðìàöèè î âõîäÿùåì TCP ñîåäèíåíèè
// It takes an IP address of interface which accepted connection
void log_AcceptTcpConnection(
FILE * file,
address_t client_addr,
int sock)
{
int port;
string peer = get_peer_address(sock, port);
char ipstr[INET6_ADDRSTRLEN];
inet_ntop(AF_INET, &client_addr.sin_addr, ipstr, sizeof ipstr);
fprintf(file, "TCP Connection from %s:%d to %s:%d\n",
ipstr,
htons(client_addr.sin_port),
peer.c_str(),
LISTEN_PORT
);
// You can modify this for writing connection info to database
}
// Under Windows HTTP_ROOT is directory where sever's executable file is located
// Unnder Linux it take pages from user's home directory
// TODO: Set HTTP_ROOT by config or/and by command line parameter
void Prepare_HTTP_ROOT()
{
char * env_root = getenv("HTTP_ROOT");
if(env_root != NULL)
{
http_root_folder = env_root;
return;
}
#if defined (_WIN32)
http_root_folder = programm_path.substr(0, programm_path.find_last_of("\\") + 1);
#else
// We use it in classroom
http_root_folder = "/home";
struct passwd *pw = getpwuid(getuid());
if (pw)
http_root_folder = pw->pw_dir;
else
http_root_folder = "/tmp";
#endif
}
// all bits set - allow access, otherwise deny any access
unsigned int CheckRemoteRights(
address_t client_addr,
address_t server_addr,
int sock)
{
// Full access for everybody. You can implement access rules here
return (unsigned int)-1;
}
//
// Ãëàâíàÿ ôóíêöèÿ ñåðâåðà. Âõîä â ïðîãðàììó - ôóíêöèÿ main()
//
int main(int argc, char *argv[])
{
int client, server;
address_t client_addr, server_addr;
int size_of_client_address;
programm_path = argv[0];
Prepare_HTTP_ROOT();
#if defined(WIN32)
WSADATA ws;
if (0 > WSAStartup(MAKEWORD(2, 2), &ws))
{
//error = WSAGetLastError();
perror("Unable initializw WinSock library");
exit(1);
}
#endif
server = socket(AF_INET, SOCK_STREAM, 0);
if (server == -1)
{
perror("Unable create socket");
exit(-1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(LISTEN_PORT);
if (bind(server, (sockaddr_t *)&server_addr, sizeof(server_addr)) < 0)
{
perror("Unable bind socket");
exit(-1);
}
if (0 > listen(server, 1000))
{
perror("Unable accept connection");
exit(-1);
}
fprintf(stdout, "Server ready to accept HTTP requests\n");
while (true)
{
size_of_client_address = sizeof(client_addr);
client = accept(server, (sockaddr_t *)&client_addr, (socklen_t*)&size_of_client_address);
if (CheckRemoteRights(client_addr, server_addr, client) != (unsigned int)-1)
{
log_AcceptTcpConnection(stdout, client_addr, client);
close(client);
continue;
}
#if ! defined(_WIN32)
if (client < 0)
{
perror("Unable accept connection");
exit(-1);
}
switch (fork())
{
case -1:
perror("Unable fork()");
break;
case 0:
serve(client);
break;
default:
log_AcceptTcpConnection(stdout, client_addr, client);
close(client);
break;
}
#else
if (client < 0)
{
fprintf(stderr, "Unable accept connection: %d\n", WSAGetLastError());
exit(-1);
}
log_AcceptTcpConnection(stdout, client_addr, client);
serve(client);
#endif
}
return 0;
}