-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.cpp
More file actions
160 lines (130 loc) · 3.38 KB
/
server.cpp
File metadata and controls
160 lines (130 loc) · 3.38 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
#include "assert.h"
#include "positive.h"
#include "authorize.h"
#include "keytie.h"
#include "bank.h"
#include "server.h"
#include "execute.h"
using namespace BankOfEuler;
Server::Server(SCTX *sctx) {
this->sctx = sctx;
std::string values = sctx->home + "/values";
bank = new Bank(sctx, values.c_str());
}
Server::~Server() {
delete bank;
}
void Server::listen(const char *sconf) {
std::string conf = std::string(sctx->home) + std::string("/") + sconf;
execlp("stunnel", "stunnel", conf.c_str(), NULL);
assert(!"cannot exec stunnel, is it in your PATH?");
}
// consume http header, if available, and send http response header which
// is small enough to be buffered by stunnel in case the application insists
// on posting data before reading. this will allow the server to be accessed
// by clients constrained to speak https.
//
// this only works because our messages never start with 'P'.
//
// returns false if the peer has disconnected since the last message.
static bool handle_http() {
int c = getc(stdin);
if (c == -1)
return false;
if (c != 'P') {
ungetc(c, stdin);
return true;
}
for (const char *p = "POST / HTTP/1."; *p; ++p)
assert(*p == getc(stdin));
char a1 = getc(stdin);
while (1) {
char a2 = getc(stdin);
if (a1 == '\n' && a2 == '\n')
break;
if (a2 != '\r')
a1 = a2;
}
printf(
"HTTP/1.1 200 OK\r\n"
"Connection: Keep-Alive\r\n"
"Content-Type: application/x-BankOfEuler\r\n"
"\r\n"
);
return true;
}
void Server::accept() {
while (handle_http()) {
unsigned int magic = read_int32(stdin);
switch (magic) {
default:
assert(!"bad magic");
case PositiveRequest::magic:
{
PositiveRequest req;
req.read(stdin, false);
assert(req.verify(sctx));
PositiveChallenge chal;
chal.generate(sctx, req);
chal.write(stdout);
}
break;
case PositiveResponse::magic:
{
PositiveResponse resp;
resp.read(stdin, false);
assert(resp.verify(sctx));
PositiveProof proof;
proof.generate(sctx, resp);
proof.write(stdout);
}
break;
case AuthorizeRequest::magic:
{
AuthorizeRequest req;
req.read(stdin, false);
assert(req.verify(sctx));
AuthorizeChallenge chal;
chal.generate(sctx, req);
chal.write(stdout);
}
break;
case AuthorizeResponse::magic:
{
AuthorizeResponse resp;
resp.read(stdin, false);
assert(resp.verify(sctx));
AuthorizeCertificate proof;
proof.generate(sctx, resp);
proof.write(stdout);
}
break;
case KeytieRequest::magic:
{
KeytieRequest req;
req.read(stdin, false);
assert(req.verify(sctx));
KeytieCertificate cert;
cert.generate(sctx, req);
cert.write(stdout);
}
break;
case ExecuteRequest::magic:
{
ExecuteRequest req;
req.read(stdin, false);
assert(req.verify(sctx));
Number cmd_hash;
sctx->hash_init(cmd_hash);
req.command->hash_update(sctx, cmd_hash);
sctx->hash_final(cmd_hash);
Number result = bank->execute(req);
ExecuteCertificate cert;
cert.generate(sctx, cmd_hash, req, result);
cert.write(stdout);
}
break;
}
fflush(stdout);
}
}