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