run.c
4.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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#include <poll.h> /* for poll system call and related */
#include <string.h> /* for memset and stuff */
#include <stdlib.h> /* for exit */
#include <errno.h> /* for errno */
#include <unistd.h>
#include <ctype.h>
#include <time.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "server.h"
#include "socket.h"
#include "logger.h"
#include "signalHandling.h"
#include "interface/class.h"
#include "interface/stream_reader.h"
#include "interface/stream_writer.h"
#include "interface/logger.h"
//* @TODO: to be removed
#include "http/request.h"
#include "http/request/parser.h"
#include "http/message/queue.h"
#include "http/response.h"
#include "http/response/writer.h"
//* until here
#undef MAX
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#include "poll.c"
#include "handle_accept.c"
#include "read.c"
void
serverRun(Server this)
{
loggerLog(this->logger, LOGGER_INFO, "service started");
/**
* @TODO: actually this is the main loop of my server. When
* stuff becomes more complicated it might be feasabible to
* split stuff into separate processes. This will definetly
* involve some IPC and syncing. Right now as this is actually
* only a simple HTTP server implementation we go on with
* this single process.
* What we can first do to get some processing between read/write
* cicles is to use the poll timeout.
*/
while (!doShutdown) /* until error or signal */
{
int events;
unsigned int i;
events = serverPoll(this);
if (doShutdown) break;
for (i=0; i < this->nfds; i++) {
int fd = (this->fds)[i].fd;
int naccs = 10, nreads = 10, nwrites = 10;
if (0 >= events) break;
if (0 != ((this->fds)[i].revents & POLLIN) && 0 < nreads) {
events--;
/**
* handle accept
*/
if (this->sock->handle == (this->fds)[i].fd) {
while(-1 != serverHandleAccept(this) && 0 < naccs) {
naccs--;
switch(errno) {
case EAGAIN:
loggerLog(this->logger,
LOGGER_DEBUG,
"server accept blocks");
break;
default:
loggerLog(this->logger,
LOGGER_DEBUG,
"server accept error");
break;
}
}
}
/**
* handle reads
*/
else {
nreads--;
/**
* do some other processing
* @TODO: actually this will hard assume that our stream reader
* is a http parser and it has its queue...think about more
* generalizing here.
*/
int size;
if (0 >= (size=serverRead(this, i))) {
serverCloseConn(this, i);
}
else {
int j;
HttpMessageQueue reqq = ((HttpRequestParser) \
(this->conns)[fd].reader)->request_queue;
HttpMessageQueue respq = ((HttpResponseWriter) \
(this->conns)[fd].writer)->response_queue;
for (j=0; j<reqq->nmsgs; j++) {
/**
* @TODO: for now simply remove request and send not found.
* Make this sane.
*/
HttpRequest request = (HttpRequest)(reqq->msgs[j]);
HttpMessage response = NULL;
if (0 == strcmp("GET", request->method) &&
0 == strcmp("/me/", request->uri)) {
response = (HttpMessage)httpResponseMe();
}
else if (0 == strcmp("GET", request->method) &&
0 == strcmp("/image/", request->uri)) {
response = (HttpMessage)httpResponseImage();
}
else {
response = (HttpMessage)httpResponse404();
}
if (httpMessageHasKeepAlive(reqq->msgs[j])) {
httpHeaderAdd(
&(response->header),
new(HttpHeader, "Connection", "Keep-Alive"));
}
else {
httpHeaderAdd(
&(response->header),
new(HttpHeader, "Connection", "Close"));
}
respq->msgs[(respq->nmsgs)++] = response;
response = NULL;
delete(&(reqq->msgs[j]));
(this->fds)[i].events |= POLLOUT;
}
reqq->nmsgs = 0;
}
}
}
/**
* handle writes
*/
if (0 != ((this->fds)[i].revents & POLLOUT) && 0 < nwrites) {
HttpResponseWriter writer =
(HttpResponseWriter)(this->conns)[fd].writer;
HttpMessage message;
events--;
nwrites--;
message = (HttpMessage)streamWriterWrite(writer, fd);
if (NULL == message) {
(this->fds)[i].events &= ~POLLOUT;
}
else {
delete(&message);
serverCloseConn(this, i);
}
}
}
}
}
// vim: set ts=4 sw=4: