Socket.hx 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /*
  2. * Copyright (C)2005-2019 Haxe Foundation
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  20. * DEALINGS IN THE SOFTWARE.
  21. */
  22. package sys.net;
  23. import haxe.io.Error;
  24. import haxe.io.Bytes;
  25. import haxe.io.BytesData;
  26. import python.Exceptions;
  27. import python.Tuple;
  28. import python.lib.socket.Socket in PSocket;
  29. import python.lib.Socket in PSocketModule;
  30. import python.lib.socket.Address in PAddress;
  31. import python.lib.Select;
  32. import python.lib.ssl.Errors;
  33. private class SocketInput extends haxe.io.Input {
  34. var __s:PSocket;
  35. public function new(s) {
  36. __s = s;
  37. }
  38. public override function readByte():Int {
  39. var r:BytesData;
  40. try {
  41. r = __s.recv(1, 0);
  42. } catch (e:BlockingIOError) {
  43. throw Blocked;
  44. }
  45. if (r.length == 0)
  46. throw new haxe.io.Eof();
  47. return python.Syntax.code("r[0]");
  48. }
  49. public override function readBytes(buf:haxe.io.Bytes, pos:Int, len:Int):Int {
  50. var r;
  51. var data = buf.getData();
  52. try {
  53. try {
  54. r = __s.recv(len, 0);
  55. } catch(e:SSLWantReadError) {
  56. return 0;
  57. }
  58. for (i in pos...(pos + r.length)) {
  59. data.set(i, r[i - pos]);
  60. }
  61. } catch (e:BlockingIOError) {
  62. throw Blocked;
  63. }
  64. if (r.length == 0)
  65. throw new haxe.io.Eof();
  66. return r.length;
  67. }
  68. public override function close() {
  69. super.close();
  70. if (__s != null)
  71. __s.close();
  72. }
  73. }
  74. private class SocketOutput extends haxe.io.Output {
  75. var __s:PSocket;
  76. public function new(s) {
  77. __s = s;
  78. }
  79. public override function writeByte(c:Int) {
  80. try {
  81. __s.send(python.Syntax.code('bytes([c])'), 0);
  82. } catch (e:BlockingIOError) {
  83. throw Blocked;
  84. }
  85. }
  86. public override function writeBytes(buf:haxe.io.Bytes, pos:Int, len:Int):Int {
  87. try {
  88. var data = buf.getData();
  89. var payload = python.Syntax.code("{0}[{1}:{1}+{2}]", data, pos, len);
  90. var r = 0;
  91. try {
  92. r = __s.send(payload, 0);
  93. } catch(e:SSLWantWriteError) {
  94. return 0;
  95. }
  96. return r;
  97. } catch (e:BlockingIOError) {
  98. throw Blocked;
  99. }
  100. }
  101. public override function close() {
  102. super.close();
  103. if (__s != null)
  104. __s.close();
  105. }
  106. }
  107. @:coreApi class Socket {
  108. var __s:PSocket;
  109. public var input(default, null):haxe.io.Input;
  110. public var output(default, null):haxe.io.Output;
  111. public var custom:Dynamic;
  112. public function new():Void {
  113. __initSocket();
  114. input = new SocketInput(__s);
  115. output = new SocketOutput(__s);
  116. }
  117. function __initSocket():Void {
  118. __s = new PSocket();
  119. }
  120. function __rebuildIoStreams():Void {
  121. input = new SocketInput(__s);
  122. output = new SocketOutput(__s);
  123. }
  124. public function close():Void {
  125. __s.close();
  126. }
  127. public function read():String {
  128. return input.readAll().toString();
  129. }
  130. public function write(content:String):Void {
  131. output.writeString(content);
  132. }
  133. public function connect(host:Host, port:Int):Void {
  134. var host_str = host.toString();
  135. __s.connect(Tuple2.make(host_str, port));
  136. }
  137. public function listen(connections:Int):Void {
  138. __s.listen(connections);
  139. }
  140. public function shutdown(read:Bool, write:Bool):Void
  141. __s.shutdown((read && write) ? PSocketModule.SHUT_RDWR : read ? PSocketModule.SHUT_RD : PSocketModule.SHUT_WR);
  142. public function bind(host:Host, port:Int):Void {
  143. var host_str = host.toString();
  144. __s.bind(Tuple2.make(host_str, port));
  145. }
  146. public function accept():Socket {
  147. var tp2:Tuple2<PSocket, PAddress> = __s.accept();
  148. var s = new Socket();
  149. s.__s = tp2._1;
  150. s.input = new SocketInput(s.__s);
  151. s.output = new SocketOutput(s.__s);
  152. return s;
  153. }
  154. public function peer():{host:Host, port:Int} {
  155. var pn = __s.getpeername();
  156. return {host: new Host(pn._1), port: pn._2}
  157. }
  158. public function host():{host:Host, port:Int} {
  159. var pn = __s.getsockname();
  160. return {host: new Host(pn._1), port: pn._2};
  161. }
  162. public function setTimeout(timeout:Float):Void {
  163. __s.settimeout(timeout);
  164. }
  165. public function waitForRead():Void {
  166. Select.select([this], [], []);
  167. }
  168. public function setBlocking(b:Bool):Void {
  169. __s.setblocking(b);
  170. }
  171. public function setFastSend(b:Bool):Void {
  172. __s.setsockopt(PSocketModule.SOL_TCP, PSocketModule.TCP_NODELAY, b);
  173. }
  174. @:keep function fileno():Int
  175. return __s.fileno();
  176. public static function select(read:Array<Socket>, write:Array<Socket>, others:Array<Socket>,
  177. ?timeout:Float):{read:Array<Socket>, write:Array<Socket>, others:Array<Socket>} {
  178. var t3 = Select.select(read, write, others, timeout);
  179. return {read: t3._1, write: t3._2, others: t3._3};
  180. }
  181. }