1 /* Cycript - Optimizing JavaScript Compiler/Runtime
2 * Copyright (C) 2009-2014 Jay Freeman (saurik)
5 /* GNU Affero General Public License, Version 3 {{{ */
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include <Foundation/Foundation.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <netinet/in.h>
34 #include "cycript.hpp"
36 #include "JavaScript.hpp"
38 #include "Pooling.hpp"
40 #include "Cycript.tab.hh"
45 const char * volatile data_;
48 // XXX: this is "tre lame"
49 @interface CYClient_ : NSObject {
52 - (void) execute:(NSValue *)value;
56 @implementation CYClient_
58 - (void) execute:(NSValue *)value {
59 CYExecute_ *execute(reinterpret_cast<CYExecute_ *>([value pointerValue]));
60 const char *data(execute->data_);
61 execute->data_ = NULL;
62 execute->data_ = CYExecute(CYGetJSContext(), execute->pool_, CYUTF8String(data));
73 CYClient(int socket) :
79 _syscall(close(socket_));
83 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
85 CYClient_ *client = [[[CYClient_ alloc] init] autorelease];
88 if (CFStringRef mode = CFRunLoopCopyCurrentMode(CFRunLoopGetMain())) {
96 if (!CYRecvAll(socket_, &size, sizeof(size)))
100 char *data(new(pool) char[size + 1]);
101 if (!CYRecvAll(socket_, data, size))
105 NSAutoreleasePool *ar = [[NSAutoreleasePool alloc] init];
107 std::string code(data, size);
108 CYExecute_ execute = {pool, code.c_str()};
109 NSValue *value([NSValue valueWithPointer:&execute]);
111 [client performSelectorOnMainThread:@selector(execute:) withObject:value waitUntilDone:YES];
113 [client execute:value];
115 const char *json(execute.data_);
116 size = json == NULL ? _not(uint32_t) : strlen(json);
120 if (!CYSendAll(socket_, &size, sizeof(size)))
123 if (!CYSendAll(socket_, json, size))
131 static void *OnClient(void *data) {
132 CYClient *client(reinterpret_cast<CYClient *>(data));
138 extern "C" void CYHandleClient(int socket) {
139 // XXX: this leaks memory... really?
140 CYPool *pool(new CYPool());
141 CYClient *client(new(*pool) CYClient(socket));
142 _assert(pthread_create(&client->thread_, NULL, &OnClient, client) == 0);
145 static void CYHandleSocket(const char *path) {
146 int socket(_syscall(::socket(PF_UNIX, SOCK_STREAM, 0)));
148 struct sockaddr_un address;
149 memset(&address, 0, sizeof(address));
150 address.sun_family = AF_UNIX;
151 strcpy(address.sun_path, path);
153 _syscall(connect(socket, reinterpret_cast<sockaddr *>(&address), SUN_LEN(&address)));
155 CYInitializeDynamic();
156 CYHandleClient(socket);
159 extern "C" void CYHandleServer(pid_t pid) { try {
161 sprintf(path, "/tmp/.s.cy.%u", pid);
162 CYHandleSocket(path);
163 } catch (const CYException &error) {
165 fprintf(stderr, "%s\n", error.PoolCString(pool));
168 extern "C" char *MSmain0(int argc, char *argv[]) { try {
170 CYHandleSocket(argv[1]);
172 static void *handle(NULL);
173 if (handle == NULL) {
175 _assert(dladdr(reinterpret_cast<void *>(&MSmain0), &info) != 0);
176 handle = dlopen(info.dli_fname, RTLD_NOLOAD);
180 } catch (const CYException &error) {
182 return strdup(error.PoolCString(pool));
190 CYServer(uint16_t port) :
198 _syscall(close(socket_));
202 socket_ = _syscall(::socket(PF_INET, SOCK_STREAM, 0)); try {
204 address.sin_family = AF_INET;
205 address.sin_addr.s_addr = INADDR_ANY;
206 address.sin_port = htons(port_);
207 _syscall(::bind(socket_, reinterpret_cast<sockaddr *>(&address), sizeof(address)));
209 _syscall(::listen(socket_, -1));
212 socklen_t length(sizeof(address));
213 int socket(_syscall(::accept(socket_, reinterpret_cast<sockaddr *>(&address), &length)));
214 CYHandleClient(socket);
216 } catch (const CYException &error) {
218 fprintf(stderr, "%s\n", error.PoolCString(pool));
223 static void *OnServer(void *data) {
224 CYServer *server(reinterpret_cast<CYServer *>(data));
230 extern "C" void CYListenServer(short port) {
231 CYInitializeDynamic();
233 CYServer *server(new CYServer(port));
234 _assert(pthread_create(&server->thread_, NULL, &OnServer, server) == 0);