From: Jay Freeman (saurik) Date: Mon, 9 Nov 2015 04:44:13 +0000 (-0800) Subject: Use CoreFoundation in Handler to #ifdef __APPLE__. X-Git-Tag: v0.9.504~15 X-Git-Url: https://git.saurik.com/cycript.git/commitdiff_plain/938d06268877e85c711ee8adb4c38673d61ee67e Use CoreFoundation in Handler to #ifdef __APPLE__. --- diff --git a/Handler.cpp b/Handler.cpp new file mode 100644 index 0000000..2ceb1fa --- /dev/null +++ b/Handler.cpp @@ -0,0 +1,253 @@ +/* Cycript - Optimizing JavaScript Compiler/Runtime + * Copyright (C) 2009-2014 Jay Freeman (saurik) +*/ + +/* GNU Affero General Public License, Version 3 {{{ */ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . +**/ +/* }}} */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef __APPLE__ +#include +#endif + +#include "cycript.hpp" + +#include "JavaScript.hpp" +#include "Parser.hpp" +#include "Pooling.hpp" + +#include "Cycript.tab.hh" +#include "Driver.hpp" + +struct CYExecute_ { + CYPool &pool_; + const char * volatile data_; + pthread_mutex_t mutex_; + pthread_cond_t condition_; +}; + +void CYPerform(void *arg) { + CYExecute_ *execute(reinterpret_cast(arg)); + + const char *data(execute->data_); + execute->data_ = NULL; + execute->data_ = CYExecute(CYGetJSContext(), execute->pool_, CYUTF8String(data)); + + pthread_mutex_lock(&execute->mutex_); + pthread_cond_signal(&execute->condition_); + pthread_mutex_unlock(&execute->mutex_); +} + +struct CYClient : + CYData +{ + int socket_; + pthread_t thread_; + + CYClient(int socket) : + socket_(socket) + { + } + + ~CYClient() { + _syscall(close(socket_)); + } + + void Handle() { + bool dispatch; +#ifdef __APPLE__ + CFRunLoopRef loop(CFRunLoopGetMain()); + if (CFStringRef mode = CFRunLoopCopyCurrentMode(loop)) { + dispatch = true; + CFRelease(mode); + } else +#endif + dispatch = false; + + for (;;) { + uint32_t size; + if (!CYRecvAll(socket_, &size, sizeof(size))) + return; + + CYLocalPool pool; + char *data(new(pool) char[size + 1]); + if (!CYRecvAll(socket_, data, size)) + return; + data[size] = '\0'; + + std::string code(data, size); + CYExecute_ execute = {pool, code.c_str()}; + + pthread_mutex_init(&execute.mutex_, NULL); + pthread_cond_init(&execute.condition_, NULL); + + if (!dispatch) + CYPerform(&execute); +#ifdef __APPLE__ + else { + CFRunLoopSourceContext context; + memset(&context, 0, sizeof(context)); + context.version = 0; + context.info = &execute; + context.perform = &CYPerform; + + CFRunLoopSourceRef source(CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context)); + + pthread_mutex_lock(&execute.mutex_); + + CFRunLoopAddSource(loop, source, kCFRunLoopCommonModes); + CFRunLoopSourceSignal(source); + + CFRunLoopWakeUp(loop); + pthread_cond_wait(&execute.condition_, &execute.mutex_); + pthread_mutex_unlock(&execute.mutex_); + + CFRunLoopRemoveSource(loop, source, kCFRunLoopCommonModes); + CFRelease(source); + } +#endif + + pthread_cond_destroy(&execute.condition_); + pthread_mutex_destroy(&execute.mutex_); + + const char *json(execute.data_); + size = json == NULL ? _not(uint32_t) : strlen(json); + + if (!CYSendAll(socket_, &size, sizeof(size))) + return; + if (json != NULL) + if (!CYSendAll(socket_, json, size)) + return; + } + } +}; + +static void *OnClient(void *data) { + CYClient *client(reinterpret_cast(data)); + client->Handle(); + delete client; + return NULL; +} + +extern "C" void CYHandleClient(int socket) { + // XXX: this leaks memory... really? + CYPool *pool(new CYPool()); + CYClient *client(new(*pool) CYClient(socket)); + _assert(pthread_create(&client->thread_, NULL, &OnClient, client) == 0); +} + +static void CYHandleSocket(const char *path) { + int socket(_syscall(::socket(PF_UNIX, SOCK_STREAM, 0))); + + struct sockaddr_un address; + memset(&address, 0, sizeof(address)); + address.sun_family = AF_UNIX; + strcpy(address.sun_path, path); + + _syscall(connect(socket, reinterpret_cast(&address), SUN_LEN(&address))); + + CYInitializeDynamic(); + CYHandleClient(socket); +} + +extern "C" void CYHandleServer(pid_t pid) { try { + char path[1024]; + sprintf(path, "/tmp/.s.cy.%u", pid); + CYHandleSocket(path); +} catch (const CYException &error) { + CYPool pool; + fprintf(stderr, "%s\n", error.PoolCString(pool)); +} } + +extern "C" char *MSmain0(int argc, char *argv[]) { try { + _assert(argc == 2); + CYHandleSocket(argv[1]); + + static void *handle(NULL); + if (handle == NULL) { + Dl_info info; + _assert(dladdr(reinterpret_cast(&MSmain0), &info) != 0); + handle = dlopen(info.dli_fname, RTLD_NOLOAD); + } + + return NULL; +} catch (const CYException &error) { + CYPool pool; + return strdup(error.PoolCString(pool)); +} } + +struct CYServer { + pthread_t thread_; + uint16_t port_; + int socket_; + + CYServer(uint16_t port) : + port_(port), + socket_(-1) + { + } + + ~CYServer() { + if (socket_ != -1) + _syscall(close(socket_)); + } + + void Listen() { + socket_ = _syscall(::socket(PF_INET, SOCK_STREAM, 0)); try { + sockaddr_in address; + address.sin_family = AF_INET; + address.sin_addr.s_addr = INADDR_ANY; + address.sin_port = htons(port_); + _syscall(::bind(socket_, reinterpret_cast(&address), sizeof(address))); + + _syscall(::listen(socket_, -1)); + + for (;;) { + socklen_t length(sizeof(address)); + int socket(_syscall(::accept(socket_, reinterpret_cast(&address), &length))); + CYHandleClient(socket); + } + } catch (const CYException &error) { + CYPool pool; + fprintf(stderr, "%s\n", error.PoolCString(pool)); + } + } +}; + +static void *OnServer(void *data) { + CYServer *server(reinterpret_cast(data)); + server->Listen(); + delete server; + return NULL; +} + +extern "C" void CYListenServer(short port) { + CYInitializeDynamic(); + + CYServer *server(new CYServer(port)); + _assert(pthread_create(&server->thread_, NULL, &OnServer, server) == 0); +} diff --git a/Handler.mm b/Handler.mm deleted file mode 100644 index bbda7df..0000000 --- a/Handler.mm +++ /dev/null @@ -1,235 +0,0 @@ -/* Cycript - Optimizing JavaScript Compiler/Runtime - * Copyright (C) 2009-2014 Jay Freeman (saurik) -*/ - -/* GNU Affero General Public License, Version 3 {{{ */ -/* - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . -**/ -/* }}} */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "cycript.hpp" - -#include "JavaScript.hpp" -#include "Parser.hpp" -#include "Pooling.hpp" - -#include "Cycript.tab.hh" -#include "Driver.hpp" - -struct CYExecute_ { - CYPool &pool_; - const char * volatile data_; -}; - -// XXX: this is "tre lame" -@interface CYClient_ : NSObject { -} - -- (void) execute:(NSValue *)value; - -@end - -@implementation CYClient_ - -- (void) execute:(NSValue *)value { - CYExecute_ *execute(reinterpret_cast([value pointerValue])); - const char *data(execute->data_); - execute->data_ = NULL; - execute->data_ = CYExecute(CYGetJSContext(), execute->pool_, CYUTF8String(data)); -} - -@end - -struct CYClient : - CYData -{ - int socket_; - pthread_t thread_; - - CYClient(int socket) : - socket_(socket) - { - } - - ~CYClient() { - _syscall(close(socket_)); - } - - void Handle() { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - CYClient_ *client = [[[CYClient_ alloc] init] autorelease]; - - bool dispatch; - if (CFStringRef mode = CFRunLoopCopyCurrentMode(CFRunLoopGetMain())) { - dispatch = true; - CFRelease(mode); - } else - dispatch = false; - - for (;;) { - uint32_t size; - if (!CYRecvAll(socket_, &size, sizeof(size))) - return; - - CYLocalPool pool; - char *data(new(pool) char[size + 1]); - if (!CYRecvAll(socket_, data, size)) - return; - data[size] = '\0'; - - NSAutoreleasePool *ar = [[NSAutoreleasePool alloc] init]; - - std::string code(data, size); - CYExecute_ execute = {pool, code.c_str()}; - NSValue *value([NSValue valueWithPointer:&execute]); - if (dispatch) - [client performSelectorOnMainThread:@selector(execute:) withObject:value waitUntilDone:YES]; - else - [client execute:value]; - - const char *json(execute.data_); - size = json == NULL ? _not(uint32_t) : strlen(json); - - [ar release]; - - if (!CYSendAll(socket_, &size, sizeof(size))) - return; - if (json != NULL) - if (!CYSendAll(socket_, json, size)) - return; - } - - [pool release]; - } -}; - -static void *OnClient(void *data) { - CYClient *client(reinterpret_cast(data)); - client->Handle(); - delete client; - return NULL; -} - -extern "C" void CYHandleClient(int socket) { - // XXX: this leaks memory... really? - CYPool *pool(new CYPool()); - CYClient *client(new(*pool) CYClient(socket)); - _assert(pthread_create(&client->thread_, NULL, &OnClient, client) == 0); -} - -static void CYHandleSocket(const char *path) { - int socket(_syscall(::socket(PF_UNIX, SOCK_STREAM, 0))); - - struct sockaddr_un address; - memset(&address, 0, sizeof(address)); - address.sun_family = AF_UNIX; - strcpy(address.sun_path, path); - - _syscall(connect(socket, reinterpret_cast(&address), SUN_LEN(&address))); - - CYInitializeDynamic(); - CYHandleClient(socket); -} - -extern "C" void CYHandleServer(pid_t pid) { try { - char path[1024]; - sprintf(path, "/tmp/.s.cy.%u", pid); - CYHandleSocket(path); -} catch (const CYException &error) { - CYPool pool; - fprintf(stderr, "%s\n", error.PoolCString(pool)); -} } - -extern "C" char *MSmain0(int argc, char *argv[]) { try { - _assert(argc == 2); - CYHandleSocket(argv[1]); - - static void *handle(NULL); - if (handle == NULL) { - Dl_info info; - _assert(dladdr(reinterpret_cast(&MSmain0), &info) != 0); - handle = dlopen(info.dli_fname, RTLD_NOLOAD); - } - - return NULL; -} catch (const CYException &error) { - CYPool pool; - return strdup(error.PoolCString(pool)); -} } - -struct CYServer { - pthread_t thread_; - uint16_t port_; - int socket_; - - CYServer(uint16_t port) : - port_(port), - socket_(-1) - { - } - - ~CYServer() { - if (socket_ != -1) - _syscall(close(socket_)); - } - - void Listen() { - socket_ = _syscall(::socket(PF_INET, SOCK_STREAM, 0)); try { - sockaddr_in address; - address.sin_family = AF_INET; - address.sin_addr.s_addr = INADDR_ANY; - address.sin_port = htons(port_); - _syscall(::bind(socket_, reinterpret_cast(&address), sizeof(address))); - - _syscall(::listen(socket_, -1)); - - for (;;) { - socklen_t length(sizeof(address)); - int socket(_syscall(::accept(socket_, reinterpret_cast(&address), &length))); - CYHandleClient(socket); - } - } catch (const CYException &error) { - CYPool pool; - fprintf(stderr, "%s\n", error.PoolCString(pool)); - } - } -}; - -static void *OnServer(void *data) { - CYServer *server(reinterpret_cast(data)); - server->Listen(); - delete server; - return NULL; -} - -extern "C" void CYListenServer(short port) { - CYInitializeDynamic(); - - CYServer *server(new CYServer(port)); - _assert(pthread_create(&server->thread_, NULL, &OnServer, server) == 0); -} diff --git a/Makefile.am b/Makefile.am index 56a0518..9a4f5d6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -82,7 +82,7 @@ libcycript_la_LIBADD += $(LTOBJECTIVEC) endif if CY_MACH -libcycript_la_SOURCES += Handler.mm +libcycript_la_SOURCES += Handler.cpp if CY_CONSOLE cycript_SOURCES += Mach/Inject.cpp diff --git a/Makefile.in b/Makefile.in index dc06265..3a82c91 100644 --- a/Makefile.in +++ b/Makefile.in @@ -112,7 +112,7 @@ host_triplet = @host@ @CY_OBJECTIVEC_TRUE@am__append_9 = ObjectiveC @CY_OBJECTIVEC_TRUE@am__append_10 = ObjectiveC/Output.cpp ObjectiveC/Replace.cpp ObjectiveC/Library.mm @CY_OBJECTIVEC_TRUE@am__append_11 = $(LTOBJECTIVEC) -@CY_MACH_TRUE@am__append_12 = Handler.mm +@CY_MACH_TRUE@am__append_12 = Handler.cpp @CY_CONSOLE_TRUE@@CY_MACH_TRUE@am__append_13 = Mach/Inject.cpp @CY_CONSOLE_TRUE@@CY_MACH_TRUE@am__append_14 = -DCY_ATTACH subdir = . @@ -176,7 +176,7 @@ am__libcycript_la_SOURCES_DIST = ConvertUTF.c Decode.cpp Driver.cpp \ Replace.cpp Cycript.tab.cc lex.cy.cpp sig/ffi_type.cpp \ sig/parse.cpp sig/copy.cpp Bridge.cpp Execute.cpp \ JavaScriptCore.cpp Java/Execute.cpp ObjectiveC/Output.cpp \ - ObjectiveC/Replace.cpp ObjectiveC/Library.mm Handler.mm + ObjectiveC/Replace.cpp ObjectiveC/Library.mm Handler.cpp am__dirstamp = $(am__leading_dot)dirstamp @CY_EXECUTE_TRUE@am__objects_1 = sig/ffi_type.lo sig/parse.lo \ @CY_EXECUTE_TRUE@ sig/copy.lo Bridge.lo Execute.lo \