]> git.saurik.com Git - cycript.git/blame - Server.cpp
Instance's toPointer() should return as CFTypeRef.
[cycript.git] / Server.cpp
CommitLineData
7341eedb
JF
1/* Cycript - The Truly Universal Scripting Language
2 * Copyright (C) 2009-2016 Jay Freeman (saurik)
b4aa79af
JF
3*/
4
f95d2598 5/* GNU Affero General Public License, Version 3 {{{ */
b4aa79af 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**/
b4aa79af
JF
20/* }}} */
21
dc68b74c 22#include <CoreFoundation/CFLogUtilities.h>
b4aa79af
JF
23#include <CFNetwork/CFNetwork.h>
24
dc68b74c 25#include <netinet/in.h>
20052ff7
JF
26#include <sys/socket.h>
27#include <sys/types.h>
dc68b74c
JF
28#include <sys/un.h>
29
20052ff7
JF
30#include "Pooling.hpp"
31
b4aa79af
JF
32struct Client {
33 CFHTTPMessageRef message_;
34 CFSocketRef socket_;
35};
36
37static 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
89static 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
dc68b74c
JF
110int 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);
b4aa79af 117
dc68b74c 118 CFDataRef data(CFDataCreate(kCFAllocatorDefault, reinterpret_cast<UInt8 *>(&address), sizeof(address)));
b4aa79af 119
dc68b74c
JF
120 CFSocketSignature signature;
121 signature.protocolFamily = AF_INET;
122 signature.socketType = SOCK_STREAM;
123 signature.protocol = IPPROTO_TCP;
124 signature.address = data;
b4aa79af 125
dc68b74c
JF
126 CFSocketRef socket(CFSocketCreateWithSocketSignature(kCFAllocatorDefault, &signature, kCFSocketAcceptCallBack, &OnAccept, NULL));
127 CFRunLoopAddSource(CFRunLoopGetCurrent(), CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket, 0), kCFRunLoopDefaultMode);
128 }
b4aa79af 129
dc68b74c
JF
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 }
b4aa79af 140}