Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added TCP support for server and client APIs #3

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
101 changes: 82 additions & 19 deletions client.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package coap

import (
"errors"
"fmt"
"net"
"time"
)
Expand All @@ -18,49 +20,110 @@ const (

// Conn is a CoAP client connection.
type Conn struct {
conn *net.UDPConn
buf []byte
connTCP *net.TCPConn
buf []byte
conn *net.UDPConn
Net string
}

type Addr struct {
Tcp *net.TCPAddr
Udp *net.UDPAddr
}

// Dial connects a CoAP client.
func Dial(n, addr string) (*Conn, error) {
uaddr, err := net.ResolveUDPAddr(n, addr)
if err != nil {
return nil, err
}
switch n {
case "udp":
uaddr, err := net.ResolveUDPAddr(n, addr)
if err != nil {
return nil, err
}

s, err := net.DialUDP("udp", nil, uaddr)
if err != nil {
return nil, err
}
s, err := net.DialUDP("udp", nil, uaddr)
if err != nil {
return nil, err
}

return &Conn{conn: s, buf: make([]byte, maxPktLen), connTCP: nil}, nil
case "tcp":
taddr, err := net.ResolveTCPAddr(n, addr)
if err != nil {
return nil, err
}

return &Conn{s, make([]byte, maxPktLen)}, nil
s, err := net.DialTCP("tcp", nil, taddr)
if err != nil {
return nil, err
}

return &Conn{conn: nil, buf: make([]byte, maxPktLen), connTCP: s}, nil
default:
return nil, errors.New("unrecognized network type")
}
}

// Send a message. Get a response if there is one.
func (c *Conn) Send(req Message) (*Message, error) {
err := Transmit(c.conn, nil, req)
func (c *Conn) Send(req Message) (Message, error) {

//defer c.Close()
//not sure if that's a good idea to have it be default behavior. Maybe have it be based on a setting in Conn?
err := Transmit(c, Addr{}, req)
if err != nil {
return nil, err
}

if !req.IsConfirmable() {
return nil, nil
}

rv, err := Receive(c.conn, c.buf)
fmt.Println("about to receive in send()")
rv, err := Receive(c, c.buf)
if err != nil {
return nil, err
}

return &rv, nil
return rv, nil
}

// Receive a message.
func (c *Conn) Receive() (*Message, error) {
rv, err := Receive(c.conn, c.buf)
func (c *Conn) Receive() (Message, error) {
rv, err := Receive(c, c.buf)
if err != nil {
return nil, err
}
return &rv, nil
return rv, nil
}

func (c *Conn) Network() (string, error) {
fmt.Println("conn.Network() called")
if c.Net != "" {
return c.Net, nil
}
if c.conn != nil && c.connTCP != nil {
fmt.Println("satisfied conditions for udp/tcp both being non-nil")
return "", errors.New("multiple non-nil connections in Conn. it should be only one")
}
if c.conn != nil {
return "udp", nil
}
if c.connTCP != nil {
return "tcp", nil
} else {
fmt.Println("both connections are nil")
return "", errors.New("all connections in Conn struct are nil")
}
}

func (c *Conn) Close() error {
n, err := c.Network()
if err != nil {
return err
}
switch n {
case "udp":
return c.conn.Close()
case "tcp":
return c.connTCP.Close()
}
return err
}
6 changes: 3 additions & 3 deletions example/client/goap_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ import (
"log"
"os"

"github.com/dustin/go-coap"
"github.com/runtimeco/go-coap"
)

func main() {

req := coap.Message{
req := coap.NewDgramMessage(coap.MessageParams{
Type: coap.Confirmable,
Code: coap.GET,
MessageID: 12345,
Payload: []byte("hello, world!"),
}
})

path := "/some/path"
if len(os.Args) > 1 {
Expand Down
6 changes: 3 additions & 3 deletions example/obsclient/obsclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@ package main
import (
"log"

"github.com/dustin/go-coap"
"github.com/runtimeco/go-coap"
)

func main() {

req := coap.Message{
req := coap.NewDgramMessage(coap.MessageParams{
Type: coap.NonConfirmable,
Code: coap.GET,
MessageID: 12345,
}
})

req.AddOption(coap.Observe, 1)
req.SetPathString("/some/path")
Expand Down
14 changes: 7 additions & 7 deletions example/obsserver/obsserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@ import (
"net"
"time"

"github.com/dustin/go-coap"
"github.com/runtimeco/go-coap"
)

func periodicTransmitter(l *net.UDPConn, a *net.UDPAddr, m *coap.Message) {
func periodicTransmitter(l *net.UDPConn, a *net.UDPAddr, m coap.Message) {
subded := time.Now()

for {
msg := coap.Message{
msg := coap.NewDgramMessage(coap.MessageParams{
Type: coap.Acknowledgement,
Code: coap.Content,
MessageID: m.MessageID,
MessageID: m.MessageID(),
Payload: []byte(fmt.Sprintf("Been running for %v", time.Since(subded))),
}
})

msg.SetOption(coap.ContentFormat, coap.TextPlain)
msg.SetOption(coap.LocationPath, m.Path())
Expand All @@ -36,9 +36,9 @@ func periodicTransmitter(l *net.UDPConn, a *net.UDPAddr, m *coap.Message) {

func main() {
log.Fatal(coap.ListenAndServe("udp", ":5683",
coap.FuncHandler(func(l *net.UDPConn, a *net.UDPAddr, m *coap.Message) *coap.Message {
coap.FuncHandler(func(l *net.UDPConn, a *net.UDPAddr, m coap.Message) coap.Message {
log.Printf("Got message path=%q: %#v from %v", m.Path(), m, a)
if m.Code == coap.GET && m.Option(coap.Observe) != nil {
if m.Code() == coap.GET && m.Option(coap.Observe) != nil {
if value, ok := m.Option(coap.Observe).([]uint8); ok &&
len(value) >= 1 && value[0] == 1 {
go periodicTransmitter(l, a, m)
Expand Down
22 changes: 11 additions & 11 deletions example/server/coap_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@ import (
"log"
"net"

"github.com/dustin/go-coap"
"github.com/runtimeco/go-coap"
)

func handleA(l *net.UDPConn, a *net.UDPAddr, m *coap.Message) *coap.Message {
func handleA(l *net.UDPConn, a *net.UDPAddr, m coap.Message) coap.Message {
log.Printf("Got message in handleA: path=%q: %#v from %v", m.Path(), m, a)
if m.IsConfirmable() {
res := &coap.Message{
res := coap.NewDgramMessage(coap.MessageParams{
Type: coap.Acknowledgement,
Code: coap.Content,
MessageID: m.MessageID,
Token: m.Token,
MessageID: m.MessageID(),
Token: m.Token(),
Payload: []byte("hello to you!"),
}
})
res.SetOption(coap.ContentFormat, coap.TextPlain)

log.Printf("Transmitting from A %#v", res)
Expand All @@ -25,16 +25,16 @@ func handleA(l *net.UDPConn, a *net.UDPAddr, m *coap.Message) *coap.Message {
return nil
}

func handleB(l *net.UDPConn, a *net.UDPAddr, m *coap.Message) *coap.Message {
func handleB(l *net.UDPConn, a *net.UDPAddr, m coap.Message) coap.Message {
log.Printf("Got message in handleB: path=%q: %#v from %v", m.Path(), m, a)
if m.IsConfirmable() {
res := &coap.Message{
res := coap.NewDgramMessage(coap.MessageParams{
Type: coap.Acknowledgement,
Code: coap.Content,
MessageID: m.MessageID,
Token: m.Token,
MessageID: m.MessageID(),
Token: m.Token(),
Payload: []byte("good bye!"),
}
})
res.SetOption(coap.ContentFormat, coap.TextPlain)

log.Printf("Transmitting from B %#v", res)
Expand Down
Loading