package net cleanup
added ReadFrom/WriteTo for packet protocols like UDP.
simplified the net.Conn interface.
added new net.PacketConn interface for packet protocols.
implemented proper UDP listener.
cleaned up LocalAddr/RemoteAddr methods - cache in netFD.
threw away various unused methods.
an interface change:
introduced net.Addr as a network address interface,
to avoid conversion of UDP host:port to string and
back for every ReadFrom/WriteTo sequence.
another interface change:
since signature of Listener.Accept was changing anyway,
dropped the middle return value, because it is available
as c.RemoteAddr(). (the Accept signature predates the
existence of that method.)
Dial and Listen still accept strings, but the proto-specific
versions DialTCP, ListenUDP, etc. take net.Addr instead.
because the generic Dial didn't change and because
no one calls Accept directly (only indirectly via the http
server), very little code will be affected by these interface
changes.
design comments welcome.
R=p
CC=go-dev, r
http://go/go-review/1018017
diff --git a/src/pkg/net/net.go b/src/pkg/net/net.go
index 8669ed3..1532fc0 100644
--- a/src/pkg/net/net.go
+++ b/src/pkg/net/net.go
@@ -10,43 +10,32 @@
import "os"
-// Conn is a generic network connection.
+// Addr represents a network end point address.
+type Addr interface {
+ Network() string; // name of the network
+ String() string; // string form of address
+}
+
+// Conn is a generic stream-oriented network connection.
type Conn interface {
- // Read blocks until data is ready from the connection
- // and then reads into b. It returns the number
- // of bytes read, or 0 if the connection has been closed.
+ // Read reads data from the connection.
+ // Read can be made to time out and return err == os.EAGAIN
+ // after a fixed time limit; see SetTimeout and SetReadTimeout.
Read(b []byte) (n int, err os.Error);
- // Write writes the data in b to the connection.
+ // Write writes data to the connection.
+ // Write can be made to time out and return err == os.EAGAIN
+ // after a fixed time limit; see SetTimeout and SetReadTimeout.
Write(b []byte) (n int, err os.Error);
// Close closes the connection.
Close() os.Error;
// LocalAddr returns the local network address.
- LocalAddr() string;
+ LocalAddr() Addr;
// RemoteAddr returns the remote network address.
- RemoteAddr() string;
-
- // For packet-based protocols such as UDP,
- // ReadFrom reads the next packet from the network,
- // returning the number of bytes read and the remote
- // address that sent them.
- ReadFrom(b []byte) (n int, addr string, err os.Error);
-
- // For packet-based protocols such as UDP,
- // WriteTo writes the byte buffer b to the network
- // as a single payload, sending it to the target address.
- WriteTo(addr string, b []byte) (n int, err os.Error);
-
- // SetReadBuffer sets the size of the operating system's
- // receive buffer associated with the connection.
- SetReadBuffer(bytes int) os.Error;
-
- // SetReadBuffer sets the size of the operating system's
- // transmit buffer associated with the connection.
- SetWriteBuffer(bytes int) os.Error;
+ RemoteAddr() Addr;
// SetTimeout sets the read and write deadlines associated
// with the connection.
@@ -63,42 +52,53 @@
// Even if write times out, it may return n > 0, indicating that
// some of the data was successfully written.
SetWriteTimeout(nsec int64) os.Error;
-
- // SetLinger sets the behavior of Close() on a connection
- // which still has data waiting to be sent or to be acknowledged.
- //
- // If sec < 0 (the default), Close returns immediately and
- // the operating system finishes sending the data in the background.
- //
- // If sec == 0, Close returns immediately and the operating system
- // discards any unsent or unacknowledged data.
- //
- // If sec > 0, Close blocks for at most sec seconds waiting for
- // data to be sent and acknowledged.
- SetLinger(sec int) os.Error;
-
- // SetReuseAddr sets whether it is okay to reuse addresses
- // from recent connections that were not properly closed.
- SetReuseAddr(reuseaddr bool) os.Error;
-
- // SetDontRoute sets whether outgoing messages should
- // bypass the system routing tables.
- SetDontRoute(dontroute bool) os.Error;
-
- // SetKeepAlive sets whether the operating system should send
- // keepalive messages on the connection.
- SetKeepAlive(keepalive bool) os.Error;
-
- // BindToDevice binds a connection to a particular network device.
- BindToDevice(dev string) os.Error;
}
-// A Listener is a generic network listener.
+// PacketConn is a generic packet-oriented network connection.
+type PacketConn interface {
+ // ReadFrom reads a packet from the connection,
+ // copying the payload into b. It returns the number of
+ // bytes copied into b and the return address that
+ // was on the packet.
+ // ReadFrom can be made to time out and return err == os.EAGAIN
+ // after a fixed time limit; see SetTimeout and SetReadTimeout.
+ ReadFrom(b []byte) (n int, addr Addr, err os.Error);
+
+ // WriteTo writes a packet with payload b to addr.
+ // WriteTo can be made to time out and return err == os.EAGAIN
+ // after a fixed time limit; see SetTimeout and SetWriteTimeout.
+ // On packet-oriented connections, write timeouts are rare.
+ WriteTo(b []byte, addr Addr) (n int, err os.Error);
+
+ // Close closes the connection.
+ Close() os.Error;
+
+ // LocalAddr returns the local network address.
+ LocalAddr() Addr;
+
+ // SetTimeout sets the read and write deadlines associated
+ // with the connection.
+ SetTimeout(nsec int64) os.Error;
+
+ // SetReadTimeout sets the time (in nanoseconds) that
+ // Read will wait for data before returning os.EAGAIN.
+ // Setting nsec == 0 (the default) disables the deadline.
+ SetReadTimeout(nsec int64) os.Error;
+
+ // SetWriteTimeout sets the time (in nanoseconds) that
+ // Write will wait to send its data before returning os.EAGAIN.
+ // Setting nsec == 0 (the default) disables the deadline.
+ // Even if write times out, it may return n > 0, indicating that
+ // some of the data was successfully written.
+ SetWriteTimeout(nsec int64) os.Error;
+}
+
+// A Listener is a generic network listener for stream-oriented protocols.
// Accept waits for the next connection and Close closes the connection.
type Listener interface {
- Accept() (c Conn, raddr string, err os.Error);
+ Accept() (c Conn, err os.Error);
Close() os.Error;
- Addr() string; // Listener's network address
+ Addr() Addr; // Listener's network address
}
// Dial connects to the remote address raddr on the network net.
@@ -116,42 +116,116 @@
// Dial("tcp", "", "google.com:80")
// Dial("tcp", "", "[de:ad:be:ef::ca:fe]:80")
// Dial("tcp", "127.0.0.1:123", "127.0.0.1:88")
+//
func Dial(net, laddr, raddr string) (c Conn, err os.Error) {
switch net {
case "tcp", "tcp4", "tcp6":
- c, err := DialTCP(net, laddr, raddr);
- if err != nil {
- return nil, err
+ var la, ra *TCPAddr;
+ if laddr != "" {
+ if la, err = ResolveTCPAddr(laddr); err != nil {
+ goto Error;
+ }
}
- return c, nil;
+ if raddr != "" {
+ if ra, err = ResolveTCPAddr(raddr); err != nil {
+ goto Error;
+ }
+ }
+ return DialTCP(net, la, ra);
case "udp", "udp4", "upd6":
- c, err := DialUDP(net, laddr, raddr);
- return c, err;
- case "unix", "unix-dgram":
- c, err := DialUnix(net, laddr, raddr);
- return c, err;
+ var la, ra *UDPAddr;
+ if laddr != "" {
+ if la, err = ResolveUDPAddr(laddr); err != nil {
+ goto Error;
+ }
+ }
+ if raddr != "" {
+ if ra, err = ResolveUDPAddr(raddr); err != nil {
+ goto Error;
+ }
+ }
+ return DialUDP(net, la, ra);
+ case "unix", "unixgram":
+ var la, ra *UnixAddr;
+ if raddr != "" {
+ if ra, err = ResolveUnixAddr(net, raddr); err != nil {
+ goto Error;
+ }
+ }
+ if laddr != "" {
+ if la, err = ResolveUnixAddr(net, laddr); err != nil {
+ goto Error;
+ }
+ }
+ return DialUnix(net, la, ra);
}
- return nil, &OpError{"dial", net, raddr, UnknownNetworkError(net)};
+ err = UnknownNetworkError(net);
+Error:
+ return nil, &OpError{"dial", net+" "+raddr, nil, err};
}
// Listen announces on the local network address laddr.
-// The network string net must be "tcp", "tcp4", "tcp6",
-// "unix", or "unix-dgram".
+// The network string net must be a stream-oriented
+// network: "tcp", "tcp4", "tcp6", or "unix".
func Listen(net, laddr string) (l Listener, err os.Error) {
switch net {
case "tcp", "tcp4", "tcp6":
- l, err := ListenTCP(net, laddr);
+ var la *TCPAddr;
+ if laddr != "" {
+ if la, err = ResolveTCPAddr(laddr); err != nil {
+ return nil, err;
+ }
+ }
+ l, err := ListenTCP(net, la);
if err != nil {
return nil, err;
}
return l, nil;
- case "unix", "unix-dgram":
- l, err := ListenUnix(net, laddr);
+ case "unix":
+ var la *UnixAddr;
+ if laddr != "" {
+ if la, err = ResolveUnixAddr(net, laddr); err != nil {
+ return nil, err;
+ }
+ }
+ l, err := ListenUnix(net, la);
if err != nil {
return nil, err;
}
return l, nil;
- // BUG(rsc): Listen should support UDP.
+ }
+ return nil, UnknownNetworkError(net);
+}
+
+// ListenPacket announces on the local network address laddr.
+// The network string net must be a packet-oriented network:
+// "udp", "udp4", "udp6", or "unixgram".
+func ListenPacket(net, laddr string) (c PacketConn, err os.Error) {
+ switch net {
+ case "udp", "udp4", "udp6":
+ var la *UDPAddr;
+ if laddr != "" {
+ if la, err = ResolveUDPAddr(laddr); err != nil {
+ return nil, err;
+ }
+ }
+ c, err := ListenUDP(net, la);
+ if err != nil {
+ return nil, err;
+ }
+ return c, nil;
+ case "unixgram":
+ var la *UnixAddr;
+ if laddr != "" {
+ if la, err = ResolveUnixAddr(net, laddr); err != nil {
+ return nil, err;
+ }
+ }
+ c, err := DialUnix(net, la, nil);
+ if err != nil {
+ return nil, err;
+ }
+ return c, nil;
}
return nil, UnknownNetworkError(net);
}
@@ -161,7 +235,7 @@
type OpError struct {
Op string;
Net string;
- Addr string;
+ Addr Addr;
Error os.Error;
}
@@ -170,8 +244,8 @@
if e.Net != "" {
s += " " + e.Net;
}
- if e.Addr != "" {
- s += " " + e.Addr;
+ if e.Addr != nil {
+ s += " " + e.Addr.String();
}
s += ": " + e.Error.String();
return s;