]> git.saurik.com Git - cycript.git/blobdiff - Handler.mm
Move the EOF "final newline" to the ctrl-d check.
[cycript.git] / Handler.mm
index 008d42639927605f4442b024f6333545dabad5dc..e7b2c3bcf5e3e16dae386d992bafd80730a49b8b 100644 (file)
@@ -1,34 +1,26 @@
 /* Cycript - Optimizing JavaScript Compiler/Runtime
- * Copyright (C) 2009-2010  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_;
 };
 
@@ -65,7 +66,7 @@ struct CYClient :
     CYData
 {
     int socket_;
-    apr_thread_t *thread_;
+    pthread_t thread_;
 
     CYClient(int socket) :
         socket_(socket)
@@ -89,7 +90,7 @@ struct CYClient :
             dispatch = false;
 
         for (;;) {
-            size_t size;
+            uint32_t size;
             if (!CYRecvAll(socket_, &size, sizeof(size)))
                 return;
 
@@ -99,16 +100,15 @@ struct CYClient :
                 return;
             data[size] = '\0';
 
-            CYDriver driver;
-            cy::parser parser(driver);
+            CYStream stream(data, data + size);
+            CYDriver driver(stream);
 
-            driver.data_ = data;
-            driver.size_ = size;
+            cy::parser parser(driver);
 
             const char *json;
             if (parser.parse() != 0 || !driver.errors_.empty()) {
                 json = NULL;
-                size = _not(size_t);
+                size = _not(uint32_t);
             } else {
                 NSAutoreleasePool *ar = [[NSAutoreleasePool alloc] init];
 
@@ -126,7 +126,7 @@ struct CYClient :
                 else
                     [client execute:value];
                 json = execute.data_;
-                size = json == NULL ? _not(size_t) : strlen(json);
+                size = json == NULL ? _not(uint32_t) : strlen(json);
 
                 [ar release];
             }
@@ -142,18 +142,18 @@ struct CYClient :
     }
 };
 
-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) {
@@ -166,13 +166,61 @@ 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);
+}