Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(5154)

Side by Side Diff: src/pkg/net/fd_windows.go

Issue 8670044: code review 8670044: net: implement netpoll for windows (Closed)
Patch Set: diff -r 0c9561ddf631 https://go.googlecode.com/hg/ Created 10 years, 11 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
87 » errno int32
88 » qty uint32
89
90 » errnoc chan error
91 » fd *netFD
92 } 92 }
93 93
94 func (o *anOp) Init(fd *netFD, mode int) { 94 func (o *anOp) Init(fd *netFD, mode int32) {
95 o.fd = fd 95 o.fd = fd
96 var i int 96 var i int
97 if mode == 'r' { 97 if mode == 'r' {
98 i = 0 98 i = 0
99 } else { 99 } else {
100 i = 1 100 i = 1
101 } 101 }
102 if fd.resultc[i] == nil {
103 fd.resultc[i] = make(chan ioResult, 1)
104 }
105 o.resultc = fd.resultc[i]
106 if fd.errnoc[i] == nil { 102 if fd.errnoc[i] == nil {
107 fd.errnoc[i] = make(chan error) 103 fd.errnoc[i] = make(chan error)
108 } 104 }
109 o.errnoc = fd.errnoc[i] 105 o.errnoc = fd.errnoc[i]
106 o.runtimeCtx = fd.pd.runtimeCtx
107 o.mode = mode
110 } 108 }
111 109
112 func (o *anOp) Op() *anOp { 110 func (o *anOp) Op() *anOp {
113 return o 111 return o
114 } 112 }
115 113
116 // bufOp is used by IO operations that read / write 114 // bufOp is used by IO operations that read / write
117 // data from / to client buffer. 115 // data from / to client buffer.
118 type bufOp struct { 116 type bufOp struct {
119 anOp 117 anOp
120 buf syscall.WSABuf 118 buf syscall.WSABuf
121 } 119 }
122 120
123 func (o *bufOp) Init(fd *netFD, buf []byte, mode int) { 121 func (o *bufOp) Init(fd *netFD, buf []byte, mode int32) {
124 o.anOp.Init(fd, mode) 122 o.anOp.Init(fd, mode)
125 o.buf.Len = uint32(len(buf)) 123 o.buf.Len = uint32(len(buf))
126 if len(buf) == 0 { 124 if len(buf) == 0 {
127 o.buf.Buf = nil 125 o.buf.Buf = nil
128 } else { 126 } else {
129 o.buf.Buf = (*byte)(unsafe.Pointer(&buf[0])) 127 o.buf.Buf = (*byte)(unsafe.Pointer(&buf[0]))
130 } 128 }
131 } 129 }
132 130
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 }
166 }
167
168 // ioSrv executes net IO requests. 131 // ioSrv executes net IO requests.
169 type ioSrv struct { 132 type ioSrv struct {
170 submchan chan anOpIface // submit IO requests 133 submchan chan anOpIface // submit IO requests
171 canchan chan anOpIface // cancel IO requests 134 canchan chan anOpIface // cancel IO requests
172 } 135 }
173 136
174 // ProcessRemoteIO will execute submit IO requests on behalf 137 // ProcessRemoteIO will execute submit IO requests on behalf
175 // of other goroutines, all on a single os thread, so it can 138 // of other goroutines, all on a single os thread, so it can
176 // cancel them later. Results of all operations will be sent 139 // cancel them later. Results of all operations will be sent
177 // back to their requesters via channel supplied in request. 140 // back to their requesters via channel supplied in request.
178 // It is used only when the CancelIoEx API is unavailable. 141 // It is used only when the CancelIoEx API is unavailable.
179 func (s *ioSrv) ProcessRemoteIO() { 142 func (s *ioSrv) ProcessRemoteIO() {
180 runtime.LockOSThread() 143 runtime.LockOSThread()
181 defer runtime.UnlockOSThread() 144 defer runtime.UnlockOSThread()
182 for { 145 for {
183 select { 146 select {
184 case o := <-s.submchan: 147 case o := <-s.submchan:
185 o.Op().errnoc <- o.Submit() 148 o.Op().errnoc <- o.Submit()
186 case o := <-s.canchan: 149 case o := <-s.canchan:
187 o.Op().errnoc <- syscall.CancelIo(syscall.Handle(o.Op(). fd.sysfd)) 150 o.Op().errnoc <- syscall.CancelIo(syscall.Handle(o.Op(). fd.sysfd))
188 } 151 }
189 } 152 }
190 } 153 }
191 154
192 // ExecIO executes a single IO operation oi. It submits and cancels 155 // ExecIO executes a single IO operation oi. It submits and cancels
193 // IO in the current thread for systems where Windows CancelIoEx API 156 // IO in the current thread for systems where Windows CancelIoEx API
194 // is available. Alternatively, it passes the request onto 157 // is available. Alternatively, it passes the request onto
195 // a special goroutine and waits for completion or cancels request. 158 // runtime netpoll and waits for completion or cancels request.
196 // deadline is unix nanos. 159 func (s *ioSrv) ExecIO(oi anOpIface) (int, error) {
197 func (s *ioSrv) ExecIO(oi anOpIface, deadline int64) (int, error) {
198 var err error 160 var err error
199 o := oi.Op() 161 o := oi.Op()
200 » // Calculate timeout delta. 162 » // Notify runtime netpoll about starting IO.
201 » var delta int64 163 » err = o.fd.pd.Prepare(int(o.mode))
202 » if deadline != 0 { 164 » if err != nil {
203 » » delta = deadline - time.Now().UnixNano() 165 » » 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 } 166 }
208 // Start IO. 167 // Start IO.
209 if canCancelIO { 168 if canCancelIO {
210 err = oi.Submit() 169 err = oi.Submit()
211 } else { 170 } else {
212 // Send request to a special dedicated thread, 171 // Send request to a special dedicated thread,
213 // so it can stop the IO with CancelIO later. 172 // so it can stop the IO with CancelIO later.
214 s.submchan <- oi 173 s.submchan <- oi
215 err = <-o.errnoc 174 err = <-o.errnoc
216 } 175 }
217 switch err { 176 switch err {
218 case nil: 177 case nil:
219 // IO completed immediately, but we need to get our completion m essage anyway. 178 // IO completed immediately, but we need to get our completion m essage anyway.
220 case syscall.ERROR_IO_PENDING: 179 case syscall.ERROR_IO_PENDING:
221 // IO started, and we have to wait for its completion. 180 // IO started, and we have to wait for its completion.
222 err = nil 181 err = nil
223 default: 182 default:
224 return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, err} 183 return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, err}
225 } 184 }
226 » // Setup timer, if deadline is given. 185 » // Wait for our request to complete.
227 » var timer <-chan time.Time 186 » err = o.fd.pd.Wait(int(o.mode))
228 » if delta > 0 { 187 » if err == nil {
229 » » t := time.NewTimer(time.Duration(delta) * time.Nanosecond) 188 » » // All is good. Extract our IO results and return.
230 » » defer t.Stop() 189 » » if o.errno != 0 {
231 » » timer = t.C 190 » » » err = syscall.Errno(o.errno)
191 » » » return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, err}
192 » » }
193 » » return int(o.qty), nil
232 } 194 }
233 » // Wait for our request to complete. 195 » // IO is interrupted by "close" or "timeout"
234 » var r ioResult 196 » netpollErr := err
235 » var cancelled, timeout bool 197 » switch netpollErr {
236 » select { 198 » case errClosing, errTimeout:
237 » case r = <-o.resultc: 199 » » // will deal with those.
238 » case <-timer: 200 » default:
239 » » cancelled = true 201 » » panic("net: unexpected runtime.netpoll error: " + netpollErr.Err or())
240 » » timeout = true
241 » case <-o.fd.closec:
242 » » cancelled = true
243 } 202 }
244 » if cancelled { 203 » // Cancel our request.
245 » » // Cancel it. 204 » if canCancelIO {
246 » » if canCancelIO { 205 » » err := syscall.CancelIoEx(syscall.Handle(o.Op().fd.sysfd), &o.o)
247 » » » err := syscall.CancelIoEx(syscall.Handle(o.Op().fd.sysfd ), &o.o) 206 » » // Assuming ERROR_NOT_FOUND is returned, if IO is completed.
248 » » » // Assuming ERROR_NOT_FOUND is returned, if IO is comple ted. 207 » » if err != nil && err != syscall.ERROR_NOT_FOUND {
249 » » » if err != nil && err != syscall.ERROR_NOT_FOUND { 208 » » » // TODO(brainman): maybe do something else, but panic.
250 » » » » // TODO(brainman): maybe do something else, but panic. 209 » » » panic(err)
251 » » » » panic(err)
252 » » » }
253 » » } else {
254 » » » s.canchan <- oi
255 » » » <-o.errnoc
256 } 210 }
257 » » // Wait for IO to be canceled or complete successfully. 211 » } else {
258 » » r = <-o.resultc 212 » » s.canchan <- oi
259 » » if r.err == syscall.ERROR_OPERATION_ABORTED { // IO Canceled 213 » » <-o.errnoc
260 » » » if timeout {
261 » » » » r.err = errTimeout
262 » » » } else {
263 » » » » r.err = errClosing
264 » » » }
265 » » }
266 } 214 }
267 » if r.err != nil { 215 » // Wait for cancelation to complete.
268 » » err = &OpError{oi.Name(), o.fd.net, o.fd.laddr, r.err} 216 » o.fd.pd.WaitCanceled(int(o.mode))
dvyukov 2013/05/19 15:20:31 wait. you need the result from WaitCanceled. at th
brainman 2013/05/20 02:12:45 I don't care if it succeeds or not, because our pr
dvyukov 2013/05/20 04:02:54 When you are writing/reading to/from network you w
269 » } 217 » return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, netpollErr}
270 » return int(r.qty), err
271 } 218 }
272 219
273 // Start helper goroutines. 220 // Start helper goroutines.
274 var resultsrv *resultSrv
275 var iosrv *ioSrv 221 var iosrv *ioSrv
276 var onceStartServer sync.Once 222 var onceStartServer sync.Once
277 223
278 func startServer() { 224 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) 225 iosrv = new(ioSrv)
288 if !canCancelIO { 226 if !canCancelIO {
289 // Only CancelIo API is available. Lets start special goroutine 227 // Only CancelIo API is available. Lets start special goroutine
290 // locked to an OS thread, that both starts and cancels IO. 228 // locked to an OS thread, that both starts and cancels IO.
291 iosrv.submchan = make(chan anOpIface) 229 iosrv.submchan = make(chan anOpIface)
292 iosrv.canchan = make(chan anOpIface) 230 iosrv.canchan = make(chan anOpIface)
293 go iosrv.ProcessRemoteIO() 231 go iosrv.ProcessRemoteIO()
294 } 232 }
295 } 233 }
296 234
297 // Network file descriptor. 235 // Network file descriptor.
298 type netFD struct { 236 type netFD struct {
299 // locking/lifetime of sysfd 237 // locking/lifetime of sysfd
300 sysmu sync.Mutex 238 sysmu sync.Mutex
301 sysref int 239 sysref int
302 closing bool 240 closing bool
303 241
304 // immutable until Close 242 // immutable until Close
305 sysfd syscall.Handle 243 sysfd syscall.Handle
306 family int 244 family int
307 sotype int 245 sotype int
308 isConnected bool 246 isConnected bool
309 net string 247 net string
310 laddr Addr 248 laddr Addr
311 raddr Addr 249 raddr Addr
312 » resultc [2]chan ioResult // read/write completion results 250 » 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 251
316 // serialize access to Read and Write methods 252 // serialize access to Read and Write methods
317 rio, wio sync.Mutex 253 rio, wio sync.Mutex
318 254
319 » // read and write deadlines 255 » // wait server
320 » rdeadline, wdeadline deadline 256 » pd pollDesc
321 } 257 }
322 258
323 func allocFD(fd syscall.Handle, family, sotype int, net string) *netFD { 259 func newFD(fd syscall.Handle, family, sotype int, net string) (*netFD, error) {
260 » if initErr != nil {
261 » » return nil, initErr
262 » }
263 » onceStartServer.Do(startServer)
324 netfd := &netFD{ 264 netfd := &netFD{
325 sysfd: fd, 265 sysfd: fd,
326 family: family, 266 family: family,
327 sotype: sotype, 267 sotype: sotype,
328 net: net, 268 net: net,
329 closec: make(chan bool),
330 } 269 }
331 » return netfd 270 » if err := netfd.pd.Init(netfd); err != nil {
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 271 return nil, err
342 } 272 }
343 » return allocFD(fd, family, proto, net), nil 273 » return netfd, nil
344 } 274 }
345 275
346 func (fd *netFD) setAddr(laddr, raddr Addr) { 276 func (fd *netFD) setAddr(laddr, raddr Addr) {
347 fd.laddr = laddr 277 fd.laddr = laddr
348 fd.raddr = raddr 278 fd.raddr = raddr
349 runtime.SetFinalizer(fd, (*netFD).closesocket) 279 runtime.SetFinalizer(fd, (*netFD).closesocket)
350 } 280 }
351 281
352 // Make new connection. 282 // Make new connection.
353 283
(...skipping 24 matching lines...) Expand all
378 default: 308 default:
379 panic("unexpected type in connect") 309 panic("unexpected type in connect")
380 } 310 }
381 if err := syscall.Bind(fd.sysfd, la); err != nil { 311 if err := syscall.Bind(fd.sysfd, la); err != nil {
382 return err 312 return err
383 } 313 }
384 // Call ConnectEx API. 314 // Call ConnectEx API.
385 var o connectOp 315 var o connectOp
386 o.Init(fd, 'w') 316 o.Init(fd, 'w')
387 o.ra = ra 317 o.ra = ra
388 » _, err := iosrv.ExecIO(&o, fd.wdeadline.value()) 318 » _, err := iosrv.ExecIO(&o)
389 if err != nil { 319 if err != nil {
390 return err 320 return err
391 } 321 }
392 // Refresh socket properties. 322 // Refresh socket properties.
393 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))) 323 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)))
394 } 324 }
395 325
396 // Add a reference to this fd. 326 // Add a reference to this fd.
397 // If closing==true, mark the fd as closing. 327 // If closing==true, mark the fd as closing.
398 // Returns an error if the fd cannot be used. 328 // Returns an error if the fd cannot be used.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
430 } 360 }
431 fd.sysmu.Unlock() 361 fd.sysmu.Unlock()
432 } 362 }
433 363
434 func (fd *netFD) Close() error { 364 func (fd *netFD) Close() error {
435 if err := fd.incref(true); err != nil { 365 if err := fd.incref(true); err != nil {
436 return err 366 return err
437 } 367 }
438 defer fd.decref() 368 defer fd.decref()
439 // unblock pending reader and writer 369 // unblock pending reader and writer
440 » close(fd.closec) 370 » fd.pd.Evict()
441 // wait for both reader and writer to exit 371 // wait for both reader and writer to exit
442 fd.rio.Lock() 372 fd.rio.Lock()
443 defer fd.rio.Unlock() 373 defer fd.rio.Unlock()
444 fd.wio.Lock() 374 fd.wio.Lock()
445 defer fd.wio.Unlock() 375 defer fd.wio.Unlock()
446 return nil 376 return nil
447 } 377 }
448 378
449 func (fd *netFD) shutdown(how int) error { 379 func (fd *netFD) shutdown(how int) error {
450 if err := fd.incref(false); err != nil { 380 if err := fd.incref(false); err != nil {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
487 417
488 func (fd *netFD) Read(buf []byte) (int, error) { 418 func (fd *netFD) Read(buf []byte) (int, error) {
489 if err := fd.incref(false); err != nil { 419 if err := fd.incref(false); err != nil {
490 return 0, err 420 return 0, err
491 } 421 }
492 defer fd.decref() 422 defer fd.decref()
493 fd.rio.Lock() 423 fd.rio.Lock()
494 defer fd.rio.Unlock() 424 defer fd.rio.Unlock()
495 var o readOp 425 var o readOp
496 o.Init(fd, buf, 'r') 426 o.Init(fd, buf, 'r')
497 » n, err := iosrv.ExecIO(&o, fd.rdeadline.value()) 427 » n, err := iosrv.ExecIO(&o)
498 if err == nil && n == 0 { 428 if err == nil && n == 0 {
499 err = io.EOF 429 err = io.EOF
500 } 430 }
501 return n, err 431 return n, err
502 } 432 }
503 433
504 // ReadFrom from network. 434 // ReadFrom from network.
505 435
506 type readFromOp struct { 436 type readFromOp struct {
507 bufOp 437 bufOp
(...skipping 16 matching lines...) Expand all
524 } 454 }
525 if err := fd.incref(false); err != nil { 455 if err := fd.incref(false); err != nil {
526 return 0, nil, err 456 return 0, nil, err
527 } 457 }
528 defer fd.decref() 458 defer fd.decref()
529 fd.rio.Lock() 459 fd.rio.Lock()
530 defer fd.rio.Unlock() 460 defer fd.rio.Unlock()
531 var o readFromOp 461 var o readFromOp
532 o.Init(fd, buf, 'r') 462 o.Init(fd, buf, 'r')
533 o.rsan = int32(unsafe.Sizeof(o.rsa)) 463 o.rsan = int32(unsafe.Sizeof(o.rsa))
534 » n, err = iosrv.ExecIO(&o, fd.rdeadline.value()) 464 » n, err = iosrv.ExecIO(&o)
535 if err != nil { 465 if err != nil {
536 return 0, nil, err 466 return 0, nil, err
537 } 467 }
538 sa, _ = o.rsa.Sockaddr() 468 sa, _ = o.rsa.Sockaddr()
539 return 469 return
540 } 470 }
541 471
542 // Write to network. 472 // Write to network.
543 473
544 type writeOp struct { 474 type writeOp struct {
(...skipping 11 matching lines...) Expand all
556 486
557 func (fd *netFD) Write(buf []byte) (int, error) { 487 func (fd *netFD) Write(buf []byte) (int, error) {
558 if err := fd.incref(false); err != nil { 488 if err := fd.incref(false); err != nil {
559 return 0, err 489 return 0, err
560 } 490 }
561 defer fd.decref() 491 defer fd.decref()
562 fd.wio.Lock() 492 fd.wio.Lock()
563 defer fd.wio.Unlock() 493 defer fd.wio.Unlock()
564 var o writeOp 494 var o writeOp
565 o.Init(fd, buf, 'w') 495 o.Init(fd, buf, 'w')
566 » return iosrv.ExecIO(&o, fd.wdeadline.value()) 496 » return iosrv.ExecIO(&o)
567 } 497 }
568 498
569 // WriteTo to network. 499 // WriteTo to network.
570 500
571 type writeToOp struct { 501 type writeToOp struct {
572 bufOp 502 bufOp
573 sa syscall.Sockaddr 503 sa syscall.Sockaddr
574 } 504 }
575 505
576 func (o *writeToOp) Submit() error { 506 func (o *writeToOp) Submit() error {
(...skipping 11 matching lines...) Expand all
588 } 518 }
589 if err := fd.incref(false); err != nil { 519 if err := fd.incref(false); err != nil {
590 return 0, err 520 return 0, err
591 } 521 }
592 defer fd.decref() 522 defer fd.decref()
593 fd.wio.Lock() 523 fd.wio.Lock()
594 defer fd.wio.Unlock() 524 defer fd.wio.Unlock()
595 var o writeToOp 525 var o writeToOp
596 o.Init(fd, buf, 'w') 526 o.Init(fd, buf, 'w')
597 o.sa = sa 527 o.sa = sa
598 » return iosrv.ExecIO(&o, fd.wdeadline.value()) 528 » return iosrv.ExecIO(&o)
599 } 529 }
600 530
601 // Accept new network connections. 531 // Accept new network connections.
602 532
603 type acceptOp struct { 533 type acceptOp struct {
604 anOp 534 anOp
605 newsock syscall.Handle 535 newsock syscall.Handle
606 attrs [2]syscall.RawSockaddrAny // space for local and remote address only 536 attrs [2]syscall.RawSockaddrAny // space for local and remote address only
607 } 537 }
608 538
(...skipping 14 matching lines...) Expand all
623 } 553 }
624 defer fd.decref() 554 defer fd.decref()
625 555
626 // Get new socket. 556 // Get new socket.
627 s, err := sysSocket(fd.family, fd.sotype, 0) 557 s, err := sysSocket(fd.family, fd.sotype, 0)
628 if err != nil { 558 if err != nil {
629 return nil, &OpError{"socket", fd.net, fd.laddr, err} 559 return nil, &OpError{"socket", fd.net, fd.laddr, err}
630 } 560 }
631 561
632 // Associate our new socket with IOCP. 562 // Associate our new socket with IOCP.
633 » onceStartServer.Do(startServer) 563 » netfd, err := newFD(s, fd.family, fd.sotype, fd.net)
634 » if _, err := syscall.CreateIoCompletionPort(s, resultsrv.iocp, 0, 0); er r != nil { 564 » if err != nil {
635 closesocket(s) 565 closesocket(s)
636 » » return nil, &OpError{"CreateIoCompletionPort", fd.net, fd.laddr, err} 566 » » return nil, &OpError{"accept", fd.net, fd.laddr, err}
637 } 567 }
638 568
639 // Submit accept request. 569 // Submit accept request.
640 var o acceptOp 570 var o acceptOp
641 o.Init(fd, 'r') 571 o.Init(fd, 'r')
642 o.newsock = s 572 o.newsock = s
643 » _, err = iosrv.ExecIO(&o, fd.rdeadline.value()) 573 » _, err = iosrv.ExecIO(&o)
644 if err != nil { 574 if err != nil {
645 closesocket(s) 575 closesocket(s)
646 return nil, err 576 return nil, err
647 } 577 }
648 578
649 // Inherit properties of the listening socket. 579 // Inherit properties of the listening socket.
650 err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT _CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd))) 580 err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT _CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd)))
651 if err != nil { 581 if err != nil {
652 closesocket(s) 582 closesocket(s)
653 return nil, &OpError{"Setsockopt", fd.net, fd.laddr, err} 583 return nil, &OpError{"Setsockopt", fd.net, fd.laddr, err}
654 } 584 }
655 585
656 // Get local and peer addr out of AcceptEx buffer. 586 // Get local and peer addr out of AcceptEx buffer.
657 var lrsa, rrsa *syscall.RawSockaddrAny 587 var lrsa, rrsa *syscall.RawSockaddrAny
658 var llen, rlen int32 588 var llen, rlen int32
659 l := uint32(unsafe.Sizeof(*lrsa)) 589 l := uint32(unsafe.Sizeof(*lrsa))
660 syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&o.attrs[0])), 590 syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&o.attrs[0])),
661 0, l, l, &lrsa, &llen, &rrsa, &rlen) 591 0, l, l, &lrsa, &llen, &rrsa, &rlen)
662 lsa, _ := lrsa.Sockaddr() 592 lsa, _ := lrsa.Sockaddr()
663 rsa, _ := rrsa.Sockaddr() 593 rsa, _ := rrsa.Sockaddr()
664 594
665 netfd := allocFD(s, fd.family, fd.sotype, fd.net)
666 netfd.setAddr(toAddr(lsa), toAddr(rsa)) 595 netfd.setAddr(toAddr(lsa), toAddr(rsa))
667 return netfd, nil 596 return netfd, nil
668 } 597 }
669 598
670 // Unimplemented functions. 599 // Unimplemented functions.
671 600
672 func (fd *netFD) dup() (*os.File, error) { 601 func (fd *netFD) dup() (*os.File, error) {
673 // TODO: Implement this 602 // TODO: Implement this
674 return nil, os.NewSyscallError("dup", syscall.EWINDOWS) 603 return nil, os.NewSyscallError("dup", syscall.EWINDOWS)
675 } 604 }
676 605
677 var errNoSupport = errors.New("address family not supported") 606 var errNoSupport = errors.New("address family not supported")
678 607
679 func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.S ockaddr, err error) { 608 func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.S ockaddr, err error) {
680 return 0, 0, 0, nil, errNoSupport 609 return 0, 0, 0, nil, errNoSupport
681 } 610 }
682 611
683 func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oob n int, err error) { 612 func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oob n int, err error) {
684 return 0, 0, errNoSupport 613 return 0, 0, errNoSupport
685 } 614 }
OLDNEW

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b