github.com/spotify/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/net/fd_windows.go (about) 1 // Copyright 2010 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package net 6 7 import ( 8 "errors" 9 "io" 10 "os" 11 "runtime" 12 "sync" 13 "syscall" 14 "time" 15 "unsafe" 16 ) 17 18 var ( 19 initErr error 20 ioSync uint64 21 ) 22 23 // CancelIo Windows API cancels all outstanding IO for a particular 24 // socket on current thread. To overcome that limitation, we run 25 // special goroutine, locked to OS single thread, that both starts 26 // and cancels IO. It means, there are 2 unavoidable thread switches 27 // for every IO. 28 // Some newer versions of Windows has new CancelIoEx API, that does 29 // not have that limitation and can be used from any thread. This 30 // package uses CancelIoEx API, if present, otherwise it fallback 31 // to CancelIo. 32 33 var ( 34 canCancelIO bool // determines if CancelIoEx API is present 35 skipSyncNotif bool 36 hasLoadSetFileCompletionNotificationModes bool 37 ) 38 39 func sysInit() { 40 var d syscall.WSAData 41 e := syscall.WSAStartup(uint32(0x202), &d) 42 if e != nil { 43 initErr = os.NewSyscallError("WSAStartup", e) 44 } 45 canCancelIO = syscall.LoadCancelIoEx() == nil 46 if syscall.LoadGetAddrInfo() == nil { 47 lookupPort = newLookupPort 48 lookupIP = newLookupIP 49 } 50 51 hasLoadSetFileCompletionNotificationModes = syscall.LoadSetFileCompletionNotificationModes() == nil 52 if hasLoadSetFileCompletionNotificationModes { 53 // It's not safe to use FILE_SKIP_COMPLETION_PORT_ON_SUCCESS if non IFS providers are installed: 54 // http://support.microsoft.com/kb/2568167 55 skipSyncNotif = true 56 protos := [2]int32{syscall.IPPROTO_TCP, 0} 57 var buf [32]syscall.WSAProtocolInfo 58 len := uint32(unsafe.Sizeof(buf)) 59 n, err := syscall.WSAEnumProtocols(&protos[0], &buf[0], &len) 60 if err != nil { 61 skipSyncNotif = false 62 } else { 63 for i := int32(0); i < n; i++ { 64 if buf[i].ServiceFlags1&syscall.XP1_IFS_HANDLES == 0 { 65 skipSyncNotif = false 66 break 67 } 68 } 69 } 70 } 71 } 72 73 func closesocket(s syscall.Handle) error { 74 return syscall.Closesocket(s) 75 } 76 77 func canUseConnectEx(net string) bool { 78 switch net { 79 case "udp", "udp4", "udp6", "ip", "ip4", "ip6": 80 // ConnectEx windows API does not support connectionless sockets. 81 return false 82 } 83 return syscall.LoadConnectEx() == nil 84 } 85 86 func dial(net string, ra Addr, dialer func(time.Time) (Conn, error), deadline time.Time) (Conn, error) { 87 if !canUseConnectEx(net) { 88 // Use the relatively inefficient goroutine-racing 89 // implementation of DialTimeout. 90 return dialChannel(net, ra, dialer, deadline) 91 } 92 return dialer(deadline) 93 } 94 95 // operation contains superset of data necessary to perform all async IO. 96 type operation struct { 97 // Used by IOCP interface, it must be first field 98 // of the struct, as our code rely on it. 99 o syscall.Overlapped 100 101 // fields used by runtime.netpoll 102 runtimeCtx uintptr 103 mode int32 104 errno int32 105 qty uint32 106 107 // fields used only by net package 108 fd *netFD 109 errc chan error 110 buf syscall.WSABuf 111 sa syscall.Sockaddr 112 rsa *syscall.RawSockaddrAny 113 rsan int32 114 handle syscall.Handle 115 flags uint32 116 } 117 118 func (o *operation) InitBuf(buf []byte) { 119 o.buf.Len = uint32(len(buf)) 120 o.buf.Buf = nil 121 if len(buf) != 0 { 122 o.buf.Buf = (*byte)(unsafe.Pointer(&buf[0])) 123 } 124 } 125 126 // ioSrv executes net IO requests. 127 type ioSrv struct { 128 req chan ioSrvReq 129 } 130 131 type ioSrvReq struct { 132 o *operation 133 submit func(o *operation) error // if nil, cancel the operation 134 } 135 136 // ProcessRemoteIO will execute submit IO requests on behalf 137 // of other goroutines, all on a single os thread, so it can 138 // cancel them later. Results of all operations will be sent 139 // back to their requesters via channel supplied in request. 140 // It is used only when the CancelIoEx API is unavailable. 141 func (s *ioSrv) ProcessRemoteIO() { 142 runtime.LockOSThread() 143 defer runtime.UnlockOSThread() 144 for r := range s.req { 145 if r.submit != nil { 146 r.o.errc <- r.submit(r.o) 147 } else { 148 r.o.errc <- syscall.CancelIo(r.o.fd.sysfd) 149 } 150 } 151 } 152 153 // ExecIO executes a single IO operation o. It submits and cancels 154 // IO in the current thread for systems where Windows CancelIoEx API 155 // is available. Alternatively, it passes the request onto 156 // runtime netpoll and waits for completion or cancels request. 157 func (s *ioSrv) ExecIO(o *operation, name string, submit func(o *operation) error) (int, error) { 158 fd := o.fd 159 // Notify runtime netpoll about starting IO. 160 err := fd.pd.Prepare(int(o.mode)) 161 if err != nil { 162 return 0, &OpError{name, fd.net, fd.laddr, err} 163 } 164 // Start IO. 165 if canCancelIO { 166 err = submit(o) 167 } else { 168 // Send request to a special dedicated thread, 169 // so it can stop the IO with CancelIO later. 170 s.req <- ioSrvReq{o, submit} 171 err = <-o.errc 172 } 173 switch err { 174 case nil: 175 // IO completed immediately 176 if o.fd.skipSyncNotif { 177 // No completion message will follow, so return immediately. 178 return int(o.qty), nil 179 } 180 // Need to get our completion message anyway. 181 case syscall.ERROR_IO_PENDING: 182 // IO started, and we have to wait for its completion. 183 err = nil 184 default: 185 return 0, &OpError{name, fd.net, fd.laddr, err} 186 } 187 // Wait for our request to complete. 188 err = fd.pd.Wait(int(o.mode)) 189 if err == nil { 190 // All is good. Extract our IO results and return. 191 if o.errno != 0 { 192 err = syscall.Errno(o.errno) 193 return 0, &OpError{name, fd.net, fd.laddr, err} 194 } 195 return int(o.qty), nil 196 } 197 // IO is interrupted by "close" or "timeout" 198 netpollErr := err 199 switch netpollErr { 200 case errClosing, errTimeout: 201 // will deal with those. 202 default: 203 panic("net: unexpected runtime.netpoll error: " + netpollErr.Error()) 204 } 205 // Cancel our request. 206 if canCancelIO { 207 err := syscall.CancelIoEx(fd.sysfd, &o.o) 208 // Assuming ERROR_NOT_FOUND is returned, if IO is completed. 209 if err != nil && err != syscall.ERROR_NOT_FOUND { 210 // TODO(brainman): maybe do something else, but panic. 211 panic(err) 212 } 213 } else { 214 s.req <- ioSrvReq{o, nil} 215 <-o.errc 216 } 217 // Wait for cancellation to complete. 218 fd.pd.WaitCanceled(int(o.mode)) 219 if o.errno != 0 { 220 err = syscall.Errno(o.errno) 221 if err == syscall.ERROR_OPERATION_ABORTED { // IO Canceled 222 err = netpollErr 223 } 224 return 0, &OpError{name, fd.net, 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 230 } 231 232 // Start helper goroutines. 233 var rsrv, wsrv *ioSrv 234 var onceStartServer sync.Once 235 236 func startServer() { 237 rsrv = new(ioSrv) 238 wsrv = new(ioSrv) 239 if !canCancelIO { 240 // Only CancelIo API is available. Lets start two special goroutines 241 // locked to an OS thread, that both starts and cancels IO. One will 242 // process read requests, while other will do writes. 243 rsrv.req = make(chan ioSrvReq) 244 go rsrv.ProcessRemoteIO() 245 wsrv.req = make(chan ioSrvReq) 246 go wsrv.ProcessRemoteIO() 247 } 248 } 249 250 // Network file descriptor. 251 type netFD struct { 252 // locking/lifetime of sysfd + serialize access to Read and Write methods 253 fdmu fdMutex 254 255 // immutable until Close 256 sysfd syscall.Handle 257 family int 258 sotype int 259 isConnected bool 260 skipSyncNotif bool 261 net string 262 laddr Addr 263 raddr Addr 264 265 rop operation // read operation 266 wop operation // write operation 267 268 // wait server 269 pd pollDesc 270 } 271 272 func newFD(sysfd syscall.Handle, family, sotype int, net string) (*netFD, error) { 273 if initErr != nil { 274 return nil, initErr 275 } 276 onceStartServer.Do(startServer) 277 return &netFD{sysfd: sysfd, family: family, sotype: sotype, net: net}, nil 278 } 279 280 func (fd *netFD) init() error { 281 if err := fd.pd.Init(fd); err != nil { 282 return err 283 } 284 if hasLoadSetFileCompletionNotificationModes { 285 // We do not use events, so we can skip them always. 286 flags := uint8(syscall.FILE_SKIP_SET_EVENT_ON_HANDLE) 287 // It's not safe to skip completion notifications for UDP: 288 // http://blogs.technet.com/b/winserverperformance/archive/2008/06/26/designing-applications-for-high-performance-part-iii.aspx 289 if skipSyncNotif && fd.net == "tcp" { 290 flags |= syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS 291 } 292 err := syscall.SetFileCompletionNotificationModes(fd.sysfd, flags) 293 if err == nil && flags&syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS != 0 { 294 fd.skipSyncNotif = true 295 } 296 } 297 fd.rop.mode = 'r' 298 fd.wop.mode = 'w' 299 fd.rop.fd = fd 300 fd.wop.fd = fd 301 fd.rop.runtimeCtx = fd.pd.runtimeCtx 302 fd.wop.runtimeCtx = fd.pd.runtimeCtx 303 if !canCancelIO { 304 fd.rop.errc = make(chan error) 305 fd.wop.errc = make(chan error) 306 } 307 return nil 308 } 309 310 func (fd *netFD) setAddr(laddr, raddr Addr) { 311 fd.laddr = laddr 312 fd.raddr = raddr 313 runtime.SetFinalizer(fd, (*netFD).Close) 314 } 315 316 func (fd *netFD) connect(la, ra syscall.Sockaddr) error { 317 // Do not need to call fd.writeLock here, 318 // because fd is not yet accessible to user, 319 // so no concurrent operations are possible. 320 if !canUseConnectEx(fd.net) { 321 return syscall.Connect(fd.sysfd, ra) 322 } 323 // ConnectEx windows API requires an unconnected, previously bound socket. 324 if la == nil { 325 switch ra.(type) { 326 case *syscall.SockaddrInet4: 327 la = &syscall.SockaddrInet4{} 328 case *syscall.SockaddrInet6: 329 la = &syscall.SockaddrInet6{} 330 default: 331 panic("unexpected type in connect") 332 } 333 if err := syscall.Bind(fd.sysfd, la); err != nil { 334 return err 335 } 336 } 337 // Call ConnectEx API. 338 o := &fd.wop 339 o.sa = ra 340 _, err := wsrv.ExecIO(o, "ConnectEx", func(o *operation) error { 341 return syscall.ConnectEx(o.fd.sysfd, o.sa, nil, 0, nil, &o.o) 342 }) 343 if err != nil { 344 return err 345 } 346 // Refresh socket properties. 347 return syscall.Setsockopt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_UPDATE_CONNECT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd))) 348 } 349 350 func (fd *netFD) destroy() { 351 if fd.sysfd == syscall.InvalidHandle { 352 return 353 } 354 // Poller may want to unregister fd in readiness notification mechanism, 355 // so this must be executed before closesocket. 356 fd.pd.Close() 357 closesocket(fd.sysfd) 358 fd.sysfd = syscall.InvalidHandle 359 // no need for a finalizer anymore 360 runtime.SetFinalizer(fd, nil) 361 } 362 363 // Add a reference to this fd. 364 // Returns an error if the fd cannot be used. 365 func (fd *netFD) incref() error { 366 if !fd.fdmu.Incref() { 367 return errClosing 368 } 369 return nil 370 } 371 372 // Remove a reference to this FD and close if we've been asked to do so 373 // (and there are no references left). 374 func (fd *netFD) decref() { 375 if fd.fdmu.Decref() { 376 fd.destroy() 377 } 378 } 379 380 // Add a reference to this fd and lock for reading. 381 // Returns an error if the fd cannot be used. 382 func (fd *netFD) readLock() error { 383 if !fd.fdmu.RWLock(true) { 384 return errClosing 385 } 386 return nil 387 } 388 389 // Unlock for reading and remove a reference to this FD. 390 func (fd *netFD) readUnlock() { 391 if fd.fdmu.RWUnlock(true) { 392 fd.destroy() 393 } 394 } 395 396 // Add a reference to this fd and lock for writing. 397 // Returns an error if the fd cannot be used. 398 func (fd *netFD) writeLock() error { 399 if !fd.fdmu.RWLock(false) { 400 return errClosing 401 } 402 return nil 403 } 404 405 // Unlock for writing and remove a reference to this FD. 406 func (fd *netFD) writeUnlock() { 407 if fd.fdmu.RWUnlock(false) { 408 fd.destroy() 409 } 410 } 411 412 func (fd *netFD) Close() error { 413 if !fd.fdmu.IncrefAndClose() { 414 return errClosing 415 } 416 // unblock pending reader and writer 417 fd.pd.Evict() 418 fd.decref() 419 return nil 420 } 421 422 func (fd *netFD) shutdown(how int) error { 423 if err := fd.incref(); err != nil { 424 return err 425 } 426 defer fd.decref() 427 err := syscall.Shutdown(fd.sysfd, how) 428 if err != nil { 429 return &OpError{"shutdown", fd.net, fd.laddr, err} 430 } 431 return nil 432 } 433 434 func (fd *netFD) CloseRead() error { 435 return fd.shutdown(syscall.SHUT_RD) 436 } 437 438 func (fd *netFD) CloseWrite() error { 439 return fd.shutdown(syscall.SHUT_WR) 440 } 441 442 func (fd *netFD) Read(buf []byte) (int, error) { 443 if err := fd.readLock(); err != nil { 444 return 0, err 445 } 446 defer fd.readUnlock() 447 o := &fd.rop 448 o.InitBuf(buf) 449 n, err := rsrv.ExecIO(o, "WSARecv", func(o *operation) error { 450 return syscall.WSARecv(o.fd.sysfd, &o.buf, 1, &o.qty, &o.flags, &o.o, nil) 451 }) 452 if err == nil && n == 0 { 453 err = io.EOF 454 } 455 if raceenabled { 456 raceAcquire(unsafe.Pointer(&ioSync)) 457 } 458 return n, err 459 } 460 461 func (fd *netFD) ReadFrom(buf []byte) (n int, sa syscall.Sockaddr, err error) { 462 if len(buf) == 0 { 463 return 0, nil, nil 464 } 465 if err := fd.readLock(); err != nil { 466 return 0, nil, err 467 } 468 defer fd.readUnlock() 469 o := &fd.rop 470 o.InitBuf(buf) 471 n, err = rsrv.ExecIO(o, "WSARecvFrom", func(o *operation) error { 472 if o.rsa == nil { 473 o.rsa = new(syscall.RawSockaddrAny) 474 } 475 o.rsan = int32(unsafe.Sizeof(*o.rsa)) 476 return syscall.WSARecvFrom(o.fd.sysfd, &o.buf, 1, &o.qty, &o.flags, o.rsa, &o.rsan, &o.o, nil) 477 }) 478 if err != nil { 479 return 0, nil, err 480 } 481 sa, _ = o.rsa.Sockaddr() 482 return 483 } 484 485 func (fd *netFD) Write(buf []byte) (int, error) { 486 if err := fd.writeLock(); err != nil { 487 return 0, err 488 } 489 defer fd.writeUnlock() 490 if raceenabled { 491 raceReleaseMerge(unsafe.Pointer(&ioSync)) 492 } 493 o := &fd.wop 494 o.InitBuf(buf) 495 return wsrv.ExecIO(o, "WSASend", func(o *operation) error { 496 return syscall.WSASend(o.fd.sysfd, &o.buf, 1, &o.qty, 0, &o.o, nil) 497 }) 498 } 499 500 func (fd *netFD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) { 501 if len(buf) == 0 { 502 return 0, nil 503 } 504 if err := fd.writeLock(); err != nil { 505 return 0, err 506 } 507 defer fd.writeUnlock() 508 o := &fd.wop 509 o.InitBuf(buf) 510 o.sa = sa 511 return wsrv.ExecIO(o, "WSASendto", func(o *operation) error { 512 return syscall.WSASendto(o.fd.sysfd, &o.buf, 1, &o.qty, 0, o.sa, &o.o, nil) 513 }) 514 } 515 516 func (fd *netFD) acceptOne(toAddr func(syscall.Sockaddr) Addr, rawsa []syscall.RawSockaddrAny, o *operation) (*netFD, error) { 517 // Get new socket. 518 s, err := sysSocket(fd.family, fd.sotype, 0) 519 if err != nil { 520 return nil, &OpError{"socket", fd.net, fd.laddr, err} 521 } 522 523 // Associate our new socket with IOCP. 524 netfd, err := newFD(s, fd.family, fd.sotype, fd.net) 525 if err != nil { 526 closesocket(s) 527 return nil, &OpError{"accept", fd.net, fd.laddr, err} 528 } 529 if err := netfd.init(); err != nil { 530 fd.Close() 531 return nil, err 532 } 533 534 // Submit accept request. 535 o.handle = s 536 o.rsan = int32(unsafe.Sizeof(rawsa[0])) 537 _, err = rsrv.ExecIO(o, "AcceptEx", func(o *operation) error { 538 return syscall.AcceptEx(o.fd.sysfd, o.handle, (*byte)(unsafe.Pointer(&rawsa[0])), 0, uint32(o.rsan), uint32(o.rsan), &o.qty, &o.o) 539 }) 540 if err != nil { 541 netfd.Close() 542 return nil, err 543 } 544 545 // Inherit properties of the listening socket. 546 err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd))) 547 if err != nil { 548 netfd.Close() 549 return nil, &OpError{"Setsockopt", fd.net, fd.laddr, err} 550 } 551 552 return netfd, nil 553 } 554 555 func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) { 556 if err := fd.readLock(); err != nil { 557 return nil, err 558 } 559 defer fd.readUnlock() 560 561 o := &fd.rop 562 var netfd *netFD 563 var err error 564 var rawsa [2]syscall.RawSockaddrAny 565 for { 566 netfd, err = fd.acceptOne(toAddr, rawsa[:], o) 567 if err == nil { 568 break 569 } 570 // Sometimes we see WSAECONNRESET and ERROR_NETNAME_DELETED is 571 // returned here. These happen if connection reset is received 572 // before AcceptEx could complete. These errors relate to new 573 // connection, not to AcceptEx, so ignore broken connection and 574 // try AcceptEx again for more connections. 575 operr, ok := err.(*OpError) 576 if !ok { 577 return nil, err 578 } 579 errno, ok := operr.Err.(syscall.Errno) 580 if !ok { 581 return nil, err 582 } 583 switch errno { 584 case syscall.ERROR_NETNAME_DELETED, syscall.WSAECONNRESET: 585 // ignore these and try again 586 default: 587 return nil, err 588 } 589 } 590 591 // Get local and peer addr out of AcceptEx buffer. 592 var lrsa, rrsa *syscall.RawSockaddrAny 593 var llen, rlen int32 594 syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&rawsa[0])), 595 0, uint32(o.rsan), uint32(o.rsan), &lrsa, &llen, &rrsa, &rlen) 596 lsa, _ := lrsa.Sockaddr() 597 rsa, _ := rrsa.Sockaddr() 598 599 netfd.setAddr(toAddr(lsa), toAddr(rsa)) 600 return netfd, nil 601 } 602 603 func skipRawSocketTests() (skip bool, skipmsg string, err error) { 604 // From http://msdn.microsoft.com/en-us/library/windows/desktop/ms740548.aspx: 605 // Note: To use a socket of type SOCK_RAW requires administrative privileges. 606 // Users running Winsock applications that use raw sockets must be a member of 607 // the Administrators group on the local computer, otherwise raw socket calls 608 // will fail with an error code of WSAEACCES. On Windows Vista and later, access 609 // for raw sockets is enforced at socket creation. In earlier versions of Windows, 610 // access for raw sockets is enforced during other socket operations. 611 s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, 0) 612 if err == syscall.WSAEACCES { 613 return true, "skipping test; no access to raw socket allowed", nil 614 } 615 if err != nil { 616 return true, "", err 617 } 618 defer syscall.Closesocket(s) 619 return false, "", nil 620 } 621 622 // Unimplemented functions. 623 624 func (fd *netFD) dup() (*os.File, error) { 625 // TODO: Implement this 626 return nil, os.NewSyscallError("dup", syscall.EWINDOWS) 627 } 628 629 var errNoSupport = errors.New("address family not supported") 630 631 func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) { 632 return 0, 0, 0, nil, errNoSupport 633 } 634 635 func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) { 636 return 0, 0, errNoSupport 637 }