Left: | ||
Right: |
OLD | NEW |
---|---|
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 |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |