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>
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
33 #include "cycript.hpp"
35 #include "JavaScript.hpp"
37 #include "Pooling.hpp"
39 #include "Cycript.tab.hh"
44 const char * volatile data_;
47 // XXX: this is "tre lame"
48 @interface CYClient_ : NSObject {
51 - (void) execute:(NSValue *)value;
55 @implementation CYClient_
57 - (void) execute:(NSValue *)value {
58 CYExecute_ *execute(reinterpret_cast<CYExecute_ *>([value pointerValue]));
59 const char *data(execute->data_);
60 execute->data_ = NULL;
61 execute->data_ = CYExecute(CYGetJSContext(), execute->pool_, CYUTF8String(data));
72 CYClient(int socket) :
78 _syscall(close(socket_));
82 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
84 CYClient_ *client = [[[CYClient_ alloc] init] autorelease];
87 if (CFStringRef mode = CFRunLoopCopyCurrentMode(CFRunLoopGetMain())) {
95 if (!CYRecvAll(socket_, &size, sizeof(size)))
99 char *data(new(pool) char[size + 1]);
100 if (!CYRecvAll(socket_, data, size))
104 NSAutoreleasePool *ar = [[NSAutoreleasePool alloc] init];
106 std::string code(data, size);
107 CYExecute_ execute = {pool, code.c_str()};
108 NSValue *value([NSValue valueWithPointer:&execute]);
110 [client performSelectorOnMainThread:@selector(execute:) withObject:value waitUntilDone:YES];
112 [client execute:value];
114 const char *json(execute.data_);
115 size = json == NULL ? _not(uint32_t) : strlen(json);
119 if (!CYSendAll(socket_, &size, sizeof(size)))
122 if (!CYSendAll(socket_, json, size))
130 static void *OnClient(void *data) {
131 CYClient *client(reinterpret_cast<CYClient *>(data));
137 extern "C" void CYHandleClient(int socket) {
138 // XXX: this leaks memory... really?
139 CYPool *pool(new CYPool());
140 CYClient *client(new(*pool) CYClient(socket));
141 _assert(pthread_create(&client->thread_, NULL, &OnClient, client) == 0);
144 static void CYHandleProcess(pid_t pid) {
145 CYInitializeDynamic();
147 int socket(_syscall(::socket(PF_UNIX, SOCK_STREAM, 0)));
149 struct sockaddr_un address;
150 memset(&address, 0, sizeof(address));
151 address.sun_family = AF_UNIX;
152 sprintf(address.sun_path, "/tmp/.s.cy.%u", pid);
154 _syscall(connect(socket, reinterpret_cast<sockaddr *>(&address), SUN_LEN(&address)));
155 CYHandleClient(socket);
158 extern "C" void CYHandleServer(pid_t pid) { try {
159 CYHandleProcess(pid);
160 } catch (const CYException &error) {
162 fprintf(stderr, "%s\n", error.PoolCString(pool));
165 extern "C" char *MSmain0(int argc, char *argv[]) { try {
170 pid_t pid(strtoul(arg, &end, 10));
171 _assert(end == arg + strlen(arg));
173 static void *handle(NULL);
174 if (handle == NULL) {
176 _assert(dladdr(reinterpret_cast<void *>(&MSmain0), &info) != 0);
177 handle = dlopen(info.dli_fname, RTLD_NOLOAD);
180 CYHandleProcess(pid);
183 } catch (const CYException &error) {
185 return strdup(error.PoolCString(pool));
193 CYServer(uint16_t port) :
201 _syscall(close(socket_));
205 socket_ = _syscall(::socket(PF_INET, SOCK_STREAM, 0)); try {
207 address.sin_family = AF_INET;
208 address.sin_addr.s_addr = INADDR_ANY;
209 address.sin_port = htons(port_);
210 _syscall(::bind(socket_, reinterpret_cast<sockaddr *>(&address), sizeof(address)));
212 _syscall(::listen(socket_, -1));
215 socklen_t length(sizeof(address));
216 int socket(_syscall(::accept(socket_, reinterpret_cast<sockaddr *>(&address), &length)));
217 CYHandleClient(socket);
219 } catch (const CYException &error) {
221 fprintf(stderr, "%s\n", error.PoolCString(pool));
226 static void *OnServer(void *data) {
227 CYServer *server(reinterpret_cast<CYServer *>(data));
233 extern "C" void CYListenServer(short port) {
234 CYInitializeDynamic();
236 CYServer *server(new CYServer(port));
237 _assert(pthread_create(&server->thread_, NULL, &OnServer, server) == 0);