14 #include <event2/http.h> |
14 #include <event2/http.h> |
15 #include <event2/event_struct.h> |
15 #include <event2/event_struct.h> |
16 |
16 |
17 #include "common.h" |
17 #include "common.h" |
18 #include "http.h" |
18 #include "http.h" |
|
19 #include "render_internal.h" |
19 #include "render.h" |
20 #include "render.h" |
20 #include "render_remote.h" |
|
21 #include "remote_node.h" |
21 #include "remote_node.h" |
22 #include "remote_pool.h" |
22 #include "remote_pool.h" |
|
23 |
|
24 // XXX: replace with a common one |
|
25 #include "render_remote.h" |
|
26 #include "render_multi.h" |
23 |
27 |
24 #define MIN_CHUNK_SIZE 4096 |
28 #define MIN_CHUNK_SIZE 4096 |
25 #define OVERFLOW_BUFFER 4096 |
29 #define OVERFLOW_BUFFER 4096 |
26 |
30 |
27 // do not do any userland socket output buffering |
31 // do not do any userland socket output buffering |
37 struct render_request { |
41 struct render_request { |
38 struct evhttp_request *http_request; |
42 struct evhttp_request *http_request; |
39 |
43 |
40 int headers_sent; |
44 int headers_sent; |
41 |
45 |
42 struct remote_render_ctx *remote_ctx; |
46 struct render_multi *render_info; |
43 |
47 |
44 size_t bytes_sent; |
48 size_t bytes_sent; |
45 |
49 |
46 int paused; |
50 int paused; |
47 }; |
51 }; |
48 |
52 |
49 // cb func prototypes |
53 // cb func prototypes |
50 void _render_http_written (struct evhttp_request *request, void *arg); |
54 static void _render_http_written (struct evhttp_request *request, void *arg); |
51 |
55 |
52 void _render_cleanup (struct render_request *ctx) { |
56 static void _render_cleanup (struct render_request *ctx) { |
53 // clean up |
57 // clean up |
54 free(ctx); |
58 free(ctx); |
55 } |
59 } |
56 |
60 |
57 void _render_sent (void *arg) { |
61 static void _render_sent (void *arg) { |
58 struct render_request *ctx = arg; |
62 struct render_request *ctx = arg; |
59 |
63 |
60 // set chunk size |
64 // set chunk size |
61 render_remote_set_recv(ctx->remote_ctx, MIN_CHUNK_SIZE, OVERFLOW_BUFFER); |
65 render_multi_set_recv(ctx->render_info, MIN_CHUNK_SIZE, OVERFLOW_BUFFER); |
62 |
66 |
63 // send headers |
67 // send headers |
64 evhttp_add_header(evhttp_request_get_output_headers(ctx->http_request), "Content-Type", "image/png"); |
68 evhttp_add_header(evhttp_request_get_output_headers(ctx->http_request), "Content-Type", "image/png"); |
65 evhttp_send_reply_start(ctx->http_request, HTTP_OK, "OK"); |
69 evhttp_send_reply_start(ctx->http_request, HTTP_OK, "OK"); |
66 |
70 |
70 ctx->headers_sent = 1; |
74 ctx->headers_sent = 1; |
71 |
75 |
72 printf("render [%p]: sent headers\n", ctx); |
76 printf("render [%p]: sent headers\n", ctx); |
73 } |
77 } |
74 |
78 |
75 void _render_data (struct evbuffer *buf, void *arg) { |
79 static void _render_data (struct evbuffer *buf, void *arg) { |
76 struct render_request *ctx = arg; |
80 struct render_request *ctx = arg; |
77 |
81 |
78 size_t buf_size = EVBUFFER_LENGTH(buf); |
82 size_t buf_size = EVBUFFER_LENGTH(buf); |
79 |
83 |
80 // ignore empty buffers, a result of render_remote_shake() |
84 // ignore empty buffers, a result of render_remote_shake() |
102 |
106 |
103 // keep a tally of total sent bytes |
107 // keep a tally of total sent bytes |
104 ctx->bytes_sent += buf_size; |
108 ctx->bytes_sent += buf_size; |
105 } |
109 } |
106 |
110 |
107 void _render_done (void *arg) { |
111 static void _render_done (void *arg) { |
108 struct render_request *ctx = arg; |
112 struct render_request *ctx = arg; |
109 |
113 |
110 // if we are paused, just shove the data into the http buffers, they might become larger than they should be, but it's easier to just move the data there and let render_remote complete |
114 // if we are paused, just shove the data into the http buffers, they might become larger than they should be, but it's easier to just move the data there and let render_remote complete |
111 if (ctx->paused) { |
115 if (ctx->paused) { |
112 printf("render [%p]: done: flushing the rest of our data\n", ctx); |
116 printf("render [%p]: done: flushing the rest of our data\n", ctx); |
113 ctx->paused = 0; |
117 ctx->paused = 0; |
114 |
118 |
115 render_remote_shake(ctx->remote_ctx); |
119 render_multi_shake(ctx->render_info); |
116 } |
120 } |
117 |
121 |
118 // send end |
122 // send end |
119 evhttp_send_reply_end(ctx->http_request); |
123 evhttp_send_reply_end(ctx->http_request); |
120 |
124 |
122 |
126 |
123 // the request is now done, clean up |
127 // the request is now done, clean up |
124 _render_cleanup(ctx); |
128 _render_cleanup(ctx); |
125 } |
129 } |
126 |
130 |
127 void _render_fail (void *arg) { |
131 static void _render_fail (void *arg) { |
128 struct render_request *ctx = arg; |
132 struct render_request *ctx = arg; |
129 |
133 |
130 if (ctx->headers_sent) { |
134 if (ctx->headers_sent) { |
131 // just terminate the PNG stream where it is |
135 // just terminate the PNG stream where it is |
132 evhttp_send_reply_end(ctx->http_request); |
136 evhttp_send_reply_end(ctx->http_request); |
137 printf("render [%p]: failed\n", ctx); |
141 printf("render [%p]: failed\n", ctx); |
138 |
142 |
139 _render_cleanup(ctx); |
143 _render_cleanup(ctx); |
140 } |
144 } |
141 |
145 |
142 void _render_http_lost (struct evhttp_request *req, void *arg) { |
146 static void _render_http_lost (struct evhttp_request *req, void *arg) { |
143 struct render_request *ctx = arg; |
147 struct render_request *ctx = arg; |
144 |
148 |
145 printf("render [%p]: lost http connection\n", ctx); |
149 printf("render [%p]: lost http connection\n", ctx); |
146 |
150 |
147 // cancel |
151 // cancel |
148 render_remote_cancel(ctx->remote_ctx); |
152 render_multi_cancel(ctx->render_info); |
149 |
153 |
150 _render_cleanup(ctx); |
154 _render_cleanup(ctx); |
151 } |
155 } |
152 |
156 |
153 void _render_http_written (struct evhttp_request *request, void *arg) { |
157 static void _render_http_written (struct evhttp_request *request, void *arg) { |
154 struct render_request *ctx = arg; |
158 struct render_request *ctx = arg; |
155 |
159 |
156 printf("render [%p]: http available for write\n", ctx); |
160 printf("render [%p]: http available for write\n", ctx); |
157 |
161 |
158 // unpause ourself |
162 // unpause ourself |
159 ctx->paused = 0; |
163 ctx->paused = 0; |
160 |
164 |
161 // shake out the buffers |
165 // shake out the buffers |
162 render_remote_shake(ctx->remote_ctx); |
166 render_multi_shake(ctx->render_info); |
163 } |
167 } |
164 |
168 |
165 void _http_render_execute (struct evhttp_request *request, u_int32_t img_w, u_int32_t img_h) { |
169 static void _http_render_execute (struct evhttp_request *request, u_int32_t img_w, u_int32_t img_h) { |
166 // render request context |
170 // render request context |
167 struct render_request *req_ctx = calloc(1, sizeof(struct render_request)); |
171 struct render_request *req_ctx = calloc(1, sizeof(struct render_request)); |
168 |
172 |
169 if (!req_ctx) |
173 if (!req_ctx) |
170 ERROR("calloc"); |
174 ERROR("calloc"); |
172 req_ctx->http_request = request; |
176 req_ctx->http_request = request; |
173 req_ctx->headers_sent = 0; |
177 req_ctx->headers_sent = 0; |
174 req_ctx->bytes_sent = 0; |
178 req_ctx->bytes_sent = 0; |
175 |
179 |
176 // render context |
180 // render context |
177 struct render *render; |
181 struct render render; |
178 |
182 |
179 if (!(render = render_alloc())) |
183 if (render_init(&render, RENDER_PNG)) |
180 ERROR("render_alloc"); |
184 ERROR("render_alloc"); |
181 |
185 |
182 if (render_set_mode(render, RENDER_PNG)) |
186 if (render_set_size(&render, img_w, img_h)) |
183 ERROR("render_set_mode"); |
|
184 |
|
185 if (render_set_size(render, img_w, img_h)) |
|
186 ERROR("render_set_size"); |
187 ERROR("render_set_size"); |
187 |
188 |
188 if (render_region_full(render)) |
189 if (render_region_full(&render)) |
189 ERROR("render_region_full"); |
190 ERROR("render_region_full"); |
190 |
191 |
|
192 /* |
191 // pick a render_node |
193 // pick a render_node |
192 struct remote_node *node_info; |
194 struct remote_node *node_info; |
193 |
195 |
194 if ((node_info = remote_pool_get(&remote_pool)) == NULL) |
196 if ((node_info = remote_pool_get(&remote_pool)) == NULL) |
195 ERROR("remote_pool_get"); |
197 ERROR("remote_pool_get"); |
|
198 */ |
196 |
199 |
197 // initiate the remote render operation |
200 // initiate the remote render operation |
198 if ((req_ctx->remote_ctx = render_remote(render, node_info, |
201 if ((req_ctx->render_info = render_multi(&render, &remote_pool, |
199 &_render_sent, |
202 &_render_sent, |
200 &_render_data, |
203 &_render_data, |
201 &_render_done, |
204 &_render_done, |
202 &_render_fail, |
205 &_render_fail, |
203 req_ctx |
206 req_ctx |
204 )) == NULL) |
207 )) == NULL) |
205 ERROR("render_remote"); |
208 ERROR("render_multi"); |
206 |
209 |
207 // set close cb |
210 // set close cb |
208 evhttp_set_reply_abortcb(request, &_render_http_lost, req_ctx); |
211 evhttp_set_reply_abortcb(request, &_render_http_lost, req_ctx); |
209 |
212 |
210 printf("render [%p]: started\n", req_ctx); |
213 printf("render [%p]: started\n", req_ctx); |
227 char *peer_address; |
230 char *peer_address; |
228 u_short peer_port; |
231 u_short peer_port; |
229 |
232 |
230 evhttp_request_get_peer(request, &peer_address, &peer_port); |
233 evhttp_request_get_peer(request, &peer_address, &peer_port); |
231 |
234 |
232 u_int32_t img_w = 256, img_h = 256; |
235 unsigned long int img_w = 256, img_h = 256; |
233 |
236 |
234 // parse request arguments |
237 // parse request arguments |
235 struct http_qarg qarg_spec[] = { |
238 struct http_qarg qarg_spec[] = { |
236 { "w", QARG_UINT, &img_w }, |
239 { "w", QARG_UINT, &img_w }, |
237 { "h", QARG_UINT, &img_h }, |
240 { "h", QARG_UINT, &img_h }, |
239 }; |
242 }; |
240 |
243 |
241 http_qarg_parse(request, qarg_spec); |
244 http_qarg_parse(request, qarg_spec); |
242 |
245 |
243 // request log |
246 // request log |
244 printf("REQ: [%s:%d] method=%d, uri=%s, img_w=%d, img_h=%d\n", peer_address, peer_port, evhttp_request_get_type(request), uri, img_w, img_h); |
247 printf("REQ: [%s:%d] method=%d, uri=%s, img_w=%lu, img_h=%lu\n", peer_address, peer_port, evhttp_request_get_type(request), uri, img_w, img_h); |
245 |
248 |
246 // do it |
249 // do it |
247 _http_render_execute(request, img_w, img_h); |
250 _http_render_execute(request, img_w, img_h); |
248 } |
251 } |
249 |
252 |