1 ! Copyright (C) 2007, 2008, Slava Pestov, Elie CHAFTARI.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors unix byte-arrays kernel debugger sequences namespaces math
4 math.order combinators init alien alien.c-types alien.strings libc
5 continuations destructors
6 openssl openssl.libcrypto openssl.libssl
7 io.files io.ports io.unix.backend io.unix.sockets
8 io.encodings.ascii io.buffers io.sockets io.sockets.secure
9 io.timeouts system summary ;
10 IN: io.unix.sockets.secure
12 M: ssl-handle handle-fd file>> handle-fd ;
14 : syscall-error ( r -- * )
15 ERR_get_error dup zero? [
18 { -1 [ err_no ECONNRESET = [ premature-close ] [ (io-error) ] if ] }
19 { 0 [ premature-close ] }
25 : check-accept-response ( handle r -- event )
26 over handle>> over SSL_get_error
28 { SSL_ERROR_NONE [ 2drop f ] }
29 { SSL_ERROR_WANT_READ [ 2drop +input+ ] }
30 { SSL_ERROR_WANT_WRITE [ 2drop +output+ ] }
31 { SSL_ERROR_SYSCALL [ syscall-error ] }
32 { SSL_ERROR_SSL [ (ssl-error) ] }
35 : do-ssl-accept ( ssl-handle -- )
36 dup dup handle>> SSL_accept check-accept-response dup
37 [ >r dup file>> r> wait-for-fd do-ssl-accept ] [ 2drop ] if ;
39 : maybe-handshake ( ssl-handle -- )
40 dup connected>> [ drop ] [
42 [ do-ssl-accept ] with-timeout
45 : check-response ( port r -- port r n )
46 over handle>> handle>> over SSL_get_error ; inline
49 : check-read-response ( port r -- event )
52 { SSL_ERROR_NONE [ swap buffer>> n>buffer f ] }
53 { SSL_ERROR_ZERO_RETURN [ 2drop f ] }
54 { SSL_ERROR_WANT_READ [ 2drop +input+ ] }
55 { SSL_ERROR_WANT_WRITE [ 2drop +output+ ] }
56 { SSL_ERROR_SYSCALL [ syscall-error ] }
57 { SSL_ERROR_SSL [ (ssl-error) ] }
65 [ buffer-capacity ] bi ! len
70 : check-write-response ( port r -- event )
73 { SSL_ERROR_NONE [ swap buffer>> buffer-consume f ] }
74 { SSL_ERROR_WANT_READ [ 2drop +input+ ] }
75 { SSL_ERROR_WANT_WRITE [ 2drop +output+ ] }
76 { SSL_ERROR_SYSCALL [ syscall-error ] }
77 { SSL_ERROR_SSL [ (ssl-error) ] }
85 [ buffer-length ] bi ! len
87 check-write-response ;
89 M: ssl-handle cancel-operation
90 file>> cancel-operation ;
93 drop secure-socket-timeout get ;
96 : <ssl-socket> ( fd -- ssl )
97 [ fd>> BIO_NOCLOSE BIO_new_socket dup ssl-error ] keep <ssl-handle>
98 [ handle>> swap dup SSL_set_bio ] keep ;
100 M: secure ((client)) ( addrspec -- handle )
101 addrspec>> ((client)) <ssl-socket> ;
103 M: secure parse-sockaddr addrspec>> parse-sockaddr <secure> ;
105 M: secure (get-local-address) addrspec>> (get-local-address) ;
107 : check-connect-response ( ssl-handle r -- event )
108 over handle>> over SSL_get_error
110 { SSL_ERROR_NONE [ 2drop f ] }
111 { SSL_ERROR_WANT_READ [ 2drop +input+ ] }
112 { SSL_ERROR_WANT_WRITE [ 2drop +output+ ] }
113 { SSL_ERROR_SYSCALL [ syscall-error ] }
114 { SSL_ERROR_SSL [ (ssl-error) ] }
117 : do-ssl-connect ( ssl-handle -- )
118 dup dup handle>> SSL_connect check-connect-response dup
119 [ dupd wait-for-fd do-ssl-connect ] [ 2drop ] if ;
121 : resume-session ( ssl-handle ssl-session -- )
122 [ [ handle>> ] dip SSL_set_session ssl-error ]
123 [ drop do-ssl-connect ]
126 : begin-session ( ssl-handle addrspec -- )
127 [ drop do-ssl-connect ]
128 [ [ handle>> SSL_get1_session ] dip save-session ]
131 : secure-connection ( ssl-handle addrspec -- )
132 dup get-session [ resume-session ] [ begin-session ] ?if ;
134 M: secure establish-connection ( client-out remote -- )
136 [ establish-connection ]
139 [ [ secure-connection ] curry with-timeout ]
140 [ drop t >>connected drop ]
144 M: secure (server) addrspec>> (server) ;
148 addrspec>> (accept) >r |dispose <ssl-socket> r>
151 : check-shutdown-response ( handle r -- event )
152 #! We don't do two-step shutdown here because I couldn't
153 #! figure out how to do it with non-blocking BIOs. Also, it
154 #! seems that SSL_shutdown always returns 0 -- this sounds
156 over handle>> over SSL_get_error
158 { SSL_ERROR_NONE [ 2drop f ] }
159 { SSL_ERROR_WANT_READ [ 2drop +input+ ] }
160 { SSL_ERROR_WANT_WRITE [ 2drop +output+ ] }
161 { SSL_ERROR_SYSCALL [ dup zero? [ 2drop f ] [ syscall-error ] if ] }
162 { SSL_ERROR_SSL [ (ssl-error) ] }
165 : (shutdown) ( handle -- )
166 dup dup handle>> SSL_shutdown check-shutdown-response
167 dup [ dupd wait-for-fd (shutdown) ] [ 2drop ] if ;
169 M: ssl-handle shutdown
171 f >>connected [ (shutdown) ] with-timeout