]> git.saurik.com Git - cycript.git/blob - Server.cpp
Allow of to be used as Identifier, not just Word.
[cycript.git] / Server.cpp
1 /* Cycript - Optimizing JavaScript Compiler/Runtime
2 * Copyright (C) 2009-2010 Jay Freeman (saurik)
3 */
4
5 /* GNU Lesser General Public License, Version 3 {{{ */
6 /*
7 * Cycript is free software: you can redistribute it and/or modify it under
8 * the terms of the GNU Lesser General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * Cycript is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 * License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with Cycript. If not, see <http://www.gnu.org/licenses/>.
19 **/
20 /* }}} */
21
22 #include <Pooling.hpp>
23
24 #include <apr_thread_proc.h>
25
26 #include <CoreFoundation/CFLogUtilities.h>
27 #include <CFNetwork/CFNetwork.h>
28
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <sys/un.h>
33
34 struct Client {
35 CFHTTPMessageRef message_;
36 CFSocketRef socket_;
37 };
38
39 static void OnData(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *value, void *info) {
40 switch (type) {
41 case kCFSocketDataCallBack:
42 CFDataRef data(reinterpret_cast<CFDataRef>(value));
43 Client *client(reinterpret_cast<Client *>(info));
44
45 if (client->message_ == NULL)
46 client->message_ = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, TRUE);
47
48 if (!CFHTTPMessageAppendBytes(client->message_, CFDataGetBytePtr(data), CFDataGetLength(data)))
49 CFLog(kCFLogLevelError, CFSTR("CFHTTPMessageAppendBytes()"));
50 else if (CFHTTPMessageIsHeaderComplete(client->message_)) {
51 CFURLRef url(CFHTTPMessageCopyRequestURL(client->message_));
52 Boolean absolute;
53 CFStringRef path(CFURLCopyStrictPath(url, &absolute));
54 CFRelease(client->message_);
55
56 CFStringRef code(CFURLCreateStringByReplacingPercentEscapes(kCFAllocatorDefault, path, CFSTR("")));
57 CFRelease(path);
58
59 JSStringRef script(JSStringCreateWithCFString(code));
60 CFRelease(code);
61
62 JSValueRef result(JSEvaluateScript(CYGetJSContext(), script, NULL, NULL, 0, NULL));
63 JSStringRelease(script);
64
65 CFHTTPMessageRef response(CFHTTPMessageCreateResponse(kCFAllocatorDefault, 200, NULL, kCFHTTPVersion1_1));
66 CFHTTPMessageSetHeaderFieldValue(response, CFSTR("Content-Type"), CFSTR("application/json; charset=utf-8"));
67
68 CFStringRef json(CYCopyJSONString(CYGetJSContext(), result, NULL));
69 CFDataRef body(CFStringCreateExternalRepresentation(kCFAllocatorDefault, json, kCFStringEncodingUTF8, NULL));
70 CFRelease(json);
71
72 CFStringRef length(CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%u"), CFDataGetLength(body)));
73 CFHTTPMessageSetHeaderFieldValue(response, CFSTR("Content-Length"), length);
74 CFRelease(length);
75
76 CFHTTPMessageSetBody(response, body);
77 CFRelease(body);
78
79 CFDataRef serialized(CFHTTPMessageCopySerializedMessage(response));
80 CFRelease(response);
81
82 CFSocketSendData(socket, NULL, serialized, 0);
83 CFRelease(serialized);
84
85 CFRelease(url);
86 }
87 break;
88 }
89 }
90
91 static void OnAccept(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *value, void *info) {
92 switch (type) {
93 case kCFSocketAcceptCallBack:
94 Client *client(new Client());
95
96 client->message_ = NULL;
97
98 CFSocketContext context;
99 context.version = 0;
100 context.info = client;
101 context.retain = NULL;
102 context.release = NULL;
103 context.copyDescription = NULL;
104
105 client->socket_ = CFSocketCreateWithNative(kCFAllocatorDefault, *reinterpret_cast<const CFSocketNativeHandle *>(value), kCFSocketDataCallBack, &OnData, &context);
106
107 CFRunLoopAddSource(CFRunLoopGetCurrent(), CFSocketCreateRunLoopSource(kCFAllocatorDefault, client->socket_, 0), kCFRunLoopDefaultMode);
108 break;
109 }
110 }
111
112 int main(int argc, char *argv[]) {
113 {
114 struct sockaddr_in address;
115 address.sin_len = sizeof(address);
116 address.sin_family = AF_INET;
117 address.sin_addr.s_addr = INADDR_ANY;
118 address.sin_port = htons(787);
119
120 CFDataRef data(CFDataCreate(kCFAllocatorDefault, reinterpret_cast<UInt8 *>(&address), sizeof(address)));
121
122 CFSocketSignature signature;
123 signature.protocolFamily = AF_INET;
124 signature.socketType = SOCK_STREAM;
125 signature.protocol = IPPROTO_TCP;
126 signature.address = data;
127
128 CFSocketRef socket(CFSocketCreateWithSocketSignature(kCFAllocatorDefault, &signature, kCFSocketAcceptCallBack, &OnAccept, NULL));
129 CFRunLoopAddSource(CFRunLoopGetCurrent(), CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket, 0), kCFRunLoopDefaultMode);
130 }
131
132 {
133 CYServer *server(new CYServer());
134 server->socket_ = _syscall(socket(PF_UNIX, SOCK_STREAM, 0));
135
136 struct sockaddr_un address;
137 memset(&address, 0, sizeof(address));
138 address.sun_family = AF_UNIX;
139
140 sprintf(address.sun_path, "/tmp/.s.cy");
141 }
142 }