command/server: tcp listener
This commit is contained in:
parent
9d5db1286d
commit
61224ce312
|
@ -0,0 +1,25 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
)
|
||||
|
||||
// ListenerFactory is the factory function to create a listener.
|
||||
type ListenerFactory func(map[string]string) (net.Listener, error)
|
||||
|
||||
// BuiltinListeners is the list of built-in listener types.
|
||||
var BuiltinListeners = map[string]ListenerFactory{
|
||||
"tcp": tcpListenerFactory,
|
||||
}
|
||||
|
||||
// NewListener creates a new listener of the given type with the given
|
||||
// configuration. The type is looked up in the BuiltinListeners map.
|
||||
func NewListener(t string, config map[string]string) (net.Listener, error) {
|
||||
f, ok := BuiltinListeners[t]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unknown listener type: %s", t)
|
||||
}
|
||||
|
||||
return f(config)
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
)
|
||||
|
||||
func tcpListenerFactory(config map[string]string) (net.Listener, error) {
|
||||
addr, ok := config["address"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("'address' must be set")
|
||||
}
|
||||
|
||||
ln, err := net.Listen("tcp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ln, nil
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTCPListener(t *testing.T) {
|
||||
ln, err := tcpListenerFactory(map[string]string{
|
||||
"address": "127.0.0.1:0",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
connFn := func(lnReal net.Listener) (net.Conn, error) {
|
||||
return net.Dial("tcp", ln.Addr().String())
|
||||
}
|
||||
|
||||
testListenerImpl(t, ln, connFn)
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
type testListenerConnFn func(net.Listener) (net.Conn, error)
|
||||
|
||||
func testListenerImpl(t *testing.T, ln net.Listener, connFn testListenerConnFn) {
|
||||
serverCh := make(chan net.Conn, 1)
|
||||
go func() {
|
||||
server, err := ln.Accept()
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
serverCh <- server
|
||||
}()
|
||||
|
||||
client, err := connFn(ln)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
server := <-serverCh
|
||||
defer client.Close()
|
||||
defer server.Close()
|
||||
|
||||
var buf bytes.Buffer
|
||||
go io.Copy(&buf, server)
|
||||
|
||||
if _, err := client.Write([]byte("foo")); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
if buf.String() != "foo" {
|
||||
t.Fatalf("bad: %v", buf.String())
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue