32 #include "../public/nsapi.h" |
32 #include "../public/nsapi.h" |
33 |
33 |
34 #include "sessionhandler.h" |
34 #include "sessionhandler.h" |
35 #include "httprequest.h" |
35 #include "httprequest.h" |
36 #include "httpparser.h" |
36 #include "httpparser.h" |
|
37 |
|
38 typedef struct _event_http_io { |
|
39 HTTPRequest *request; |
|
40 HttpParser *parser; |
|
41 } EventHttpIO; |
37 |
42 |
38 SessionHandler* create_basic_session_handler() { |
43 SessionHandler* create_basic_session_handler() { |
39 BasicSessionHandler *handler = malloc(sizeof(BasicSessionHandler)); |
44 BasicSessionHandler *handler = malloc(sizeof(BasicSessionHandler)); |
40 handler->threadpool = threadpool_new(8); |
45 handler->threadpool = threadpool_new(8); |
41 handler->sh.enqueue_connection = basic_enq_conn; |
46 handler->sh.enqueue_connection = basic_enq_conn; |
98 |
103 |
99 |
104 |
100 return NULL; |
105 return NULL; |
101 } |
106 } |
102 |
107 |
103 |
108 /* ----- event session handler ----- */ |
|
109 |
|
110 SessionHandler* create_event_session_handler() { |
|
111 EventSessionHandler *handler = malloc(sizeof(EventSessionHandler)); |
|
112 handler->eventhandler = get_default_event_handler(); |
|
113 handler->sh.enqueue_connection = evt_enq_conn; |
|
114 return (SessionHandler*)handler; |
|
115 } |
|
116 |
|
117 void evt_enq_conn(SessionHandler *handler, Connection *conn) { |
|
118 HTTPRequest *request = http_request_new(); |
|
119 request->connection = conn; |
|
120 |
|
121 // set socket non blocking |
|
122 int flags; |
|
123 if (-1 == (flags = fcntl(conn->fd, F_GETFL, 0))) { |
|
124 flags = 0; |
|
125 } |
|
126 if (fcntl(conn->fd, F_SETFL, flags | O_NONBLOCK) != 0) { |
|
127 perror("Error: start_event_session: fcntl"); |
|
128 // TODO: error |
|
129 } |
|
130 |
|
131 // TODO: remove code redundancy (basic_run_session) |
|
132 |
|
133 // read request |
|
134 netbuf *buf = malloc(sizeof(netbuf)); |
|
135 buf->rdtimeout = 120; |
|
136 buf->pos = 0; |
|
137 buf->cursize = 0; |
|
138 buf->maxsize = 2048; |
|
139 buf->sd = &conn->fd; |
|
140 buf->inbuf = malloc(2048); |
|
141 buf->errmsg = NULL; |
|
142 |
|
143 request->netbuf = buf; |
|
144 |
|
145 HttpParser *parser = http_parser_new(request); |
|
146 |
|
147 EventHttpIO *io = malloc(sizeof(EventHttpIO)); |
|
148 if(io == NULL) { |
|
149 // TODO: error handling |
|
150 } |
|
151 io->request = request; |
|
152 io->parser = parser; |
|
153 |
|
154 /* |
|
155 * to start the request handling, we begin with a poll on the socket, |
|
156 * |
|
157 * evt_enq_conn() --> event handler --> handle_request() |
|
158 */ |
|
159 |
|
160 event_handler_t *ev = ((EventSessionHandler*)handler)->eventhandler; |
|
161 |
|
162 event_t *event = malloc(sizeof(event_t)); |
|
163 event->fn = evt_request_input; |
|
164 event->cookie = io; |
|
165 |
|
166 if(ev_pollin(ev, conn->fd, event) != 0) { |
|
167 perror("poll"); |
|
168 } |
|
169 } |
|
170 |
|
171 void evt_request_input(event_handler_t *handler, event_t *event) { |
|
172 EventHttpIO *io = event->cookie; |
|
173 HttpParser *parser = io->parser; |
|
174 HTTPRequest *request = io->request; |
|
175 netbuf *buf = request->netbuf; |
|
176 |
|
177 int state; |
|
178 int r; |
|
179 r = read( |
|
180 request->connection->fd, |
|
181 buf->inbuf + buf->pos, |
|
182 buf->maxsize - buf->pos); |
|
183 if(r == -1) { |
|
184 // TODO: error handling |
|
185 fprintf(stderr, "%s\n", "Error: Cannot read from socket"); |
|
186 return; |
|
187 } |
|
188 |
|
189 buf->cursize += r; |
|
190 state = http_parser_process(parser); |
|
191 if(state == 2) { |
|
192 // TODO: error handling |
|
193 fprintf(stderr, "%s\n", "Error: Cannot parse http request"); |
|
194 return; |
|
195 } else if(state == 1) { |
|
196 // we need more data -> begin poll, which repeats this function |
|
197 ev_pollin(handler, request->connection->fd, event); |
|
198 // TODO: check ev_pollin return value for errors |
|
199 return; |
|
200 } |
|
201 |
|
202 // we are done with reading |
|
203 |
|
204 // set socket blocking |
|
205 int flags; |
|
206 if (-1 == (flags = fcntl(request->connection->fd, F_GETFL, 0))) { |
|
207 flags = 0; |
|
208 } |
|
209 if (fcntl(request->connection->fd, F_SETFL, flags & ~O_NONBLOCK) != 0) { |
|
210 perror("Error: evt_request_input: fcntl"); |
|
211 // TODO: critical error |
|
212 } |
|
213 |
|
214 r = handle_request(request); |
|
215 } |