aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorrc_05 <contact@rc-05.com>2024-05-24 23:03:55 +0200
committerrc_05 <contact@rc-05.com>2024-05-25 00:58:25 +0200
commit2095935c2488d1a46c7dd0c9d2325e41715b8ad9 (patch)
tree9761c6b5956d9b89e37a1eb6630ba63d39a8128a /src
downloadhaxe-unix-sockets-2095935c2488d1a46c7dd0c9d2325e41715b8ad9.tar.gz
First commit1.0.0
Diffstat (limited to 'src')
-rw-r--r--src/externs/Build.xml9
-rw-r--r--src/externs/Socket.cpp.hx32
-rw-r--r--src/unix/UnixSocket.cpp.hx150
-rw-r--r--src/unix/UnixSocket.hx8
4 files changed, 199 insertions, 0 deletions
diff --git a/src/externs/Build.xml b/src/externs/Build.xml
new file mode 100644
index 0000000..312314f
--- /dev/null
+++ b/src/externs/Build.xml
@@ -0,0 +1,9 @@
+<xml>
+ <section>
+ <files id="haxe" if="linux">
+ <compilerflag value="-I/usr/include"/>
+ <compilerflag value="-L/usr/lib"/>
+ <compilerflag value="-L/usr/lib64"/>
+ </files>
+ </section>
+</xml>
diff --git a/src/externs/Socket.cpp.hx b/src/externs/Socket.cpp.hx
new file mode 100644
index 0000000..6103cea
--- /dev/null
+++ b/src/externs/Socket.cpp.hx
@@ -0,0 +1,32 @@
+package externs;
+
+import cpp.Void;
+import cpp.SizeT;
+import cpp.Star;
+import cpp.Int32;
+import cpp.ConstStar;
+import cpp.ConstCharStar;
+
+@:include("sys/socket.h")
+@:native("struct sockaddr")
+@:structAccess
+extern class SockAddr {}
+
+@:include("sys/un.h")
+@:native("struct sockaddr_un")
+@:structAccess
+extern class SockAddrUnix {}
+
+@:buildXml("<include name='${haxelib:haxe-unix-sockets}/src/externs/Build.xml'/>")
+@:include("unistd.h")
+@:include("sys/socket.h")
+extern class Socket {
+ @:native("socket") static function socket(domain:Int32, type:Int32, protocol:Int32):Int32;
+ @:native("bind") static function bind(sockfd:Int32, addr:ConstStar<SockAddr>, addrlen:Int32):Int32;
+ @:native("listen") static function listen(sockfd:Int32, backlog:Int32):Int32;
+ @:native("accept") static function accept(sockfd:Int32, addr:Star<SockAddr>, addrlen:Star<Int32>):Int32;
+ @:native("connect") static function connect(sockfd:Int32, addr:ConstStar<SockAddr>, addrlen:Int32):Int32;
+ @:native("read") static function read(fd:Int32, buf:Star<Void>, count:SizeT):SizeT;
+ @:native("write") static function write(fd:Int32, buf:ConstStar<Void>, count:SizeT):SizeT;
+ @:native("close") static function close(fd:Int32):Int32;
+}
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);
+ }
+}
diff --git a/src/unix/UnixSocket.hx b/src/unix/UnixSocket.hx
new file mode 100644
index 0000000..1e5cea2
--- /dev/null
+++ b/src/unix/UnixSocket.hx
@@ -0,0 +1,8 @@
+package unix;
+
+/*
+ This is a dummy file.
+
+ See UnixSocket.<target>.hx for the actual implementation for each target.
+*/
+class UnixSocket {}