📚 canopus - Awesome Go Library for Networking
CoAP Client/Server implementation (RFC 7252).
🏷️ Networking
📂 Libraries for working with various layers of the network.
⭐ 155 stars
Detailed Description of canopus
Canopus
Canopus is a client/server implementation of the Constrained Application Protocol (CoAP)
Updates
25.11.2016
I've added basic dTLS Support based on [Julien Vermillard's][JVERMILLARD] [implementation][NATIVEDTLS]. Thanks Julien! It should now support PSK-based authentication. I've also gone ahead and refactored the APIs to make it that bit more Go idiomatic. [JVERMILLARD]: https://github.com/jvermillard [NATIVEDTLS]: https://github.com/jvermillard/nativedtls
Building and running
- git submodule update --init --recursive
- cd openssl
- ./config && make
- You should then be able to run the examples in the /examples folder
Simple Example
// Server
// See /examples/simple/server/main.go
server := canopus.NewServer()
server.Get("/hello", func(req canopus.Request) canopus.Response {
msg := canopus.ContentMessage(req.GetMessage().GetMessageId(), canopus.MessageAcknowledgment)
msg.SetStringPayload("Acknowledged: " + req.GetMessage().GetPayload().String())
res := canopus.NewResponse(msg, nil)
return res
})
server.ListenAndServe(":5683")
// Client
// See /examples/simple/client/main.go
conn, err := canopus.Dial("localhost:5683")
if err != nil {
panic(err.Error())
}
req := canopus.NewRequest(canopus.MessageConfirmable, canopus.Get, canopus.GenerateMessageID()).(*canopus.CoapRequest)
req.SetStringPayload("Hello, canopus")
req.SetRequestURI("/hello")
resp, err := conn.Send(req)
if err != nil {
panic(err.Error())
}
fmt.Println("Got Response:" + resp.GetMessage().GetPayload().String())
Observe / Notify
// Server
// See /examples/observe/server/main.go
server := canopus.NewServer()
server.Get("/watch/this", func(req canopus.Request) canopus.Response {
msg := canopus.NewMessageOfType(canopus.MessageAcknowledgment, req.GetMessage().GetMessageId(), canopus.NewPlainTextPayload("Acknowledged"))
res := canopus.NewResponse(msg, nil)
return res
})
ticker := time.NewTicker(3 * time.Second)
go func() {
for {
select {
case <-ticker.C:
changeVal := strconv.Itoa(rand.Int())
fmt.Println("[SERVER << ] Change of value -->", changeVal)
server.NotifyChange("/watch/this", changeVal, false)
}
}
}()
server.OnObserve(func(resource string, msg canopus.Message) {
fmt.Println("[SERVER << ] Observe Requested for " + resource)
})
server.ListenAndServe(":5683")
// Client
// See /examples/observe/client/main.go
conn, err := canopus.Dial("localhost:5683")
tok, err := conn.ObserveResource("/watch/this")
if err != nil {
panic(err.Error())
}
obsChannel := make(chan canopus.ObserveMessage)
done := make(chan bool)
go conn.Observe(obsChannel)
notifyCount := 0
for {
select {
case obsMsg, _ := <-obsChannel:
if notifyCount == 5 {
fmt.Println("[CLIENT >> ] Canceling observe after 5 notifications..")
go conn.CancelObserveResource("watch/this", tok)
go conn.StopObserve(obsChannel)
return
} else {
notifyCount++
// msg := obsMsg.Msg\
resource := obsMsg.GetResource()
val := obsMsg.GetValue()
fmt.Println("[CLIENT >> ] Got Change Notification for resource and value: ", notifyCount, resource, val)
}
}
}
dTLS with PSK
// Server
// See /examples/dtls/simple-psk/server/main.go
server := canopus.NewServer()
server.Get("/hello", func(req canopus.Request) canopus.Response {
msg := canopus.ContentMessage(req.GetMessage().GetMessageId(), canopus.MessageAcknowledgment)
msg.SetStringPayload("Acknowledged: " + req.GetMessage().GetPayload().String())
res := canopus.NewResponse(msg, nil)
return res
})
server.HandlePSK(func(id string) []byte {
return []byte("secretPSK")
})
server.ListenAndServeDTLS(":5684")
// Client
// See /examples/dtls/simple-psk/client/main.go
conn, err := canopus.DialDTLS("localhost:5684", "canopus", "secretPSK")
if err != nil {
panic(err.Error())
}
req := canopus.NewRequest(canopus.MessageConfirmable, canopus.Get, canopus.GenerateMessageID())
req.SetStringPayload("Hello, canopus")
req.SetRequestURI("/hello")
resp, err := conn.Send(req)
if err != nil {
panic(err.Error())
}
fmt.Println("Got Response:" + resp.GetMessage().GetPayload().String())
CoAP-CoAP Proxy
// Server
// See /examples/proxy/coap/server/main.go
server := canopus.NewServer()
server.Get("/proxycall", func(req canopus.Request) canopus.Response {
msg := canopus.ContentMessage(req.GetMessage().GetMessageId(), canopus.MessageAcknowledgment)
msg.SetStringPayload("Data from :5685 -- " + req.GetMessage().GetPayload().String())
res := canopus.NewResponse(msg, nil)
return res
})
server.ListenAndServe(":5685")
// Proxy Server
// See /examples/proxy/coap/proxy/main.go
server := canopus.NewServer()
server.ProxyOverCoap(true)
server.Get("/proxycall", func(req canopus.Request) canopus.Response {
canopus.PrintMessage(req.GetMessage())
msg := canopus.ContentMessage(req.GetMessage().GetMessageId(), canopus.MessageAcknowledgment)
msg.SetStringPayload("Acknowledged: " + req.GetMessage().GetPayload().String())
res := canopus.NewResponse(msg, nil)
return res
})
server.ListenAndServe(":5683")
// Client
// See /examples/proxy/coap/client/main.go
conn, err := canopus.Dial("localhost:5683")
if err != nil {
panic(err.Error())
}
req := canopus.NewRequest(canopus.MessageConfirmable, canopus.Get, canopus.GenerateMessageID())
req.SetProxyURI("coap://localhost:5685/proxycall")
resp, err := conn.Send(req)
if err != nil {
println("err", err)
}
canopus.PrintMessage(resp.GetMessage())
CoAP-HTTP Proxy
// Server
// See /examples/proxy/http/server/main.go
server := canopus.NewServer()
server.ProxyOverHttp(true)
server.ListenAndServe(":5683")
// Client
// See /examples/proxy/http/client/main.go
conn, err := canopus.Dial("localhost:5683")
if err != nil {
panic(err.Error())
}
req := canopus.NewRequest(canopus.MessageConfirmable, canopus.Get, canopus.GenerateMessageID())
req.SetProxyURI("https://httpbin.org/get")
resp, err := conn.Send(req)
if err != nil {
println("err", err)
}
canopus.PrintMessage(resp.GetMessage())