LEFT | RIGHT |
1 // Copyright 2010 The Go Authors. All rights reserved. | 1 // Copyright 2010 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package net | 5 package net |
6 | 6 |
7 import ( | 7 import ( |
8 "errors" | 8 "errors" |
9 "io" | 9 "io" |
10 "os" | 10 "os" |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 // implementation of DialTimeout. | 60 // implementation of DialTimeout. |
61 return resolveAndDialChannel(net, addr, localAddr, deadline) | 61 return resolveAndDialChannel(net, addr, localAddr, deadline) |
62 } | 62 } |
63 ra, err := resolveAddr("dial", net, addr, deadline) | 63 ra, err := resolveAddr("dial", net, addr, deadline) |
64 if err != nil { | 64 if err != nil { |
65 return nil, err | 65 return nil, err |
66 } | 66 } |
67 return dial(net, addr, localAddr, ra, deadline) | 67 return dial(net, addr, localAddr, ra, deadline) |
68 } | 68 } |
69 | 69 |
70 // Interface for all IO operations. | 70 // operation contains superset of data necessary to perform all async IO. |
71 type anOpIface interface { | 71 type operation struct { |
72 » Op() *anOp | |
73 » Name() string | |
74 » Submit() error | |
75 } | |
76 | |
77 // anOp implements functionality common to all IO operations. | |
78 // Its beginning must be the same as runtime.net_anOp. Keep these in sync. | |
79 type anOp struct { | |
80 // Used by IOCP interface, it must be first field | 72 // Used by IOCP interface, it must be first field |
81 // of the struct, as our code rely on it. | 73 // of the struct, as our code rely on it. |
82 o syscall.Overlapped | 74 o syscall.Overlapped |
83 | 75 |
84 // fields used by runtime.netpoll | 76 // fields used by runtime.netpoll |
85 runtimeCtx uintptr | 77 runtimeCtx uintptr |
86 mode int32 | 78 mode int32 |
87 errno int32 | 79 errno int32 |
88 qty uint32 | 80 qty uint32 |
89 | 81 |
90 » errnoc chan error | 82 » // fields used only by net package |
| 83 » mu sync.Mutex |
91 fd *netFD | 84 fd *netFD |
92 } | 85 » errc chan error |
93 | 86 » buf syscall.WSABuf |
94 func (o *anOp) Init(fd *netFD, mode int32) { | 87 » sa syscall.Sockaddr |
95 » o.fd = fd | 88 » rsa *syscall.RawSockaddrAny |
96 » o.mode = mode | 89 » rsan int32 |
97 » o.runtimeCtx = fd.pd.runtimeCtx | 90 » handle syscall.Handle |
98 » if !canCancelIO { | 91 » flags uint32 |
99 » » var i int | 92 } |
100 » » if mode == 'r' { | 93 |
101 » » » i = 0 | 94 func (o *operation) InitBuf(buf []byte) { |
102 » » } else { | |
103 » » » i = 1 | |
104 » » } | |
105 » » if fd.errnoc[i] == nil { | |
106 » » » fd.errnoc[i] = make(chan error) | |
107 » » } | |
108 » » o.errnoc = fd.errnoc[i] | |
109 » } | |
110 } | |
111 | |
112 func (o *anOp) Op() *anOp { | |
113 » return o | |
114 } | |
115 | |
116 // bufOp is used by IO operations that read / write | |
117 // data from / to client buffer. | |
118 type bufOp struct { | |
119 » anOp | |
120 » buf syscall.WSABuf | |
121 } | |
122 | |
123 func (o *bufOp) Init(fd *netFD, buf []byte, mode int32) { | |
124 » o.anOp.Init(fd, mode) | |
125 o.buf.Len = uint32(len(buf)) | 95 o.buf.Len = uint32(len(buf)) |
126 » if len(buf) == 0 { | 96 » o.buf.Buf = nil |
127 » » o.buf.Buf = nil | 97 » if len(buf) != 0 { |
128 » } else { | |
129 o.buf.Buf = (*byte)(unsafe.Pointer(&buf[0])) | 98 o.buf.Buf = (*byte)(unsafe.Pointer(&buf[0])) |
130 } | 99 } |
131 } | 100 } |
132 | 101 |
133 // ioSrv executes net IO requests. | 102 // ioSrv executes net IO requests. |
134 type ioSrv struct { | 103 type ioSrv struct { |
135 » submchan chan anOpIface // submit IO requests | 104 » req chan ioSrvReq |
136 » canchan chan anOpIface // cancel IO requests | 105 } |
| 106 |
| 107 type ioSrvReq struct { |
| 108 » o *operation |
| 109 » submit func(o *operation) error // if nil, cancel the operation |
137 } | 110 } |
138 | 111 |
139 // ProcessRemoteIO will execute submit IO requests on behalf | 112 // ProcessRemoteIO will execute submit IO requests on behalf |
140 // of other goroutines, all on a single os thread, so it can | 113 // of other goroutines, all on a single os thread, so it can |
141 // cancel them later. Results of all operations will be sent | 114 // cancel them later. Results of all operations will be sent |
142 // back to their requesters via channel supplied in request. | 115 // back to their requesters via channel supplied in request. |
143 // It is used only when the CancelIoEx API is unavailable. | 116 // It is used only when the CancelIoEx API is unavailable. |
144 func (s *ioSrv) ProcessRemoteIO() { | 117 func (s *ioSrv) ProcessRemoteIO() { |
145 runtime.LockOSThread() | 118 runtime.LockOSThread() |
146 defer runtime.UnlockOSThread() | 119 defer runtime.UnlockOSThread() |
147 » for { | 120 » for r := range s.req { |
148 » » select { | 121 » » if r.submit != nil { |
149 » » case o := <-s.submchan: | 122 » » » r.o.errc <- r.submit(r.o) |
150 » » » o.Op().errnoc <- o.Submit() | 123 » » } else { |
151 » » case o := <-s.canchan: | 124 » » » r.o.errc <- syscall.CancelIo(r.o.fd.sysfd) |
152 » » » o.Op().errnoc <- syscall.CancelIo(syscall.Handle(o.Op().
fd.sysfd)) | 125 » » } |
153 » » } | 126 » } |
154 » } | 127 } |
155 } | 128 |
156 | 129 // ExecIO executes a single IO operation o. It submits and cancels |
157 // ExecIO executes a single IO operation oi. It submits and cancels | |
158 // IO in the current thread for systems where Windows CancelIoEx API | 130 // IO in the current thread for systems where Windows CancelIoEx API |
159 // is available. Alternatively, it passes the request onto | 131 // is available. Alternatively, it passes the request onto |
160 // runtime netpoll and waits for completion or cancels request. | 132 // runtime netpoll and waits for completion or cancels request. |
161 func (s *ioSrv) ExecIO(oi anOpIface) (int, error) { | 133 func (s *ioSrv) ExecIO(o *operation, name string, submit func(o *operation) erro
r) (int, error) { |
162 » var err error | 134 » fd := o.fd |
163 » o := oi.Op() | |
164 // Notify runtime netpoll about starting IO. | 135 // Notify runtime netpoll about starting IO. |
165 » err = o.fd.pd.Prepare(int(o.mode)) | 136 » err := fd.pd.Prepare(int(o.mode)) |
166 » if err != nil { | 137 » if err != nil { |
167 » » return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, err} | 138 » » return 0, &OpError{name, fd.net, fd.laddr, err} |
168 } | 139 } |
169 // Start IO. | 140 // Start IO. |
170 if canCancelIO { | 141 if canCancelIO { |
171 » » err = oi.Submit() | 142 » » err = submit(o) |
172 } else { | 143 } else { |
173 // Send request to a special dedicated thread, | 144 // Send request to a special dedicated thread, |
174 // so it can stop the IO with CancelIO later. | 145 // so it can stop the IO with CancelIO later. |
175 » » s.submchan <- oi | 146 » » s.req <- ioSrvReq{o, submit} |
176 » » err = <-o.errnoc | 147 » » err = <-o.errc |
177 } | 148 } |
178 switch err { | 149 switch err { |
179 case nil: | 150 case nil: |
180 // IO completed immediately, but we need to get our completion m
essage anyway. | 151 // IO completed immediately, but we need to get our completion m
essage anyway. |
181 case syscall.ERROR_IO_PENDING: | 152 case syscall.ERROR_IO_PENDING: |
182 // IO started, and we have to wait for its completion. | 153 // IO started, and we have to wait for its completion. |
183 err = nil | 154 err = nil |
184 default: | 155 default: |
185 » » return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, err} | 156 » » return 0, &OpError{name, fd.net, fd.laddr, err} |
186 } | 157 } |
187 // Wait for our request to complete. | 158 // Wait for our request to complete. |
188 » err = o.fd.pd.Wait(int(o.mode)) | 159 » err = fd.pd.Wait(int(o.mode)) |
189 if err == nil { | 160 if err == nil { |
190 // All is good. Extract our IO results and return. | 161 // All is good. Extract our IO results and return. |
191 if o.errno != 0 { | 162 if o.errno != 0 { |
192 err = syscall.Errno(o.errno) | 163 err = syscall.Errno(o.errno) |
193 » » » return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, err} | 164 » » » return 0, &OpError{name, fd.net, fd.laddr, err} |
194 } | 165 } |
195 return int(o.qty), nil | 166 return int(o.qty), nil |
196 } | 167 } |
197 // IO is interrupted by "close" or "timeout" | 168 // IO is interrupted by "close" or "timeout" |
198 netpollErr := err | 169 netpollErr := err |
199 switch netpollErr { | 170 switch netpollErr { |
200 case errClosing, errTimeout: | 171 case errClosing, errTimeout: |
201 // will deal with those. | 172 // will deal with those. |
202 default: | 173 default: |
203 panic("net: unexpected runtime.netpoll error: " + netpollErr.Err
or()) | 174 panic("net: unexpected runtime.netpoll error: " + netpollErr.Err
or()) |
204 } | 175 } |
205 // Cancel our request. | 176 // Cancel our request. |
206 if canCancelIO { | 177 if canCancelIO { |
207 » » err := syscall.CancelIoEx(syscall.Handle(o.Op().fd.sysfd), &o.o) | 178 » » err := syscall.CancelIoEx(fd.sysfd, &o.o) |
208 // Assuming ERROR_NOT_FOUND is returned, if IO is completed. | 179 // Assuming ERROR_NOT_FOUND is returned, if IO is completed. |
209 if err != nil && err != syscall.ERROR_NOT_FOUND { | 180 if err != nil && err != syscall.ERROR_NOT_FOUND { |
210 // TODO(brainman): maybe do something else, but panic. | 181 // TODO(brainman): maybe do something else, but panic. |
211 panic(err) | 182 panic(err) |
212 } | 183 } |
213 } else { | 184 } else { |
214 » » s.canchan <- oi | 185 » » s.req <- ioSrvReq{o, nil} |
215 » » <-o.errnoc | 186 » » <-o.errc |
216 } | 187 } |
217 // Wait for cancellation to complete. | 188 // Wait for cancellation to complete. |
218 » o.fd.pd.WaitCanceled(int(o.mode)) | 189 » fd.pd.WaitCanceled(int(o.mode)) |
219 if o.errno != 0 { | 190 if o.errno != 0 { |
220 err = syscall.Errno(o.errno) | 191 err = syscall.Errno(o.errno) |
221 if err == syscall.ERROR_OPERATION_ABORTED { // IO Canceled | 192 if err == syscall.ERROR_OPERATION_ABORTED { // IO Canceled |
222 err = netpollErr | 193 err = netpollErr |
223 } | 194 } |
224 » » return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, err} | 195 » » return 0, &OpError{name, fd.net, fd.laddr, err} |
225 } | 196 } |
226 // We issued cancellation request. But, it seems, IO operation succeeded | 197 // We issued cancellation request. But, it seems, IO operation succeeded |
227 // before cancellation request run. We need to treat IO operation as | 198 // before cancellation request run. We need to treat IO operation as |
228 // succeeded (the bytes are actually sent/recv from network). | 199 // succeeded (the bytes are actually sent/recv from network). |
229 return int(o.qty), nil | 200 return int(o.qty), nil |
230 } | 201 } |
231 | 202 |
232 // Start helper goroutines. | 203 // Start helper goroutines. |
233 var iosrv *ioSrv | 204 var iosrv *ioSrv |
234 var onceStartServer sync.Once | 205 var onceStartServer sync.Once |
235 | 206 |
236 func startServer() { | 207 func startServer() { |
237 iosrv = new(ioSrv) | 208 iosrv = new(ioSrv) |
238 if !canCancelIO { | 209 if !canCancelIO { |
239 // Only CancelIo API is available. Lets start special goroutine | 210 // Only CancelIo API is available. Lets start special goroutine |
240 // locked to an OS thread, that both starts and cancels IO. | 211 // locked to an OS thread, that both starts and cancels IO. |
241 » » iosrv.submchan = make(chan anOpIface) | 212 » » iosrv.req = make(chan ioSrvReq) |
242 » » iosrv.canchan = make(chan anOpIface) | |
243 go iosrv.ProcessRemoteIO() | 213 go iosrv.ProcessRemoteIO() |
244 } | 214 } |
245 } | 215 } |
246 | 216 |
247 // Network file descriptor. | 217 // Network file descriptor. |
248 type netFD struct { | 218 type netFD struct { |
249 // locking/lifetime of sysfd | 219 // locking/lifetime of sysfd |
250 sysmu sync.Mutex | 220 sysmu sync.Mutex |
251 sysref int | 221 sysref int |
252 closing bool | 222 closing bool |
253 | 223 |
254 // immutable until Close | 224 // immutable until Close |
255 sysfd syscall.Handle | 225 sysfd syscall.Handle |
256 family int | 226 family int |
257 sotype int | 227 sotype int |
258 isConnected bool | 228 isConnected bool |
259 net string | 229 net string |
260 laddr Addr | 230 laddr Addr |
261 raddr Addr | 231 raddr Addr |
262 » errnoc [2]chan error // read/write submit or cancel operation error
s | 232 |
263 | 233 » rop operation // read operation |
264 » // serialize access to Read and Write methods | 234 » wop operation // write operation |
265 » rio, wio sync.Mutex | |
266 | 235 |
267 // wait server | 236 // wait server |
268 pd pollDesc | 237 pd pollDesc |
269 } | 238 } |
270 | 239 |
271 func newFD(sysfd syscall.Handle, family, sotype int, net string) (*netFD, error)
{ | 240 func newFD(sysfd syscall.Handle, family, sotype int, net string) (*netFD, error)
{ |
272 if initErr != nil { | 241 if initErr != nil { |
273 return nil, initErr | 242 return nil, initErr |
274 } | 243 } |
275 onceStartServer.Do(startServer) | 244 onceStartServer.Do(startServer) |
276 return &netFD{sysfd: sysfd, family: family, sotype: sotype, net: net}, n
il | 245 return &netFD{sysfd: sysfd, family: family, sotype: sotype, net: net}, n
il |
277 } | 246 } |
278 | 247 |
279 func (fd *netFD) init() error { | 248 func (fd *netFD) init() error { |
280 if err := fd.pd.Init(fd); err != nil { | 249 if err := fd.pd.Init(fd); err != nil { |
281 return err | 250 return err |
| 251 } |
| 252 fd.rop.mode = 'r' |
| 253 fd.wop.mode = 'w' |
| 254 fd.rop.fd = fd |
| 255 fd.wop.fd = fd |
| 256 fd.rop.runtimeCtx = fd.pd.runtimeCtx |
| 257 fd.wop.runtimeCtx = fd.pd.runtimeCtx |
| 258 if !canCancelIO { |
| 259 fd.rop.errc = make(chan error) |
| 260 fd.rop.errc = make(chan error) |
282 } | 261 } |
283 return nil | 262 return nil |
284 } | 263 } |
285 | 264 |
286 func (fd *netFD) setAddr(laddr, raddr Addr) { | 265 func (fd *netFD) setAddr(laddr, raddr Addr) { |
287 fd.laddr = laddr | 266 fd.laddr = laddr |
288 fd.raddr = raddr | 267 fd.raddr = raddr |
289 runtime.SetFinalizer(fd, (*netFD).Close) | 268 runtime.SetFinalizer(fd, (*netFD).Close) |
290 } | |
291 | |
292 // Make new connection. | |
293 | |
294 type connectOp struct { | |
295 anOp | |
296 ra syscall.Sockaddr | |
297 } | |
298 | |
299 func (o *connectOp) Submit() error { | |
300 return syscall.ConnectEx(o.fd.sysfd, o.ra, nil, 0, nil, &o.o) | |
301 } | |
302 | |
303 func (o *connectOp) Name() string { | |
304 return "ConnectEx" | |
305 } | 269 } |
306 | 270 |
307 func (fd *netFD) connect(la, ra syscall.Sockaddr) error { | 271 func (fd *netFD) connect(la, ra syscall.Sockaddr) error { |
308 if !canUseConnectEx(fd.net) { | 272 if !canUseConnectEx(fd.net) { |
309 return syscall.Connect(fd.sysfd, ra) | 273 return syscall.Connect(fd.sysfd, ra) |
310 } | 274 } |
311 // ConnectEx windows API requires an unconnected, previously bound socke
t. | 275 // ConnectEx windows API requires an unconnected, previously bound socke
t. |
312 if la == nil { | 276 if la == nil { |
313 switch ra.(type) { | 277 switch ra.(type) { |
314 case *syscall.SockaddrInet4: | 278 case *syscall.SockaddrInet4: |
315 la = &syscall.SockaddrInet4{} | 279 la = &syscall.SockaddrInet4{} |
316 case *syscall.SockaddrInet6: | 280 case *syscall.SockaddrInet6: |
317 la = &syscall.SockaddrInet6{} | 281 la = &syscall.SockaddrInet6{} |
318 default: | 282 default: |
319 panic("unexpected type in connect") | 283 panic("unexpected type in connect") |
320 } | 284 } |
321 if err := syscall.Bind(fd.sysfd, la); err != nil { | 285 if err := syscall.Bind(fd.sysfd, la); err != nil { |
322 return err | 286 return err |
323 } | 287 } |
324 } | 288 } |
325 // Call ConnectEx API. | 289 // Call ConnectEx API. |
326 » var o connectOp | 290 » o := &fd.wop |
327 » o.Init(fd, 'w') | 291 » o.mu.Lock() |
328 » o.ra = ra | 292 » defer o.mu.Unlock() |
329 » _, err := iosrv.ExecIO(&o) | 293 » o.sa = ra |
| 294 » _, err := iosrv.ExecIO(o, "ConnectEx", func(o *operation) error { |
| 295 » » return syscall.ConnectEx(o.fd.sysfd, o.sa, nil, 0, nil, &o.o) |
| 296 » }) |
330 if err != nil { | 297 if err != nil { |
331 return err | 298 return err |
332 } | 299 } |
333 // Refresh socket properties. | 300 // Refresh socket properties. |
334 return syscall.Setsockopt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_UPDAT
E_CONNECT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sy
sfd))) | 301 return syscall.Setsockopt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_UPDAT
E_CONNECT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sy
sfd))) |
335 } | 302 } |
336 | 303 |
337 // Add a reference to this fd. | 304 // Add a reference to this fd. |
338 // If closing==true, mark the fd as closing. | 305 // If closing==true, mark the fd as closing. |
339 // Returns an error if the fd cannot be used. | 306 // Returns an error if the fd cannot be used. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
376 } | 343 } |
377 | 344 |
378 func (fd *netFD) Close() error { | 345 func (fd *netFD) Close() error { |
379 if err := fd.incref(true); err != nil { | 346 if err := fd.incref(true); err != nil { |
380 return err | 347 return err |
381 } | 348 } |
382 defer fd.decref() | 349 defer fd.decref() |
383 // unblock pending reader and writer | 350 // unblock pending reader and writer |
384 fd.pd.Evict() | 351 fd.pd.Evict() |
385 // wait for both reader and writer to exit | 352 // wait for both reader and writer to exit |
386 » fd.rio.Lock() | 353 » fd.rop.mu.Lock() |
387 » defer fd.rio.Unlock() | 354 » fd.wop.mu.Lock() |
388 » fd.wio.Lock() | 355 » fd.rop.mu.Unlock() |
389 » defer fd.wio.Unlock() | 356 » fd.wop.mu.Unlock() |
390 return nil | 357 return nil |
391 } | 358 } |
392 | 359 |
393 func (fd *netFD) shutdown(how int) error { | 360 func (fd *netFD) shutdown(how int) error { |
394 if err := fd.incref(false); err != nil { | 361 if err := fd.incref(false); err != nil { |
395 return err | 362 return err |
396 } | 363 } |
397 defer fd.decref() | 364 defer fd.decref() |
398 err := syscall.Shutdown(fd.sysfd, how) | 365 err := syscall.Shutdown(fd.sysfd, how) |
399 if err != nil { | 366 if err != nil { |
400 return &OpError{"shutdown", fd.net, fd.laddr, err} | 367 return &OpError{"shutdown", fd.net, fd.laddr, err} |
401 } | 368 } |
402 return nil | 369 return nil |
403 } | 370 } |
404 | 371 |
405 func (fd *netFD) CloseRead() error { | 372 func (fd *netFD) CloseRead() error { |
406 return fd.shutdown(syscall.SHUT_RD) | 373 return fd.shutdown(syscall.SHUT_RD) |
407 } | 374 } |
408 | 375 |
409 func (fd *netFD) CloseWrite() error { | 376 func (fd *netFD) CloseWrite() error { |
410 return fd.shutdown(syscall.SHUT_WR) | 377 return fd.shutdown(syscall.SHUT_WR) |
411 } | 378 } |
412 | 379 |
413 // Read from network. | |
414 | |
415 type readOp struct { | |
416 bufOp | |
417 } | |
418 | |
419 func (o *readOp) Submit() error { | |
420 var d, f uint32 | |
421 return syscall.WSARecv(syscall.Handle(o.fd.sysfd), &o.buf, 1, &d, &f, &o
.o, nil) | |
422 } | |
423 | |
424 func (o *readOp) Name() string { | |
425 return "WSARecv" | |
426 } | |
427 | |
428 func (fd *netFD) Read(buf []byte) (int, error) { | 380 func (fd *netFD) Read(buf []byte) (int, error) { |
429 if err := fd.incref(false); err != nil { | 381 if err := fd.incref(false); err != nil { |
430 return 0, err | 382 return 0, err |
431 } | 383 } |
432 defer fd.decref() | 384 defer fd.decref() |
433 » fd.rio.Lock() | 385 » o := &fd.rop |
434 » defer fd.rio.Unlock() | 386 » o.mu.Lock() |
435 » var o readOp | 387 » defer o.mu.Unlock() |
436 » o.Init(fd, buf, 'r') | 388 » o.InitBuf(buf) |
437 » n, err := iosrv.ExecIO(&o) | 389 » n, err := iosrv.ExecIO(o, "WSARecv", func(o *operation) error { |
| 390 » » return syscall.WSARecv(o.fd.sysfd, &o.buf, 1, &o.qty, &o.flags,
&o.o, nil) |
| 391 » }) |
438 if err == nil && n == 0 { | 392 if err == nil && n == 0 { |
439 err = io.EOF | 393 err = io.EOF |
440 } | 394 } |
441 return n, err | 395 return n, err |
442 } | |
443 | |
444 // ReadFrom from network. | |
445 | |
446 type readFromOp struct { | |
447 bufOp | |
448 rsa syscall.RawSockaddrAny | |
449 rsan int32 | |
450 } | |
451 | |
452 func (o *readFromOp) Submit() error { | |
453 var d, f uint32 | |
454 return syscall.WSARecvFrom(o.fd.sysfd, &o.buf, 1, &d, &f, &o.rsa, &o.rsa
n, &o.o, nil) | |
455 } | |
456 | |
457 func (o *readFromOp) Name() string { | |
458 return "WSARecvFrom" | |
459 } | 396 } |
460 | 397 |
461 func (fd *netFD) ReadFrom(buf []byte) (n int, sa syscall.Sockaddr, err error) { | 398 func (fd *netFD) ReadFrom(buf []byte) (n int, sa syscall.Sockaddr, err error) { |
462 if len(buf) == 0 { | 399 if len(buf) == 0 { |
463 return 0, nil, nil | 400 return 0, nil, nil |
464 } | 401 } |
465 if err := fd.incref(false); err != nil { | 402 if err := fd.incref(false); err != nil { |
466 return 0, nil, err | 403 return 0, nil, err |
467 } | 404 } |
468 defer fd.decref() | 405 defer fd.decref() |
469 » fd.rio.Lock() | 406 » o := &fd.rop |
470 » defer fd.rio.Unlock() | 407 » o.mu.Lock() |
471 » var o readFromOp | 408 » defer o.mu.Unlock() |
472 » o.Init(fd, buf, 'r') | 409 » o.InitBuf(buf) |
473 » o.rsan = int32(unsafe.Sizeof(o.rsa)) | 410 » n, err = iosrv.ExecIO(o, "WSARecvFrom", func(o *operation) error { |
474 » n, err = iosrv.ExecIO(&o) | 411 » » if o.rsa == nil { |
| 412 » » » o.rsa = new(syscall.RawSockaddrAny) |
| 413 » » } |
| 414 » » o.rsan = int32(unsafe.Sizeof(*o.rsa)) |
| 415 » » return syscall.WSARecvFrom(o.fd.sysfd, &o.buf, 1, &o.qty, &o.fla
gs, o.rsa, &o.rsan, &o.o, nil) |
| 416 » }) |
475 if err != nil { | 417 if err != nil { |
476 return 0, nil, err | 418 return 0, nil, err |
477 } | 419 } |
478 sa, _ = o.rsa.Sockaddr() | 420 sa, _ = o.rsa.Sockaddr() |
479 return | 421 return |
480 } | |
481 | |
482 // Write to network. | |
483 | |
484 type writeOp struct { | |
485 bufOp | |
486 } | |
487 | |
488 func (o *writeOp) Submit() error { | |
489 var d uint32 | |
490 return syscall.WSASend(o.fd.sysfd, &o.buf, 1, &d, 0, &o.o, nil) | |
491 } | |
492 | |
493 func (o *writeOp) Name() string { | |
494 return "WSASend" | |
495 } | 422 } |
496 | 423 |
497 func (fd *netFD) Write(buf []byte) (int, error) { | 424 func (fd *netFD) Write(buf []byte) (int, error) { |
498 if err := fd.incref(false); err != nil { | 425 if err := fd.incref(false); err != nil { |
499 return 0, err | 426 return 0, err |
500 } | 427 } |
501 defer fd.decref() | 428 defer fd.decref() |
502 » fd.wio.Lock() | 429 » o := &fd.wop |
503 » defer fd.wio.Unlock() | 430 » o.mu.Lock() |
504 » var o writeOp | 431 » defer o.mu.Unlock() |
505 » o.Init(fd, buf, 'w') | 432 » o.InitBuf(buf) |
506 » return iosrv.ExecIO(&o) | 433 » return iosrv.ExecIO(o, "WSASend", func(o *operation) error { |
507 } | 434 » » return syscall.WSASend(o.fd.sysfd, &o.buf, 1, &o.qty, 0, &o.o, n
il) |
508 | 435 » }) |
509 // WriteTo to network. | |
510 | |
511 type writeToOp struct { | |
512 » bufOp | |
513 » sa syscall.Sockaddr | |
514 } | |
515 | |
516 func (o *writeToOp) Submit() error { | |
517 » var d uint32 | |
518 » return syscall.WSASendto(o.fd.sysfd, &o.buf, 1, &d, 0, o.sa, &o.o, nil) | |
519 } | |
520 | |
521 func (o *writeToOp) Name() string { | |
522 » return "WSASendto" | |
523 } | 436 } |
524 | 437 |
525 func (fd *netFD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) { | 438 func (fd *netFD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) { |
526 if len(buf) == 0 { | 439 if len(buf) == 0 { |
527 return 0, nil | 440 return 0, nil |
528 } | 441 } |
529 if err := fd.incref(false); err != nil { | 442 if err := fd.incref(false); err != nil { |
530 return 0, err | 443 return 0, err |
531 } | 444 } |
532 defer fd.decref() | 445 defer fd.decref() |
533 » fd.wio.Lock() | 446 » o := &fd.wop |
534 » defer fd.wio.Unlock() | 447 » o.mu.Lock() |
535 » var o writeToOp | 448 » defer o.mu.Unlock() |
536 » o.Init(fd, buf, 'w') | 449 » o.InitBuf(buf) |
537 o.sa = sa | 450 o.sa = sa |
538 » return iosrv.ExecIO(&o) | 451 » return iosrv.ExecIO(o, "WSASendto", func(o *operation) error { |
539 } | 452 » » return syscall.WSASendto(o.fd.sysfd, &o.buf, 1, &o.qty, 0, o.sa,
&o.o, nil) |
540 | 453 » }) |
541 // Accept new network connections. | |
542 | |
543 type acceptOp struct { | |
544 » anOp | |
545 » newsock syscall.Handle | |
546 » attrs [2]syscall.RawSockaddrAny // space for local and remote address
only | |
547 } | |
548 | |
549 func (o *acceptOp) Submit() error { | |
550 » var d uint32 | |
551 » l := uint32(unsafe.Sizeof(o.attrs[0])) | |
552 » return syscall.AcceptEx(o.fd.sysfd, o.newsock, | |
553 » » (*byte)(unsafe.Pointer(&o.attrs[0])), 0, l, l, &d, &o.o) | |
554 } | |
555 | |
556 func (o *acceptOp) Name() string { | |
557 » return "AcceptEx" | |
558 } | 454 } |
559 | 455 |
560 func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) { | 456 func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) { |
561 if err := fd.incref(false); err != nil { | 457 if err := fd.incref(false); err != nil { |
562 return nil, err | 458 return nil, err |
563 } | 459 } |
564 defer fd.decref() | 460 defer fd.decref() |
565 | 461 |
566 // Get new socket. | 462 // Get new socket. |
567 s, err := sysSocket(fd.family, fd.sotype, 0) | 463 s, err := sysSocket(fd.family, fd.sotype, 0) |
568 if err != nil { | 464 if err != nil { |
569 return nil, &OpError{"socket", fd.net, fd.laddr, err} | 465 return nil, &OpError{"socket", fd.net, fd.laddr, err} |
570 } | 466 } |
571 | 467 |
572 // Associate our new socket with IOCP. | 468 // Associate our new socket with IOCP. |
573 netfd, err := newFD(s, fd.family, fd.sotype, fd.net) | 469 netfd, err := newFD(s, fd.family, fd.sotype, fd.net) |
574 if err != nil { | 470 if err != nil { |
575 closesocket(s) | 471 closesocket(s) |
576 return nil, &OpError{"accept", fd.net, fd.laddr, err} | 472 return nil, &OpError{"accept", fd.net, fd.laddr, err} |
577 } | 473 } |
578 if err := netfd.init(); err != nil { | 474 if err := netfd.init(); err != nil { |
579 fd.Close() | 475 fd.Close() |
580 return nil, err | 476 return nil, err |
581 } | 477 } |
582 | 478 |
583 // Submit accept request. | 479 // Submit accept request. |
584 » fd.rio.Lock() | 480 » o := &fd.rop |
585 » defer fd.rio.Unlock() | 481 » o.mu.Lock() |
586 » var o acceptOp | 482 » defer o.mu.Unlock() |
587 » o.Init(fd, 'r') | 483 » o.handle = s |
588 » o.newsock = s | 484 » var rawsa [2]syscall.RawSockaddrAny |
589 » _, err = iosrv.ExecIO(&o) | 485 » o.rsan = int32(unsafe.Sizeof(rawsa[0])) |
| 486 » _, err = iosrv.ExecIO(o, "AcceptEx", func(o *operation) error { |
| 487 » » return syscall.AcceptEx(o.fd.sysfd, o.handle, (*byte)(unsafe.Poi
nter(&rawsa[0])), 0, uint32(o.rsan), uint32(o.rsan), &o.qty, &o.o) |
| 488 » }) |
590 if err != nil { | 489 if err != nil { |
591 netfd.Close() | 490 netfd.Close() |
592 return nil, err | 491 return nil, err |
593 } | 492 } |
594 | 493 |
595 // Inherit properties of the listening socket. | 494 // Inherit properties of the listening socket. |
596 err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT
_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd))) | 495 err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT
_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd))) |
597 if err != nil { | 496 if err != nil { |
598 netfd.Close() | 497 netfd.Close() |
599 return nil, &OpError{"Setsockopt", fd.net, fd.laddr, err} | 498 return nil, &OpError{"Setsockopt", fd.net, fd.laddr, err} |
600 } | 499 } |
601 | 500 |
602 // Get local and peer addr out of AcceptEx buffer. | 501 // Get local and peer addr out of AcceptEx buffer. |
603 var lrsa, rrsa *syscall.RawSockaddrAny | 502 var lrsa, rrsa *syscall.RawSockaddrAny |
604 var llen, rlen int32 | 503 var llen, rlen int32 |
605 » l := uint32(unsafe.Sizeof(*lrsa)) | 504 » syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&rawsa[0])), |
606 » syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&o.attrs[0])), | 505 » » 0, uint32(o.rsan), uint32(o.rsan), &lrsa, &llen, &rrsa, &rlen) |
607 » » 0, l, l, &lrsa, &llen, &rrsa, &rlen) | |
608 lsa, _ := lrsa.Sockaddr() | 506 lsa, _ := lrsa.Sockaddr() |
609 rsa, _ := rrsa.Sockaddr() | 507 rsa, _ := rrsa.Sockaddr() |
610 | 508 |
611 netfd.setAddr(toAddr(lsa), toAddr(rsa)) | 509 netfd.setAddr(toAddr(lsa), toAddr(rsa)) |
612 return netfd, nil | 510 return netfd, nil |
613 } | 511 } |
614 | 512 |
615 // Unimplemented functions. | 513 // Unimplemented functions. |
616 | 514 |
617 func (fd *netFD) dup() (*os.File, error) { | 515 func (fd *netFD) dup() (*os.File, error) { |
618 // TODO: Implement this | 516 // TODO: Implement this |
619 return nil, os.NewSyscallError("dup", syscall.EWINDOWS) | 517 return nil, os.NewSyscallError("dup", syscall.EWINDOWS) |
620 } | 518 } |
621 | 519 |
622 var errNoSupport = errors.New("address family not supported") | 520 var errNoSupport = errors.New("address family not supported") |
623 | 521 |
624 func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.S
ockaddr, err error) { | 522 func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.S
ockaddr, err error) { |
625 return 0, 0, 0, nil, errNoSupport | 523 return 0, 0, 0, nil, errNoSupport |
626 } | 524 } |
627 | 525 |
628 func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oob
n int, err error) { | 526 func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oob
n int, err error) { |
629 return 0, 0, errNoSupport | 527 return 0, 0, errNoSupport |
630 } | 528 } |
LEFT | RIGHT |