SSLStream.hx 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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 hl.uv;
  23. class SSLStream extends Stream {
  24. var sub : Stream;
  25. var ssl : sys.ssl.Context;
  26. var conf : sys.ssl.Context.Config;
  27. var bio : hl.NativeArray<Dynamic>;
  28. var onWrite : Bool -> Void;
  29. var onData : hl.Bytes -> Int -> Void;
  30. var tmp = haxe.io.Bytes.alloc(0);
  31. var inputBuffer = haxe.io.Bytes.alloc(65536);
  32. var outputBuffer = haxe.io.Bytes.alloc(65536);
  33. var inputLen : Int = 0;
  34. var waitHandshake = true;
  35. public function new(sub,?cert:sys.ssl.Certificate,?key:sys.ssl.Key) {
  36. this.sub = sub;
  37. super(sub.handle);
  38. conf = new sys.ssl.Context.Config(cert != null);
  39. if( cert != null )
  40. conf.setCert(@:privateAccess cert.__x, @:privateAccess key.__k);
  41. var verify = sys.ssl.Socket.DEFAULT_VERIFY_CERT;
  42. var caCert = @:privateAccess sys.ssl.Socket.getDefaultCA();
  43. conf.setCa(@:privateAccess caCert?.__x);
  44. conf.setVerify(if( verify ) 1 else if ( verify == null) 2 else 0);
  45. bio = new hl.NativeArray<Dynamic>(3);
  46. bio[0] = this;
  47. bio[1] = staticRead;
  48. bio[2] = staticWrite;
  49. ssl = new sys.ssl.Context(conf);
  50. ssl.setBio(bio);
  51. }
  52. static function staticRead( s : SSLStream, buf : hl.Bytes, len : Int ) : Int {
  53. var avail = s.inputLen;
  54. if( avail == 0 )
  55. return -2;
  56. var size = len > avail ? avail : len;
  57. buf.blit(0, s.inputBuffer, 0, size);
  58. avail -= size;
  59. if( avail > 0 ) s.inputBuffer.blit(0, s.inputBuffer, size, avail);
  60. s.inputLen = avail;
  61. return size;
  62. }
  63. static function staticWrite( s : SSLStream, buf : hl.Bytes, len : Int ) : Int {
  64. var tmp = s.tmp;
  65. @:privateAccess {
  66. tmp.b = buf;
  67. tmp.length = len;
  68. };
  69. s.sub.write(tmp,s.onWrite,0,len);
  70. return len;
  71. }
  72. override function write(bytes:haxe.io.Bytes, ?onWrite:Bool->Void, pos = 0, len = -1) {
  73. this.onWrite = onWrite;
  74. var w = ssl.send(bytes,pos,len);
  75. if( w < 0 )
  76. onWrite(false);
  77. }
  78. override function readStartRaw(onData:hl.Bytes->Int->Void) {
  79. this.onData = onData;
  80. }
  81. public function handshake( onHandShake : Null<String> -> Void ) {
  82. ssl.handshake();
  83. sub.readStartRaw(function(bytes:hl.Bytes,len:Int) {
  84. if( len < 0 ) {
  85. if( waitHandshake )
  86. onHandShake("Connection closed");
  87. else
  88. onData(null,len);
  89. return;
  90. }
  91. @:privateAccess {
  92. tmp.b = bytes;
  93. tmp.length = len;
  94. };
  95. var pos = 0;
  96. while( len > 0 ) {
  97. var max = inputBuffer.length - inputLen;
  98. var size = len > max ? max : len;
  99. inputBuffer.blit(inputLen, tmp, pos, size);
  100. pos += size;
  101. len -= size;
  102. inputLen += size;
  103. if( waitHandshake ) {
  104. var r = try ssl.handshake() catch( e : Dynamic ) {
  105. onHandShake(Std.string(e));
  106. return;
  107. }
  108. if( r == 0 ) {
  109. waitHandshake = false;
  110. onHandShake(null);
  111. } else if( r == -1 )
  112. continue;
  113. else {
  114. onHandShake("Handshake error");
  115. break;
  116. }
  117. }
  118. var r = ssl.recv(outputBuffer, 0, outputBuffer.length);
  119. if( r == -1 )
  120. return;
  121. if( onData == null ) {
  122. // missing readStart. most likely an error, so let's discard data
  123. continue;
  124. }
  125. onData(outputBuffer, r);
  126. }
  127. });
  128. }
  129. override function listen(n:Int, onConnect:Void->Void) {
  130. sub.listen(n,function() {
  131. throw "TODO:handshake";
  132. });
  133. }
  134. override function close(?callb) {
  135. sub.close(function() {
  136. ssl.close();
  137. conf.close();
  138. bio = null;
  139. sub = null;
  140. ssl = null;
  141. conf = null;
  142. inputBuffer = outputBuffer = null;
  143. if( callb != null ) callb();
  144. });
  145. }
  146. }