Skip to content

Commit adb87a0

Browse files
committed
Use ClientOpt and ServerOpt for websocket TLS config
Signed-off-by: Lorenzo <[email protected]>
1 parent e61d3d8 commit adb87a0

File tree

9 files changed

+95
-83
lines changed

9 files changed

+95
-83
lines changed

example/1.6/cp/charge_point_sim.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,10 @@ func setupTlsChargePoint(chargePointID string) ocpp16.ChargePoint {
6464
}
6565
}
6666
// Create client with TLS config
67-
client := ws.NewTLSClient(&tls.Config{
67+
client := ws.NewClient(ws.WithClientTLSConfig(&tls.Config{
6868
RootCAs: certPool,
6969
Certificates: clientCertificates,
70-
})
70+
}))
7171
return ocpp16.NewChargePoint(chargePointID, nil, client)
7272
}
7373

example/1.6/cs/central_system_sim.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,10 @@ func setupTlsCentralSystem() ocpp16.CentralSystem {
6767
if !ok {
6868
log.Fatalf("no required %v found", envVarServerCertificateKey)
6969
}
70-
server := ws.NewTLSServer(certificate, key, &tls.Config{
70+
server := ws.NewServer(ws.WithServerTLSConfig(certificate, key, &tls.Config{
7171
ClientAuth: tls.RequireAndVerifyClientCert,
7272
ClientCAs: certPool,
73-
})
73+
}))
7474
return ocpp16.NewCentralSystem(nil, server)
7575
}
7676

example/2.0.1/chargingstation/charging_station_sim.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,10 @@ func setupTlsChargingStation(chargingStationID string) ocpp2.ChargingStation {
6666
}
6767
}
6868
// Create client with TLS config
69-
client := ws.NewTLSClient(&tls.Config{
69+
client := ws.NewClient(ws.WithClientTLSConfig(&tls.Config{
7070
RootCAs: certPool,
7171
Certificates: clientCertificates,
72-
})
72+
}))
7373
return ocpp2.NewChargingStation(chargingStationID, nil, client)
7474
}
7575

example/2.0.1/csms/csms_sim.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,10 @@ func setupTlsCentralSystem() ocpp2.CSMS {
7070
if !ok {
7171
log.Fatalf("no required %v found", envVarServerCertificateKey)
7272
}
73-
server := ws.NewTLSServer(certificate, key, &tls.Config{
73+
server := ws.NewServer(ws.WithServerTLSConfig(certificate, key, &tls.Config{
7474
ClientAuth: tls.RequireAndVerifyClientCert,
7575
ClientCAs: certPool,
76-
})
76+
}))
7777
return ocpp2.NewCSMS(nil, server)
7878
}
7979

ocpp1.6/v16.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,9 @@ type ChargePoint interface {
153153
// if !ok {
154154
// log.Fatal("couldn't parse PEM certificate")
155155
// }
156-
// cp := NewClient("someUniqueId", nil, ws.NewTLSClient(&tls.Config{
156+
// cp := NewClient("someUniqueId", nil, ws.NewClient(ws.WithClientTLSConfig(&tls.Config{
157157
// RootCAs: certPool,
158-
// })
158+
// }))
159159
//
160160
// For more advanced options, or if a customer networking/occpj layer is required,
161161
// please refer to ocppj.Client and ws.Client.
@@ -338,7 +338,7 @@ type CentralSystem interface {
338338
//
339339
// If you need a TLS server, you may use the following:
340340
//
341-
// cs := NewServer(nil, ws.NewTLSServer("certificatePath", "privateKeyPath"))
341+
// cs := NewServer(nil, ws.NewServer(ws.WithServerTLSConfig("certificatePath", "privateKeyPath", nil)))
342342
func NewCentralSystem(endpoint *ocppj.Server, server ws.Server) CentralSystem {
343343
if server == nil {
344344
server = ws.NewServer()

ocpp2.0.1/v2.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -202,9 +202,9 @@ type ChargingStation interface {
202202
// if !ok {
203203
// log.Fatal("couldn't parse PEM certificate")
204204
// }
205-
// cs := NewChargingStation("someUniqueId", nil, ws.NewTLSClient(&tls.Config{
205+
// cs := NewChargingStation("someUniqueId", nil, ws.NewClient(ws.WithClientTLSConfig(&tls.Config{
206206
// RootCAs: certPool,
207-
// })
207+
// }))
208208
//
209209
// For more advanced options, or if a custom networking/occpj layer is required,
210210
// please refer to ocppj.Client and ws.Client.
@@ -414,7 +414,7 @@ type CSMS interface {
414414
//
415415
// If you need a TLS server, you may use the following:
416416
//
417-
// csms := NewCSMS(nil, ws.NewTLSServer("certificatePath", "privateKeyPath"))
417+
// csms := NewCSMS(nil, ws.NewServer(ws.WithServerTLSConfig("certificatePath", "privateKeyPath", nil)))
418418
func NewCSMS(endpoint *ocppj.Server, server ws.Server) CSMS {
419419
if server == nil {
420420
server = ws.NewServer()

ws/client.go

+31-26
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@ import (
2323
//
2424
// client := NewClient()
2525
//
26-
// If you need a TLS ws client instead, use:
26+
// If you need a secure websocket client instead, pass a tls.Config to the NewClient function:
2727
//
2828
// certPool, err := x509.SystemCertPool()
2929
// if err != nil {
3030
// log.Fatal(err)
3131
// }
32-
// // You may add more trusted certificates to the pool before creating the TLSClientConfig
33-
// client := NewTLSClient(&tls.Config{
32+
// // You may add more trusted certificates to the pool before creating the TLS Config
33+
// client := NewClient(&tls.Config{
3434
// RootCAs: certPool,
3535
// })
3636
//
@@ -122,7 +122,7 @@ type Client interface {
122122

123123
// client is the default implementation of a Websocket client.
124124
//
125-
// Use the NewClient or NewTLSClient functions to create a new client.
125+
// Use the NewClient function to create a new client.
126126
type client struct {
127127
webSocket *webSocket
128128
url url.URL
@@ -136,52 +136,57 @@ type client struct {
136136
reconnectC chan struct{} // used for signaling, that a reconnection attempt should be interrupted
137137
}
138138

139-
// Creates a new simple websocket client (the channel is not secured).
140-
//
141-
// Additional options may be added using the AddOption function.
142-
//
143-
// Basic authentication can be set using the SetBasicAuth function.
144-
//
145-
// By default, the client will not neogtiate any subprotocol. This value needs to be set via the
146-
// respective SetRequestedSubProtocol method.
147-
func NewClient() Client {
148-
return &client{
149-
dialOptions: []func(*websocket.Dialer){},
150-
timeoutConfig: NewClientTimeoutConfig(),
151-
reconnectC: make(chan struct{}, 1),
152-
header: http.Header{},
139+
// ClientOpt is a function that can be used to set options on a client during creation.
140+
type ClientOpt func(c *client)
141+
142+
// WithClientTLSConfig sets the TLS configuration for the client.
143+
// If the passed tlsConfig is nil, the client will not use TLS.
144+
func WithClientTLSConfig(tlsConfig *tls.Config) ClientOpt {
145+
return func(c *client) {
146+
if tlsConfig != nil {
147+
c.dialOptions = append(c.dialOptions, func(dialer *websocket.Dialer) {
148+
dialer.TLSClientConfig = tlsConfig
149+
})
150+
}
153151
}
154152
}
155153

156-
// NewTLSClient creates a new secure websocket client. If supported by the server, the websocket channel will use TLS.
154+
// NewClient creates a new websocket client.
155+
//
156+
// If the optional tlsConfig is not nil, and the server supports secure communication,
157+
// the websocket channel will use TLS.
157158
//
158159
// Additional options may be added using the AddOption function.
160+
//
159161
// Basic authentication can be set using the SetBasicAuth function.
160162
//
163+
// By default, the client will not negotiate any sub-protocol. This value needs to be set via the
164+
// respective SetRequestedSubProtocol method.
165+
//
161166
// To set a client certificate, you may do:
162167
//
163168
// certificate, _ := tls.LoadX509KeyPair(clientCertPath, clientKeyPath)
164169
// clientCertificates := []tls.Certificate{certificate}
165-
// client := ws.NewTLSClient(&tls.Config{
170+
// client := ws.NewClient(ws.WithClientTLSConfig(&tls.Config{
166171
// RootCAs: certPool,
167172
// Certificates: clientCertificates,
168-
// })
173+
// }))
169174
//
170-
// You can set any other TLS option within the same constructor as well.
175+
// You can set any other TLS option within the same constructor config as well.
171176
// For example, if you wish to test connecting to a server having a
172177
// self-signed certificate (do not use in production!), pass:
173178
//
174179
// InsecureSkipVerify: true
175-
func NewTLSClient(tlsConfig *tls.Config) Client {
180+
func NewClient(opts ...ClientOpt) Client {
176181
c := &client{
177182
dialOptions: []func(*websocket.Dialer){},
178183
timeoutConfig: NewClientTimeoutConfig(),
179184
reconnectC: make(chan struct{}, 1),
180185
header: http.Header{},
181186
}
182-
c.dialOptions = append(c.dialOptions, func(dialer *websocket.Dialer) {
183-
dialer.TLSClientConfig = tlsConfig
184-
})
187+
for _, o := range opts {
188+
o(c)
189+
}
185190
return c
186191
}
187192

ws/server.go

+35-28
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ type CheckClientHandler func(id string, r *http.Request) bool
2626
//
2727
// server := NewServer()
2828
//
29-
// If you need a TLS ws server instead, use:
29+
// If you need a server with TLS support, pass the following option:
3030
//
31-
// server := NewTLSServer("cert.pem", "privateKey.pem")
31+
// server := NewServer(WithServerTLSConfig("cert.pem", "privateKey.pem", nil))
3232
//
3333
// To support client basic authentication, use:
3434
//
@@ -125,7 +125,7 @@ type Server interface {
125125

126126
// Default implementation of a Websocket server.
127127
//
128-
// Use the NewServer or NewTLSServer functions to create a new server.
128+
// Use the NewServer function to create a new server.
129129
type server struct {
130130
connections map[string]*webSocket
131131
httpServer *http.Server
@@ -144,43 +144,50 @@ type server struct {
144144
httpHandler *mux.Router
145145
}
146146

147-
// Creates a new simple websocket server (the websockets are not secured).
148-
func NewServer() Server {
149-
router := mux.NewRouter()
150-
return &server{
151-
httpServer: &http.Server{},
152-
timeoutConfig: NewServerTimeoutConfig(),
153-
upgrader: websocket.Upgrader{Subprotocols: []string{}},
154-
httpHandler: router,
147+
// ServerOpt is a function that can be used to set options on a server during creation.
148+
type ServerOpt func(s *server)
149+
150+
// WithServerTLSConfig sets the TLS configuration for the server.
151+
// If the passed tlsConfig is nil, the client will not use TLS.
152+
func WithServerTLSConfig(certificatePath string, certificateKey string, tlsConfig *tls.Config) ServerOpt {
153+
return func(s *server) {
154+
s.tlsCertificatePath = certificatePath
155+
s.tlsCertificateKey = certificateKey
156+
if tlsConfig != nil {
157+
s.httpServer.TLSConfig = tlsConfig
158+
}
155159
}
156160
}
157161

158-
// NewTLSServer creates a new secure websocket server. All created websocket channels will use TLS.
162+
// NewServer Creates a new websocket server.
163+
//
164+
// Additional options may be added using the AddOption function.
159165
//
160-
// You need to pass a filepath to the server TLS certificate and key.
166+
// By default, the websockets are not secure, and the server will not perform any client certificate verification.
161167
//
162-
// It is recommended to pass a valid TLSConfig for the server to use.
163-
// For example to require client certificate verification:
168+
// To add TLS support to the server, a valid server certificate path and key must be passed.
169+
// To also add support for client certificate verification, a valid TLSConfig needs to be configured.
170+
// For example:
164171
//
165-
// tlsConfig := &tls.Config{
166-
// ClientAuth: tls.RequireAndVerifyClientCert,
167-
// ClientCAs: clientCAs,
168-
// }
172+
// tlsConfig := &tls.Config{
173+
// ClientAuth: tls.RequireAndVerifyClientCert,
174+
// ClientCAs: clientCAs,
175+
// }
176+
// server := ws.NewServer(ws.WithServerTLSConfig("cert.pem", "privateKey.pem", tlsConfig))
169177
//
170-
// If no tlsConfig parameter is passed, the server will by default
171-
// not perform any client certificate verification.
172-
func NewTLSServer(certificatePath string, certificateKey string, tlsConfig *tls.Config) Server {
178+
// When TLS is correctly configured, the server will automatically use it for all created websocket channels.
179+
func NewServer(opts ...ServerOpt) Server {
173180
router := mux.NewRouter()
174-
return &server{
175-
tlsCertificatePath: certificatePath,
176-
tlsCertificateKey: certificateKey,
177-
httpServer: &http.Server{
178-
TLSConfig: tlsConfig,
179-
},
181+
s := &server{
182+
httpServer: &http.Server{},
180183
timeoutConfig: NewServerTimeoutConfig(),
181184
upgrader: websocket.Upgrader{Subprotocols: []string{}},
182185
httpHandler: router,
183186
}
187+
for _, o := range opts {
188+
o(s)
189+
}
190+
return s
184191
}
185192

186193
func (s *server) SetMessageHandler(handler MessageHandler) {

0 commit comments

Comments
 (0)