1 /* 2 * Copyright 2016 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "Request.h" 9 #include "Response.h" 10 11 #include "SkCommandLineFlags.h" 12 #include "SkGraphics.h" 13 14 #include "microhttpd.h" 15 16 #include "urlhandlers/UrlHandler.h" 17 18 #include <errno.h> 19 20 #if !defined _WIN32 21 #include <sys/socket.h> 22 #include <arpa/inet.h> 23 #endif 24 25 using namespace Response; 26 27 DEFINE_int32(port, 8888, "The port to listen on."); 28 DEFINE_string(address, "127.0.0.1", "The address to bind to."); 29 DEFINE_bool(hosted, false, "Running in hosted mode on debugger.skia.org."); 30 31 class UrlManager { 32 public: 33 UrlManager() { 34 // Register handlers 35 fHandlers.push_back(new RootHandler); 36 fHandlers.push_back(new PostHandler); 37 fHandlers.push_back(new ImgHandler); 38 fHandlers.push_back(new ClipAlphaHandler); 39 fHandlers.push_back(new EnableGPUHandler); 40 fHandlers.push_back(new CmdHandler); 41 fHandlers.push_back(new InfoHandler); 42 fHandlers.push_back(new DownloadHandler); 43 fHandlers.push_back(new DataHandler); 44 fHandlers.push_back(new BreakHandler); 45 fHandlers.push_back(new OpsHandler); 46 fHandlers.push_back(new OpBoundsHandler); 47 fHandlers.push_back(new ColorModeHandler); 48 fHandlers.push_back(new QuitHandler); 49 } 50 51 ~UrlManager() { 52 for (int i = 0; i < fHandlers.count(); i++) { delete fHandlers[i]; } 53 } 54 55 // This is clearly not efficient for a large number of urls and handlers 56 int invoke(Request* request, MHD_Connection* connection, const char* url, const char* method, 57 const char* upload_data, size_t* upload_data_size) const { 58 for (int i = 0; i < fHandlers.count(); i++) { 59 if (fHandlers[i]->canHandle(method, url)) { 60 return fHandlers[i]->handle(request, connection, url, method, upload_data, 61 upload_data_size); 62 } 63 } 64 return MHD_NO; 65 } 66 67 private: 68 SkTArray<UrlHandler*> fHandlers; 69 }; 70 71 const UrlManager kUrlManager; 72 73 int answer_to_connection(void* cls, struct MHD_Connection* connection, 74 const char* url, const char* method, const char* version, 75 const char* upload_data, size_t* upload_data_size, 76 void** con_cls) { 77 SkDebugf("New %s request for %s using version %s\n", method, url, version); 78 79 Request* request = reinterpret_cast<Request*>(cls); 80 int result = kUrlManager.invoke(request, connection, url, method, upload_data, 81 upload_data_size); 82 if (MHD_NO == result) { 83 fprintf(stderr, "Invalid method and / or url: %s %s\n", method, url); 84 } 85 return result; 86 } 87 88 int skiaserve_main() { 89 SkGraphics::Init(); 90 Request request(SkString("/data")); // This simple server has one request 91 92 struct sockaddr_in address; 93 address.sin_family = AF_INET; 94 address.sin_port = htons(FLAGS_port); 95 int result = inet_pton(AF_INET, FLAGS_address[0], &address.sin_addr); 96 if (result != 1) { 97 printf("inet_pton for %s:%d failed with return %d %s\n", 98 FLAGS_address[0], FLAGS_port, result, strerror(errno)); 99 return 1; 100 } 101 102 printf("Visit http://%s:%d in your browser.\n", FLAGS_address[0], FLAGS_port); 103 104 struct MHD_Daemon* daemon; 105 daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY 106 #ifdef SK_DEBUG 107 | MHD_USE_DEBUG 108 #endif 109 , FLAGS_port, nullptr, nullptr, 110 &answer_to_connection, &request, 111 MHD_OPTION_SOCK_ADDR, &address, 112 MHD_OPTION_END); 113 if (nullptr == daemon) { 114 SkDebugf("Could not initialize daemon\n"); 115 return 1; 116 } 117 118 if (FLAGS_hosted) { 119 while (1) { 120 SkDebugf("loop\n"); 121 #if defined(SK_BUILD_FOR_WIN) 122 Sleep(60 * 1000); 123 #else 124 sleep(60); 125 #endif 126 } 127 } else { 128 getchar(); 129 } 130 MHD_stop_daemon(daemon); 131 return 0; 132 } 133 134 #if !defined SK_BUILD_FOR_IOS 135 int main(int argc, char** argv) { 136 SkCommandLineFlags::Parse(argc, argv); 137 return skiaserve_main(); 138 } 139 #endif 140