LEFT | RIGHT |
(no file at all) | |
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 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 // Interface for all IO operations. |
71 type anOpIface interface { | 71 type anOpIface interface { |
72 Op() *anOp | 72 Op() *anOp |
73 Name() string | 73 Name() string |
74 Submit() error | 74 Submit() error |
75 } | 75 } |
76 | 76 |
77 // IO completion result parameters. | |
78 type ioResult struct { | |
79 qty uint32 | |
80 err error | |
81 } | |
82 | |
83 // anOp implements functionality common to all IO operations. | 77 // anOp implements functionality common to all IO operations. |
| 78 // Its beginning must be the same as runtime.net_anOp. Keep these in sync. |
84 type anOp struct { | 79 type anOp struct { |
85 // Used by IOCP interface, it must be first field | 80 // Used by IOCP interface, it must be first field |
86 // of the struct, as our code rely on it. | 81 // of the struct, as our code rely on it. |
87 o syscall.Overlapped | 82 o syscall.Overlapped |
88 | 83 |
89 » resultc chan ioResult | 84 » // fields used by runtime.netpoll |
90 » errnoc chan error | 85 » runtimeCtx uintptr |
91 » fd *netFD | 86 » mode int32 |
92 } | 87 » errno int32 |
93 | 88 » qty uint32 |
94 func (o *anOp) Init(fd *netFD, mode int) { | 89 |
| 90 » errnoc chan error |
| 91 » fd *netFD |
| 92 } |
| 93 |
| 94 func (o *anOp) Init(fd *netFD, mode int32) { |
95 o.fd = fd | 95 o.fd = fd |
96 » var i int | 96 » o.mode = mode |
97 » if mode == 'r' { | 97 » o.runtimeCtx = fd.pd.runtimeCtx |
98 » » i = 0 | 98 » if !canCancelIO { |
99 » } else { | 99 » » var i int |
100 » » i = 1 | 100 » » if mode == 'r' { |
101 » } | 101 » » » i = 0 |
102 » if fd.resultc[i] == nil { | 102 » » } else { |
103 » » fd.resultc[i] = make(chan ioResult, 1) | 103 » » » i = 1 |
104 » } | 104 » » } |
105 » o.resultc = fd.resultc[i] | 105 » » if fd.errnoc[i] == nil { |
106 » if fd.errnoc[i] == nil { | 106 » » » fd.errnoc[i] = make(chan error) |
107 » » fd.errnoc[i] = make(chan error) | 107 » » } |
108 » } | 108 » » o.errnoc = fd.errnoc[i] |
109 » o.errnoc = fd.errnoc[i] | 109 » } |
110 } | 110 } |
111 | 111 |
112 func (o *anOp) Op() *anOp { | 112 func (o *anOp) Op() *anOp { |
113 return o | 113 return o |
114 } | 114 } |
115 | 115 |
116 // bufOp is used by IO operations that read / write | 116 // bufOp is used by IO operations that read / write |
117 // data from / to client buffer. | 117 // data from / to client buffer. |
118 type bufOp struct { | 118 type bufOp struct { |
119 anOp | 119 anOp |
120 buf syscall.WSABuf | 120 buf syscall.WSABuf |
121 } | 121 } |
122 | 122 |
123 func (o *bufOp) Init(fd *netFD, buf []byte, mode int) { | 123 func (o *bufOp) Init(fd *netFD, buf []byte, mode int32) { |
124 o.anOp.Init(fd, mode) | 124 o.anOp.Init(fd, mode) |
125 o.buf.Len = uint32(len(buf)) | 125 o.buf.Len = uint32(len(buf)) |
126 if len(buf) == 0 { | 126 if len(buf) == 0 { |
127 o.buf.Buf = nil | 127 o.buf.Buf = nil |
128 } else { | 128 } else { |
129 o.buf.Buf = (*byte)(unsafe.Pointer(&buf[0])) | 129 o.buf.Buf = (*byte)(unsafe.Pointer(&buf[0])) |
130 } | |
131 } | |
132 | |
133 // resultSrv will retrieve all IO completion results from | |
134 // iocp and send them to the correspondent waiting client | |
135 // goroutine via channel supplied in the request. | |
136 type resultSrv struct { | |
137 iocp syscall.Handle | |
138 } | |
139 | |
140 func runtime_blockingSyscallHint() | |
141 | |
142 func (s *resultSrv) Run() { | |
143 var o *syscall.Overlapped | |
144 var key uint32 | |
145 var r ioResult | |
146 for { | |
147 r.err = syscall.GetQueuedCompletionStatus(s.iocp, &(r.qty), &key
, &o, 0) | |
148 if r.err == syscall.Errno(syscall.WAIT_TIMEOUT) && o == nil { | |
149 runtime_blockingSyscallHint() | |
150 r.err = syscall.GetQueuedCompletionStatus(s.iocp, &(r.qt
y), &key, &o, syscall.INFINITE) | |
151 } | |
152 switch { | |
153 case r.err == nil: | |
154 // Dequeued successfully completed IO packet. | |
155 case r.err == syscall.Errno(syscall.WAIT_TIMEOUT) && o == nil: | |
156 // Wait has timed out (should not happen now, but might
be used in the future). | |
157 panic("GetQueuedCompletionStatus timed out") | |
158 case o == nil: | |
159 // Failed to dequeue anything -> report the error. | |
160 panic("GetQueuedCompletionStatus failed " + r.err.Error(
)) | |
161 default: | |
162 // Dequeued failed IO packet. | |
163 } | |
164 (*anOp)(unsafe.Pointer(o)).resultc <- r | |
165 } | 130 } |
166 } | 131 } |
167 | 132 |
168 // ioSrv executes net IO requests. | 133 // ioSrv executes net IO requests. |
169 type ioSrv struct { | 134 type ioSrv struct { |
170 submchan chan anOpIface // submit IO requests | 135 submchan chan anOpIface // submit IO requests |
171 canchan chan anOpIface // cancel IO requests | 136 canchan chan anOpIface // cancel IO requests |
172 } | 137 } |
173 | 138 |
174 // ProcessRemoteIO will execute submit IO requests on behalf | 139 // ProcessRemoteIO will execute submit IO requests on behalf |
(...skipping 10 matching lines...) Expand all Loading... |
185 o.Op().errnoc <- o.Submit() | 150 o.Op().errnoc <- o.Submit() |
186 case o := <-s.canchan: | 151 case o := <-s.canchan: |
187 o.Op().errnoc <- syscall.CancelIo(syscall.Handle(o.Op().
fd.sysfd)) | 152 o.Op().errnoc <- syscall.CancelIo(syscall.Handle(o.Op().
fd.sysfd)) |
188 } | 153 } |
189 } | 154 } |
190 } | 155 } |
191 | 156 |
192 // ExecIO executes a single IO operation oi. It submits and cancels | 157 // ExecIO executes a single IO operation oi. It submits and cancels |
193 // IO in the current thread for systems where Windows CancelIoEx API | 158 // IO in the current thread for systems where Windows CancelIoEx API |
194 // is available. Alternatively, it passes the request onto | 159 // is available. Alternatively, it passes the request onto |
195 // a special goroutine and waits for completion or cancels request. | 160 // runtime netpoll and waits for completion or cancels request. |
196 // deadline is unix nanos. | 161 func (s *ioSrv) ExecIO(oi anOpIface) (int, error) { |
197 func (s *ioSrv) ExecIO(oi anOpIface, deadline int64) (int, error) { | |
198 var err error | 162 var err error |
199 o := oi.Op() | 163 o := oi.Op() |
200 » // Calculate timeout delta. | 164 » // Notify runtime netpoll about starting IO. |
201 » var delta int64 | 165 » err = o.fd.pd.Prepare(int(o.mode)) |
202 » if deadline != 0 { | 166 » if err != nil { |
203 » » delta = deadline - time.Now().UnixNano() | 167 » » return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, err} |
204 » » if delta <= 0 { | |
205 » » » return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, errT
imeout} | |
206 » » } | |
207 } | 168 } |
208 // Start IO. | 169 // Start IO. |
209 if canCancelIO { | 170 if canCancelIO { |
210 err = oi.Submit() | 171 err = oi.Submit() |
211 } else { | 172 } else { |
212 // Send request to a special dedicated thread, | 173 // Send request to a special dedicated thread, |
213 // so it can stop the IO with CancelIO later. | 174 // so it can stop the IO with CancelIO later. |
214 s.submchan <- oi | 175 s.submchan <- oi |
215 err = <-o.errnoc | 176 err = <-o.errnoc |
216 } | 177 } |
217 switch err { | 178 switch err { |
218 case nil: | 179 case nil: |
219 // IO completed immediately, but we need to get our completion m
essage anyway. | 180 // IO completed immediately, but we need to get our completion m
essage anyway. |
220 case syscall.ERROR_IO_PENDING: | 181 case syscall.ERROR_IO_PENDING: |
221 // IO started, and we have to wait for its completion. | 182 // IO started, and we have to wait for its completion. |
222 err = nil | 183 err = nil |
223 default: | 184 default: |
224 return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, err} | 185 return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, err} |
225 } | 186 } |
226 // Setup timer, if deadline is given. | |
227 var timer <-chan time.Time | |
228 if delta > 0 { | |
229 t := time.NewTimer(time.Duration(delta) * time.Nanosecond) | |
230 defer t.Stop() | |
231 timer = t.C | |
232 } | |
233 // Wait for our request to complete. | 187 // Wait for our request to complete. |
234 » var r ioResult | 188 » err = o.fd.pd.Wait(int(o.mode)) |
235 » var cancelled, timeout bool | 189 » if err == nil { |
236 » select { | 190 » » // All is good. Extract our IO results and return. |
237 » case r = <-o.resultc: | 191 » » if o.errno != 0 { |
238 » case <-timer: | 192 » » » err = syscall.Errno(o.errno) |
239 » » cancelled = true | 193 » » » return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, err} |
240 » » timeout = true | 194 » » } |
241 » case <-o.fd.closec: | 195 » » return int(o.qty), nil |
242 » » cancelled = true | 196 » } |
243 » } | 197 » // IO is interrupted by "close" or "timeout" |
244 » if cancelled { | 198 » netpollErr := err |
245 » » // Cancel it. | 199 » switch netpollErr { |
246 » » if canCancelIO { | 200 » case errClosing, errTimeout: |
247 » » » err := syscall.CancelIoEx(syscall.Handle(o.Op().fd.sysfd
), &o.o) | 201 » » // will deal with those. |
248 » » » // Assuming ERROR_NOT_FOUND is returned, if IO is comple
ted. | 202 » default: |
249 » » » if err != nil && err != syscall.ERROR_NOT_FOUND { | 203 » » panic("net: unexpected runtime.netpoll error: " + netpollErr.Err
or()) |
250 » » » » // TODO(brainman): maybe do something else, but
panic. | 204 » } |
251 » » » » panic(err) | 205 » // Cancel our request. |
252 » » » } | 206 » if canCancelIO { |
253 » » } else { | 207 » » err := syscall.CancelIoEx(syscall.Handle(o.Op().fd.sysfd), &o.o) |
254 » » » s.canchan <- oi | 208 » » // Assuming ERROR_NOT_FOUND is returned, if IO is completed. |
255 » » » <-o.errnoc | 209 » » if err != nil && err != syscall.ERROR_NOT_FOUND { |
256 » » } | 210 » » » // TODO(brainman): maybe do something else, but panic. |
257 » » // Wait for IO to be canceled or complete successfully. | 211 » » » panic(err) |
258 » » r = <-o.resultc | 212 » » } |
259 » » if r.err == syscall.ERROR_OPERATION_ABORTED { // IO Canceled | 213 » } else { |
260 » » » if timeout { | 214 » » s.canchan <- oi |
261 » » » » r.err = errTimeout | 215 » » <-o.errnoc |
262 » » » } else { | 216 » } |
263 » » » » r.err = errClosing | 217 » // Wait for cancellation to complete. |
264 » » » } | 218 » o.fd.pd.WaitCanceled(int(o.mode)) |
265 » » } | 219 » if o.errno != 0 { |
266 » } | 220 » » err = syscall.Errno(o.errno) |
267 » if r.err != nil { | 221 » » if err == syscall.ERROR_OPERATION_ABORTED { // IO Canceled |
268 » » err = &OpError{oi.Name(), o.fd.net, o.fd.laddr, r.err} | 222 » » » err = netpollErr |
269 » } | 223 » » } |
270 » return int(r.qty), err | 224 » » return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, err} |
| 225 » } |
| 226 » // We issued cancellation request. But, it seems, IO operation succeeded |
| 227 » // before cancellation request run. We need to treat IO operation as |
| 228 » // succeeded (the bytes are actually sent/recv from network). |
| 229 » return int(o.qty), nil |
271 } | 230 } |
272 | 231 |
273 // Start helper goroutines. | 232 // Start helper goroutines. |
274 var resultsrv *resultSrv | |
275 var iosrv *ioSrv | 233 var iosrv *ioSrv |
276 var onceStartServer sync.Once | 234 var onceStartServer sync.Once |
277 | 235 |
278 func startServer() { | 236 func startServer() { |
279 resultsrv = new(resultSrv) | |
280 var err error | |
281 resultsrv.iocp, err = syscall.CreateIoCompletionPort(syscall.InvalidHand
le, 0, 0, 1) | |
282 if err != nil { | |
283 panic("CreateIoCompletionPort: " + err.Error()) | |
284 } | |
285 go resultsrv.Run() | |
286 | |
287 iosrv = new(ioSrv) | 237 iosrv = new(ioSrv) |
288 if !canCancelIO { | 238 if !canCancelIO { |
289 // Only CancelIo API is available. Lets start special goroutine | 239 // Only CancelIo API is available. Lets start special goroutine |
290 // locked to an OS thread, that both starts and cancels IO. | 240 // locked to an OS thread, that both starts and cancels IO. |
291 iosrv.submchan = make(chan anOpIface) | 241 iosrv.submchan = make(chan anOpIface) |
292 iosrv.canchan = make(chan anOpIface) | 242 iosrv.canchan = make(chan anOpIface) |
293 go iosrv.ProcessRemoteIO() | 243 go iosrv.ProcessRemoteIO() |
294 } | 244 } |
295 } | 245 } |
296 | 246 |
297 // Network file descriptor. | 247 // Network file descriptor. |
298 type netFD struct { | 248 type netFD struct { |
299 // locking/lifetime of sysfd | 249 // locking/lifetime of sysfd |
300 sysmu sync.Mutex | 250 sysmu sync.Mutex |
301 sysref int | 251 sysref int |
302 closing bool | 252 closing bool |
303 | 253 |
304 // immutable until Close | 254 // immutable until Close |
305 sysfd syscall.Handle | 255 sysfd syscall.Handle |
306 family int | 256 family int |
307 sotype int | 257 sotype int |
308 isConnected bool | 258 isConnected bool |
309 net string | 259 net string |
310 laddr Addr | 260 laddr Addr |
311 raddr Addr | 261 raddr Addr |
312 » resultc [2]chan ioResult // read/write completion results | 262 » errnoc [2]chan error // read/write submit or cancel operation error
s |
313 » errnoc [2]chan error // read/write submit or cancel operation er
rors | |
314 » closec chan bool // used by Close to cancel pending IO | |
315 | 263 |
316 // serialize access to Read and Write methods | 264 // serialize access to Read and Write methods |
317 rio, wio sync.Mutex | 265 rio, wio sync.Mutex |
318 | 266 |
319 » // read and write deadlines | 267 » // wait server |
320 » rdeadline, wdeadline deadline | 268 » pd pollDesc |
321 } | 269 } |
322 | 270 |
323 func allocFD(fd syscall.Handle, family, sotype int, net string) *netFD { | 271 func newFD(fd syscall.Handle, family, sotype int, net string) (*netFD, error) { |
| 272 » if initErr != nil { |
| 273 » » return nil, initErr |
| 274 » } |
| 275 » onceStartServer.Do(startServer) |
324 netfd := &netFD{ | 276 netfd := &netFD{ |
325 sysfd: fd, | 277 sysfd: fd, |
326 family: family, | 278 family: family, |
327 sotype: sotype, | 279 sotype: sotype, |
328 net: net, | 280 net: net, |
329 » » closec: make(chan bool), | 281 » } |
330 » } | 282 » if err := netfd.pd.Init(netfd); err != nil { |
331 » return netfd | |
332 } | |
333 | |
334 func newFD(fd syscall.Handle, family, proto int, net string) (*netFD, error) { | |
335 » if initErr != nil { | |
336 » » return nil, initErr | |
337 » } | |
338 » onceStartServer.Do(startServer) | |
339 » // Associate our socket with resultsrv.iocp. | |
340 » if _, err := syscall.CreateIoCompletionPort(syscall.Handle(fd), resultsr
v.iocp, 0, 0); err != nil { | |
341 return nil, err | 283 return nil, err |
342 } | 284 } |
343 » return allocFD(fd, family, proto, net), nil | 285 » return netfd, nil |
344 } | 286 } |
345 | 287 |
346 func (fd *netFD) setAddr(laddr, raddr Addr) { | 288 func (fd *netFD) setAddr(laddr, raddr Addr) { |
347 fd.laddr = laddr | 289 fd.laddr = laddr |
348 fd.raddr = raddr | 290 fd.raddr = raddr |
349 runtime.SetFinalizer(fd, (*netFD).closesocket) | 291 runtime.SetFinalizer(fd, (*netFD).closesocket) |
350 } | 292 } |
351 | 293 |
352 // Make new connection. | 294 // Make new connection. |
353 | 295 |
(...skipping 25 matching lines...) Expand all Loading... |
379 panic("unexpected type in connect") | 321 panic("unexpected type in connect") |
380 } | 322 } |
381 if err := syscall.Bind(fd.sysfd, la); err != nil { | 323 if err := syscall.Bind(fd.sysfd, la); err != nil { |
382 return err | 324 return err |
383 } | 325 } |
384 } | 326 } |
385 // Call ConnectEx API. | 327 // Call ConnectEx API. |
386 var o connectOp | 328 var o connectOp |
387 o.Init(fd, 'w') | 329 o.Init(fd, 'w') |
388 o.ra = ra | 330 o.ra = ra |
389 » _, err := iosrv.ExecIO(&o, fd.wdeadline.value()) | 331 » _, err := iosrv.ExecIO(&o) |
390 if err != nil { | 332 if err != nil { |
391 return err | 333 return err |
392 } | 334 } |
393 // Refresh socket properties. | 335 // Refresh socket properties. |
394 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))) | 336 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))) |
395 } | 337 } |
396 | 338 |
397 // Add a reference to this fd. | 339 // Add a reference to this fd. |
398 // If closing==true, mark the fd as closing. | 340 // If closing==true, mark the fd as closing. |
399 // Returns an error if the fd cannot be used. | 341 // Returns an error if the fd cannot be used. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
431 } | 373 } |
432 fd.sysmu.Unlock() | 374 fd.sysmu.Unlock() |
433 } | 375 } |
434 | 376 |
435 func (fd *netFD) Close() error { | 377 func (fd *netFD) Close() error { |
436 if err := fd.incref(true); err != nil { | 378 if err := fd.incref(true); err != nil { |
437 return err | 379 return err |
438 } | 380 } |
439 defer fd.decref() | 381 defer fd.decref() |
440 // unblock pending reader and writer | 382 // unblock pending reader and writer |
441 » close(fd.closec) | 383 » fd.pd.Evict() |
442 // wait for both reader and writer to exit | 384 // wait for both reader and writer to exit |
443 fd.rio.Lock() | 385 fd.rio.Lock() |
444 defer fd.rio.Unlock() | 386 defer fd.rio.Unlock() |
445 fd.wio.Lock() | 387 fd.wio.Lock() |
446 defer fd.wio.Unlock() | 388 defer fd.wio.Unlock() |
447 return nil | 389 return nil |
448 } | 390 } |
449 | 391 |
450 func (fd *netFD) shutdown(how int) error { | 392 func (fd *netFD) shutdown(how int) error { |
451 if err := fd.incref(false); err != nil { | 393 if err := fd.incref(false); err != nil { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
488 | 430 |
489 func (fd *netFD) Read(buf []byte) (int, error) { | 431 func (fd *netFD) Read(buf []byte) (int, error) { |
490 if err := fd.incref(false); err != nil { | 432 if err := fd.incref(false); err != nil { |
491 return 0, err | 433 return 0, err |
492 } | 434 } |
493 defer fd.decref() | 435 defer fd.decref() |
494 fd.rio.Lock() | 436 fd.rio.Lock() |
495 defer fd.rio.Unlock() | 437 defer fd.rio.Unlock() |
496 var o readOp | 438 var o readOp |
497 o.Init(fd, buf, 'r') | 439 o.Init(fd, buf, 'r') |
498 » n, err := iosrv.ExecIO(&o, fd.rdeadline.value()) | 440 » n, err := iosrv.ExecIO(&o) |
499 if err == nil && n == 0 { | 441 if err == nil && n == 0 { |
500 err = io.EOF | 442 err = io.EOF |
501 } | 443 } |
502 return n, err | 444 return n, err |
503 } | 445 } |
504 | 446 |
505 // ReadFrom from network. | 447 // ReadFrom from network. |
506 | 448 |
507 type readFromOp struct { | 449 type readFromOp struct { |
508 bufOp | 450 bufOp |
(...skipping 16 matching lines...) Expand all Loading... |
525 } | 467 } |
526 if err := fd.incref(false); err != nil { | 468 if err := fd.incref(false); err != nil { |
527 return 0, nil, err | 469 return 0, nil, err |
528 } | 470 } |
529 defer fd.decref() | 471 defer fd.decref() |
530 fd.rio.Lock() | 472 fd.rio.Lock() |
531 defer fd.rio.Unlock() | 473 defer fd.rio.Unlock() |
532 var o readFromOp | 474 var o readFromOp |
533 o.Init(fd, buf, 'r') | 475 o.Init(fd, buf, 'r') |
534 o.rsan = int32(unsafe.Sizeof(o.rsa)) | 476 o.rsan = int32(unsafe.Sizeof(o.rsa)) |
535 » n, err = iosrv.ExecIO(&o, fd.rdeadline.value()) | 477 » n, err = iosrv.ExecIO(&o) |
536 if err != nil { | 478 if err != nil { |
537 return 0, nil, err | 479 return 0, nil, err |
538 } | 480 } |
539 sa, _ = o.rsa.Sockaddr() | 481 sa, _ = o.rsa.Sockaddr() |
540 return | 482 return |
541 } | 483 } |
542 | 484 |
543 // Write to network. | 485 // Write to network. |
544 | 486 |
545 type writeOp struct { | 487 type writeOp struct { |
(...skipping 11 matching lines...) Expand all Loading... |
557 | 499 |
558 func (fd *netFD) Write(buf []byte) (int, error) { | 500 func (fd *netFD) Write(buf []byte) (int, error) { |
559 if err := fd.incref(false); err != nil { | 501 if err := fd.incref(false); err != nil { |
560 return 0, err | 502 return 0, err |
561 } | 503 } |
562 defer fd.decref() | 504 defer fd.decref() |
563 fd.wio.Lock() | 505 fd.wio.Lock() |
564 defer fd.wio.Unlock() | 506 defer fd.wio.Unlock() |
565 var o writeOp | 507 var o writeOp |
566 o.Init(fd, buf, 'w') | 508 o.Init(fd, buf, 'w') |
567 » return iosrv.ExecIO(&o, fd.wdeadline.value()) | 509 » return iosrv.ExecIO(&o) |
568 } | 510 } |
569 | 511 |
570 // WriteTo to network. | 512 // WriteTo to network. |
571 | 513 |
572 type writeToOp struct { | 514 type writeToOp struct { |
573 bufOp | 515 bufOp |
574 sa syscall.Sockaddr | 516 sa syscall.Sockaddr |
575 } | 517 } |
576 | 518 |
577 func (o *writeToOp) Submit() error { | 519 func (o *writeToOp) Submit() error { |
(...skipping 11 matching lines...) Expand all Loading... |
589 } | 531 } |
590 if err := fd.incref(false); err != nil { | 532 if err := fd.incref(false); err != nil { |
591 return 0, err | 533 return 0, err |
592 } | 534 } |
593 defer fd.decref() | 535 defer fd.decref() |
594 fd.wio.Lock() | 536 fd.wio.Lock() |
595 defer fd.wio.Unlock() | 537 defer fd.wio.Unlock() |
596 var o writeToOp | 538 var o writeToOp |
597 o.Init(fd, buf, 'w') | 539 o.Init(fd, buf, 'w') |
598 o.sa = sa | 540 o.sa = sa |
599 » return iosrv.ExecIO(&o, fd.wdeadline.value()) | 541 » return iosrv.ExecIO(&o) |
600 } | 542 } |
601 | 543 |
602 // Accept new network connections. | 544 // Accept new network connections. |
603 | 545 |
604 type acceptOp struct { | 546 type acceptOp struct { |
605 anOp | 547 anOp |
606 newsock syscall.Handle | 548 newsock syscall.Handle |
607 attrs [2]syscall.RawSockaddrAny // space for local and remote address
only | 549 attrs [2]syscall.RawSockaddrAny // space for local and remote address
only |
608 } | 550 } |
609 | 551 |
(...skipping 14 matching lines...) Expand all Loading... |
624 } | 566 } |
625 defer fd.decref() | 567 defer fd.decref() |
626 | 568 |
627 // Get new socket. | 569 // Get new socket. |
628 s, err := sysSocket(fd.family, fd.sotype, 0) | 570 s, err := sysSocket(fd.family, fd.sotype, 0) |
629 if err != nil { | 571 if err != nil { |
630 return nil, &OpError{"socket", fd.net, fd.laddr, err} | 572 return nil, &OpError{"socket", fd.net, fd.laddr, err} |
631 } | 573 } |
632 | 574 |
633 // Associate our new socket with IOCP. | 575 // Associate our new socket with IOCP. |
634 » onceStartServer.Do(startServer) | 576 » netfd, err := newFD(s, fd.family, fd.sotype, fd.net) |
635 » if _, err := syscall.CreateIoCompletionPort(s, resultsrv.iocp, 0, 0); er
r != nil { | 577 » if err != nil { |
636 closesocket(s) | 578 closesocket(s) |
637 » » return nil, &OpError{"CreateIoCompletionPort", fd.net, fd.laddr,
err} | 579 » » return nil, &OpError{"accept", fd.net, fd.laddr, err} |
638 } | 580 } |
639 | 581 |
640 // Submit accept request. | 582 // Submit accept request. |
641 var o acceptOp | 583 var o acceptOp |
642 o.Init(fd, 'r') | 584 o.Init(fd, 'r') |
643 o.newsock = s | 585 o.newsock = s |
644 » _, err = iosrv.ExecIO(&o, fd.rdeadline.value()) | 586 » _, err = iosrv.ExecIO(&o) |
645 if err != nil { | 587 if err != nil { |
646 closesocket(s) | 588 closesocket(s) |
647 return nil, err | 589 return nil, err |
648 } | 590 } |
649 | 591 |
650 // Inherit properties of the listening socket. | 592 // Inherit properties of the listening socket. |
651 err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT
_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd))) | 593 err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT
_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd))) |
652 if err != nil { | 594 if err != nil { |
653 closesocket(s) | 595 closesocket(s) |
654 return nil, &OpError{"Setsockopt", fd.net, fd.laddr, err} | 596 return nil, &OpError{"Setsockopt", fd.net, fd.laddr, err} |
655 } | 597 } |
656 | 598 |
657 // Get local and peer addr out of AcceptEx buffer. | 599 // Get local and peer addr out of AcceptEx buffer. |
658 var lrsa, rrsa *syscall.RawSockaddrAny | 600 var lrsa, rrsa *syscall.RawSockaddrAny |
659 var llen, rlen int32 | 601 var llen, rlen int32 |
660 l := uint32(unsafe.Sizeof(*lrsa)) | 602 l := uint32(unsafe.Sizeof(*lrsa)) |
661 syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&o.attrs[0])), | 603 syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&o.attrs[0])), |
662 0, l, l, &lrsa, &llen, &rrsa, &rlen) | 604 0, l, l, &lrsa, &llen, &rrsa, &rlen) |
663 lsa, _ := lrsa.Sockaddr() | 605 lsa, _ := lrsa.Sockaddr() |
664 rsa, _ := rrsa.Sockaddr() | 606 rsa, _ := rrsa.Sockaddr() |
665 | 607 |
666 netfd := allocFD(s, fd.family, fd.sotype, fd.net) | |
667 netfd.setAddr(toAddr(lsa), toAddr(rsa)) | 608 netfd.setAddr(toAddr(lsa), toAddr(rsa)) |
668 return netfd, nil | 609 return netfd, nil |
669 } | 610 } |
670 | 611 |
671 // Unimplemented functions. | 612 // Unimplemented functions. |
672 | 613 |
673 func (fd *netFD) dup() (*os.File, error) { | 614 func (fd *netFD) dup() (*os.File, error) { |
674 // TODO: Implement this | 615 // TODO: Implement this |
675 return nil, os.NewSyscallError("dup", syscall.EWINDOWS) | 616 return nil, os.NewSyscallError("dup", syscall.EWINDOWS) |
676 } | 617 } |
677 | 618 |
678 var errNoSupport = errors.New("address family not supported") | 619 var errNoSupport = errors.New("address family not supported") |
679 | 620 |
680 func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.S
ockaddr, err error) { | 621 func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.S
ockaddr, err error) { |
681 return 0, 0, 0, nil, errNoSupport | 622 return 0, 0, 0, nil, errNoSupport |
682 } | 623 } |
683 | 624 |
684 func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oob
n int, err error) { | 625 func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oob
n int, err error) { |
685 return 0, 0, errNoSupport | 626 return 0, 0, errNoSupport |
686 } | 627 } |
LEFT | RIGHT |