Skip to content

Commit

Permalink
feat: add server for coap example
Browse files Browse the repository at this point in the history
Signed-off-by: 1998-felix <[email protected]>
  • Loading branch information
felixgateru committed May 23, 2024
1 parent 55594f0 commit 0089ebe
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 50 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ LB tasks can be offloaded to a standard ingress proxy - for example, NginX.
- Golang
- Mosquitto MQTT Server
- Mosquitto Publisher and Subscriber Client
- coap-client or Magistrala coap-cli

### Example Setup of mProxy

Expand Down Expand Up @@ -195,8 +196,8 @@ Bash scripts available in `examples/client/http` directory help to test the mPro

### Test mProxy server for CoAP protocols

Bash scripts available in `example/client/coap` directory help to test the mProxy servers running for CoAP protocols.
This scripts can be used after changing the `MPROXY_COAP_WITHOUT_DTLS_TARGET` and `MPROXY_COAP_WITH_DTLS_TARGET` to a public coap server such as `coap://coap.me:5683`
Bash scripts available in `example/client/coap` directory help to test the mProxy servers running for CoAP protocols. You will require to have either the coap-client or the [Magistrala coap-cli](https://github.com/absmach/coap-cli).
The script can be used alongside the simple go-coap server provided at `example/server/coap`.

- Script to test mProxy server running at 5682 for CoAP without DTLS

Expand All @@ -207,7 +208,7 @@ This scripts can be used after changing the `MPROXY_COAP_WITHOUT_DTLS_TARGET` an
- Script to test mProxy server running at 5684 for CoAP with DTLS

```bash
examples/client/coap/without_dtls.sh
examples/client/coap/with_dtls.sh
```

## Configuration
Expand Down
10 changes: 9 additions & 1 deletion examples/client/coap/without_dtls.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,16 @@ content=0x32
message="{\"message\": \"Hello mProxy\"}"
auth="TOKEN"

#Examples using lib-coap coap-client
echo "Posting message to ${protocol}://${host}:${port}/${path} without tls ..."
coap-client -m post coap://${host}:${port}/${path} -e "${message}" -O 12,${content} -O 15,auth=${auth}

echo "Getting message from ${protocol}://${host}:${port}/${path} without tls ..."
coap-client -m get coap://${host}:${port}/${path} -O 6,0x00 -O 15,auth=${auth} -
coap-client -m get coap://${host}:${port}/${path} -O 6,0x00 -O 15,auth=${auth}

#Examples using Magisrala coap-cli
echo "Posting message to ${protocol}://${host}:${port}/${path} without tls ..."
coap-cli post ${host}:${port}/${path} -d "${message}" -O 12,${content} -O 15,auth=${auth}

echo "Getting message from ${protocol}://${host}:${port}/${path} without tls ..."
coap-cli get ${host}:${port}/${path} -O 6,0x00 -O 15,auth=${auth}
37 changes: 37 additions & 0 deletions examples/server/coap/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0

package main

import (
"fmt"
"log"
"strings"

coap "github.com/plgd-dev/go-coap/v3"
"github.com/plgd-dev/go-coap/v3/message"
"github.com/plgd-dev/go-coap/v3/message/codes"
"github.com/plgd-dev/go-coap/v3/mux"
)

const defaultPort = "5683"

func handleRequest(w mux.ResponseWriter, r *mux.Message) {
resp := w.Conn().AcquireMessage(r.Context())
defer w.Conn().ReleaseMessage(resp)
resp.SetCode(codes.Content)
resp.SetToken(r.Token())
resp.SetContentFormat(message.TextPlain)
resp.SetBody(strings.NewReader(fmt.Sprintf("%v OK", r.Code())))
err := w.Conn().WriteMessage(resp)
if err != nil {
log.Printf("Cannot send response: %v", err)
}
}

func main() {
r := mux.NewRouter()
r.DefaultHandle(mux.HandlerFunc(handleRequest))
log.Println("starting coap server, listening on port " + defaultPort)
log.Fatal(coap.ListenAndServe("udp", ":"+defaultPort, r))
}
86 changes: 40 additions & 46 deletions pkg/coap/coap.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@ import (
"github.com/plgd-dev/go-coap/v3/udp"
)

var (
errUnsupportedConfig = errors.New("unsupported CoAP configuration")
errUnsupportedMethod = errors.New("unsupported CoAP method")
)
var errUnsupportedMethod = errors.New("unsupported CoAP method")

type Proxy struct {
config mproxy.Config
Expand All @@ -52,6 +49,12 @@ func sendErrorMessage(cc mux.Conn, token []byte, err error, code codes.Code) err
}

func (p *Proxy) postUpstream(cc mux.Conn, req *mux.Message, token []byte) error {
outbound, err := udp.Dial(p.config.Target)
if err != nil {
return err
}
defer outbound.Close()

path, err := req.Options().Path()
if err != nil {
return err
Expand All @@ -65,12 +68,7 @@ func (p *Proxy) postUpstream(cc mux.Conn, req *mux.Message, token []byte) error
}
}

targetConn, err := udp.Dial(p.config.Target)
if err != nil {
return err
}
defer targetConn.Close()
pm, err := targetConn.Post(cc.Context(), path, format, req.Body(), req.Options()...)
pm, err := outbound.Post(cc.Context(), path, format, req.Body(), req.Options()...)
if err != nil {
return err
}
Expand All @@ -84,12 +82,12 @@ func (p *Proxy) getUpstream(cc mux.Conn, req *mux.Message, token []byte) error {
return err
}

targetConn, err := udp.Dial(p.config.Target)
outbound, err := udp.Dial(p.config.Target)
if err != nil {
return err
}
defer targetConn.Close()
pm, err := targetConn.Get(cc.Context(), path, req.Options()...)
defer outbound.Close()
pm, err := outbound.Get(cc.Context(), path, req.Options()...)
if err != nil {
return err
}
Expand All @@ -98,16 +96,16 @@ func (p *Proxy) getUpstream(cc mux.Conn, req *mux.Message, token []byte) error {
}

func (p *Proxy) observeUpstream(ctx context.Context, cc mux.Conn, opts []message.Option, token []byte, path string) {
targetConn, err := udp.Dial(p.config.Target)
outbound, err := udp.Dial(p.config.Target)
if err != nil {
if err := sendErrorMessage(cc, token, err, codes.BadGateway); err != nil {
p.logger.Error(fmt.Sprintf("cannot send error response: %v", err))
}
}
defer targetConn.Close()
defer outbound.Close()
doneObserving := make(chan struct{})

obs, err := targetConn.Observe(ctx, path, func(req *pool.Message) {
obs, err := outbound.Observe(ctx, path, func(req *pool.Message) {
req.SetToken(token)
if err := cc.WriteMessage(req); err != nil {
if err := sendErrorMessage(cc, token, err, codes.BadGateway); err != nil {
Expand Down Expand Up @@ -236,16 +234,15 @@ func (p *Proxy) handlePost(ctx context.Context, con mux.Conn, body, token []byte
}

func (p *Proxy) Listen(ctx context.Context) error {
switch {
case p.config.DTLSConfig == nil:
l, err := net.NewListenUDP("udp", p.config.Address)
if p.config.DTLSConfig != nil {
l, err := net.NewDTLSListener("udp", p.config.Address, p.config.DTLSConfig)
if err != nil {
return err
}
defer l.Close()

p.logger.Info(fmt.Sprintf("CoAP proxy server started at %s without DTLS", p.config.Address))
s := udp.NewServer(options.WithMux(mux.HandlerFunc(p.handler)))
p.logger.Info(fmt.Sprintf("CoAP proxy server started on port %s with DTLS", p.config.Address))
s := dtls.NewServer(options.WithMux(mux.HandlerFunc(p.handler)))

errCh := make(chan error)
go func() {
Expand All @@ -254,38 +251,35 @@ func (p *Proxy) Listen(ctx context.Context) error {

select {
case <-ctx.Done():
p.logger.Info(fmt.Sprintf("CoAP proxy server at %s without DTLS exiting ...", p.config.Address))
p.logger.Info(fmt.Sprintf("CoAP proxy server on port %s with DTLS exiting ...", p.config.Address))
l.Close()
case err := <-errCh:
p.logger.Error(fmt.Sprintf("CoAP proxy server at %s without DTLS exiting with errors: %s", p.config.Address, err.Error()))
p.logger.Error(fmt.Sprintf("CoAP proxy server on port %s with DTLS exiting with errors: %s", p.config.Address, err.Error()))
return err
}
return nil
case p.config.DTLSConfig != nil:
l, err := net.NewDTLSListener("udp", p.config.Address, p.config.DTLSConfig)
if err != nil {
return err
}
defer l.Close()
}
l, err := net.NewListenUDP("udp", p.config.Address)
if err != nil {
return err
}
defer l.Close()

p.logger.Info(fmt.Sprintf("CoAP proxy server started at %s with DTLS", p.config.Address))
s := dtls.NewServer(options.WithMux(mux.HandlerFunc(p.handler)))
p.logger.Info(fmt.Sprintf("CoAP proxy server started at %s without DTLS", p.config.Address))
s := udp.NewServer(options.WithMux(mux.HandlerFunc(p.handler)))

errCh := make(chan error)
go func() {
errCh <- s.Serve(l)
}()
errCh := make(chan error)
go func() {
errCh <- s.Serve(l)
}()

select {
case <-ctx.Done():
p.logger.Info(fmt.Sprintf("CoAP proxy server at %s with DTLS exiting ...", p.config.Address))
l.Close()
case err := <-errCh:
p.logger.Error(fmt.Sprintf("CoAP proxy server at %s with DTLS exiting with errors: %s", p.config.Address, err.Error()))
return err
}
return nil
default:
return errUnsupportedConfig
select {
case <-ctx.Done():
p.logger.Info(fmt.Sprintf("CoAP proxy server on port %s without DTLS exiting ...", p.config.Address))
l.Close()
case err := <-errCh:
p.logger.Error(fmt.Sprintf("CoAP proxy server on port %s without DTLS exiting with errors: %s", p.config.Address, err.Error()))
return err
}
return nil
}

0 comments on commit 0089ebe

Please sign in to comment.