Skip to content

Commit 25d476c

Browse files
committed
TLS support
1 parent 1cf0eaf commit 25d476c

File tree

5 files changed

+84
-8
lines changed

5 files changed

+84
-8
lines changed

README.md

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ The library has been tested with the following MQTT servers:
1111
- [fluux.io platform](https://fluux.io/)
1212
- [Mosquitto](https://mosquitto.org/)
1313

14+
## Features
15+
16+
- MQTT v3.1.1, QOS 0
17+
- Client manager to support auto-reconnect with exponential backoff.
18+
- TLS Support
19+
1420
## Short term tasks
1521

1622
Implement support for QOS 1 and 2 (with storage backend interface and default backends).
@@ -23,7 +29,44 @@ You can launch unit tests with:
2329

2430
## Testing with Fluux public MQTT server
2531

26-
We encourage you to experiment and test on a public Fluux test server. It is available on mqtt.fluux.io (on ports 1883 for cleartext and 8883 for TLS).
32+
We encourage you to experiment and test on a public Fluux test server. It is available on mqtt.fluux.io (on ports 1883
33+
for cleartext and 8883 for TLS).
34+
35+
Here is example code for a simple client:
36+
37+
```
38+
package main
39+
40+
import (
41+
"log"
42+
"time"
43+
44+
"gosrc.io/mqtt"
45+
)
46+
47+
func main() {
48+
client := mqtt.NewClient("tls://mqtt.fluux.io:8883")
49+
client.ClientID = "MQTT-Sub"
50+
log.Printf("Connecting on: %s\n", client.Address)
51+
52+
messages := make(chan mqtt.Message)
53+
client.Messages = messages
54+
55+
postConnect := func(c *mqtt.Client) {
56+
log.Println("Connected")
57+
name := "/mremond/test-topic-1"
58+
topic := mqtt.Topic{Name: name, QOS: 0}
59+
c.Subscribe(topic)
60+
}
61+
62+
cm := mqtt.NewClientManager(client, postConnect)
63+
cm.Start()
64+
65+
for m := range messages {
66+
log.Printf("Received message from MQTT server on topic %s: %+v\n", m.Topic, m.Payload)
67+
}
68+
}
69+
```
2770

2871
## Setting Mosquitto on OSX for testing
2972

client.go

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ package mqtt // import "gosrc.io/mqtt"
22

33
import "C"
44
import (
5+
"crypto/tls"
56
"errors"
67
"fmt"
78
"net"
9+
"net/url"
810
"sync"
911
"time"
1012
)
@@ -18,7 +20,7 @@ var (
1820
const (
1921
// DefaultMQTTServer is a shortcut to define connection to local
2022
// server
21-
DefaultMQTTServer = "localhost:1883"
23+
DefaultMQTTServer = "tcp://localhost:1883"
2224
)
2325

2426
//=============================================================================
@@ -120,6 +122,8 @@ type Client struct {
120122

121123
// New generates a new MQTT client with default parameters. Address
122124
// must be set as we cannot find relevant default value for server.
125+
// address is of the form tcp://hostname:port for cleartext connection
126+
// or tls://hostname:port for TLS connection.
123127
// TODO: Should messages channel be set on New ?
124128
func NewClient(address string) *Client {
125129
return &Client{
@@ -222,12 +226,39 @@ Inflight: %v`, c.Subscriptions, c.inflight)
222226
// ============================================================================
223227
// Internal
224228

225-
func (c *Client) connect() error {
226-
conn, err := net.DialTimeout("tcp", c.Address, 5*time.Second)
229+
func (c *Client) connect() (err error) {
230+
// Parse address string
231+
uri, err := url.Parse(c.Address)
227232
if err != nil {
228233
return err
229234
}
230235

236+
var conn net.Conn
237+
switch uri.Scheme {
238+
case "tcp":
239+
conn, err = net.DialTimeout("tcp", uri.Host, 5*time.Second)
240+
if err != nil {
241+
return err
242+
}
243+
return c.login(conn)
244+
case "tls":
245+
conn, err = net.DialTimeout("tcp", uri.Host, 5*time.Second)
246+
if err != nil {
247+
return err
248+
}
249+
config := tls.Config{ServerName: uri.Hostname()}
250+
tlsConn := tls.Client(conn, &config)
251+
err = tlsConn.Handshake()
252+
if err != nil {
253+
return err
254+
}
255+
return c.login(tlsConn)
256+
default:
257+
return errors.New("url scheme must be tcp or tls")
258+
}
259+
}
260+
261+
func (c *Client) login(conn net.Conn) (err error) {
231262
// 1. Open session - Login
232263
// Send connect packet
233264
connectPacket := ConnectPacket{ProtocolLevel: c.ProtocolLevel, ProtocolName: "MQTT"}
@@ -237,10 +268,11 @@ func (c *Client) connect() error {
237268
connectPacket.Username = c.Username
238269
connectPacket.Password = c.Password
239270
buf := connectPacket.Marshall()
240-
if _, err := conn.Write(buf); err != nil {
271+
if _, err = conn.Write(buf); err != nil {
241272
return err
242273
}
243274

275+
// 2. Check login result
244276
if err = conn.SetReadDeadline(time.Now().Add(c.ConnectTimeout)); err != nil {
245277
return err
246278
}
@@ -264,6 +296,7 @@ func (c *Client) connect() error {
264296
return err
265297
}
266298

299+
// 3. Configure sender and receiver
267300
c.setSender(initSender(conn, c.Keepalive))
268301
// Start routine to receive incoming data
269302
receiverChannel := spawnReceiver(conn, c.Messages, c.sender)

examples/mqtt_pub/mqtt_pub.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import (
1717

1818
func main() {
1919
messages := make(chan mqtt.Message)
20-
client := mqtt.NewClient("localhost:1883")
20+
client := mqtt.NewClient("tcp://localhost:1883")
2121
client.ClientID = "MQTT-Pub"
2222
fmt.Printf("Server to connect to: %s\n", client.Address)
2323

examples/mqtt_sub/mqtt_sub.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
)
1212

1313
func main() {
14-
client := mqtt.NewClient("localhost:1883")
14+
client := mqtt.NewClient("tcp://localhost:1883")
1515
client.ClientID = "MQTT-Sub"
1616
log.Printf("Server to connect to: %s\n", client.Address)
1717

examples/mqtt_temp_sub/mqtt_temp_pub.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import (
1414
)
1515

1616
func main() {
17-
client := mqtt.NewClient("localhost:1883")
17+
client := mqtt.NewClient("tcp://localhost:1883")
1818
client.ClientID = "mremond-osx"
1919

2020
if err := client.Connect(nil); err != nil {

0 commit comments

Comments
 (0)