Commit 6a360785 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 827ad6d3
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
// //
// See COPYING file for full licensing terms. // See COPYING file for full licensing terms.
// Package pipenet provides all-in-memory network of net.Pipes // Package pipenet provides in-memory network of net.Pipes
// //
// TODO describe addressing scheme // TODO describe addressing scheme
// //
...@@ -28,48 +28,54 @@ import ( ...@@ -28,48 +28,54 @@ import (
"net" "net"
) )
//const Network = "pipe" // pipenet packages handles only this network const NetPrefix = "pipe" // pipenet package works only with "pipe*" networks
var errBadNetwork = errors.New("invalid network") var errNetNotFound = errors.New("no such network")
//var errBadNetwork = errors.New("invalid network")
var errBadAddress = errors.New("invalid address") var errBadAddress = errors.New("invalid address")
var errAddrAlreadyUsed = errors.New("address already in use") var errAddrAlreadyUsed = errors.New("address already in use")
var errConnRefused = errors.New("connection refused") var errConnRefused = errors.New("connection refused")
// Network represents network of in memory pipes // Network represents network of in-memory pipes
// It can be worked with the same way a regular TCP network is handled with Dial/Listen/Accept/... // It can be worked with the same way a regular TCP network is handled with Dial/Listen/Accept/...
//
// Network must be created with New
type Network struct { type Network struct {
Name string // name of this network, e.g. "pipe" // name (suffix) of this network, e.g. ""
// full network name will be reported as "pipe"+Name
Name string
mu sync.Mutex mu sync.Mutex
pipev []... // port -> listener + net.Pipe (?) pipev []pipe // port -> listener + net.Pipe (?)
// listenv []chan dialReq // listener[port] is waiting here if != nil // listenv []chan dialReq // listener[port] is waiting here if != nil
} }
// pipe represents one pipenet connection
// it can be either already connected (2 endpoints) or only listening (1 endpoint) XXX
type pipe struct {
// TODO
}
// Addr represents address of a pipe endpoint // Addr represents address of a pipe endpoint
type Addr { type Addr struct {
network *Network network *Network
addr string // XXX -> port ? + including c/s ? addr string // XXX -> port ? + including c/s ?
} }
var _ net.Addr = (*Addr)nil var _ net.Addr = (*Addr)(nil)
func (a *Addr) Network() string { return Network } func (a *Addr) Network() string { return a.network.netname() }
func (a *Addr) String() string { return a.addr } func (a *Addr) String() string { return a.addr } // XXX Network() + ":" + a.addr ?
func (n *Network) netname() string { return NetPrefix + n.Name }
// XXX do we need Conn wrapping net.Pipe ? (e.g. to override String()) // XXX do we need Conn wrapping net.Pipe ? (e.g. to override String())
func (n *Network) Listen(laddr string) (net.Listener, error) {
func (n *Network) Listen(network, laddr string) (net.Listener, error) {
lerr := func(err error) error { lerr := func(err error) error {
return &net.OpError{Op: "listen", Net: network, Addr: laddr, Err: err} return &net.OpError{Op: "listen", Net: n.netname(), Addr: laddr, Err: err}
}
if network != n.Name {
return lerr(errBadNetwork)
} }
// laddr must be empty or int >= 0 // laddr must be empty or int >= 0
...@@ -155,10 +161,6 @@ func (n *Network) Dial(network, addr string) (net.Conn, error) { ...@@ -155,10 +161,6 @@ func (n *Network) Dial(network, addr string) (net.Conn, error) {
return &net.OpError{Op: "dial", Net: network, Addr: addr, Err: err} return &net.OpError{Op: "dial", Net: network, Addr: addr, Err: err}
} }
if network != n.Name {
return derr(errBadNetwork)
}
port, err := strconv.Atoi(addr) port, err := strconv.Atoi(addr)
if err != nil || port < 0 { if err != nil || port < 0 {
return derr(errBadAddress) return derr(errBadAddress)
...@@ -192,12 +194,56 @@ func (n *Network) Dial(network, addr string) (net.Conn, error) { ...@@ -192,12 +194,56 @@ func (n *Network) Dial(network, addr string) (net.Conn, error) {
// ---------------------------------------- // ----------------------------------------
var DefaultNet = Network{Name: "pipe"}
func Dial(netw, addr string) (net.Conn, error) { var (
return DefaultNet.Dial(netw, addr) netMu sync.Mutex
networks = map[string]*Network{} // netsuffix -> Network
DefaultNet = New("")
)
// New creates, initializes and returns new pipenet Network
// network name must be unique - if not New will panic
func New(name string) *Network {
netMu.Lock()
defer netMu.Unlock()
_, already := networks[name]
if already {
panic(fmt.Errorf("pipenet %v already registered", name)
}
n := &Network{Name: name}
networks[name] = n
return n
}
// lookupNet lookups Network by name
// returns nil, if not found
func lookupNet(name string) *Network {
netMu.Lock()
defer netMu.Unlock()
return networks[name]
} }
func Listen(netw, laddr string) (net.Listen, error) { // Dial dials addr on a pipenet
return DefaultNet.Listen(netw, laddr) // network should be valid registered pipe network name
func Dial(network, addr string) (net.Conn, error) {
n := lookupNet(network)
if n == nil {
return nil, &net.OpError{Op: "dial", Net: NetPrefix + network, Addr: addr, Err: err}
}
return n.Dial(addr)
}
// XXX text
func Listen(network, laddr string) (net.Listen, error) {
n := lookupNet(network)
if n == nil {
return nil, &net.OpError{Op: "listen", Net: NetPrefix + network, Addr: addr, Err: err}
}
return n.Listen(netw, laddr)
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment