@@ -33,8 +33,7 @@ import javax.net.ssl.{
33
33
SSLContext ,
34
34
SSLEngine ,
35
35
TrustManagerFactory ,
36
- X509ExtendedTrustManager ,
37
- X509TrustManager
36
+ X509ExtendedTrustManager
38
37
}
39
38
import cats .Applicative
40
39
import cats .effect .kernel .{Async , Resource }
@@ -47,43 +46,85 @@ import java.util.function.BiFunction
47
46
*/
48
47
sealed trait TLSContext [F [_]] {
49
48
50
- /** Creates a `TLSSocket` in client mode, using the supplied parameters.
51
- * Internal debug logging of the session can be enabled by passing a logger.
52
- */
49
+ /** Creates a `TLSSocket` builder in client mode. */
50
+ def client (socket : Socket [F ]): Resource [F , TLSSocket [F ]] =
51
+ clientBuilder(socket).build
52
+
53
+ /** Creates a `TLSSocket` builder in client mode, allowing optional parameters to be configured. */
54
+ def clientBuilder (socket : Socket [F ]): TLSContext .SocketBuilder [F , TLSSocket ]
55
+
56
+ @ deprecated(" Use client(socket) or clientBuilder(socket).with(...).build" , " 3.0.6" )
53
57
def client (
54
58
socket : Socket [F ],
55
59
params : TLSParameters = TLSParameters .Default ,
56
60
logger : Option [String => F [Unit ]] = None
57
- ): Resource [F , TLSSocket [F ]]
61
+ ): Resource [F , TLSSocket [F ]] =
62
+ clientBuilder(socket).withParameters(params).withOldLogging(logger).build
63
+
64
+ /** Creates a `TLSSocket` builder in server mode. */
65
+ def server (socket : Socket [F ]): Resource [F , TLSSocket [F ]] =
66
+ serverBuilder(socket).build
58
67
59
- /** Creates a `TLSSocket` in server mode, using the supplied parameters.
60
- * Internal debug logging of the session can be enabled by passing a logger.
61
- */
68
+ /** Creates a `TLSSocket` builder in server mode, allowing optional parameters to be configured. */
69
+ def serverBuilder (socket : Socket [F ]): TLSContext .SocketBuilder [F , TLSSocket ]
70
+
71
+ @ deprecated(" Use server(socket) or serverBuilder(socket).with(...).build" , " 3.0.6" )
62
72
def server (
63
73
socket : Socket [F ],
64
74
params : TLSParameters = TLSParameters .Default ,
65
75
logger : Option [String => F [Unit ]] = None
66
- ): Resource [F , TLSSocket [F ]]
76
+ ): Resource [F , TLSSocket [F ]] =
77
+ serverBuilder(socket).withParameters(params).withOldLogging(logger).build
78
+
79
+ /** Creates a `DTLSSocket` builder in client mode. */
80
+ def dtlsClient (
81
+ socket : DatagramSocket [F ],
82
+ remoteAddress : SocketAddress [IpAddress ]
83
+ ): Resource [F , DTLSSocket [F ]] =
84
+ dtlsClientBuilder(socket, remoteAddress).build
85
+
86
+ /** Creates a `DTLSSocket` builder in client mode, allowing optional parameters to be configured. */
87
+ def dtlsClientBuilder (
88
+ socket : DatagramSocket [F ],
89
+ remoteAddress : SocketAddress [IpAddress ]
90
+ ): TLSContext .SocketBuilder [F , DTLSSocket ]
67
91
68
- /** Creates a `DTLSSocket` in client mode, using the supplied parameters.
69
- * Internal debug logging of the session can be enabled by passing a logger.
70
- */
92
+ @ deprecated(
93
+ " Use dtlsClient(socket, remoteAddress) or dtlsClientBuilder(socket, remoteAddress).with(...).build" ,
94
+ " 3.0.6"
95
+ )
71
96
def dtlsClient (
72
97
socket : DatagramSocket [F ],
73
98
remoteAddress : SocketAddress [IpAddress ],
74
99
params : TLSParameters = TLSParameters .Default ,
75
100
logger : Option [String => F [Unit ]] = None
76
- ): Resource [F , DTLSSocket [F ]]
101
+ ): Resource [F , DTLSSocket [F ]] =
102
+ dtlsClientBuilder(socket, remoteAddress).withParameters(params).withOldLogging(logger).build
77
103
78
- /** Creates a `DTLSSocket` in server mode, using the supplied parameters.
79
- * Internal debug logging of the session can be enabled by passing a logger.
80
- */
104
+ /** Creates a `DTLSSocket` builder in server mode. */
105
+ def dtlsServer (
106
+ socket : DatagramSocket [F ],
107
+ remoteAddress : SocketAddress [IpAddress ]
108
+ ): Resource [F , DTLSSocket [F ]] =
109
+ dtlsServerBuilder(socket, remoteAddress).build
110
+
111
+ /** Creates a `DTLSSocket` builder in client mode, allowing optional parameters to be configured. */
112
+ def dtlsServerBuilder (
113
+ socket : DatagramSocket [F ],
114
+ remoteAddress : SocketAddress [IpAddress ]
115
+ ): TLSContext .SocketBuilder [F , DTLSSocket ]
116
+
117
+ @ deprecated(
118
+ " Use dtlsServer(socket, remoteAddress) or dtlsClientBuilder(socket, remoteAddress).with(...).build" ,
119
+ " 3.0.6"
120
+ )
81
121
def dtlsServer (
82
122
socket : DatagramSocket [F ],
83
123
remoteAddress : SocketAddress [IpAddress ],
84
124
params : TLSParameters = TLSParameters .Default ,
85
125
logger : Option [String => F [Unit ]] = None
86
- ): Resource [F , DTLSSocket [F ]]
126
+ ): Resource [F , DTLSSocket [F ]] =
127
+ dtlsServerBuilder(socket, remoteAddress).withParameters(params).withOldLogging(logger).build
87
128
}
88
129
89
130
object TLSContext {
@@ -128,35 +169,17 @@ object TLSContext {
128
169
ctx : SSLContext
129
170
): TLSContext [F ] =
130
171
new TLSContext [F ] {
131
- def client (
132
- socket : Socket [F ],
133
- params : TLSParameters ,
134
- logger : Option [String => F [Unit ]]
135
- ): Resource [F , TLSSocket [F ]] =
136
- mkSocket(
137
- socket,
138
- true ,
139
- params,
140
- logger
141
- )
142
-
143
- def server (
144
- socket : Socket [F ],
145
- params : TLSParameters ,
146
- logger : Option [String => F [Unit ]]
147
- ): Resource [F , TLSSocket [F ]] =
148
- mkSocket(
149
- socket,
150
- false ,
151
- params,
152
- logger
153
- )
172
+ def clientBuilder (socket : Socket [F ]) =
173
+ SocketBuilder ((p, l) => mkSocket(socket, true , p, l))
174
+
175
+ def serverBuilder (socket : Socket [F ]) =
176
+ SocketBuilder ((p, l) => mkSocket(socket, false , p, l))
154
177
155
178
private def mkSocket (
156
179
socket : Socket [F ],
157
180
clientMode : Boolean ,
158
181
params : TLSParameters ,
159
- logger : Option [ String => F [ Unit ] ]
182
+ logger : TLSLogger [ F ]
160
183
): Resource [F , TLSSocket [F ]] =
161
184
Resource
162
185
.eval(
@@ -174,40 +197,24 @@ object TLSContext {
174
197
)
175
198
.flatMap(engine => TLSSocket (socket, engine))
176
199
177
- def dtlsClient (
200
+ def dtlsClientBuilder (
178
201
socket : DatagramSocket [F ],
179
- remoteAddress : SocketAddress [IpAddress ],
180
- params : TLSParameters ,
181
- logger : Option [String => F [Unit ]]
182
- ): Resource [F , DTLSSocket [F ]] =
183
- mkDtlsSocket(
184
- socket,
185
- remoteAddress,
186
- true ,
187
- params,
188
- logger
189
- )
190
-
191
- def dtlsServer (
202
+ remoteAddress : SocketAddress [IpAddress ]
203
+ ) =
204
+ SocketBuilder ((p, l) => mkDtlsSocket(socket, remoteAddress, true , p, l))
205
+
206
+ def dtlsServerBuilder (
192
207
socket : DatagramSocket [F ],
193
- remoteAddress : SocketAddress [IpAddress ],
194
- params : TLSParameters ,
195
- logger : Option [String => F [Unit ]]
196
- ): Resource [F , DTLSSocket [F ]] =
197
- mkDtlsSocket(
198
- socket,
199
- remoteAddress,
200
- false ,
201
- params,
202
- logger
203
- )
208
+ remoteAddress : SocketAddress [IpAddress ]
209
+ ) =
210
+ SocketBuilder ((p, l) => mkDtlsSocket(socket, remoteAddress, false , p, l))
204
211
205
212
private def mkDtlsSocket (
206
213
socket : DatagramSocket [F ],
207
214
remoteAddress : SocketAddress [IpAddress ],
208
215
clientMode : Boolean ,
209
216
params : TLSParameters ,
210
- logger : Option [ String => F [ Unit ] ]
217
+ logger : TLSLogger [ F ]
211
218
): Resource [F , DTLSSocket [F ]] =
212
219
Resource
213
220
.eval(
@@ -230,7 +237,7 @@ object TLSContext {
230
237
binding : TLSEngine .Binding [F ],
231
238
clientMode : Boolean ,
232
239
params : TLSParameters ,
233
- logger : Option [ String => F [ Unit ] ]
240
+ logger : TLSLogger [ F ]
234
241
): F [TLSEngine [F ]] = {
235
242
val sslEngine = Async [F ].blocking {
236
243
val engine = ctx.createSSLEngine()
@@ -345,4 +352,46 @@ object TLSContext {
345
352
.map(fromSSLContext(_))
346
353
}
347
354
}
355
+
356
+ sealed trait SocketBuilder [F [_], S [_[_]]] {
357
+ def withParameters (params : TLSParameters ): SocketBuilder [F , S ]
358
+ def withLogging (log : (=> String ) => F [Unit ]): SocketBuilder [F , S ]
359
+ def withoutLogging : SocketBuilder [F , S ]
360
+ def withLogger (logger : TLSLogger [F ]): SocketBuilder [F , S ]
361
+ private [TLSContext ] def withOldLogging (log : Option [String => F [Unit ]]): SocketBuilder [F , S ]
362
+ def build : Resource [F , S [F ]]
363
+ }
364
+
365
+ object SocketBuilder {
366
+ private [TLSContext ] type Build [F [_], S [_[_]]] =
367
+ (TLSParameters , TLSLogger [F ]) => Resource [F , S [F ]]
368
+
369
+ private [TLSContext ] def apply [F [_], S [_[_]]](
370
+ mkSocket : Build [F , S ]
371
+ ): SocketBuilder [F , S ] =
372
+ instance(mkSocket, TLSParameters .Default , TLSLogger .Disabled )
373
+
374
+ private def instance [F [_], S [_[_]]](
375
+ mkSocket : Build [F , S ],
376
+ params : TLSParameters ,
377
+ logger : TLSLogger [F ]
378
+ ): SocketBuilder [F , S ] =
379
+ new SocketBuilder [F , S ] {
380
+ def withParameters (params : TLSParameters ): SocketBuilder [F , S ] =
381
+ instance(mkSocket, params, logger)
382
+ def withLogging (log : (=> String ) => F [Unit ]): SocketBuilder [F , S ] =
383
+ withLogger(TLSLogger .Enabled (log))
384
+ def withoutLogging : SocketBuilder [F , S ] =
385
+ withLogger(TLSLogger .Disabled )
386
+ def withLogger (logger : TLSLogger [F ]): SocketBuilder [F , S ] =
387
+ instance(mkSocket, params, logger)
388
+ private [TLSContext ] def withOldLogging (
389
+ log : Option [String => F [Unit ]]
390
+ ): SocketBuilder [F , S ] =
391
+ log.map(f => withLogging(m => f(m))).getOrElse(withoutLogging)
392
+ def build : Resource [F , S [F ]] =
393
+ mkSocket(params, logger)
394
+ }
395
+ }
396
+
348
397
}
0 commit comments