]> git.saurik.com Git - cycript.git/blob - Server.cpp
Enable/disable argument for JavaScript (engine).
[cycript.git] / Server.cpp
1 /* Cycript - Inlining/Optimizing JavaScript Compiler
2 * Copyright (C) 2009 Jay Freeman (saurik)
3 */
4
5 /* Modified BSD License {{{ */
6 /*
7 * Redistribution and use in source and binary
8 * forms, with or without modification, are permitted
9 * provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the
12 * above copyright notice, this list of conditions
13 * and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the
15 * above copyright notice, this list of conditions
16 * and the following disclaimer in the documentation
17 * and/or other materials provided with the
18 * distribution.
19 * 3. The name of the author may not be used to endorse
20 * or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
25 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
34 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
36 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 */
38 /* }}} */
39
40 #include <Pooling.hpp>
41
42 #include <apr_thread_proc.h>
43
44 #include <CoreFoundation/CFLogUtilities.h>
45 #include <CFNetwork/CFNetwork.h>
46
47 #include <sys/types.h>
48 #include <sys/socket.h>
49 #include <netinet/in.h>
50 #include <sys/un.h>
51
52 struct Client {
53 CFHTTPMessageRef message_;
54 CFSocketRef socket_;
55 };
56
57 static void OnData(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *value, void *info) {
58 switch (type) {
59 case kCFSocketDataCallBack:
60 CFDataRef data(reinterpret_cast<CFDataRef>(value));
61 Client *client(reinterpret_cast<Client *>(info));
62
63 if (client->message_ == NULL)
64 client->message_ = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, TRUE);
65
66 if (!CFHTTPMessageAppendBytes(client->message_, CFDataGetBytePtr(data), CFDataGetLength(data)))
67 CFLog(kCFLogLevelError, CFSTR("CFHTTPMessageAppendBytes()"));
68 else if (CFHTTPMessageIsHeaderComplete(client->message_)) {
69 CFURLRef url(CFHTTPMessageCopyRequestURL(client->message_));
70 Boolean absolute;
71 CFStringRef path(CFURLCopyStrictPath(url, &absolute));
72 CFRelease(client->message_);
73
74 CFStringRef code(CFURLCreateStringByReplacingPercentEscapes(kCFAllocatorDefault, path, CFSTR("")));
75 CFRelease(path);
76
77 JSStringRef script(JSStringCreateWithCFString(code));
78 CFRelease(code);
79
80 JSValueRef result(JSEvaluateScript(CYGetJSContext(), script, NULL, NULL, 0, NULL));
81 JSStringRelease(script);
82
83 CFHTTPMessageRef response(CFHTTPMessageCreateResponse(kCFAllocatorDefault, 200, NULL, kCFHTTPVersion1_1));
84 CFHTTPMessageSetHeaderFieldValue(response, CFSTR("Content-Type"), CFSTR("application/json; charset=utf-8"));
85
86 CFStringRef json(CYCopyJSONString(CYGetJSContext(), result, NULL));
87 CFDataRef body(CFStringCreateExternalRepresentation(kCFAllocatorDefault, json, kCFStringEncodingUTF8, NULL));
88 CFRelease(json);
89
90 CFStringRef length(CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%u"), CFDataGetLength(body)));
91 CFHTTPMessageSetHeaderFieldValue(response, CFSTR("Content-Length"), length);
92 CFRelease(length);
93
94 CFHTTPMessageSetBody(response, body);
95 CFRelease(body);
96
97 CFDataRef serialized(CFHTTPMessageCopySerializedMessage(response));
98 CFRelease(response);
99
100 CFSocketSendData(socket, NULL, serialized, 0);
101 CFRelease(serialized);
102
103 CFRelease(url);
104 }
105 break;
106 }
107 }
108
109 static void OnAccept(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *value, void *info) {
110 switch (type) {
111 case kCFSocketAcceptCallBack:
112 Client *client(new Client());
113
114 client->message_ = NULL;
115
116 CFSocketContext context;
117 context.version = 0;
118 context.info = client;
119 context.retain = NULL;
120 context.release = NULL;
121 context.copyDescription = NULL;
122
123 client->socket_ = CFSocketCreateWithNative(kCFAllocatorDefault, *reinterpret_cast<const CFSocketNativeHandle *>(value), kCFSocketDataCallBack, &OnData, &context);
124
125 CFRunLoopAddSource(CFRunLoopGetCurrent(), CFSocketCreateRunLoopSource(kCFAllocatorDefault, client->socket_, 0), kCFRunLoopDefaultMode);
126 break;
127 }
128 }
129
130 int main(int argc, char *argv[]) {
131 {
132 struct sockaddr_in address;
133 address.sin_len = sizeof(address);
134 address.sin_family = AF_INET;
135 address.sin_addr.s_addr = INADDR_ANY;
136 address.sin_port = htons(787);
137
138 CFDataRef data(CFDataCreate(kCFAllocatorDefault, reinterpret_cast<UInt8 *>(&address), sizeof(address)));
139
140 CFSocketSignature signature;
141 signature.protocolFamily = AF_INET;
142 signature.socketType = SOCK_STREAM;
143 signature.protocol = IPPROTO_TCP;
144 signature.address = data;
145
146 CFSocketRef socket(CFSocketCreateWithSocketSignature(kCFAllocatorDefault, &signature, kCFSocketAcceptCallBack, &OnAccept, NULL));
147 CFRunLoopAddSource(CFRunLoopGetCurrent(), CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket, 0), kCFRunLoopDefaultMode);
148 }
149
150 {
151 CYServer *server(new CYServer());
152 server->socket_ = _syscall(socket(PF_UNIX, SOCK_STREAM, 0));
153
154 struct sockaddr_un address;
155 memset(&address, 0, sizeof(address));
156 address.sun_family = AF_UNIX;
157
158 sprintf(address.sun_path, "/tmp/.s.cy");
159 }
160 }