Skip to content

Commit

Permalink
feature: add listen and serve with option function (plgd-dev#470)
Browse files Browse the repository at this point in the history
* feat: add listern and server with options
  • Loading branch information
CaiYueTing authored and HRogge committed Oct 26, 2023
1 parent 483ad53 commit 0f1c0b0
Show file tree
Hide file tree
Showing 2 changed files with 176 additions and 0 deletions.
95 changes: 95 additions & 0 deletions examples/options/server/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package main

import (
"bytes"
"context"
"crypto/tls"
"fmt"
"log"

piondtls "github.com/pion/dtls/v2"
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"
"github.com/plgd-dev/go-coap/v3/options"

dtlsServer "github.com/plgd-dev/go-coap/v3/dtls/server"
tcpServer "github.com/plgd-dev/go-coap/v3/tcp/server"
udpClient "github.com/plgd-dev/go-coap/v3/udp/client"
)

func handleA(w mux.ResponseWriter, r *mux.Message) {
log.Printf("got message in handleA: %+v from %v\n", r, w.Conn().RemoteAddr())
err := w.SetResponse(codes.GET, message.TextPlain, bytes.NewReader([]byte("A hello world")))
if err != nil {
log.Printf("cannot set response: %v", err)
}
}

func handleB(w mux.ResponseWriter, r *mux.Message) {
log.Printf("got message in handleB: %+v from %v\n", r, w.Conn().RemoteAddr())
customResp := w.Conn().AcquireMessage(r.Context())
defer w.Conn().ReleaseMessage(customResp)
customResp.SetCode(codes.Content)
customResp.SetToken(r.Token())
customResp.SetContentFormat(message.TextPlain)
customResp.SetBody(bytes.NewReader([]byte("B hello world")))
err := w.Conn().WriteMessage(customResp)
if err != nil {
log.Printf("cannot set response: %v", err)
}
}

func handleOnNewConn(cc *udpClient.Conn) {
dtlsConn, ok := cc.NetConn().(*piondtls.Conn)
if !ok {
log.Fatalf("invalid type %T", cc.NetConn())
}
clientId := dtlsConn.ConnectionState().IdentityHint
cc.SetContextValue("clientId", clientId)
cc.AddOnClose(func() {
clientId := dtlsConn.ConnectionState().IdentityHint
log.Printf("closed connection clientId: %s", clientId)
})
}

func main() {
m := mux.NewRouter()
m.Handle("/a", mux.HandlerFunc(handleA))
m.Handle("/b", mux.HandlerFunc(handleB))

tcpOpts := []tcpServer.Option{}
tcpOpts = append(tcpOpts,
options.WithMux(m),
options.WithContext(context.Background()))

dtlsOpts := []dtlsServer.Option{}
dtlsOpts = append(dtlsOpts,
options.WithMux(m),
options.WithContext(context.Background()),
options.WithOnNewConn(handleOnNewConn),
)

go func() {
// serve a tcp server on :5686
log.Fatal(coap.ListenAndServeWithOptions("tcp", ":5686", tcpOpts))
}()

go func() {
// serve a tls tcp server on :5687
log.Fatal(coap.ListenAndServeTCPTLSWithOptions("tcp", "5687", &tls.Config{}, tcpOpts...))
}()

go func() {
// serve a udp dtls server on :5688
log.Fatal(coap.ListenAndServeDTLSWithOptions("udp", ":5688", &piondtls.Config{
PSK: func(hint []byte) ([]byte, error) {
fmt.Printf("Client's hint: %s \n", hint)
return []byte{0xAB, 0xC1, 0x23}, nil
},
PSKIdentityHint: []byte("Pion DTLS Client"),
CipherSuites: []piondtls.CipherSuiteID{piondtls.TLS_PSK_WITH_AES_128_CCM_8},
}, dtlsOpts...))
}()
}
81 changes: 81 additions & 0 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ import (

piondtls "github.com/pion/dtls/v2"
"github.com/plgd-dev/go-coap/v3/dtls"
dtlsServer "github.com/plgd-dev/go-coap/v3/dtls/server"
"github.com/plgd-dev/go-coap/v3/mux"
"github.com/plgd-dev/go-coap/v3/net"
"github.com/plgd-dev/go-coap/v3/options"
"github.com/plgd-dev/go-coap/v3/tcp"
tcpServer "github.com/plgd-dev/go-coap/v3/tcp/server"
"github.com/plgd-dev/go-coap/v3/udp"
udpServer "github.com/plgd-dev/go-coap/v3/udp/server"
)

// ListenAndServe Starts a server on address and network specified Invoke handler
Expand Down Expand Up @@ -78,3 +81,81 @@ func ListenAndServeDTLS(network string, addr string, config *piondtls.Config, ha
s := dtls.NewServer(options.WithMux(handler))
return s.Serve(l)
}

// ListenAndServeWithOption Starts a server on address and network specified Invoke options
// for incoming queries. The options is only support tcpServer.Option and udpServer.Option
func ListenAndServeWithOptions(network, addr string, opts ...any) (err error) {
tcpOptions := []tcpServer.Option{}
udpOptions := []udpServer.Option{}
for _, opt := range opts {
switch o := opt.(type) {
case tcpServer.Option:
tcpOptions = append(tcpOptions, o)
case udpServer.Option:
udpOptions = append(udpOptions, o)
default:
return fmt.Errorf("only support tcpServer.Option and udpServer.Option")
}
}

switch network {
case "udp", "udp4", "udp6", "":
l, err := net.NewListenUDP(network, addr)
if err != nil {
return err
}
defer func() {
if errC := l.Close(); errC != nil && err == nil {
err = errC
}
}()
s := udp.NewServer(udpOptions...)
return s.Serve(l)
case "tcp", "tcp4", "tcp6":
l, err := net.NewTCPListener(network, addr)
if err != nil {
return err
}
defer func() {
if errC := l.Close(); errC != nil && err == nil {
err = errC
}
}()
s := tcp.NewServer(tcpOptions...)
return s.Serve(l)
default:
return fmt.Errorf("invalid network (%v)", network)
}
}

// ListenAndServeTCPTLSWithOptions Starts a server on address and network over TLS specified Invoke options
// for incoming queries.
func ListenAndServeTCPTLSWithOptions(network, addr string, config *tls.Config, opts ...tcpServer.Option) (err error) {
l, err := net.NewTLSListener(network, addr, config)
if err != nil {
return err
}
defer func() {
if errC := l.Close(); errC != nil && err == nil {
err = errC
}
}()
s := tcp.NewServer(opts...)
return s.Serve(l)
}

// ListenAndServeDTLSWithOptions Starts a server on address and network over DTLS specified Invoke options
// for incoming queries.
func ListenAndServeDTLSWithOptions(network string, addr string, config *piondtls.Config, opts ...dtlsServer.Option) (err error) {
l, err := net.NewDTLSListener(network, addr, config)
if err != nil {
return err
}
defer func() {
if errC := l.Close(); errC != nil && err == nil {
err = errC
}
}()
s := dtls.NewServer(opts...)
return s.Serve(l)
}

0 comments on commit 0f1c0b0

Please sign in to comment.