2
0
Эх сурвалжийг харах

implemented hxd.Socket using HL/libuv

ncannasse 8 жил өмнө
parent
commit
f06fbae3a9
2 өөрчлөгдсөн 224 нэмэгдсэн , 85 устгасан
  1. 217 84
      hxd/net/Socket.hx
  2. 7 1
      hxd/net/SocketHost.hx

+ 217 - 84
hxd/net/Socket.hx

@@ -30,84 +30,6 @@ private class SocketInput extends haxe.io.Input {
 
 }
 
-#if flash
-private class FlashSocketOutput extends SocketOutput {
-	var s : flash.net.Socket;
-	var autoFlush = true;
-
-	public function new(s) {
-		super();
-		this.s = s;
-		s.endian = flash.utils.Endian.LITTLE_ENDIAN;
-	}
-
-	inline function f() if( autoFlush ) s.flush();
-
-	override function wait() {
-		autoFlush = false;
-	}
-
-	override function flush() {
-		autoFlush = true;
-		s.flush();
-	}
-
-	override function writeByte( c : Int ) {
-		s.writeByte(c);
-		f();
-	}
-
-	override function writeBytes( b : haxe.io.Bytes, pos : Int, len : Int ) : Int {
-		if( len > 0 ) {
-			s.writeBytes(b.getData(), pos, len);
-			f();
-		}
-		return len;
-	}
-
-	override function writeInt32( i : Int ) {
-		s.writeInt(i);
-		f();
-	}
-
-	override function writeString( str : String ) {
-		s.writeUTFBytes(str);
-		f();
-	}
-
-}
-
-private class FlashSocketInput extends SocketInput {
-
-	var sock : flash.net.Socket;
-
-	public function new(s) {
-		sock = s;
-	}
-
-	override function get_available() {
-		return sock.bytesAvailable;
-	}
-
-	override function readBytes( bytes : haxe.io.Bytes, pos : Int, len : Int ) {
-		if( len > (sock.bytesAvailable : Int) ) {
-			len = sock.bytesAvailable;
-			if( len == 0 ) throw new haxe.io.Eof();
-		}
-		if( len > 0 )
-			sock.readBytes(bytes.getData(), pos, len);
-		return len;
-	}
-
-	override function readByte() {
-		if( sock.bytesAvailable == 0 )
-			throw new haxe.io.Eof();
-		return sock.readUnsignedByte();
-	}
-
-}
-#end
-
 class Socket {
 
 	static var openedSocks = [];
@@ -117,12 +39,16 @@ class Socket {
 	#if (flash && air3)
 	var serv : flash.net.ServerSocket;
 	#end
+	#if hl
+	var s : hl.uv.Stream;
+	#end
 	public var out(default, null) : SocketOutput;
 	public var input(default, null) : SocketInput;
 	public var timeout(default, set) : Null<Float>;
 
 	public function new() {
 		out = new SocketOutput();
+		hl.uv.Loop.register();
 	}
 
 	public function set_timeout(t:Null<Float>) {
@@ -145,13 +71,26 @@ class Socket {
 		});
 		bindEvents();
 		s.connect(host, port);
+		#elseif hl
+		var tcp = new hl.uv.Tcp();
+		s = tcp;
+		tcp.connect(new sys.net.Host(host), port, function(b) {
+			if( !b ) {
+				close();
+				onError("Failed to connect");
+				return;
+			}
+			out = new HLSocketOutput(this);
+			input = new HLSocketInput(this);
+			onConnect();
+		});
 		#else
 		throw "Not implemented";
 		#end
 	}
 
+	#if flash
 	function bindEvents() {
-		#if flash
 		s.addEventListener(flash.events.IOErrorEvent.IO_ERROR, function(e:flash.events.IOErrorEvent) {
 			close();
 			onError(e.text);
@@ -163,8 +102,8 @@ class Socket {
 		s.addEventListener(flash.events.ProgressEvent.SOCKET_DATA, function(e:flash.events.ProgressEvent) {
 			onData();
 		});
-		#end
 	}
+	#end
 
 	public static inline var ALLOW_BIND = #if (flash && air3) true #else false #end;
 
@@ -188,6 +127,24 @@ class Socket {
 			openedSocks.push(s);
 			onConnect(s);
 		});
+		#elseif hl
+		var tcp = new hl.uv.Tcp();
+		s = tcp;
+		try {
+			tcp.bind(new sys.net.Host(host), port);
+			tcp.listen(10, function() {
+				var sock = tcp.accept();
+				var s = new Socket();
+				s.s = sock;
+				s.out = new HLSocketOutput(s);
+				s.input = new HLSocketInput(s);
+				openedSocks.push(s);
+				onConnect(s);
+			});
+		} catch( e : Dynamic ) {
+			close();
+			throw e;
+		}
 		#else
 		throw "Not implemented";
 		#end
@@ -201,14 +158,12 @@ class Socket {
 			serv = null;
 		}
 		#end
-		#if flash
+		#if (flash || hl)
 		if( s != null ) {
 			try s.close() catch( e : Dynamic ) { };
 			out = new SocketOutput();
 			s = null;
 		}
-		#else
-		throw "Not implemented";
 		#end
 	}
 
@@ -219,4 +174,182 @@ class Socket {
 	public dynamic function onData() {
 	}
 
-}
+}
+
+
+#if flash
+private class FlashSocketOutput extends SocketOutput {
+	var s : flash.net.Socket;
+	var autoFlush = true;
+
+	public function new(s) {
+		super();
+		this.s = s;
+		s.endian = flash.utils.Endian.LITTLE_ENDIAN;
+	}
+
+	inline function f() if( autoFlush ) s.flush();
+
+	override function wait() {
+		autoFlush = false;
+	}
+
+	override function flush() {
+		autoFlush = true;
+		s.flush();
+	}
+
+	override function writeByte( c : Int ) {
+		s.writeByte(c);
+		f();
+	}
+
+	override function writeBytes( b : haxe.io.Bytes, pos : Int, len : Int ) : Int {
+		if( len > 0 ) {
+			s.writeBytes(b.getData(), pos, len);
+			f();
+		}
+		return len;
+	}
+
+	override function writeInt32( i : Int ) {
+		s.writeInt(i);
+		f();
+	}
+
+	override function writeString( str : String ) {
+		s.writeUTFBytes(str);
+		f();
+	}
+
+}
+
+private class FlashSocketInput extends SocketInput {
+
+	var sock : flash.net.Socket;
+
+	public function new(s) {
+		sock = s;
+	}
+
+	override function get_available() {
+		return sock.bytesAvailable;
+	}
+
+	override function readBytes( bytes : haxe.io.Bytes, pos : Int, len : Int ) {
+		if( len > (sock.bytesAvailable : Int) ) {
+			len = sock.bytesAvailable;
+			if( len == 0 ) throw new haxe.io.Eof();
+		}
+		if( len > 0 )
+			sock.readBytes(bytes.getData(), pos, len);
+		return len;
+	}
+
+	override function readByte() {
+		if( sock.bytesAvailable == 0 )
+			throw new haxe.io.Eof();
+		return sock.readUnsignedByte();
+	}
+
+}
+
+#elseif hl
+
+class HLSocketOutput extends SocketOutput {
+
+	var tmpBuf : haxe.io.Bytes;
+	var s : Socket;
+	var onWriteResult : Bool -> Void;
+
+	public function new(s) {
+		super();
+		this.s = s;
+		onWriteResult = writeResult;
+	}
+
+	function writeResult(b) {
+		if( !b ) {
+			s.close();
+			s.onError("Failed to write data");
+		}
+	}
+
+	override function writeByte(c:Int) {
+		if( tmpBuf == null )
+			tmpBuf = haxe.io.Bytes.alloc(1);
+		tmpBuf.set(0, c);
+		@:privateAccess s.s.write(tmpBuf, onWriteResult);
+	}
+
+	override function writeBytes(buf:haxe.io.Bytes, pos:Int, len:Int):Int {
+		@:privateAccess s.s.write(buf, onWriteResult, pos, len);
+		return len;
+	}
+
+}
+
+class HLSocketInput extends SocketInput {
+
+	var s : Socket;
+	var data : hl.Bytes;
+	var pos : Int;
+	var len : Int;
+	var size : Int;
+
+	public function new(sock) {
+		this.s = sock;
+		@:privateAccess s.s.readStartRaw(onData);
+	}
+
+	function onData(recvData:hl.Bytes, recv:Int) {
+		if( recv < 0 ) {
+			s.close();
+			s.onError("Connection closed");
+			return;
+		}
+		//trace(">" + recvData.toBytes(recv).toHex());
+		var req = pos + len + recv;
+		if( req > size && pos >= (size >> 1) ) {
+			data.blit(0, data, pos, len);
+			pos = 0;
+			req -= pos;
+		}
+		if( req > size ) {
+			var nsize = size == 0 ? 1024 : size;
+			while( nsize < req ) nsize = (nsize * 3) >> 1;
+			var ndata = new hl.Bytes(nsize);
+			ndata.blit(0, data, pos, len);
+			data = ndata;
+			size = nsize;
+			pos = 0;
+		}
+		data.blit(pos + len, recvData, 0, recv);
+		len += recv;
+		s.onData();
+	}
+
+	override function get_available() {
+		return len;
+	}
+
+	override function readByte():Int {
+		if( len == 0 ) throw new haxe.io.Eof();
+		var c = data[pos++];
+		len--;
+		return c;
+	}
+
+	override function readBytes(s:haxe.io.Bytes, pos:Int, len:Int):Int {
+		if( pos < 0 || len < 0  || pos + len > s.length ) throw haxe.io.Error.OutsideBounds;
+		var max = len < this.len ? len : this.len;
+		@:privateAccess s.b.blit(pos, data, pos, max);
+		//trace("<" + s.sub(pos,len).toHex());
+		pos += max;
+		len -= max;
+		return max;
+	}
+
+}
+
+#end

+ 7 - 1
hxd/net/SocketHost.hx

@@ -144,7 +144,13 @@ class SocketHost extends NetworkHost {
 		l.loadBytes(flash.Lib.current.loaderInfo.bytes, ctx);
 		win.activate();
 		#else
-		throw "Not implemented";
+		var args = Sys.args();
+		for( i in 0...args.length )
+			if( args[i] == "--host" )
+				args[i] = "--client";
+		var hlFile = @:privateAccess Sys.makePath(Sys.sys_hl_file());
+		args.unshift(hlFile);
+		new sys.io.Process("hl.exe", args);
 		#end
 	}