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; |
} |