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

[python] Fixed python.net.SslSocket when python-version >= 3.4 (#8401) (#11050)

* [python] Fixed python.net.SslSocket when python-version >= 3.4 (#8401)

The issue where SslSocket throws an exception is due to hostName being
null in wrap_socket.  This fix delays wrap_socket until after connect is
called, so we can pass a host in.

* added compilation flag to only run this for python

* removed sys.net.Host import; it was unused, and it caused issues on
non-sys targets

* fixed test to work across platforms (see comment in code)

fixed copy/paste error in code comments

* added gettimeout, getblocking, and getsockopt to
python.lib.socket.Socket
(also added overload of setsockopt to take an Int value)

updated Issue8401 to remove casts

* replaced eq with feq in test for settimeout values
Jesse Rosalia 2 жил өмнө
parent
commit
a521f7a445

+ 5 - 0
std/python/_std/sys/net/Socket.hx

@@ -126,6 +126,11 @@ private class SocketOutput extends haxe.io.Output {
 		__s = new PSocket();
 		__s = new PSocket();
 	}
 	}
 
 
+    function __rebuildIoStreams():Void {
+		input = new SocketInput(__s);
+		output = new SocketOutput(__s);
+    }
+
 	public function close():Void {
 	public function close():Void {
 		__s.close();
 		__s.close();
 	}
 	}

+ 17 - 0
std/python/lib/socket/Socket.hx

@@ -80,6 +80,11 @@ extern class Socket {
 	**/
 	**/
 	function getsockname():python.lib.socket.Address;
 	function getsockname():python.lib.socket.Address;
 
 
+	/**
+		Return the timeout for the socket or null if no timeout has been set.
+	**/
+	function gettimeout():Null<Float>;
+
 	/**
 	/**
 		Gives a timeout after which blocking socket operations (such as reading and writing) will abort and throw an exception.
 		Gives a timeout after which blocking socket operations (such as reading and writing) will abort and throw an exception.
 	**/
 	**/
@@ -90,14 +95,26 @@ extern class Socket {
 	**/
 	**/
 	function waitForRead():Void;
 	function waitForRead():Void;
 
 
+	/**
+		Return the current blocking mode of the socket.
+	**/
+	@:require(python_version >= 3.7)
+	function getblocking():Bool;
+
 	/**
 	/**
 		Change the blocking mode of the socket. A blocking socket is the default behavior. A non-blocking socket will abort blocking operations immediately by throwing a haxe.io.Error.Blocked value.
 		Change the blocking mode of the socket. A blocking socket is the default behavior. A non-blocking socket will abort blocking operations immediately by throwing a haxe.io.Error.Blocked value.
 	**/
 	**/
 	function setblocking(b:Bool):Void;
 	function setblocking(b:Bool):Void;
 
 
 	/**
 	/**
+		Return the current value of the sockopt as an Int or a Bytes buffer (if buflen is specified).
+	**/
+	function getsockopt(family:Int, option:Int):Int;
 
 
+	/**
+		Change the value of the given socket option.
 	**/
 	**/
+	@:overload(function(family:Int, option:Int, value:Int):Void {})
 	function setsockopt(family:Int, option:Int, value:Bool):Void;
 	function setsockopt(family:Int, option:Int, value:Bool):Void;
 
 
 	function fileno():Int;
 	function fileno():Int;

+ 34 - 5
std/python/net/SslSocket.hx

@@ -25,12 +25,15 @@ package python.net;
 import python.lib.Ssl;
 import python.lib.Ssl;
 import python.lib.ssl.Purpose;
 import python.lib.ssl.Purpose;
 import python.lib.socket.Socket as PSocket;
 import python.lib.socket.Socket as PSocket;
+import python.lib.Socket in PSocketModule;
 import sys.net.Host;
 import sys.net.Host;
 
 
 class SslSocket extends sys.net.Socket {
 class SslSocket extends sys.net.Socket {
-	var hostName:String;
+	var _timeout:Null<Float> = null;
+	var _blocking:Null<Bool> = null;
+	var _fastSend:Null<Bool> = null;
 
 
-	override function __initSocket():Void {
+	function wrapSocketWithSslContext(hostName:String):Void {
 		#if (python_version >= 3.4)
 		#if (python_version >= 3.4)
 		var context = Ssl.create_default_context(Purpose.SERVER_AUTH);
 		var context = Ssl.create_default_context(Purpose.SERVER_AUTH);
 		#else
 		#else
@@ -43,16 +46,42 @@ class SslSocket extends sys.net.Socket {
 		context.options |= Ssl.OP_NO_COMPRESSION;
 		context.options |= Ssl.OP_NO_COMPRESSION;
 		#end
 		#end
 		context.options |= Ssl.OP_NO_TLSv1 #if (python_version >= 3.4) | Ssl.OP_NO_TLSv1_1 #end; // python 3.4 | Ssl.OP_NO_TLSv1_1;
 		context.options |= Ssl.OP_NO_TLSv1 #if (python_version >= 3.4) | Ssl.OP_NO_TLSv1_1 #end; // python 3.4 | Ssl.OP_NO_TLSv1_1;
-		__s = new PSocket();
-		__s = context.wrap_socket(__s, false, true, true, this.hostName);
+		__s = context.wrap_socket(__s, false, true, true, hostName);
+		if (_timeout != null) {
+			super.setTimeout(_timeout);
+		}
+
+		if (_blocking != null) {
+			super.setBlocking(_blocking);
+		}
+
+		if (_fastSend != null) {
+			super.setFastSend(_fastSend);
+		}
+		__rebuildIoStreams();
 	}
 	}
 
 
 	public override function connect(host:Host, port:Int):Void {
 	public override function connect(host:Host, port:Int):Void {
-		this.hostName = host.host;
+		wrapSocketWithSslContext(host.host);
 		super.connect(host, port);
 		super.connect(host, port);
 	}
 	}
 
 
 	public override function bind(host:Host, port:Int):Void {
 	public override function bind(host:Host, port:Int):Void {
 		throw new haxe.exceptions.NotImplementedException();
 		throw new haxe.exceptions.NotImplementedException();
 	}
 	}
+
+	public override function setTimeout(timeout:Float):Void {
+		_timeout = timeout;
+		super.setTimeout(_timeout);
+	}
+
+	public override function setBlocking(b:Bool):Void {
+		_blocking = b;
+		super.setBlocking(_blocking);
+	}
+
+	public override function setFastSend(b:Bool):Void {
+		_fastSend = b;
+		super.setFastSend(_fastSend);
+	}
 }
 }

+ 2 - 0
tests/runci/targets/Python.hx

@@ -63,6 +63,8 @@ class Python {
 		runCommand("haxe", ["compile-python.hxml"].concat(args));
 		runCommand("haxe", ["compile-python.hxml"].concat(args));
 		for (py in pys) {
 		for (py in pys) {
 			runCommand(py, ["bin/unit.py"]);
 			runCommand(py, ["bin/unit.py"]);
+			// Additional test for python-version >= 3.4
+			runCommand(py, ["bin/unit34.py"]);
 		}
 		}
 
 
 		changeDirectory(sysDir);
 		changeDirectory(sysDir);

+ 10 - 1
tests/unit/compile-python.hxml

@@ -1,3 +1,12 @@
 compile-each.hxml
 compile-each.hxml
+
+--each
+
 --main unit.TestMain
 --main unit.TestMain
--python bin/unit.py
+-python bin/unit.py
+
+--next
+
+-D python-version=3.4
+--main unit.TestMain
+-python bin/unit34.py

+ 50 - 0
tests/unit/src/unit/issues/Issue8401.hx

@@ -0,0 +1,50 @@
+package unit.issues;
+
+class Issue8401 extends unit.Test {
+#if python
+	function testNew() {
+		var sock = new python.net.SslSocket();
+		// With Issue8401, construction fails immediately; if we get this far, it's a pass
+		utest.Assert.pass();
+	}
+
+	@:access(python.net.SslSocket.__s)
+	@:access(python.net.SslSocket.wrapSocketWithSslContext)
+	function testTimeout() {
+		var sock = new python.net.SslSocket();
+		eq(null, sock.__s.gettimeout());
+		sock.setTimeout(500);
+		feq(500, sock.__s.gettimeout());
+		// This will change __s.  Make sure we set the timeout properly.
+		sock.wrapSocketWithSslContext("127.0.0.1");
+		feq(500, sock.__s.gettimeout());
+	}
+
+	#if (python_verion >= 3.7)
+	@:access(python.net.SslSocket.__s)
+	@:access(python.net.SslSocket.wrapSocketWithSslContext)
+	function testBlocking() {
+		var sock = new python.net.SslSocket();
+		t(sock.__s.getblocking());
+		sock.setBlocking(false);
+		f(sock.__s.getblocking());
+		// This will change __s.  Make sure we set the blocking flag properly.
+		sock.wrapSocketWithSslContext("127.0.0.1");
+		f(sock.__s.getblocking());
+	}
+	#end
+
+	@:access(python.net.SslSocket.__s)
+	@:access(python.net.SslSocket.wrapSocketWithSslContext)
+	function testFastSend() {
+		var sock = new python.net.SslSocket();
+		eq(0, sock.__s.getsockopt(python.lib.Socket.SOL_TCP, python.lib.Socket.TCP_NODELAY));
+		sock.setFastSend(true);
+        // NOTE: this number can vary per platform; non-zero means true/enabled
+		utest.Assert.notEquals(0, sock.__s.getsockopt(python.lib.Socket.SOL_TCP, python.lib.Socket.TCP_NODELAY));
+		// This will change __s.  Make sure we set the sock opt properly.
+		sock.wrapSocketWithSslContext("127.0.0.1");
+		utest.Assert.notEquals(0, sock.__s.getsockopt(python.lib.Socket.SOL_TCP, python.lib.Socket.TCP_NODELAY));
+	}
+#end
+}