]> git.saurik.com Git - cycript.git/blobdiff - Connector.cpp
Broke apart Connector from Library and fixed cases where '- -' was serialized as...
[cycript.git] / Connector.cpp
diff --git a/Connector.cpp b/Connector.cpp
new file mode 100644 (file)
index 0000000..dddaa8b
--- /dev/null
@@ -0,0 +1,87 @@
+#include <substrate.h>
+
+#include "cycript.hpp"
+#include "Pooling.hpp"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+
+#include <apr-1/apr_thread_proc.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#import <CoreFoundation/CFLogUtilities.h>
+
+struct CYServer :
+    CYData
+{
+    int socket_;
+};
+
+apr_status_t CYPoolDLClose_(void *data) {
+    void *handle(reinterpret_cast<void *>(data));
+    dlclose(handle);
+    return APR_SUCCESS;
+}
+
+static void * APR_THREAD_FUNC Cyrver(apr_thread_t *thread, void *data) {
+    CYServer *server(reinterpret_cast<CYServer *>(data));
+
+    for (;;) {
+        int socket(_syscall(accept(server->socket_, NULL, NULL)));
+
+        if (void *handle = dlopen("/usr/lib/libcycript.dylib", RTLD_LAZY | RTLD_LOCAL)) {
+            apr_pool_t *pool;
+            _aprcall(apr_pool_create(&pool, NULL));
+
+            apr_pool_cleanup_register(pool, handle, &CYPoolDLClose_, &apr_pool_cleanup_null);
+
+            if (void (*CYHandleClient_)(apr_pool_t *, int) = reinterpret_cast<void (*)(apr_pool_t *, int)>(dlsym(handle, "CYHandleClient")))
+                (*CYHandleClient_)(pool, socket);
+            else
+                apr_pool_destroy(pool);
+        } else
+            CFLog(kCFLogLevelError, CFSTR("CY:Error: cannot load: %s"), dlerror());
+    }
+
+    delete server;
+    return NULL;
+}
+
+static void Unlink() {
+    pid_t pid(getpid());
+    char path[104];
+    sprintf(path, "/tmp/.s.cy.%u", pid);
+    unlink(path);
+}
+
+MSInitialize {
+    _aprcall(apr_initialize());
+
+    CYServer *server(new CYServer());
+    server->socket_ = _syscall(socket(PF_UNIX, SOCK_STREAM, 0));
+
+    struct sockaddr_un address;
+    memset(&address, 0, sizeof(address));
+    address.sun_family = AF_UNIX;
+
+    pid_t pid(getpid());
+    sprintf(address.sun_path, "/tmp/.s.cy.%u", pid);
+
+    try {
+        _syscall(bind(server->socket_, reinterpret_cast<sockaddr *>(&address), SUN_LEN(&address)));
+        atexit(&Unlink);
+        _syscall(listen(server->socket_, 0));
+
+        apr_threadattr_t *attr;
+        _aprcall(apr_threadattr_create(&attr, server->pool_));
+
+        apr_thread_t *thread;
+        _aprcall(apr_thread_create(&thread, attr, &Cyrver, server, server->pool_));
+    } catch (...) {
+        CFLog(kCFLogLevelError, CFSTR("CY:Error: cannot bind unix domain socket"));
+    }
+}