64
64
import com .oracle .truffle .api .CompilerDirectives ;
65
65
import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
66
66
67
+ /**
68
+ * This class implements equivalents of OpenSSL transport functions ({@code SSL_read} etc) on top of
69
+ * JDK's {@link SSLEngine}. It takes care of the handshake, packeting, network and application data
70
+ * buffering and network or memory buffer IO. In addition to what the OpenSSL functions would do, it
71
+ * also handles Python-specific error handling, non-blocking IO and socket timeouts.
72
+ */
67
73
public class SSLEngineHelper {
68
74
69
75
private static final ByteBuffer EMPTY_BUFFER = ByteBuffer .allocate (0 );
70
76
private static final int TLS_HEADER_SIZE = 5 ;
71
77
78
+ /**
79
+ * Equivalent of {@code SSL_write}. Attempts to transmit all the data in the supplied buffer
80
+ * into given {@link PSSLSocket} (which can be backed by a memory buffer).
81
+ *
82
+ * Errors are wrapped into Python exceptions. Requests for IO in non-blocking modes are
83
+ * indicated using Python exceptions ({@code SSLErrorWantRead}, {@code SSLErrorWantWrite}).
84
+ */
72
85
@ TruffleBoundary
73
86
public static void write (PNodeWithRaise node , PSSLSocket socket , ByteBuffer input ) {
74
87
loop (node , socket , input , EMPTY_BUFFER , Operation .WRITE );
75
88
}
76
89
90
+ /**
91
+ * Equivalent of {@code SSL_read}. Attempts to read bytes from the {@link PSSLSocket} (which can
92
+ * be backed by a memory buffer) into given buffer. Will read at most the data of one TLS
93
+ * packet. Decrypted but not read data is buffered on the socket and returned by the next call.
94
+ * Empty output buffer after the call signifies the peer closed the connection cleanly.
95
+ *
96
+ * Errors are wrapped into Python exceptions. Requests for IO in non-blocking modes are
97
+ * indicated using Python exceptions ({@code SSLErrorWantRead}, {@code SSLErrorWantWrite}).
98
+ */
77
99
@ TruffleBoundary
78
100
public static void read (PNodeWithRaise node , PSSLSocket socket , ByteBuffer target ) {
79
101
loop (node , socket , EMPTY_BUFFER , target , Operation .READ );
80
102
}
81
103
104
+ /**
105
+ * Equivalent of {@code SSL_do_handshake}. Initiate a handshake if one has not been initiated
106
+ * already. Becomes a no-op after the initial handshake is done, i.e. cannot be used to perform
107
+ * renegotiation.
108
+ *
109
+ * Errors are wrapped into Python exceptions. Requests for IO in non-blocking modes are
110
+ * indicated using Python exceptions ({@code SSLErrorWantRead}, {@code SSLErrorWantWrite}).
111
+ */
82
112
@ TruffleBoundary
83
113
public static void handshake (PNodeWithRaise node , PSSLSocket socket ) {
84
114
if (!socket .isHandshakeComplete ()) {
@@ -92,6 +122,13 @@ public static void handshake(PNodeWithRaise node, PSSLSocket socket) {
92
122
}
93
123
}
94
124
125
+ /**
126
+ * Equivalent of {@code SSL_do_shutdown}. Initiates a duplex close of the TLS connection - sends
127
+ * a close_notify message and tries to receive a close_notify from the peer.
128
+ *
129
+ * Errors are wrapped into Python exceptions. Requests for IO in non-blocking modes are
130
+ * indicated using Python exceptions ({@code SSLErrorWantRead}, {@code SSLErrorWantWrite}).
131
+ */
95
132
@ TruffleBoundary
96
133
public static void shutdown (PNodeWithRaise node , PSSLSocket socket ) {
97
134
socket .getEngine ().closeOutbound ();
0 commit comments