aboutsummaryrefslogtreecommitdiff
path: root/src/unix/UnixSocket.cpp.hx
diff options
context:
space:
mode:
Diffstat (limited to 'src/unix/UnixSocket.cpp.hx')
-rw-r--r--src/unix/UnixSocket.cpp.hx150
1 files changed, 150 insertions, 0 deletions
diff --git a/src/unix/UnixSocket.cpp.hx b/src/unix/UnixSocket.cpp.hx
new file mode 100644
index 0000000..32a57d2
--- /dev/null
+++ b/src/unix/UnixSocket.cpp.hx
@@ -0,0 +1,150 @@
+package unix;
+
+import cpp.RawPointer;
+import cpp.Stdlib;
+import cpp.UInt8;
+import externs.Socket.SockAddr;
+import externs.Socket.SockAddrUnix;
+import externs.Socket;
+import haxe.io.Bytes;
+
+/**
+ Unix socket for local interprocess communication.
+
+ All the functions except for [readBytes](#readBytes) and [writeBytes](#writeBytes) must be called for the
+ server socket.
+**/
+class UnixSocket {
+ var nativeAddr:SockAddrUnix;
+ var nativeBuffer:RawPointer<UInt8>;
+ var nativeBufferLength = 0;
+
+ /**
+ Socket file path.
+ **/
+ public var path(default, null):String;
+
+ /**
+ File descriptor associated with the socket.
+ **/
+ public var fileDescriptor(default, null):Int;
+
+ /**
+ Configures the socket to work as a UNIX socket.
+ **/
+ function configure() {
+ // Configure the socket to work as a UNIX one and set it up.
+ nativeAddr = untyped __cpp__("{}");
+ untyped __cpp__("nativeAddr.sun_family = AF_UNIX");
+ for (i in 0...path.length) {
+ untyped __cpp__("nativeAddr.sun_path[{0}] = {1}", i, path.charCodeAt(i));
+ }
+ #if debug
+ trace('Configured socket with path $path and file descriptor $fileDescriptor');
+ #end
+ }
+
+ /**
+ Creates a new unconnected socket with a `path`.
+ **/
+ public function new(path:String) {
+ // Trim the string so that it's always 107 characters long.
+ this.path = path.substr(0, 108);
+ nativeBufferLength = 1024;
+ nativeBuffer = cast Stdlib.nativeMalloc(nativeBufferLength);
+
+ configure();
+ }
+
+ /**
+ Initializes the unconnected socket.
+ **/
+ public function init() {
+ fileDescriptor = Socket.socket(untyped __cpp__("AF_UNIX"), untyped __cpp__("SOCK_STREAM"), 0);
+ }
+
+ /**
+ Closes the socket.
+ **/
+ @:native("closeSocket")
+ public function close() {
+ Stdlib.nativeFree(cast nativeBuffer);
+ Socket.close(fileDescriptor);
+ #if debug
+ trace('Succesfully closed socket with $path and file descriptor $fileDescriptor');
+ #end
+ }
+
+ /**
+ Binds the socket to the configured path.
+ **/
+ @:native("bindSocket")
+ public function bind() {
+ Socket.bind(fileDescriptor, untyped __cpp__("(const sockaddr *) &nativeAddr"), untyped __cpp__("sizeof(nativeAddr)"));
+ }
+
+ /**
+ Instructs the socket to start listening to incoming connections while
+ allowing for a maximum of `numMaxConnections` connections.
+ **/
+ @:native("listenSocket")
+ public function listen(numMaxConnections:Int) {
+ Socket.listen(fileDescriptor, numMaxConnections);
+ }
+
+ /**
+ Accepts a client's connection and returns the client's socket.
+ **/
+ @:native("acceptSocket")
+ public function accept():UnixSocket {
+ var clientFileDescriptor = Socket.accept(fileDescriptor, untyped __cpp__("(sockaddr *) &nativeAddr"), untyped __cpp__("NULL"));
+ var clientSocket = new UnixSocket(path);
+
+ return clientSocket;
+ }
+
+ /**
+ Connects to the socket.
+ **/
+ @:native("connectSocket")
+ public function connect() {
+ Socket.connect(fileDescriptor, untyped __cpp__("(const sockaddr *) &nativeAddr"), untyped __cpp__("sizeof(nativeAddr)"));
+ }
+
+ /**
+ Reads `n` bytes from the socket.
+ **/
+ public function readBytes(n:Int):Bytes {
+ var bytes = Bytes.alloc(n);
+
+ if (n > nativeBufferLength) {
+ nativeBufferLength *= 2;
+ nativeBuffer = cast Stdlib.nativeRealloc(cast nativeBuffer, nativeBufferLength);
+ }
+
+ Socket.read(fileDescriptor, cast nativeBuffer, n);
+
+ for (i in 0...n) {
+ var byte = nativeBuffer[i];
+ bytes.set(i, byte);
+ }
+
+ return bytes;
+ }
+
+ /**
+ Writes `bytes` to the socket.
+ **/
+ public function writeBytes(bytes:Bytes) {
+ if (bytes.length > nativeBufferLength) {
+ nativeBufferLength *= 2;
+ nativeBuffer = cast Stdlib.nativeRealloc(cast nativeBuffer, nativeBufferLength);
+ }
+
+ for (i in 0...bytes.length) {
+ nativeBuffer[i] = bytes.get(i);
+ }
+
+ Socket.write(fileDescriptor, cast nativeBuffer, bytes.length);
+ }
+}