summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrea Barberio <insomniac@slackware.it>2019-04-17 00:03:45 +0100
committerinsomniac <insomniacslk@users.noreply.github.com>2019-04-17 11:38:11 +0100
commitbbe0e65b24bf53191fc56b67d0d98624030e3d26 (patch)
treed2c009516c5f86b1a44b6c566602e2714e81919b
parentac4db3f5fb61a34cf65d81fb4efe6e3d2627b461 (diff)
[server] Serve returns an error, and closes when done
Server6 and Server4 had Serve methods that return without reporting an error, changed in this PR. Serve now also closes the connection when done. Signed-off-by: Andrea Barberio <insomniac@slackware.it>
-rw-r--r--dhcpv4/server4/server.go34
-rw-r--r--dhcpv6/server6/server.go58
2 files changed, 75 insertions, 17 deletions
diff --git a/dhcpv4/server4/server.go b/dhcpv4/server4/server.go
index 1ccd5f4..3a2aee0 100644
--- a/dhcpv4/server4/server.go
+++ b/dhcpv4/server4/server.go
@@ -3,24 +3,27 @@ package server4
import (
"log"
"net"
- "sync"
"github.com/insomniacslk/dhcp/dhcpv4"
)
/*
To use the DHCPv4 server code you have to call NewServer with two arguments:
+ - an address to listen on, and
- a handler function, that will be called every time a valid DHCPv4 packet is
- received, and
- - an address to listen on.
+ received.
+
+ The address to listen on is used to know IP address, port and optionally the
+ scope to create and UDP socket to listen on for DHCPv4 traffic.
The handler is a function that takes as input a packet connection, that can be
used to reply to the client; a peer address, that identifies the client sending
the request, and the DHCPv4 packet itself. Just implement your custom logic in
the handler.
- The address to listen on is used to know IP address, port and optionally the
- scope to create and UDP socket to listen on for DHCPv4 traffic.
+ Optionally, NewServer can receive options that will modify the server object.
+ Some options already exist, for example WithConn. If this option is passed with
+ a valid connection, the listening address argument is ignored.
Example program:
@@ -32,6 +35,7 @@ import (
"net"
"github.com/insomniacslk/dhcp/dhcpv4"
+ "github.com/insomniacslk/dhcp/dhcpv4/server4"
)
func handler(conn net.PacketConn, peer net.Addr, m *dhcpv4.DHCPv4) {
@@ -44,7 +48,7 @@ func main() {
IP: net.ParseIP("127.0.0.1"),
Port: 67,
}
- server, err := dhcpv4.NewServer(laddr, handler)
+ server, err := server4.NewServer(&laddr, handler)
if err != nil {
log.Fatal(err)
}
@@ -62,22 +66,22 @@ type Handler func(conn net.PacketConn, peer net.Addr, m *dhcpv4.DHCPv4)
// Server represents a DHCPv4 server object
type Server struct {
- conn net.PacketConn
- connMutex sync.Mutex
- shouldStop chan bool
- Handler Handler
+ conn net.PacketConn
+ Handler Handler
}
// Serve serves requests.
-func (s *Server) Serve() {
+func (s *Server) Serve() error {
log.Printf("Server listening on %s", s.conn.LocalAddr())
log.Print("Ready to handle requests")
+
+ defer s.Close()
for {
rbuf := make([]byte, 4096) // FIXME this is bad
n, peer, err := s.conn.ReadFrom(rbuf)
if err != nil {
log.Printf("Error reading from packet conn: %v", err)
- return
+ return err
}
log.Printf("Handling request from %v", peer)
@@ -108,8 +112,7 @@ func WithConn(c net.PacketConn) ServerOpt {
// NewServer initializes and returns a new Server object
func NewServer(addr *net.UDPAddr, handler Handler, opt ...ServerOpt) (*Server, error) {
s := &Server{
- Handler: handler,
- shouldStop: make(chan bool, 1),
+ Handler: handler,
}
for _, o := range opt {
@@ -117,10 +120,11 @@ func NewServer(addr *net.UDPAddr, handler Handler, opt ...ServerOpt) (*Server, e
}
if s.conn == nil {
var err error
- s.conn, err = net.ListenUDP("udp4", addr)
+ conn, err := net.ListenUDP("udp4", addr)
if err != nil {
return nil, err
}
+ s.conn = conn
}
return s, nil
}
diff --git a/dhcpv6/server6/server.go b/dhcpv6/server6/server.go
index f6fb826..e4fcf91 100644
--- a/dhcpv6/server6/server.go
+++ b/dhcpv6/server6/server.go
@@ -1,5 +1,58 @@
package server6
+/*
+ To use the DHCPv6 server code you have to call NewServer with two arguments:
+ - an address to listen on, and
+ - a handler function, that will be called every time a valid DHCPv6 packet is
+ received.
+
+ The address to listen on is used to know IP address, port and optionally the
+ scope to create and UDP socket to listen on for DHCPv6 traffic.
+
+ The handler is a function that takes as input a packet connection, that can be
+ used to reply to the client; a peer address, that identifies the client sending
+ the request, and the DHCPv6 packet itself. Just implement your custom logic in
+ the handler.
+
+ Optionally, NewServer can receive options that will modify the server object.
+ Some options already exist, for example WithConn. If this option is passed with
+ a valid connection, the listening address argument is ignored.
+
+ Example program:
+
+
+package main
+
+import (
+ "log"
+ "net"
+
+ "github.com/insomniacslk/dhcp/dhcpv6"
+ "github.com/insomniacslk/dhcp/dhcpv6/server6"
+)
+
+func handler(conn net.PacketConn, peer net.Addr, m dhcpv6.DHCPv6) {
+ // this function will just print the received DHCPv6 message, without replying
+ log.Print(m.Summary())
+}
+
+func main() {
+ laddr := net.UDPAddr{
+ IP: net.ParseIP("::1"),
+ Port: 547,
+ }
+ server, err := server6.NewServer(&laddr, handler)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // This never returns. If you want to do other stuff, dump it into a
+ // goroutine.
+ server.Serve()
+}
+
+*/
+
import (
"log"
"net"
@@ -19,16 +72,17 @@ type Server struct {
// Serve starts the DHCPv6 server. The listener will run in background, and can
// be interrupted with `Server.Close`.
-func (s *Server) Serve() {
+func (s *Server) Serve() error {
log.Printf("Server listening on %s", s.conn.LocalAddr())
log.Print("Ready to handle requests")
+ defer s.Close()
for {
rbuf := make([]byte, 4096) // FIXME this is bad
n, peer, err := s.conn.ReadFrom(rbuf)
if err != nil {
log.Printf("Error reading from packet conn: %v", err)
- return
+ return err
}
log.Printf("Handling request from %v", peer)