1 module yu.asyncsocket.sslsocket;
2 
3 version (USE_SSL)  : import core.stdc.errno;
4 import core.stdc.string;
5 
6 import core.thread;
7 
8 import std.string;
9 import std.socket;
10 import std.exception;
11 import std.experimental.logger;
12 
13 import yu.eventloop;
14 import yu.asyncsocket.transport;
15 import yu.asyncsocket.tcpsocket;
16 import yu.exception;
17 
18 import deimos.openssl.ssl;
19 import deimos.openssl.bio;
20 
21 @trusted class SSLSocket : TCPSocket {
22     static if (IOMode == IO_MODE.iocp) {
23         this(EventLoop loop, Socket sock, SSL * ssl, BIO * bioRead, BIO * bioWrite) {
24             super(loop, sock);
25             _ssl = ssl;
26             _bioIn = bioRead;
27             _bioOut = bioWrite;
28             _rBuffer = makeArray!ubyte(yuAlloctor, TCP_READ_BUFFER_SIZE);
29             _wBuffer = makeArray!ubyte(yuAlloctor, TCP_READ_BUFFER_SIZE);
30         }
31     } else {
32         this(EventLoop loop, Socket sock, SSL * ssl) {
33             super(loop, sock);
34             _ssl = ssl;
35         }
36     }
37 
38     ~this() {
39         if (_ssl) {
40             SSL_shutdown(_ssl);
41             SSL_free(_ssl);
42             _ssl = null;
43             _bioIn = null;
44             _bioOut = null;
45         }
46         static if (IOMode == IO_MODE.iocp) {
47             yDel(_rBuffer);
48             yDel(_wBuffer);
49         }
50     }
51 
52     override @property bool isAlive() @trusted nothrow {
53         return alive() && _isHandshaked;
54     }
55 
56     pragma(inline) void setHandshakeCallBack(CallBack cback) {
57         _handshakeCback = cback;
58     }
59 
60     protected : override void onClose() {
61         if (_ssl) {
62             SSL_shutdown(_ssl);
63             SSL_free(_ssl);
64             _ssl = null;
65             _bioIn = null;
66             _bioOut = null;
67         }
68         super.onClose();
69     }
70     static if (IOMode == IO_MODE.iocp) {
71 
72         override void onWrite() {
73             if (writeBIOtoSocket() || _writeQueue.empty)
74                 return;
75             try {
76                 if (_lastWrite > 0) {
77                     auto buffer = _writeQueue.front;
78                     if (buffer.add(_lastWrite)) {
79                         _writeQueue.deQueue().doCallBack();
80                     }
81                 }
82                 if (!alive || _writeQueue.empty)
83                     return;
84                 auto buffer = _writeQueue.front;
85                 _lastWrite = SSL_write(_ssl, buffer.data.ptr, cast(int) buffer.length); // data中存放了要发送的数据
86                 writeBIOtoSocket();
87             }
88             catch (Exception e) {
89                 showException(e);
90             }
91         }
92         override void onRead() {
93             try {
94                 if (!alive)
95                     return;
96                 //trace("read data : data.length: ", _event.readLen);
97                 if (_event.readLen > 0) {
98                     BIO_write(_bioIn, _readBuffer.ptr, cast(int) _event.readLen);
99                     if (!_isHandshaked) {
100                         if (!handlshake()) {
101                             _event.readLen = 0;
102                             doRead();
103                             return;
104                         }
105                         onWrite();
106                     }
107                     while (true) {
108                         int ret = SSL_read(_ssl, _rBuffer.ptr, cast(int) _rBuffer.length);
109                         if (ret > 0) {
110                             _readCallBack(_rBuffer[0 .. ret]);
111                             continue;
112                         } else {
113                             break;
114                         }
115                     }
116                 } else {
117                     onClose();
118                     return;
119                 }
120             }
121             catch (Exception e) {
122                 showException(e);
123             }
124             _event.readLen = 0;
125             if (alive)
126                 doRead();
127         }
128         bool writeBIOtoSocket() nothrow {
129             if (!alive)
130                 return true;
131             int hasread = BIO_read(_bioOut, _wBuffer.ptr, cast(int) _wBuffer.length);
132             if (hasread > 0) {
133                 _iocpWBuf.len = hasread;
134                 _iocpWBuf.buf = cast(char * ) _wBuffer.ptr;
135                 _event.writeLen = 0;
136                 doWrite();
137                 return true;
138             }
139             return false;
140         }
141     } else {
142         override void onWrite() {
143             if (alive && !_isHandshaked) {
144                 if (!handlshake())
145                     return;
146             }
147             try {
148                 while (alive && !_writeQueue.empty) {
149                     auto buffer = _writeQueue.front;
150                     auto len = SSL_write(_ssl, buffer.data.ptr, cast(int) buffer.length); // _socket.send(buffer.data);
151                     if (len > 0) {
152                         if (buffer.add(len)) {
153                             _writeQueue.deQueue().doCallBack();
154                         }
155                         continue;
156                     } else {
157                         int sslerron = SSL_get_error(_ssl, len);
158                         if (sslerron == SSL_ERROR_WANT_READ || errno == EWOULDBLOCK
159                                 || errno == EAGAIN)
160                             break;
161                         else if (errno == 4) // erro 4 :系统中断组织了
162                             continue;
163                     }
164                     error("write size: ", len,
165                         " \n\tDo Close the erro code : ", errno,
166                         "  erro is : ", fromStringz(strerror(errno)), " \n\tthe socket fd : ",
167                         fd);
168                     onClose();
169                     return;
170                 }
171             }
172             catch (Exception e) {
173                 import yu.exception;
174 
175                 showException(e);
176                 onClose();
177                 return;
178             }
179         }
180 
181         override void onRead() {
182             try {
183                 while (alive) {
184                     if (!_isHandshaked) {
185                         if (!handlshake())
186                             return;
187                     }
188                     auto len = SSL_read(_ssl, (_readBuffer.ptr), cast(int)(_readBuffer.length));
189                     if (len > 0) {
190                         _readCallBack(_readBuffer[0 .. len]);
191                         continue;
192                     } else if (len < 0) {
193                         int sslerron = SSL_get_error(_ssl, len);
194                         if (sslerron == SSL_ERROR_WANT_READ || errno == EWOULDBLOCK
195                                 || errno == EAGAIN)
196                             break;
197                         else if (errno == 4) // erro 4 :系统中断组织了
198                             continue;
199                         import core.stdc.string;
200 
201                         error("Do Close the erro code : ", errno,
202                             "  erro is : ", fromStringz(strerror(errno)),
203                             " \n\tthe socket fd : ", fd);
204                     }
205                     onClose();
206                     return;
207                 }
208             }
209             catch (Exception e) {
210                 import yu.exception;
211 
212                 showException(e);
213                 onClose();
214             }
215         }
216     }
217     final bool handlshake() nothrow {
218         int r = SSL_do_handshake(_ssl);
219         static if (IOMode == IO_MODE.iocp)
220             writeBIOtoSocket();
221         if (r == 1) {
222             _isHandshaked = true;
223             if (_handshakeCback) {
224                 _handshakeCback();
225             }
226             return true;
227         }
228         int err = SSL_get_error(_ssl, r);
229         if (err == SSL_ERROR_WANT_WRITE) {
230             static if (IOMode == IO_MODE.iocp)
231                 writeBIOtoSocket();
232             return false;
233         } else if (err == SSL_ERROR_WANT_READ) {
234             return false;
235         } else {
236             yuCathException(error("SSL_do_handshake return: ", r, "  erro :",
237                 err, "  errno:", errno, "  erro string:", fromStringz(strerror(errno))));
238             onClose();
239             return false;
240         }
241     }
242 
243     protected : bool _isHandshaked = false;
244 
245     private : SSL * _ssl;
246     CallBack _handshakeCback;
247     static if (IOMode == IO_MODE.iocp) {
248         BIO * _bioIn;
249         BIO * _bioOut;
250         ubyte[] _rBuffer;
251         ubyte[] _wBuffer;
252         ptrdiff_t _lastWrite = 0;
253     }
254 }