1 /* Cycript - The Truly Universal Scripting Language
2 * Copyright (C) 2009-2016 Jay Freeman (saurik)
5 /* GNU Affero General Public License, Version 3 {{{ */
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.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
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/>.
22 #include <CoreFoundation/CFLogUtilities.h>
23 #include <CFNetwork/CFNetwork.h>
25 #include <netinet/in.h>
26 #include <sys/socket.h>
27 #include <sys/types.h>
30 #include "Pooling.hpp"
33 CFHTTPMessageRef message_
;
37 static void OnData(CFSocketRef socket
, CFSocketCallBackType type
, CFDataRef address
, const void *value
, void *info
) {
39 case kCFSocketDataCallBack
:
40 CFDataRef
data(reinterpret_cast<CFDataRef
>(value
));
41 Client
*client(reinterpret_cast<Client
*>(info
));
43 if (client
->message_
== NULL
)
44 client
->message_
= CFHTTPMessageCreateEmpty(kCFAllocatorDefault
, TRUE
);
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_
));
51 CFStringRef
path(CFURLCopyStrictPath(url
, &absolute
));
52 CFRelease(client
->message_
);
54 CFStringRef
code(CFURLCreateStringByReplacingPercentEscapes(kCFAllocatorDefault
, path
, CFSTR("")));
57 JSStringRef
script(JSStringCreateWithCFString(code
));
60 JSValueRef
result(JSEvaluateScript(CYGetJSContext(), script
, NULL
, NULL
, 0, NULL
));
61 JSStringRelease(script
);
63 CFHTTPMessageRef
response(CFHTTPMessageCreateResponse(kCFAllocatorDefault
, 200, NULL
, kCFHTTPVersion1_1
));
64 CFHTTPMessageSetHeaderFieldValue(response
, CFSTR("Content-Type"), CFSTR("application/json; charset=utf-8"));
66 CFStringRef
json(CYCopyJSONString(CYGetJSContext(), result
, NULL
));
67 CFDataRef
body(CFStringCreateExternalRepresentation(kCFAllocatorDefault
, json
, kCFStringEncodingUTF8
, NULL
));
70 CFStringRef
length(CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("%u"), CFDataGetLength(body
)));
71 CFHTTPMessageSetHeaderFieldValue(response
, CFSTR("Content-Length"), length
);
74 CFHTTPMessageSetBody(response
, body
);
77 CFDataRef
serialized(CFHTTPMessageCopySerializedMessage(response
));
80 CFSocketSendData(socket
, NULL
, serialized
, 0);
81 CFRelease(serialized
);
89 static void OnAccept(CFSocketRef socket
, CFSocketCallBackType type
, CFDataRef address
, const void *value
, void *info
) {
91 case kCFSocketAcceptCallBack
:
92 Client
*client(new Client());
94 client
->message_
= NULL
;
96 CFSocketContext context
;
98 context
.info
= client
;
99 context
.retain
= NULL
;
100 context
.release
= NULL
;
101 context
.copyDescription
= NULL
;
103 client
->socket_
= CFSocketCreateWithNative(kCFAllocatorDefault
, *reinterpret_cast<const CFSocketNativeHandle
*>(value
), kCFSocketDataCallBack
, &OnData
, &context
);
105 CFRunLoopAddSource(CFRunLoopGetCurrent(), CFSocketCreateRunLoopSource(kCFAllocatorDefault
, client
->socket_
, 0), kCFRunLoopDefaultMode
);
110 int main(int argc
, char *argv
[]) {
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);
118 CFDataRef
data(CFDataCreate(kCFAllocatorDefault
, reinterpret_cast<UInt8
*>(&address
), sizeof(address
)));
120 CFSocketSignature signature
;
121 signature
.protocolFamily
= AF_INET
;
122 signature
.socketType
= SOCK_STREAM
;
123 signature
.protocol
= IPPROTO_TCP
;
124 signature
.address
= data
;
126 CFSocketRef
socket(CFSocketCreateWithSocketSignature(kCFAllocatorDefault
, &signature
, kCFSocketAcceptCallBack
, &OnAccept
, NULL
));
127 CFRunLoopAddSource(CFRunLoopGetCurrent(), CFSocketCreateRunLoopSource(kCFAllocatorDefault
, socket
, 0), kCFRunLoopDefaultMode
);
131 CYServer
*server(new CYServer());
132 server
->socket_
= _syscall(socket(PF_UNIX
, SOCK_STREAM
, 0));
134 struct sockaddr_un address
;
135 memset(&address
, 0, sizeof(address
));
136 address
.sun_family
= AF_UNIX
;
138 sprintf(address
.sun_path
, "/tmp/.s.cy");