diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/externs/Build.xml | 9 | ||||
-rw-r--r-- | src/externs/Socket.cpp.hx | 32 | ||||
-rw-r--r-- | src/unix/UnixSocket.cpp.hx | 150 | ||||
-rw-r--r-- | src/unix/UnixSocket.hx | 8 |
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 {} |