/* Cycript - Optimizing JavaScript Compiler/Runtime
- * Copyright (C) 2009-2012 Jay Freeman (saurik)
+ * Copyright (C) 2009-2013 Jay Freeman (saurik)
*/
-/* GNU Lesser General Public License, Version 3 {{{ */
+/* GNU General Public License, Version 3 {{{ */
/*
- * Cycript is free software: you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation, either version 3 of the License, or (at your
- * option) any later version.
+ * Cycript is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation, either version 3 of the License,
+ * or (at your option) any later version.
*
- * Cycript is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- * License for more details.
+ * Cycript is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU Lesser General Public License
+ * You should have received a copy of the GNU General Public License
* along with Cycript. If not, see <http://www.gnu.org/licenses/>.
**/
/* }}} */
-#include "cycript.hpp"
-#include "JavaScript.hpp"
-
-#include "Pooling.hpp"
-#include "Parser.hpp"
-
-#include "Cycript.tab.hh"
-
#include <Foundation/Foundation.h>
-#include <apr_thread_proc.h>
+#include <pthread.h>
#include <unistd.h>
#include <sstream>
#include <netinet/in.h>
#include <sys/un.h>
+#include "cycript.hpp"
+
+#include "JavaScript.hpp"
+#include "Parser.hpp"
+#include "Pooling.hpp"
+
+#include "Cycript.tab.hh"
+#include "Driver.hpp"
+
struct CYExecute_ {
- apr_pool_t *pool_;
+ CYPool &pool_;
const char * volatile data_;
};
CYExecute_ *execute(reinterpret_cast<CYExecute_ *>([value pointerValue]));
const char *data(execute->data_);
execute->data_ = NULL;
- execute->data_ = CYExecute(execute->pool_, CYUTF8String(data));
+ execute->data_ = CYExecute(CYGetJSContext(), execute->pool_, CYUTF8String(data));
}
@end
CYData
{
int socket_;
- apr_thread_t *thread_;
+ pthread_t thread_;
CYClient(int socket) :
socket_(socket)
dispatch = false;
for (;;) {
- size_t size;
+ uint32_t size;
if (!CYRecvAll(socket_, &size, sizeof(size)))
return;
return;
data[size] = '\0';
- CYStream stream(data, data + size);
- CYDriver driver(stream);
-
- cy::parser parser(driver);
-
- const char *json;
- if (parser.parse() != 0 || !driver.errors_.empty()) {
- json = NULL;
- size = _not(size_t);
- } else {
- NSAutoreleasePool *ar = [[NSAutoreleasePool alloc] init];
-
- CYOptions options;
- CYContext context(options);
- driver.program_->Replace(context);
- std::ostringstream str;
- CYOutput out(str, options);
- out << *driver.program_;
- std::string code(str.str());
- CYExecute_ execute = {pool, code.c_str()};
- NSValue *value([NSValue valueWithPointer:&execute]);
- if (dispatch)
- [client performSelectorOnMainThread:@selector(execute:) withObject:value waitUntilDone:YES];
- else
- [client execute:value];
- json = execute.data_;
- size = json == NULL ? _not(size_t) : strlen(json);
-
- [ar release];
- }
+ NSAutoreleasePool *ar = [[NSAutoreleasePool alloc] init];
+
+ std::string code(data, size);
+ CYExecute_ execute = {pool, code.c_str()};
+ NSValue *value([NSValue valueWithPointer:&execute]);
+ if (dispatch)
+ [client performSelectorOnMainThread:@selector(execute:) withObject:value waitUntilDone:YES];
+ else
+ [client execute:value];
+
+ const char *json(execute.data_);
+ size = json == NULL ? _not(uint32_t) : strlen(json);
+
+ [ar release];
if (!CYSendAll(socket_, &size, sizeof(size)))
return;
}
};
-static void * APR_THREAD_FUNC OnClient(apr_thread_t *thread, void *data) {
+static void *OnClient(void *data) {
CYClient *client(reinterpret_cast<CYClient *>(data));
client->Handle();
delete client;
return NULL;
}
-extern "C" void CYHandleClient(apr_pool_t *pool, int socket) {
- CYClient *client(new(pool) CYClient(socket));
- apr_threadattr_t *attr;
- _aprcall(apr_threadattr_create(&attr, client->pool_));
- _aprcall(apr_thread_create(&client->thread_, attr, &OnClient, client, client->pool_));
+extern "C" void CYHandleClient(int socket) {
+ // XXX: this leaks memory... really?
+ CYPool *pool(new CYPool());
+ CYClient *client(new(*pool) CYClient(socket));
+ _assert(pthread_create(&client->thread_, NULL, &OnClient, client) == 0);
}
extern "C" void CYHandleServer(pid_t pid) {
sprintf(address.sun_path, "/tmp/.s.cy.%u", pid);
_syscall(connect(socket, reinterpret_cast<sockaddr *>(&address), SUN_LEN(&address)));
-
- apr_pool_t *pool;
- apr_pool_create(&pool, NULL);
-
- CYHandleClient(pool, socket);
+ CYHandleClient(socket);
} catch (const CYException &error) {
CYPool pool;
fprintf(stderr, "%s\n", error.PoolCString(pool));
}
}
+
+struct CYServer {
+ pthread_t thread_;
+ uint16_t port_;
+ int socket_;
+
+ CYServer(uint16_t port) :
+ port_(port),
+ socket_(-1)
+ {
+ }
+
+ ~CYServer() {
+ if (socket_ != -1)
+ _syscall(close(socket_));
+ }
+
+ void Listen() {
+ socket_ = _syscall(::socket(PF_INET, SOCK_STREAM, 0)); try {
+ sockaddr_in address;
+ address.sin_family = AF_INET;
+ address.sin_addr.s_addr = INADDR_ANY;
+ address.sin_port = htons(port_);
+ _syscall(::bind(socket_, reinterpret_cast<sockaddr *>(&address), sizeof(address)));
+
+ _syscall(::listen(socket_, -1));
+
+ for (;;) {
+ socklen_t length(sizeof(address));
+ int socket(_syscall(::accept(socket_, reinterpret_cast<sockaddr *>(&address), &length)));
+ CYHandleClient(socket);
+ }
+ } catch (const CYException &error) {
+ CYPool pool;
+ fprintf(stderr, "%s\n", error.PoolCString(pool));
+ }
+ }
+};
+
+static void *OnServer(void *data) {
+ CYServer *server(reinterpret_cast<CYServer *>(data));
+ server->Listen();
+ delete server;
+ return NULL;
+}
+
+extern "C" void CYListenServer(short port) {
+ CYInitializeDynamic();
+
+ CYServer *server(new CYServer(port));
+ _assert(pthread_create(&server->thread_, NULL, &OnServer, server) == 0);
+}