]> git.saurik.com Git - cycript.git/blame - Server.cpp
While let might not be Identifier, it sure is Word.
[cycript.git] / Server.cpp
CommitLineData
b3378a02
JF
1/* Cycript - Optimizing JavaScript Compiler/Runtime
2 * Copyright (C) 2009-2010 Jay Freeman (saurik)
b4aa79af
JF
3*/
4
b3378a02 5/* GNU Lesser General Public License, Version 3 {{{ */
b4aa79af 6/*
b3378a02
JF
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.
b4aa79af 11 *
b3378a02
JF
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.
b4aa79af 16 *
b3378a02
JF
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**/
b4aa79af
JF
20/* }}} */
21
dc68b74c
JF
22#include <Pooling.hpp>
23
9185d5ef 24#include <apr_thread_proc.h>
dc68b74c
JF
25
26#include <CoreFoundation/CFLogUtilities.h>
b4aa79af
JF
27#include <CFNetwork/CFNetwork.h>
28
dc68b74c
JF
29#include <sys/types.h>
30#include <sys/socket.h>
31#include <netinet/in.h>
32#include <sys/un.h>
33
b4aa79af
JF
34struct Client {
35 CFHTTPMessageRef message_;
36 CFSocketRef socket_;
37};
38
39static 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
91static 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
dc68b74c
JF
112int 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);
b4aa79af 119
dc68b74c 120 CFDataRef data(CFDataCreate(kCFAllocatorDefault, reinterpret_cast<UInt8 *>(&address), sizeof(address)));
b4aa79af 121
dc68b74c
JF
122 CFSocketSignature signature;
123 signature.protocolFamily = AF_INET;
124 signature.socketType = SOCK_STREAM;
125 signature.protocol = IPPROTO_TCP;
126 signature.address = data;
b4aa79af 127
dc68b74c
JF
128 CFSocketRef socket(CFSocketCreateWithSocketSignature(kCFAllocatorDefault, &signature, kCFSocketAcceptCallBack, &OnAccept, NULL));
129 CFRunLoopAddSource(CFRunLoopGetCurrent(), CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket, 0), kCFRunLoopDefaultMode);
130 }
b4aa79af 131
dc68b74c
JF
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 }
b4aa79af 142}