OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrCaps.h" | 8 #include "GrCaps.h" |
9 #include "GrContextFactory.h" | 9 #include "GrContextFactory.h" |
10 #include "SkCanvas.h" | 10 #include "SkCanvas.h" |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 if (redirect) { | 165 if (redirect) { |
166 MHD_add_response_header (response, "Location", redirectUrl); | 166 MHD_add_response_header (response, "Location", redirectUrl); |
167 status = MHD_HTTP_SEE_OTHER; | 167 status = MHD_HTTP_SEE_OTHER; |
168 } | 168 } |
169 | 169 |
170 int ret = MHD_queue_response(connection, status, response); | 170 int ret = MHD_queue_response(connection, status, response); |
171 MHD_destroy_response(response); | 171 MHD_destroy_response(response); |
172 return ret; | 172 return ret; |
173 } | 173 } |
174 | 174 |
175 typedef int (*UrlHandler)(Request* request, MHD_Connection* connection, | 175 class UrlHandler { |
176 const char* upload_data, size_t* upload_data_size); | 176 public: |
| 177 virtual ~UrlHandler() {} |
| 178 virtual bool canHandle(const char* method, const char* url) = 0; |
| 179 virtual int handle(Request* request, MHD_Connection* connection, |
| 180 const char* upload_data, size_t* upload_data_size) = 0; |
| 181 }; |
177 | 182 |
178 int rootHandler(Request* request, MHD_Connection* connection, | 183 class InfoHandler : public UrlHandler { |
179 const char* upload_data, size_t* upload_data_size) { | 184 public: |
180 return SendTemplate(connection); | 185 bool canHandle(const char* method, const char* url) override { |
181 } | 186 return 0 == strcmp(method, MHD_HTTP_METHOD_GET) && |
182 | 187 0 == strcmp(url, "/cmd"); |
183 int postHandler(Request* request, MHD_Connection* connection, | |
184 const char* upload_data, size_t* upload_data_size) { | |
185 UploadContext* uc = request->fUploadContext; | |
186 | |
187 // New connection | |
188 if (!uc) { | |
189 // TODO make this a method on request | |
190 uc = new UploadContext; | |
191 uc->connection = connection; | |
192 uc->fPostProcessor = MHD_create_post_processor(connection, kBufferSize, | |
193 &process_upload_data, uc)
; | |
194 SkASSERT(uc->fPostProcessor); | |
195 | |
196 request->fUploadContext = uc; | |
197 return MHD_YES; | |
198 } | 188 } |
199 | 189 |
200 // in process upload | 190 int handle(Request* request, MHD_Connection* connection, |
201 if (0 != *upload_data_size) { | 191 const char* upload_data, size_t* upload_data_size) override { |
202 SkASSERT(uc->fPostProcessor); | 192 if (request->fPicture.get()) { |
203 MHD_post_process(uc->fPostProcessor, upload_data, *upload_data_size); | 193 return SendJSON(connection, request->fPicture); |
204 *upload_data_size = 0; | 194 } |
205 return MHD_YES; | 195 return MHD_NO; |
| 196 } |
| 197 }; |
| 198 |
| 199 class ImgHandler : public UrlHandler { |
| 200 public: |
| 201 bool canHandle(const char* method, const char* url) override { |
| 202 static const char* kBasePath = "/img"; |
| 203 return 0 == strcmp(method, MHD_HTTP_METHOD_GET) && |
| 204 0 == strncmp(url, kBasePath, strlen(kBasePath)); |
206 } | 205 } |
207 | 206 |
208 // end of upload | 207 int handle(Request* request, MHD_Connection* connection, |
209 MHD_destroy_post_processor(uc->fPostProcessor); | 208 const char* upload_data, size_t* upload_data_size) override { |
210 uc->fPostProcessor = nullptr; | 209 if (request->fPNG.get()) { |
| 210 SkData* data = request->fPNG.get(); |
| 211 return SendData(connection, data, "image/png"); |
| 212 } |
| 213 return MHD_NO; |
| 214 } |
| 215 }; |
211 | 216 |
212 // TODO response | 217 class PostHandler : public UrlHandler { |
213 SkString error; | 218 public: |
214 if (!setupAndDrawToCanvas(request, &error)) { | 219 bool canHandle(const char* method, const char* url) override { |
215 // TODO send error | 220 return 0 == strcmp(method, MHD_HTTP_METHOD_POST) && |
216 return MHD_YES; | 221 0 == strcmp(url, "/new"); |
217 } | 222 } |
218 | 223 |
219 return SendTemplate(connection, true, "/"); | 224 int handle(Request* request, MHD_Connection* connection, |
220 } | 225 const char* upload_data, size_t* upload_data_size) override { |
| 226 UploadContext* uc = request->fUploadContext; |
221 | 227 |
222 int imgHandler(Request* request, MHD_Connection* connection, | 228 // New connection |
223 const char* upload_data, size_t* upload_data_size) { | 229 if (!uc) { |
224 if (request->fPNG.get()) { | 230 // TODO make this a method on request |
225 SkData* data = request->fPNG.get(); | 231 uc = new UploadContext; |
226 return SendData(connection, data, "image/png"); | 232 uc->connection = connection; |
| 233 uc->fPostProcessor = MHD_create_post_processor(connection, kBufferSi
ze, |
| 234 &process_upload_data,
uc); |
| 235 SkASSERT(uc->fPostProcessor); |
| 236 |
| 237 request->fUploadContext = uc; |
| 238 return MHD_YES; |
| 239 } |
| 240 |
| 241 // in process upload |
| 242 if (0 != *upload_data_size) { |
| 243 SkASSERT(uc->fPostProcessor); |
| 244 MHD_post_process(uc->fPostProcessor, upload_data, *upload_data_size)
; |
| 245 *upload_data_size = 0; |
| 246 return MHD_YES; |
| 247 } |
| 248 |
| 249 // end of upload |
| 250 MHD_destroy_post_processor(uc->fPostProcessor); |
| 251 uc->fPostProcessor = nullptr; |
| 252 |
| 253 // TODO response |
| 254 SkString error; |
| 255 if (!setupAndDrawToCanvas(request, &error)) { |
| 256 // TODO send error |
| 257 return MHD_YES; |
| 258 } |
| 259 |
| 260 return SendTemplate(connection, true, "/"); |
227 } | 261 } |
228 return MHD_NO; | 262 }; |
229 } | |
230 | 263 |
231 int infoHandler(Request* request, MHD_Connection* connection, | 264 class RootHandler : public UrlHandler { |
232 const char* upload_data, size_t* upload_data_size) { | 265 public: |
233 if (request->fPicture.get()) { | 266 bool canHandle(const char* method, const char* url) override { |
234 return SendJSON(connection, request->fPicture); | 267 return 0 == strcmp(method, MHD_HTTP_METHOD_GET) && |
| 268 0 == strcmp(url, "/"); |
235 } | 269 } |
236 return MHD_NO; | 270 |
237 } | 271 int handle(Request* request, MHD_Connection* connection, |
| 272 const char* upload_data, size_t* upload_data_size) override { |
| 273 return SendTemplate(connection); |
| 274 } |
| 275 }; |
238 | 276 |
239 class UrlManager { | 277 class UrlManager { |
240 public: | 278 public: |
241 UrlManager() { | 279 UrlManager() { |
242 // Register handlers | 280 // Register handlers |
243 fHandlers.push_back({MHD_HTTP_METHOD_GET, "/", rootHandler}); | 281 fHandlers.push_back(new RootHandler); |
244 fHandlers.push_back({MHD_HTTP_METHOD_POST, "/new", postHandler}); | 282 fHandlers.push_back(new PostHandler); |
245 fHandlers.push_back({MHD_HTTP_METHOD_GET, "/img", imgHandler}); | 283 fHandlers.push_back(new ImgHandler); |
246 fHandlers.push_back({MHD_HTTP_METHOD_GET, "/cmd", infoHandler}); | 284 fHandlers.push_back(new InfoHandler); |
| 285 } |
| 286 |
| 287 ~UrlManager() { |
| 288 for (int i = 0; i < fHandlers.count(); i++) { delete fHandlers[i]; } |
247 } | 289 } |
248 | 290 |
249 // This is clearly not efficient for a large number of urls and handlers | 291 // This is clearly not efficient for a large number of urls and handlers |
250 int invoke(Request* request, MHD_Connection* connection, const char* url, co
nst char* method, | 292 int invoke(Request* request, MHD_Connection* connection, const char* url, co
nst char* method, |
251 const char* upload_data, size_t* upload_data_size) const { | 293 const char* upload_data, size_t* upload_data_size) const { |
252 for (int i = 0; i < fHandlers.count(); i++) { | 294 for (int i = 0; i < fHandlers.count(); i++) { |
253 const Url& urlHandler = fHandlers[i]; | 295 if (fHandlers[i]->canHandle(method, url)) { |
254 if (0 == strcmp(method, urlHandler.fMethod) && | 296 return fHandlers[i]->handle(request, connection, upload_data, up
load_data_size); |
255 0 == strcmp(url, urlHandler.fPath)) { | |
256 return (*urlHandler.fHandler)(request, connection, upload_da
ta, | |
257 upload_data_size); | |
258 } | 297 } |
259 } | 298 } |
260 return MHD_NO; | 299 return MHD_NO; |
261 } | 300 } |
262 | 301 |
263 private: | 302 private: |
264 struct Url { | 303 SkTArray<UrlHandler*> fHandlers; |
265 const char* fMethod; | |
266 const char* fPath; | |
267 UrlHandler fHandler; | |
268 }; | |
269 SkTArray<Url> fHandlers; | |
270 }; | 304 }; |
271 | 305 |
272 const UrlManager kUrlManager; | 306 const UrlManager kUrlManager; |
273 | 307 |
274 int answer_to_connection(void* cls, struct MHD_Connection* connection, | 308 int answer_to_connection(void* cls, struct MHD_Connection* connection, |
275 const char* url, const char* method, const char* versio
n, | 309 const char* url, const char* method, const char* versio
n, |
276 const char* upload_data, size_t* upload_data_size, | 310 const char* upload_data, size_t* upload_data_size, |
277 void** con_cls) { | 311 void** con_cls) { |
278 SkDebugf("New %s request for %s using version %s\n", method, url, version); | 312 SkDebugf("New %s request for %s using version %s\n", method, url, version); |
279 | 313 |
280 Request* request = reinterpret_cast<Request*>(cls); | 314 Request* request = reinterpret_cast<Request*>(cls); |
281 return kUrlManager.invoke(request, connection, url, method, upload_data, upl
oad_data_size); | 315 int result = kUrlManager.invoke(request, connection, url, method, upload_dat
a, |
| 316 upload_data_size); |
| 317 if (MHD_NO == result) { |
| 318 fprintf(stderr, "Invalid method and / or url: %s %s)\n", method, url); |
| 319 } |
| 320 return result; |
282 } | 321 } |
283 | 322 |
284 int skiaserve_main() { | 323 int skiaserve_main() { |
285 Request request; // This simple server has one request | 324 Request request; // This simple server has one request |
286 struct MHD_Daemon* daemon; | 325 struct MHD_Daemon* daemon; |
287 // TODO Add option to bind this strictly to an address, e.g. localhost, for
security. | 326 // TODO Add option to bind this strictly to an address, e.g. localhost, for
security. |
288 daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, FLAGS_port, nullptr, nu
llptr, | 327 daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, FLAGS_port, nullptr, nu
llptr, |
289 &answer_to_connection, &request, | 328 &answer_to_connection, &request, |
290 MHD_OPTION_END); | 329 MHD_OPTION_END); |
291 if (NULL == daemon) { | 330 if (NULL == daemon) { |
292 return 1; | 331 return 1; |
293 } | 332 } |
294 | 333 |
295 getchar(); | 334 getchar(); |
296 MHD_stop_daemon(daemon); | 335 MHD_stop_daemon(daemon); |
297 return 0; | 336 return 0; |
298 } | 337 } |
299 | 338 |
300 #if !defined SK_BUILD_FOR_IOS | 339 #if !defined SK_BUILD_FOR_IOS |
301 int main(int argc, char** argv) { | 340 int main(int argc, char** argv) { |
302 SkCommandLineFlags::Parse(argc, argv); | 341 SkCommandLineFlags::Parse(argc, argv); |
303 return skiaserve_main(); | 342 return skiaserve_main(); |
304 } | 343 } |
305 #endif | 344 #endif |
OLD | NEW |