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