| Index: tools/skiaserve/skiaserve.cpp
|
| diff --git a/tools/skiaserve/skiaserve.cpp b/tools/skiaserve/skiaserve.cpp
|
| index effd28973c226bd007a98b7e185b63aa04001d58..9252da85dcba497504ca8c52b43abf760a32cba9 100644
|
| --- a/tools/skiaserve/skiaserve.cpp
|
| +++ b/tools/skiaserve/skiaserve.cpp
|
| @@ -9,20 +9,11 @@
|
| #include "GrContextFactory.h"
|
| #include "SkCanvas.h"
|
| #include "SkCommandLineFlags.h"
|
| -#include "SkOSFile.h"
|
| -#include <SkPicture.h>
|
| +#include "SkPicture.h"
|
| #include "SkStream.h"
|
| #include "SkSurface.h"
|
|
|
| -// temporary junk
|
| -#include "SkGradientShader.h"
|
| -
|
| -#include <stdio.h>
|
| -#include <sys/types.h>
|
| -#include <sys/select.h>
|
| -#include <sys/stat.h>
|
| #include <sys/socket.h>
|
| -#include <fcntl.h>
|
| #include <microhttpd.h>
|
|
|
| // To get image decoders linked in we have to do the below magic
|
| @@ -42,7 +33,7 @@ static const int kImageWidth = 1920;
|
| static const int kImageHeight = 1080;
|
|
|
| // TODO factor this out into functions, also handle CPU path
|
| -SkData* setupAndDrawToCanvas(const char* path, SkString* error) {
|
| +SkData* setupAndDrawToCanvas(SkStream* stream, SkString* error) {
|
| GrContextOptions grContextOpts;
|
| SkAutoTDelete<GrContextFactory> factory(new GrContextFactory(grContextOpts));
|
|
|
| @@ -64,15 +55,9 @@ SkData* setupAndDrawToCanvas(const char* path, SkString* error) {
|
| gl->makeCurrent();
|
|
|
| // draw
|
| - SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(path));
|
| - if (stream.get() == nullptr) {
|
| - error->appendf("Could not read %s.\n", path);
|
| - return nullptr;
|
| - }
|
| -
|
| - SkAutoTUnref<SkPicture> pic(SkPicture::CreateFromStream(stream.get()));
|
| + SkAutoTUnref<SkPicture> pic(SkPicture::CreateFromStream(stream));
|
| if (pic.get() == nullptr) {
|
| - error->appendf("Could not read %s as an SkPicture.\n", path);
|
| + error->appendf("Could not create picture from stream.\n");
|
| return nullptr;
|
| }
|
|
|
| @@ -95,7 +80,6 @@ SkData* setupAndDrawToCanvas(const char* path, SkString* error) {
|
| }
|
| return data;
|
| }
|
| -
|
| // TODO move to template file
|
| SkString generateTemplate(SkString source) {
|
| SkString debuggerTemplate;
|
| @@ -119,53 +103,127 @@ SkString generateTemplate(SkString source) {
|
|
|
| }
|
|
|
| +struct UploadContext {
|
| + SkDynamicMemoryWStream stream;
|
| + MHD_PostProcessor* pp;
|
| + MHD_Connection* connection;
|
| +};
|
| +
|
| +struct Request {
|
| + Request() : fUploadContext(nullptr) {}
|
| + UploadContext* fUploadContext;
|
| + SkAutoTUnref<SkData> fPNG;
|
| +};
|
| +
|
| +static const size_t kBufferSize = 1024;
|
| +
|
| +static int process_upload_data(void* cls, enum MHD_ValueKind kind,
|
| + const char* key, const char* filename,
|
| + const char* content_type, const char* transfer_encoding,
|
| + const char* data, uint64_t off, size_t size) {
|
| + struct UploadContext* uc = reinterpret_cast<UploadContext*>(cls);
|
| +
|
| + if (0 != size) {
|
| + uc->stream.write(data, size);
|
| + }
|
| + return MHD_YES;
|
| +}
|
| +
|
| int answer_to_connection(void* cls, struct MHD_Connection* connection,
|
| const char* url, const char* method, const char* version,
|
| const char* upload_data, size_t* upload_data_size,
|
| void** con_cls) {
|
| - printf ("New %s request for %s using version %s\n", method, url, version);
|
| -
|
| - struct MHD_Response* response;
|
| -
|
| - // serve html to root
|
| - // TODO better url handling
|
| - int ret;
|
| - if (0 == strcmp("/", url)) {
|
| + SkDebugf("New %s request for %s using version %s\n", method, url, version);
|
| +
|
| + Request* request = reinterpret_cast<Request*>(cls);
|
| +
|
| + MHD_Response* response;
|
| + int ret = MHD_NO;
|
| +
|
| + // TODO url handlers
|
| + // handle uploads
|
| + if (0 == strcmp(method, MHD_HTTP_METHOD_POST) &&
|
| + 0 == strcmp(url, "/new")) {
|
| + UploadContext* uc = request->fUploadContext;
|
| +
|
| + // New connection
|
| + if (!uc) {
|
| + // TODO make this a method on request
|
| + uc = new UploadContext;
|
| + uc->connection = connection;
|
| + uc->pp = MHD_create_post_processor(connection, kBufferSize, &process_upload_data, uc);
|
| + SkASSERT(uc->pp);
|
| +
|
| + request->fUploadContext = uc;
|
| + return MHD_YES;
|
| + }
|
| +
|
| + // in process upload
|
| + if (0 != *upload_data_size) {
|
| + SkASSERT(uc->pp);
|
| + MHD_post_process(uc->pp, upload_data, *upload_data_size);
|
| + *upload_data_size = 0;
|
| + return MHD_YES;
|
| + }
|
| +
|
| + // end of upload
|
| + MHD_destroy_post_processor(uc->pp);
|
| + uc->pp = nullptr;
|
| +
|
| + // TODO response
|
| + SkString error;
|
| + SkData* data = setupAndDrawToCanvas(uc->stream.detachAsStream(), &error);
|
| + if (!data) {
|
| + // TODO send error
|
| + return MHD_YES;
|
| + }
|
| +
|
| + request->fPNG.reset(data);
|
| + // TODO Hack
|
| SkString debuggerTemplate = generateTemplate(SkString("http://debugger.skia.org"));
|
|
|
| response = MHD_create_response_from_buffer(debuggerTemplate.size(),
|
| - (void*)const_cast<char*>(debuggerTemplate.c_str()),
|
| + (void*) const_cast<char*>(debuggerTemplate.c_str()),
|
| MHD_RESPMEM_MUST_COPY);
|
| +
|
| ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
|
| MHD_destroy_response(response);
|
| - return MHD_YES;
|
| - }
|
| -
|
| - // otherwise serve an image
|
| - // TODO take from post
|
| - SkString resourceName;
|
| - resourceName.appendf("%s/%s.skp", FLAGS_dir[0], FLAGS_name[0]);
|
| - SkDebugf("Loading skp: %s\n", resourceName.c_str());
|
| -
|
| - SkString error;
|
| - SkAutoTUnref<SkData> data(setupAndDrawToCanvas(resourceName.c_str(), &error));
|
| - if (!data) {
|
| - // TODO send error
|
| - return MHD_YES;
|
| + } else if (0 == strcmp(method, MHD_HTTP_METHOD_GET)) {
|
| + if (0 == strcmp(url, "/")) {
|
| + SkString debuggerTemplate = generateTemplate(SkString("http://debugger.skia.org"));
|
| +
|
| + response = MHD_create_response_from_buffer(debuggerTemplate.size(),
|
| + (void*) const_cast<char*>(debuggerTemplate.c_str()),
|
| + MHD_RESPMEM_MUST_COPY);
|
| +
|
| + ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
|
| + MHD_destroy_response(response);
|
| + } else if (0 == strcmp(url, "/img")) {
|
| + if (request->fPNG.get()) {
|
| + SkData* data = request->fPNG.get();
|
| + response = MHD_create_response_from_buffer(data->size(),
|
| + const_cast<void*>(data->data()),
|
| + MHD_RESPMEM_MUST_COPY);
|
| + MHD_add_response_header(response, "Content-Type", "image/png");
|
| +
|
| + ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
|
| + MHD_destroy_response(response);
|
| + }
|
| + }
|
| + } else {
|
| + SkFAIL("whoops, need proper error handling");
|
| + return MHD_NO;
|
| }
|
|
|
| - response = MHD_create_response_from_buffer(data->size(), const_cast<void*>(data->data()),
|
| - MHD_RESPMEM_MUST_COPY);
|
| - MHD_add_response_header(response, "Content-Type", "image/png");
|
| - ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
|
| - MHD_destroy_response(response);
|
| return ret;
|
| }
|
|
|
| int skiaserve_main() {
|
| + Request request; // This simple server has one request
|
| struct MHD_Daemon* daemon;
|
| - daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL,
|
| - &answer_to_connection, NULL, MHD_OPTION_END);
|
| + daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, PORT, nullptr, nullptr,
|
| + &answer_to_connection, &request,
|
| + MHD_OPTION_END);
|
| if (NULL == daemon) {
|
| return 1;
|
| }
|
|
|