Skip to content

Commit 1217c5f

Browse files
authored
Tls (#32)
* add tls, tls-listen * add wss-listen * version bump
1 parent 44d3d7f commit 1217c5f

File tree

4 files changed

+129
-1
lines changed

4 files changed

+129
-1
lines changed

hookah.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
)
1313

1414
// Version of hookah API.
15-
const Version = "2.0.0"
15+
const Version = "2.1.0"
1616

1717
// API is an instance of the Hookah API.
1818
type API struct {
@@ -86,11 +86,14 @@ func (a *API) registerProtocols() {
8686
a.RegisterProtocol("stdout", "stdout", protocols.Stdout)
8787
a.RegisterProtocol("tcp", "tcp://address", protocols.TCP)
8888
a.RegisterProtocol("tcp-listen", "tcp-listen://address", protocols.TCPListen)
89+
a.RegisterProtocol("tls", "tls://address?cert=path&insecure=false", protocols.TLS)
90+
a.RegisterProtocol("tls-listen", "tls-listen://address?cert=path&key=path", protocols.TLSListen)
8991
a.RegisterProtocol("unix", "unix://path/to/sock", protocols.Unix)
9092
a.RegisterProtocol("unix-listen", "unix-listen://path/to/sock", protocols.UnixListen)
9193
a.RegisterProtocol("ws", "ws://address", protocols.WS)
9294
a.RegisterProtocol("wss", "wss://address", protocols.WSS)
9395
a.RegisterProtocol("ws-listen", "ws-listen://address", protocols.WSListen)
96+
a.RegisterProtocol("wss-listen", "wss-listen://address?cert=path&key=path", protocols.WSSListen)
9497
}
9598

9699
func parseOptions(op string) (string, string) {

internal/protocols/tls.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package protocols
2+
3+
import (
4+
"crypto/tls"
5+
"crypto/x509"
6+
"errors"
7+
"io/ioutil"
8+
"net/url"
9+
"strings"
10+
11+
"github.com/wybiral/hookah/pkg/node"
12+
)
13+
14+
// TLS creates a TLS client node
15+
func TLS(arg string) (*node.Node, error) {
16+
var opts url.Values
17+
// Parse options
18+
addrOpts := strings.SplitN(arg, "?", 2)
19+
addr := addrOpts[0]
20+
if len(addrOpts) == 2 {
21+
op, err := url.ParseQuery(addrOpts[1])
22+
if err != nil {
23+
return nil, err
24+
}
25+
opts = op
26+
}
27+
cfg := &tls.Config{}
28+
// Handle cert option
29+
cert := opts.Get("cert")
30+
if len(cert) != 0 {
31+
pem, err := ioutil.ReadFile(cert)
32+
if err != nil {
33+
return nil, err
34+
}
35+
certPool := x509.NewCertPool()
36+
certPool.AppendCertsFromPEM(pem)
37+
cfg.RootCAs = certPool
38+
}
39+
// Handle insecure option
40+
insecure := opts.Get("insecure")
41+
if insecure == "true" {
42+
cfg.InsecureSkipVerify = true
43+
} else if insecure != "false" && len(insecure) > 0 {
44+
return nil, errors.New("invalid option for insecure")
45+
}
46+
// Open connection with config
47+
rwc, err := tls.Dial("tcp", addr, cfg)
48+
if err != nil {
49+
return nil, err
50+
}
51+
return node.New(rwc), nil
52+
}

internal/protocols/tlslisten.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package protocols
2+
3+
import (
4+
"crypto/tls"
5+
"net/url"
6+
"strings"
7+
8+
"github.com/wybiral/hookah/pkg/fanout"
9+
"github.com/wybiral/hookah/pkg/node"
10+
)
11+
12+
// TLSListen creates a TLS listener Node
13+
func TLSListen(arg string) (*node.Node, error) {
14+
var opts url.Values
15+
// Parse options
16+
addrOpts := strings.SplitN(arg, "?", 2)
17+
addr := addrOpts[0]
18+
if len(addrOpts) == 2 {
19+
op, err := url.ParseQuery(addrOpts[1])
20+
if err != nil {
21+
return nil, err
22+
}
23+
opts = op
24+
}
25+
// Load cert and key files
26+
cert := opts.Get("cert")
27+
key := opts.Get("key")
28+
app := &listenApp{}
29+
c, err := tls.LoadX509KeyPair(cert, key)
30+
if err != nil {
31+
return nil, err
32+
}
33+
cfg := &tls.Config{Certificates: []tls.Certificate{c}}
34+
// Create listener from config
35+
ln, err := tls.Listen("tcp", addr, cfg)
36+
if err != nil {
37+
return nil, err
38+
}
39+
app.ln = ln
40+
app.fan = fanout.New()
41+
app.ch = make(chan []byte)
42+
go app.serve()
43+
return node.New(app), nil
44+
}

internal/protocols/wslisten.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package protocols
33
import (
44
"errors"
55
"net/http"
6+
"net/url"
7+
"strings"
68
"sync"
79

810
"github.com/gorilla/websocket"
@@ -41,6 +43,33 @@ func WSListen(addr string) (*node.Node, error) {
4143
return node.New(app), nil
4244
}
4345

46+
// WSSListen creates a wss WebSocket listener Node
47+
func WSSListen(arg string) (*node.Node, error) {
48+
var opts url.Values
49+
// Parse options
50+
addrOpts := strings.SplitN(arg, "?", 2)
51+
addr := addrOpts[0]
52+
if len(addrOpts) == 2 {
53+
op, err := url.ParseQuery(addrOpts[1])
54+
if err != nil {
55+
return nil, err
56+
}
57+
opts = op
58+
}
59+
// Load cert and key files
60+
cert := opts.Get("cert")
61+
key := opts.Get("key")
62+
app := &wsListenApp{}
63+
app.server = &http.Server{
64+
Addr: addr,
65+
Handler: http.HandlerFunc(app.handle),
66+
}
67+
app.fan = fanout.New()
68+
app.ch = make(chan []byte)
69+
go app.server.ListenAndServeTLS(cert, key)
70+
return node.New(app), nil
71+
}
72+
4473
func (app *wsListenApp) Read(b []byte) (int, error) {
4574
app.Lock()
4675
defer app.Unlock()

0 commit comments

Comments
 (0)