7
7
package net
8
8
9
9
import (
10
+ "os"
10
11
"syscall"
11
12
"time"
12
13
)
@@ -48,6 +49,15 @@ func socket(net string, f, t, p int, ipv6only bool, laddr, raddr sockaddr, deadl
48
49
return nil , err
49
50
}
50
51
52
+ if fd , err = newFD (s , f , t , net ); err != nil {
53
+ closesocket (s )
54
+ return nil , err
55
+ }
56
+ if err := fd .init (); err != nil {
57
+ fd .Close ()
58
+ return nil , err
59
+ }
60
+
51
61
// This function makes a network file descriptor for stream
52
62
// and datagram dialers, stream and datagram listeners.
53
63
//
@@ -62,69 +72,115 @@ func socket(net string, f, t, p int, ipv6only bool, laddr, raddr sockaddr, deadl
62
72
// it's just for a listener or a datagram dialer when laddr is
63
73
// not nil but raddr is nil.
64
74
65
- var lsa syscall.Sockaddr
66
75
if laddr != nil && raddr == nil {
67
- // We provide a socket that listens to a wildcard
68
- // address with reusable UDP port when the given laddr
69
- // is an appropriate UDP multicast address prefix.
70
- // This makes it possible for a single UDP listener
71
- // to join multiple different group addresses, for
72
- // multiple UDP listeners that listen on the same UDP
73
- // port to join the same group address.
74
- if lsa , err = listenerSockaddr (s , f , laddr ); err != nil {
75
- closesocket (s )
76
- return nil , err
77
- }
78
- } else if laddr != nil && raddr != nil {
79
- if lsa , err = laddr .sockaddr (f ); err != nil {
80
- closesocket (s )
81
- return nil , err
76
+ switch t {
77
+ case syscall .SOCK_STREAM , syscall .SOCK_SEQPACKET :
78
+ if err := fd .listenStream (laddr , toAddr ); err != nil {
79
+ fd .Close ()
80
+ return nil , err
81
+ }
82
+ return fd , nil
83
+ case syscall .SOCK_DGRAM :
84
+ if err := fd .listenDatagram (laddr , toAddr ); err != nil {
85
+ fd .Close ()
86
+ return nil , err
87
+ }
88
+ return fd , nil
82
89
}
83
90
}
84
-
85
- if lsa != nil {
86
- if err = syscall .Bind (s , lsa ); err != nil {
87
- closesocket (s )
88
- return nil , err
89
- }
90
- }
91
-
92
- if fd , err = newFD (s , f , t , net ); err != nil {
93
- closesocket (s )
94
- return nil , err
95
- }
96
- if err := fd .init (); err != nil {
91
+ if err := fd .dial (laddr , raddr , deadline , toAddr ); err != nil {
97
92
fd .Close ()
98
93
return nil , err
99
94
}
95
+ return fd , nil
96
+ }
100
97
98
+ func (fd * netFD ) dial (laddr , raddr sockaddr , deadline time.Time , toAddr func (syscall.Sockaddr ) Addr ) error {
99
+ var err error
100
+ var lsa syscall.Sockaddr
101
+ if laddr != nil {
102
+ if lsa , err = laddr .sockaddr (fd .family ); err != nil {
103
+ return err
104
+ } else if lsa != nil {
105
+ if err := syscall .Bind (fd .sysfd , lsa ); err != nil {
106
+ return os .NewSyscallError ("bind" , err )
107
+ }
108
+ }
109
+ }
101
110
var rsa syscall.Sockaddr
102
111
if raddr != nil {
103
- rsa , err = raddr .sockaddr (f )
104
- if err != nil {
105
- return nil , err
112
+ if rsa , err = raddr .sockaddr (fd .family ); err != nil {
113
+ return err
114
+ } else if rsa != nil {
115
+ if ! deadline .IsZero () {
116
+ setWriteDeadline (fd , deadline )
117
+ }
118
+ if err := fd .connect (lsa , rsa ); err != nil {
119
+ return err
120
+ }
121
+ fd .isConnected = true
122
+ if ! deadline .IsZero () {
123
+ setWriteDeadline (fd , noDeadline )
124
+ }
106
125
}
107
126
}
127
+ lsa , _ = syscall .Getsockname (fd .sysfd )
128
+ if rsa , _ = syscall .Getpeername (fd .sysfd ); rsa != nil {
129
+ fd .setAddr (toAddr (lsa ), toAddr (rsa ))
130
+ } else {
131
+ fd .setAddr (toAddr (lsa ), raddr )
132
+ }
133
+ return nil
134
+ }
108
135
109
- if rsa != nil {
110
- if ! deadline .IsZero () {
111
- setWriteDeadline (fd , deadline )
112
- }
113
- if err = fd .connect (lsa , rsa ); err != nil {
114
- fd .Close ()
115
- return nil , err
116
- }
117
- fd .isConnected = true
118
- if ! deadline .IsZero () {
119
- setWriteDeadline (fd , noDeadline )
136
+ func (fd * netFD ) listenStream (laddr sockaddr , toAddr func (syscall.Sockaddr ) Addr ) error {
137
+ if err := setDefaultListenerSockopts (fd .sysfd ); err != nil {
138
+ return err
139
+ }
140
+ if lsa , err := laddr .sockaddr (fd .family ); err != nil {
141
+ return err
142
+ } else if lsa != nil {
143
+ if err := syscall .Bind (fd .sysfd , lsa ); err != nil {
144
+ return os .NewSyscallError ("bind" , err )
120
145
}
121
146
}
147
+ lsa , _ := syscall .Getsockname (fd .sysfd )
148
+ fd .setAddr (toAddr (lsa ), nil )
149
+ return nil
150
+ }
122
151
123
- lsa , _ = syscall .Getsockname (s )
124
- if rsa , _ = syscall .Getpeername (s ); rsa != nil {
125
- fd .setAddr (toAddr (lsa ), toAddr (rsa ))
126
- } else {
127
- fd .setAddr (toAddr (lsa ), raddr )
152
+ func (fd * netFD ) listenDatagram (laddr sockaddr , toAddr func (syscall.Sockaddr ) Addr ) error {
153
+ switch addr := laddr .(type ) {
154
+ case * UDPAddr :
155
+ // We provide a socket that listens to a wildcard
156
+ // address with reusable UDP port when the given laddr
157
+ // is an appropriate UDP multicast address prefix.
158
+ // This makes it possible for a single UDP listener to
159
+ // join multiple different group addresses, for
160
+ // multiple UDP listeners that listen on the same UDP
161
+ // port to join the same group address.
162
+ if addr .IP != nil && addr .IP .IsMulticast () {
163
+ if err := setDefaultMulticastSockopts (fd .sysfd ); err != nil {
164
+ return err
165
+ }
166
+ addr := * addr
167
+ switch fd .family {
168
+ case syscall .AF_INET :
169
+ addr .IP = IPv4zero
170
+ case syscall .AF_INET6 :
171
+ addr .IP = IPv6unspecified
172
+ }
173
+ laddr = & addr
174
+ }
128
175
}
129
- return fd , nil
176
+ if lsa , err := laddr .sockaddr (fd .family ); err != nil {
177
+ return err
178
+ } else if lsa != nil {
179
+ if err := syscall .Bind (fd .sysfd , lsa ); err != nil {
180
+ return os .NewSyscallError ("bind" , err )
181
+ }
182
+ }
183
+ lsa , _ := syscall .Getsockname (fd .sysfd )
184
+ fd .setAddr (toAddr (lsa ), nil )
185
+ return nil
130
186
}
0 commit comments