]> git.saurik.com Git - cycript.git/blame - Handler.mm
Delay expansion of MAKE, to allow using jobserver.
[cycript.git] / Handler.mm
CommitLineData
b3378a02 1/* Cycript - Optimizing JavaScript Compiler/Runtime
f95d2598 2 * Copyright (C) 2009-2014 Jay Freeman (saurik)
b24eb750
JF
3*/
4
f95d2598 5/* GNU Affero General Public License, Version 3 {{{ */
b24eb750 6/*
f95d2598
JF
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.
11
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
c15969fd 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
f95d2598
JF
15 * GNU Affero General Public License for more details.
16
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/>.
b3378a02 19**/
b24eb750
JF
20/* }}} */
21
b24eb750 22#include <Foundation/Foundation.h>
7cfc264c 23#include <dlfcn.h>
63129b67 24#include <pthread.h>
b24eb750
JF
25#include <unistd.h>
26#include <sstream>
27
f8d45a20 28#include <sys/stat.h>
bb1c419c
JF
29#include <sys/types.h>
30#include <sys/socket.h>
31#include <netinet/in.h>
32#include <sys/un.h>
33
b12a9965
JF
34#include "cycript.hpp"
35
36#include "JavaScript.hpp"
37#include "Parser.hpp"
38#include "Pooling.hpp"
39
40#include "Cycript.tab.hh"
41#include "Driver.hpp"
42
b24eb750 43struct CYExecute_ {
b799113b 44 CYPool &pool_;
b24eb750
JF
45 const char * volatile data_;
46};
47
48// XXX: this is "tre lame"
49@interface CYClient_ : NSObject {
50}
51
52- (void) execute:(NSValue *)value;
53
54@end
55
56@implementation CYClient_
57
58- (void) execute:(NSValue *)value {
59 CYExecute_ *execute(reinterpret_cast<CYExecute_ *>([value pointerValue]));
60 const char *data(execute->data_);
61 execute->data_ = NULL;
89d16b11 62 execute->data_ = CYExecute(CYGetJSContext(), execute->pool_, CYUTF8String(data));
b24eb750
JF
63}
64
65@end
66
67struct CYClient :
68 CYData
69{
70 int socket_;
63129b67 71 pthread_t thread_;
b24eb750
JF
72
73 CYClient(int socket) :
74 socket_(socket)
75 {
76 }
77
78 ~CYClient() {
79 _syscall(close(socket_));
80 }
81
37954781 82 void Handle() {
d3760804
JF
83 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
84
85 CYClient_ *client = [[[CYClient_ alloc] init] autorelease];
b24eb750 86
bb1c419c
JF
87 bool dispatch;
88 if (CFStringRef mode = CFRunLoopCopyCurrentMode(CFRunLoopGetMain())) {
89 dispatch = true;
90 CFRelease(mode);
91 } else
92 dispatch = false;
93
b24eb750 94 for (;;) {
9d79cefc 95 uint32_t size;
b24eb750
JF
96 if (!CYRecvAll(socket_, &size, sizeof(size)))
97 return;
98
97f6a005 99 CYLocalPool pool;
b24eb750
JF
100 char *data(new(pool) char[size + 1]);
101 if (!CYRecvAll(socket_, data, size))
102 return;
103 data[size] = '\0';
104
0df6a201
JF
105 NSAutoreleasePool *ar = [[NSAutoreleasePool alloc] init];
106
107 std::string code(data, size);
108 CYExecute_ execute = {pool, code.c_str()};
109 NSValue *value([NSValue valueWithPointer:&execute]);
110 if (dispatch)
111 [client performSelectorOnMainThread:@selector(execute:) withObject:value waitUntilDone:YES];
112 else
113 [client execute:value];
114
115 const char *json(execute.data_);
116 size = json == NULL ? _not(uint32_t) : strlen(json);
117
118 [ar release];
b24eb750
JF
119
120 if (!CYSendAll(socket_, &size, sizeof(size)))
121 return;
122 if (json != NULL)
123 if (!CYSendAll(socket_, json, size))
124 return;
125 }
37954781 126
d3760804 127 [pool release];
b24eb750
JF
128 }
129};
130
0cbeddf8 131static void *OnClient(void *data) {
b24eb750
JF
132 CYClient *client(reinterpret_cast<CYClient *>(data));
133 client->Handle();
134 delete client;
135 return NULL;
136}
137
3429e25c
JF
138extern "C" void CYHandleClient(int socket) {
139 // XXX: this leaks memory... really?
140 CYPool *pool(new CYPool());
141 CYClient *client(new(*pool) CYClient(socket));
63129b67 142 _assert(pthread_create(&client->thread_, NULL, &OnClient, client) == 0);
b24eb750 143}
994434e5 144
f8d45a20 145static void CYHandleSocket(const char *path) {
7cfc264c
JF
146 int socket(_syscall(::socket(PF_UNIX, SOCK_STREAM, 0)));
147
148 struct sockaddr_un address;
149 memset(&address, 0, sizeof(address));
150 address.sun_family = AF_UNIX;
f8d45a20 151 strcpy(address.sun_path, path);
7cfc264c
JF
152
153 _syscall(connect(socket, reinterpret_cast<sockaddr *>(&address), SUN_LEN(&address)));
f8d45a20
JF
154
155 CYInitializeDynamic();
7cfc264c 156 CYHandleClient(socket);
994434e5 157}
666eedb9 158
7cfc264c 159extern "C" void CYHandleServer(pid_t pid) { try {
f8d45a20
JF
160 char path[1024];
161 sprintf(path, "/tmp/.s.cy.%u", pid);
162 CYHandleSocket(path);
7cfc264c
JF
163} catch (const CYException &error) {
164 CYPool pool;
165 fprintf(stderr, "%s\n", error.PoolCString(pool));
166} }
167
168extern "C" char *MSmain0(int argc, char *argv[]) { try {
169 _assert(argc == 2);
f8d45a20 170 CYHandleSocket(argv[1]);
7cfc264c
JF
171
172 static void *handle(NULL);
173 if (handle == NULL) {
174 Dl_info info;
175 _assert(dladdr(reinterpret_cast<void *>(&MSmain0), &info) != 0);
176 handle = dlopen(info.dli_fname, RTLD_NOLOAD);
177 }
178
7cfc264c
JF
179 return NULL;
180} catch (const CYException &error) {
181 CYPool pool;
182 return strdup(error.PoolCString(pool));
183} }
184
666eedb9
JF
185struct CYServer {
186 pthread_t thread_;
187 uint16_t port_;
188 int socket_;
189
190 CYServer(uint16_t port) :
191 port_(port),
192 socket_(-1)
193 {
194 }
195
196 ~CYServer() {
197 if (socket_ != -1)
198 _syscall(close(socket_));
199 }
200
201 void Listen() {
202 socket_ = _syscall(::socket(PF_INET, SOCK_STREAM, 0)); try {
203 sockaddr_in address;
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)));
208
209 _syscall(::listen(socket_, -1));
210
211 for (;;) {
212 socklen_t length(sizeof(address));
213 int socket(_syscall(::accept(socket_, reinterpret_cast<sockaddr *>(&address), &length)));
214 CYHandleClient(socket);
215 }
216 } catch (const CYException &error) {
217 CYPool pool;
218 fprintf(stderr, "%s\n", error.PoolCString(pool));
219 }
220 }
221};
222
223static void *OnServer(void *data) {
224 CYServer *server(reinterpret_cast<CYServer *>(data));
225 server->Listen();
226 delete server;
227 return NULL;
228}
229
230extern "C" void CYListenServer(short port) {
231 CYInitializeDynamic();
232
233 CYServer *server(new CYServer(port));
234 _assert(pthread_create(&server->thread_, NULL, &OnServer, server) == 0);
235}