Переглянути джерело

[cpp] Add ipv6 connections for cpp sockets

Hugh Sanderson 8 роки тому
батько
коміт
b023e2c4e1
3 змінених файлів з 241 додано та 198 видалено
  1. 12 1
      std/cpp/NativeSocket.hx
  2. 6 2
      std/cpp/_std/sys/net/Host.hx
  3. 223 195
      std/cpp/_std/sys/net/Socket.hx

+ 12 - 1
std/cpp/NativeSocket.hx

@@ -12,6 +12,9 @@ extern class NativeSocket
    @:extern @:native("_hx_std_socket_new")
    public static function socket_new(udp:Bool) : Dynamic return null;
 
+   @:extern @:native("_hx_std_socket_new")
+   public static function socket_new_ip(udp:Bool,ipv6:Bool) : Dynamic return null;
+
 
    @:extern @:native("_hx_std_socket_close")
    public static function socket_close(handle:Dynamic) : Void { }
@@ -20,6 +23,9 @@ extern class NativeSocket
    @:extern @:native("_hx_std_socket_bind")
    public static function socket_bind(o:Dynamic,host:Int,port:Int) : Void { }
 
+   @:extern @:native("_hx_std_socket_bind_ipv6")
+   public static function socket_bind_ipv6(o:Dynamic,host:haxe.io.BytesData,port:Int) : Void { }
+
 
    @:extern @:native("_hx_std_socket_send_char")
    public static function socket_send_char(o:Dynamic,c:Int) : Void { }
@@ -45,7 +51,7 @@ extern class NativeSocket
    public static function socket_read(o:Dynamic) : haxe.io.BytesData return null;
 
    @:extern @:native("_hx_std_host_resolve_ipv6")
-   public static function host_resolve_ipv6(host:String,onlyIfNoIpv4:Bool) : haxe.io.BytesData return null;
+   public static function host_resolve_ipv6(host:String) : haxe.io.BytesData return null;
 
 
    @:extern @:native("_hx_std_host_resolve")
@@ -69,10 +75,15 @@ extern class NativeSocket
    @:extern @:native("_hx_std_host_local")
    public static function host_local() : String return null;
 
+   inline public static function host_local_ipv6() : String return "::1";
+
 
    @:extern @:native("_hx_std_socket_connect")
    public static function socket_connect(o:Dynamic,host:Int,port:Int) : Void { }
 
+   @:extern @:native("_hx_std_socket_connect_ipv6")
+   public static function socket_connect_ipv6(o:Dynamic,host:haxe.io.BytesData,port:Int) : Void { }
+
 
    @:extern @:native("_hx_std_socket_listen")
    public static function socket_listen(o:Dynamic,n:Int) : Void { }

+ 6 - 2
std/cpp/_std/sys/net/Host.hx

@@ -34,9 +34,13 @@ class Host {
 
 	public function new( name : String ) : Void {
 		host = name;
-		ipv6 = NativeSocket.host_resolve_ipv6(name,true);
-		if (ipv6==null)
+      try {
 			ip = NativeSocket.host_resolve(name);
+      }
+      catch(e:Dynamic)
+      {
+		   ipv6 = NativeSocket.host_resolve_ipv6(name);
+      }
 	}
 
 	public function toString() : String {

+ 223 - 195
std/cpp/_std/sys/net/Socket.hx

@@ -26,87 +26,87 @@ import cpp.NativeSocket;
 
 private class SocketInput extends haxe.io.Input {
 
-	var __s : Dynamic;
-
-	public function new(s) {
-		__s = s;
-	}
-
-	public override function readByte() {
-		return try {
-			NativeSocket.socket_recv_char(__s);
-		} catch( e : Dynamic ) {
-			if( e == "Blocking" )
-				throw Blocked;
-			else if( __s == null )
-				throw Custom(e);
-			else
-				throw new haxe.io.Eof();
-		}
-	}
-
-	public override function readBytes( buf : haxe.io.Bytes, pos : Int, len : Int ) : Int {
-		var r;
-		if (__s==null)
-			throw "Invalid handle";
-		try {
-			r = NativeSocket.socket_recv(__s,buf.getData(),pos,len);
-		} catch( e : Dynamic ) {
-			if( e == "Blocking" )
-				throw Blocked;
-			else
-				throw Custom(e);
-		}
-		if( r == 0 )
-			throw new haxe.io.Eof();
-		return r;
-	}
-
-	public override function close() {
-		super.close();
-		if( __s != null ) NativeSocket.socket_close(__s);
-	}
+   var __s : Dynamic;
+
+   public function new(s) {
+      __s = s;
+   }
+
+   public override function readByte() {
+      return try {
+         NativeSocket.socket_recv_char(__s);
+      } catch( e : Dynamic ) {
+         if( e == "Blocking" )
+            throw Blocked;
+         else if( __s == null )
+            throw Custom(e);
+         else
+            throw new haxe.io.Eof();
+      }
+   }
+
+   public override function readBytes( buf : haxe.io.Bytes, pos : Int, len : Int ) : Int {
+      var r;
+      if (__s==null)
+         throw "Invalid handle";
+      try {
+         r = NativeSocket.socket_recv(__s,buf.getData(),pos,len);
+      } catch( e : Dynamic ) {
+         if( e == "Blocking" )
+            throw Blocked;
+         else
+            throw Custom(e);
+      }
+      if( r == 0 )
+         throw new haxe.io.Eof();
+      return r;
+   }
+
+   public override function close() {
+      super.close();
+      if( __s != null ) NativeSocket.socket_close(__s);
+   }
 
 }
 
 private class SocketOutput extends haxe.io.Output {
 
-	var __s : Dynamic;
-
-	public function new(s) {
-		__s = s;
-	}
-
-	public override function writeByte( c : Int ) {
-		if (__s==null)
-			throw "Invalid handle";
-		try {
-			NativeSocket.socket_send_char(__s, c);
-		} catch( e : Dynamic ) {
-			if( e == "Blocking" )
-				throw Blocked;
-			else
-				throw Custom(e);
-		}
-	}
-
-	public override function writeBytes( buf : haxe.io.Bytes, pos : Int, len : Int) : Int {
-		return try {
-			NativeSocket.socket_send(__s, buf.getData(), pos, len);
-		} catch( e : Dynamic ) {
-			if( e == "Blocking" )
-				throw Blocked;
-			else if (e == "EOF")
-				throw new haxe.io.Eof();
-			else
-				throw Custom(e);
-		}
-	}
-
-	public override function close() {
-		super.close();
-		if( __s != null ) NativeSocket.socket_close(__s);
-	}
+   var __s : Dynamic;
+
+   public function new(s) {
+      __s = s;
+   }
+
+   public override function writeByte( c : Int ) {
+      if (__s==null)
+         throw "Invalid handle";
+      try {
+         NativeSocket.socket_send_char(__s, c);
+      } catch( e : Dynamic ) {
+         if( e == "Blocking" )
+            throw Blocked;
+         else
+            throw Custom(e);
+      }
+   }
+
+   public override function writeBytes( buf : haxe.io.Bytes, pos : Int, len : Int) : Int {
+      return try {
+         NativeSocket.socket_send(__s, buf.getData(), pos, len);
+      } catch( e : Dynamic ) {
+         if( e == "Blocking" )
+            throw Blocked;
+         else if (e == "EOF")
+            throw new haxe.io.Eof();
+         else
+            throw Custom(e);
+      }
+   }
+
+   public override function close() {
+      super.close();
+      if( __s != null ) NativeSocket.socket_close(__s);
+   }
 
 }
 
@@ -114,124 +114,152 @@ private class SocketOutput extends haxe.io.Output {
 @:coreApi
 class Socket {
 
-	private var __s : Dynamic;
-	public var input(default,null) : haxe.io.Input;
-	public var output(default,null) : haxe.io.Output;
-	public var custom : Dynamic;
-
-	public function new() : Void {
-		init();
-	}
-
-	private function init() : Void {
-		if( __s == null )__s = NativeSocket.socket_new(false);
-		input = new SocketInput(__s);
-		output = new SocketOutput(__s);
-	}
-
-	public function close() : Void {
-		NativeSocket.socket_close(__s);
-		untyped {
-			var input : SocketInput = cast input;
-			var output : SocketOutput = cast output;
-			input.__s = null;
-			output.__s = null;
-		}
-		input.close();
-		output.close();
-	}
-
-	public function read() : String {
-		var bytes:haxe.io.BytesData = NativeSocket.socket_read(__s);
-		if (bytes==null) return "";
-		return bytes.toString();
-	}
-
-	public function write( content : String ) : Void {
-		NativeSocket.socket_write(__s, haxe.io.Bytes.ofString(content).getData() );
-	}
-
-	public function connect(host : Host, port : Int) : Void {
-		try {
-			NativeSocket.socket_connect(__s, host.ip, port);
-		} catch( s : String ) {
-			if( s == "Invalid socket handle" )
-				throw "Failed to connect on "+host.toString()+":"+port;
-			else if (s == "Blocking") {
-				// Do nothing, this is not a real error, it simply indicates
-				// that a non-blocking connect is in progress
-			}
-			else
-				cpp.Lib.rethrow(s);
-		}
-	}
-
-	public function listen(connections : Int) : Void {
-		NativeSocket.socket_listen(__s, connections);
-	}
-
-	public function shutdown( read : Bool, write : Bool ) : Void {
-		NativeSocket.socket_shutdown(__s,read,write);
-	}
-
-	public function bind(host : Host, port : Int) : Void {
-		NativeSocket.socket_bind(__s, host.ip, port);
-	}
-
-	public function accept() : Socket {
-		var c = NativeSocket.socket_accept(__s);
-		var s = Type.createEmptyInstance(Socket);
-		s.__s = c;
-		s.input = new SocketInput(c);
-		s.output = new SocketOutput(c);
-		return s;
-	}
-
-	public function peer() : { host : Host, port : Int } {
-		var a : Dynamic = NativeSocket.socket_peer(__s);
-		if (a == null) {
-			return null;
-		}
-		var h = new Host("127.0.0.1");
-		untyped h.ip = a[0];
-		return { host : h, port : a[1] };
-	}
-
-	public function host() : { host : Host, port : Int } {
-		var a : Dynamic = NativeSocket.socket_host(__s);
-		if (a == null) {
-			return null;
-		}
-		var h = new Host("127.0.0.1");
-		untyped h.ip = a[0];
-		return { host : h, port : a[1] };
-	}
-
-	public function setTimeout( timeout : Float ) : Void {
-		NativeSocket.socket_set_timeout(__s, timeout);
-	}
-
-	public function waitForRead() : Void {
-		select([this],null,null,null);
-	}
-
-	public function setBlocking( b : Bool ) : Void {
-		NativeSocket.socket_set_blocking(__s,b);
-	}
-
-	public function setFastSend( b : Bool ) : Void {
-		NativeSocket.socket_set_fast_send(__s,b);
-	}
-
-	public static function select(read : Array<Socket>, write : Array<Socket>, others : Array<Socket>, ?timeout : Float ) : {read: Array<Socket>,write: Array<Socket>,others: Array<Socket>} {
-		var neko_array = NativeSocket.socket_select(read,write,others, timeout);
-		if (neko_array==null)
-			throw "Select error";
-		return @:fixed {
-			read: neko_array[0],
-			write: neko_array[1],
-			others: neko_array[2]
-		};
-	}
+   private var __s : Dynamic;
+   public var input(default,null) : haxe.io.Input;
+   public var output(default,null) : haxe.io.Output;
+   public var custom : Dynamic;
+
+   public function new() : Void {
+      init();
+   }
+
+   private function init() : Void {
+      if( __s == null )__s = NativeSocket.socket_new(false);
+      input = new SocketInput(__s);
+      output = new SocketOutput(__s);
+   }
+
+   public function close() : Void {
+      NativeSocket.socket_close(__s);
+      untyped {
+         var input : SocketInput = cast input;
+         var output : SocketOutput = cast output;
+         input.__s = null;
+         output.__s = null;
+      }
+      input.close();
+      output.close();
+   }
+
+   public function read() : String {
+      var bytes:haxe.io.BytesData = NativeSocket.socket_read(__s);
+      if (bytes==null) return "";
+      return bytes.toString();
+   }
+
+   public function write( content : String ) : Void {
+      NativeSocket.socket_write(__s, haxe.io.Bytes.ofString(content).getData() );
+   }
+
+   public function connect(host : Host, port : Int) : Void {
+      try {
+         if (host.ip==0) {
+            // hack, hack, hack
+            var ipv6:haxe.io.BytesData = Reflect.field(host,"ipv6");
+            if (ipv6!=null)
+            {
+                close();
+                __s = NativeSocket.socket_new_ip(false,true);
+                init();
+                NativeSocket.socket_connect_ipv6(__s, ipv6, port);
+            }
+            else
+               throw "Unresolved host";
+         }
+         else
+            NativeSocket.socket_connect(__s, host.ip, port);
+      } catch( s : String ) {
+         if( s == "Invalid socket handle" )
+            throw "Failed to connect on "+host.toString()+":"+port;
+         else if (s == "Blocking") {
+            // Do nothing, this is not a real error, it simply indicates
+            // that a non-blocking connect is in progress
+         }
+         else
+            cpp.Lib.rethrow(s);
+      }
+   }
+
+   public function listen(connections : Int) : Void {
+      NativeSocket.socket_listen(__s, connections);
+   }
+
+   public function shutdown( read : Bool, write : Bool ) : Void {
+      NativeSocket.socket_shutdown(__s,read,write);
+   }
+
+   public function bind(host : Host, port : Int) : Void {
+      if (host.ip==0)
+      {
+          var ipv6:haxe.io.BytesData = Reflect.field(host,"ipv6");
+          if (ipv6!=null)
+          {
+              close();
+              __s = NativeSocket.socket_new_ip(false,true);
+              init();
+              NativeSocket.socket_bind_ipv6(__s, ipv6, port);
+          }
+          else
+             throw "Unresolved host";
+      }
+      else
+         NativeSocket.socket_bind(__s, host.ip, port);
+   }
+
+   public function accept() : Socket {
+      var c = NativeSocket.socket_accept(__s);
+      var s = Type.createEmptyInstance(Socket);
+      s.__s = c;
+      s.input = new SocketInput(c);
+      s.output = new SocketOutput(c);
+      return s;
+   }
+
+   public function peer() : { host : Host, port : Int } {
+      var a : Dynamic = NativeSocket.socket_peer(__s);
+      if (a == null) {
+         return null;
+      }
+      var h = new Host("127.0.0.1");
+      untyped h.ip = a[0];
+      return { host : h, port : a[1] };
+   }
+
+   public function host() : { host : Host, port : Int } {
+      var a : Dynamic = NativeSocket.socket_host(__s);
+      if (a == null) {
+         return null;
+      }
+      var h = new Host("127.0.0.1");
+      untyped h.ip = a[0];
+      return { host : h, port : a[1] };
+   }
+
+   public function setTimeout( timeout : Float ) : Void {
+      NativeSocket.socket_set_timeout(__s, timeout);
+   }
+
+   public function waitForRead() : Void {
+      select([this],null,null,null);
+   }
+
+   public function setBlocking( b : Bool ) : Void {
+      NativeSocket.socket_set_blocking(__s,b);
+   }
+
+   public function setFastSend( b : Bool ) : Void {
+      NativeSocket.socket_set_fast_send(__s,b);
+   }
+
+   public static function select(read : Array<Socket>, write : Array<Socket>, others : Array<Socket>, ?timeout : Float ) : {read: Array<Socket>,write: Array<Socket>,others: Array<Socket>} {
+      var neko_array = NativeSocket.socket_select(read,write,others, timeout);
+      if (neko_array==null)
+         throw "Select error";
+      return @:fixed {
+         read: neko_array[0],
+         write: neko_array[1],
+         others: neko_array[2]
+      };
+   }
 
 }