Skip to content

Commit 028e48c

Browse files
committed
net: deduplicate raw IP socket code
This change consolidates functions and methods related to IPAddr and IPConn for maintenance purpose, especially for documentation. The followup changes will update comments and examples. Updates #10624. Change-Id: Ia5146f234225704a3c0b6459e1903e56a7b68134 Reviewed-on: https://go-review.googlesource.com/20124 TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 20de705 commit 028e48c

File tree

3 files changed

+163
-177
lines changed

3 files changed

+163
-177
lines changed

src/net/iprawsock.go

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
package net
66

7+
import "syscall"
8+
79
// IPAddr represents the address of an IP end point.
810
type IPAddr struct {
911
IP IP
@@ -60,3 +62,130 @@ func ResolveIPAddr(net, addr string) (*IPAddr, error) {
6062
}
6163
return addrs.first(isIPv4).(*IPAddr), nil
6264
}
65+
66+
// IPConn is the implementation of the Conn and PacketConn interfaces
67+
// for IP network connections.
68+
type IPConn struct {
69+
conn
70+
}
71+
72+
// ReadFromIP reads an IP packet from c, copying the payload into b.
73+
// It returns the number of bytes copied into b and the return address
74+
// that was on the packet.
75+
//
76+
// ReadFromIP can be made to time out and return an error with
77+
// Timeout() == true after a fixed time limit; see SetDeadline and
78+
// SetReadDeadline.
79+
func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) {
80+
if !c.ok() {
81+
return 0, nil, syscall.EINVAL
82+
}
83+
n, addr, err := c.readFrom(b)
84+
if err != nil {
85+
err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
86+
}
87+
return n, addr, err
88+
}
89+
90+
// ReadFrom implements the PacketConn ReadFrom method.
91+
func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
92+
if !c.ok() {
93+
return 0, nil, syscall.EINVAL
94+
}
95+
n, addr, err := c.readFrom(b)
96+
if err != nil {
97+
err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
98+
}
99+
if addr == nil {
100+
return n, nil, err
101+
}
102+
return n, addr, err
103+
}
104+
105+
// ReadMsgIP reads a packet from c, copying the payload into b and the
106+
// associated out-of-band data into oob. It returns the number of
107+
// bytes copied into b, the number of bytes copied into oob, the flags
108+
// that were set on the packet and the source address of the packet.
109+
func (c *IPConn) ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err error) {
110+
if !c.ok() {
111+
return 0, 0, 0, nil, syscall.EINVAL
112+
}
113+
n, oobn, flags, addr, err = c.readMsg(b, oob)
114+
if err != nil {
115+
err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
116+
}
117+
return
118+
}
119+
120+
// WriteToIP writes an IP packet to addr via c, copying the payload
121+
// from b.
122+
//
123+
// WriteToIP can be made to time out and return an error with
124+
// Timeout() == true after a fixed time limit; see SetDeadline and
125+
// SetWriteDeadline. On packet-oriented connections, write timeouts
126+
// are rare.
127+
func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) {
128+
if !c.ok() {
129+
return 0, syscall.EINVAL
130+
}
131+
n, err := c.writeTo(b, addr)
132+
if err != nil {
133+
err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
134+
}
135+
return n, err
136+
}
137+
138+
// WriteTo implements the PacketConn WriteTo method.
139+
func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) {
140+
if !c.ok() {
141+
return 0, syscall.EINVAL
142+
}
143+
a, ok := addr.(*IPAddr)
144+
if !ok {
145+
return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: syscall.EINVAL}
146+
}
147+
n, err := c.writeTo(b, a)
148+
if err != nil {
149+
err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: a.opAddr(), Err: err}
150+
}
151+
return n, err
152+
}
153+
154+
// WriteMsgIP writes a packet to addr via c, copying the payload from
155+
// b and the associated out-of-band data from oob. It returns the
156+
// number of payload and out-of-band bytes written.
157+
func (c *IPConn) WriteMsgIP(b, oob []byte, addr *IPAddr) (n, oobn int, err error) {
158+
if !c.ok() {
159+
return 0, 0, syscall.EINVAL
160+
}
161+
n, oobn, err = c.writeMsg(b, oob, addr)
162+
if err != nil {
163+
err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
164+
}
165+
return
166+
}
167+
168+
func newIPConn(fd *netFD) *IPConn { return &IPConn{conn{fd}} }
169+
170+
// DialIP connects to the remote address raddr on the network protocol
171+
// netProto, which must be "ip", "ip4", or "ip6" followed by a colon
172+
// and a protocol number or name.
173+
func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) {
174+
c, err := dialIP(netProto, laddr, raddr, noDeadline)
175+
if err != nil {
176+
return nil, &OpError{Op: "dial", Net: netProto, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: err}
177+
}
178+
return c, nil
179+
}
180+
181+
// ListenIP listens for incoming IP packets addressed to the local
182+
// address laddr. The returned connection's ReadFrom and WriteTo
183+
// methods can be used to receive and send IP packets with per-packet
184+
// addressing.
185+
func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
186+
c, err := listenIP(netProto, laddr)
187+
if err != nil {
188+
return nil, &OpError{Op: "listen", Net: netProto, Source: nil, Addr: laddr.opAddr(), Err: err}
189+
}
190+
return c, nil
191+
}

src/net/iprawsock_plan9.go

Lines changed: 11 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -9,74 +9,26 @@ import (
99
"time"
1010
)
1111

12-
// IPConn is the implementation of the Conn and PacketConn interfaces
13-
// for IP network connections.
14-
type IPConn struct {
15-
conn
12+
func (c *IPConn) readFrom(b []byte) (int, *IPAddr, error) {
13+
return 0, nil, syscall.EPLAN9
1614
}
1715

18-
// ReadFromIP reads an IP packet from c, copying the payload into b.
19-
// It returns the number of bytes copied into b and the return address
20-
// that was on the packet.
21-
//
22-
// ReadFromIP can be made to time out and return an error with
23-
// Timeout() == true after a fixed time limit; see SetDeadline and
24-
// SetReadDeadline.
25-
func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) {
26-
return 0, nil, &OpError{Op: "read", Net: c.fd.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: syscall.EPLAN9}
16+
func (c *IPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err error) {
17+
return 0, 0, 0, nil, syscall.EPLAN9
2718
}
2819

29-
// ReadFrom implements the PacketConn ReadFrom method.
30-
func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
31-
return 0, nil, &OpError{Op: "read", Net: c.fd.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: syscall.EPLAN9}
20+
func (c *IPConn) writeTo(b []byte, addr *IPAddr) (int, error) {
21+
return 0, syscall.EPLAN9
3222
}
3323

34-
// ReadMsgIP reads a packet from c, copying the payload into b and the
35-
// associated out-of-band data into oob. It returns the number of
36-
// bytes copied into b, the number of bytes copied into oob, the flags
37-
// that were set on the packet and the source address of the packet.
38-
func (c *IPConn) ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err error) {
39-
return 0, 0, 0, nil, &OpError{Op: "read", Net: c.fd.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: syscall.EPLAN9}
40-
}
41-
42-
// WriteToIP writes an IP packet to addr via c, copying the payload
43-
// from b.
44-
//
45-
// WriteToIP can be made to time out and return an error with
46-
// Timeout() == true after a fixed time limit; see SetDeadline and
47-
// SetWriteDeadline. On packet-oriented connections, write timeouts
48-
// are rare.
49-
func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) {
50-
return 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr.opAddr(), Err: syscall.EPLAN9}
51-
}
52-
53-
// WriteTo implements the PacketConn WriteTo method.
54-
func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) {
55-
return 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr, Err: syscall.EPLAN9}
56-
}
57-
58-
// WriteMsgIP writes a packet to addr via c, copying the payload from
59-
// b and the associated out-of-band data from oob. It returns the
60-
// number of payload and out-of-band bytes written.
61-
func (c *IPConn) WriteMsgIP(b, oob []byte, addr *IPAddr) (n, oobn int, err error) {
62-
return 0, 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr.opAddr(), Err: syscall.EPLAN9}
63-
}
64-
65-
// DialIP connects to the remote address raddr on the network protocol
66-
// netProto, which must be "ip", "ip4", or "ip6" followed by a colon
67-
// and a protocol number or name.
68-
func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) {
69-
return dialIP(netProto, laddr, raddr, noDeadline)
24+
func (c *IPConn) writeMsg(b, oob []byte, addr *IPAddr) (n, oobn int, err error) {
25+
return 0, 0, syscall.EPLAN9
7026
}
7127

7228
func dialIP(netProto string, laddr, raddr *IPAddr, deadline time.Time) (*IPConn, error) {
73-
return nil, &OpError{Op: "dial", Net: netProto, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: syscall.EPLAN9}
29+
return nil, syscall.EPLAN9
7430
}
7531

76-
// ListenIP listens for incoming IP packets addressed to the local
77-
// address laddr. The returned connection's ReadFrom and WriteTo
78-
// methods can be used to receive and send IP packets with per-packet
79-
// addressing.
80-
func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
81-
return nil, &OpError{Op: "listen", Net: netProto, Source: nil, Addr: laddr.opAddr(), Err: syscall.EPLAN9}
32+
func listenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
33+
return nil, syscall.EPLAN9
8234
}

0 commit comments

Comments
 (0)