1 // Copyright 2015 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 socktest 6 7 import "syscall" 8 9 // Socket wraps syscall.Socket. 10 func (sw *Switch) Socket(family, sotype, proto int) (s syscall.Handle, err error) { 11 sw.once.Do(sw.init) 12 13 so := &Status{Cookie: cookie(family, sotype, proto)} 14 sw.fmu.RLock() 15 f, _ := sw.fltab[FilterSocket] 16 sw.fmu.RUnlock() 17 18 af, err := f.apply(so) 19 if err != nil { 20 return syscall.InvalidHandle, err 21 } 22 s, so.Err = syscall.Socket(family, sotype, proto) 23 if err = af.apply(so); err != nil { 24 if so.Err == nil { 25 syscall.Closesocket(s) 26 } 27 return syscall.InvalidHandle, err 28 } 29 30 sw.smu.Lock() 31 defer sw.smu.Unlock() 32 if so.Err != nil { 33 sw.stats.getLocked(so.Cookie).OpenFailed++ 34 return syscall.InvalidHandle, so.Err 35 } 36 nso := sw.addLocked(s, family, sotype, proto) 37 sw.stats.getLocked(nso.Cookie).Opened++ 38 return s, nil 39 } 40 41 // Closesocket wraps syscall.Closesocket. 42 func (sw *Switch) Closesocket(s syscall.Handle) (err error) { 43 so := sw.sockso(s) 44 if so == nil { 45 return syscall.Closesocket(s) 46 } 47 sw.fmu.RLock() 48 f, _ := sw.fltab[FilterClose] 49 sw.fmu.RUnlock() 50 51 af, err := f.apply(so) 52 if err != nil { 53 return err 54 } 55 so.Err = syscall.Closesocket(s) 56 if err = af.apply(so); err != nil { 57 return err 58 } 59 60 sw.smu.Lock() 61 defer sw.smu.Unlock() 62 if so.Err != nil { 63 sw.stats.getLocked(so.Cookie).CloseFailed++ 64 return so.Err 65 } 66 delete(sw.sotab, s) 67 sw.stats.getLocked(so.Cookie).Closed++ 68 return nil 69 } 70 71 // Connect wraps syscall.Connect. 72 func (sw *Switch) Connect(s syscall.Handle, sa syscall.Sockaddr) (err error) { 73 so := sw.sockso(s) 74 if so == nil { 75 return syscall.Connect(s, sa) 76 } 77 sw.fmu.RLock() 78 f, _ := sw.fltab[FilterConnect] 79 sw.fmu.RUnlock() 80 81 af, err := f.apply(so) 82 if err != nil { 83 return err 84 } 85 so.Err = syscall.Connect(s, sa) 86 if err = af.apply(so); err != nil { 87 return err 88 } 89 90 sw.smu.Lock() 91 defer sw.smu.Unlock() 92 if so.Err != nil { 93 sw.stats.getLocked(so.Cookie).ConnectFailed++ 94 return so.Err 95 } 96 sw.stats.getLocked(so.Cookie).Connected++ 97 return nil 98 } 99 100 // ConnectEx wraps syscall.ConnectEx. 101 func (sw *Switch) ConnectEx(s syscall.Handle, sa syscall.Sockaddr, b *byte, n uint32, nwr *uint32, o *syscall.Overlapped) (err error) { 102 so := sw.sockso(s) 103 if so == nil { 104 return syscall.ConnectEx(s, sa, b, n, nwr, o) 105 } 106 sw.fmu.RLock() 107 f, _ := sw.fltab[FilterConnect] 108 sw.fmu.RUnlock() 109 110 af, err := f.apply(so) 111 if err != nil { 112 return err 113 } 114 so.Err = syscall.ConnectEx(s, sa, b, n, nwr, o) 115 if err = af.apply(so); err != nil { 116 return err 117 } 118 119 sw.smu.Lock() 120 defer sw.smu.Unlock() 121 if so.Err != nil { 122 sw.stats.getLocked(so.Cookie).ConnectFailed++ 123 return so.Err 124 } 125 sw.stats.getLocked(so.Cookie).Connected++ 126 return nil 127 } 128 129 // Listen wraps syscall.Listen. 130 func (sw *Switch) Listen(s syscall.Handle, backlog int) (err error) { 131 so := sw.sockso(s) 132 if so == nil { 133 return syscall.Listen(s, backlog) 134 } 135 sw.fmu.RLock() 136 f, _ := sw.fltab[FilterListen] 137 sw.fmu.RUnlock() 138 139 af, err := f.apply(so) 140 if err != nil { 141 return err 142 } 143 so.Err = syscall.Listen(s, backlog) 144 if err = af.apply(so); err != nil { 145 return err 146 } 147 148 sw.smu.Lock() 149 defer sw.smu.Unlock() 150 if so.Err != nil { 151 sw.stats.getLocked(so.Cookie).ListenFailed++ 152 return so.Err 153 } 154 sw.stats.getLocked(so.Cookie).Listened++ 155 return nil 156 } 157