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 // +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris 6 7 package socktest 8 9 import "syscall" 10 11 // Socket wraps syscall.Socket. 12 func (sw *Switch) Socket(family, sotype, proto int) (s int, err error) { 13 sw.once.Do(sw.init) 14 15 so := &Status{Cookie: cookie(family, sotype, proto)} 16 sw.fmu.RLock() 17 f, _ := sw.fltab[FilterSocket] 18 sw.fmu.RUnlock() 19 20 af, err := f.apply(so) 21 if err != nil { 22 return -1, err 23 } 24 s, so.Err = syscall.Socket(family, sotype, proto) 25 if err = af.apply(so); err != nil { 26 if so.Err == nil { 27 syscall.Close(s) 28 } 29 return -1, err 30 } 31 32 sw.smu.Lock() 33 defer sw.smu.Unlock() 34 if so.Err != nil { 35 sw.stats.getLocked(so.Cookie).OpenFailed++ 36 return -1, so.Err 37 } 38 nso := sw.addLocked(s, family, sotype, proto) 39 sw.stats.getLocked(nso.Cookie).Opened++ 40 return s, nil 41 } 42 43 // Close wraps syscall.Close. 44 func (sw *Switch) Close(s int) (err error) { 45 so := sw.sockso(s) 46 if so == nil { 47 return syscall.Close(s) 48 } 49 sw.fmu.RLock() 50 f, _ := sw.fltab[FilterClose] 51 sw.fmu.RUnlock() 52 53 af, err := f.apply(so) 54 if err != nil { 55 return err 56 } 57 so.Err = syscall.Close(s) 58 if err = af.apply(so); err != nil { 59 return err 60 } 61 62 sw.smu.Lock() 63 defer sw.smu.Unlock() 64 if so.Err != nil { 65 sw.stats.getLocked(so.Cookie).CloseFailed++ 66 return so.Err 67 } 68 delete(sw.sotab, s) 69 sw.stats.getLocked(so.Cookie).Closed++ 70 return nil 71 } 72 73 // Connect wraps syscall.Connect. 74 func (sw *Switch) Connect(s int, sa syscall.Sockaddr) (err error) { 75 so := sw.sockso(s) 76 if so == nil { 77 return syscall.Connect(s, sa) 78 } 79 sw.fmu.RLock() 80 f, _ := sw.fltab[FilterConnect] 81 sw.fmu.RUnlock() 82 83 af, err := f.apply(so) 84 if err != nil { 85 return err 86 } 87 so.Err = syscall.Connect(s, sa) 88 if err = af.apply(so); err != nil { 89 return err 90 } 91 92 sw.smu.Lock() 93 defer sw.smu.Unlock() 94 if so.Err != nil { 95 sw.stats.getLocked(so.Cookie).ConnectFailed++ 96 return so.Err 97 } 98 sw.stats.getLocked(so.Cookie).Connected++ 99 return nil 100 } 101 102 // Listen wraps syscall.Listen. 103 func (sw *Switch) Listen(s, backlog int) (err error) { 104 so := sw.sockso(s) 105 if so == nil { 106 return syscall.Listen(s, backlog) 107 } 108 sw.fmu.RLock() 109 f, _ := sw.fltab[FilterListen] 110 sw.fmu.RUnlock() 111 112 af, err := f.apply(so) 113 if err != nil { 114 return err 115 } 116 so.Err = syscall.Listen(s, backlog) 117 if err = af.apply(so); err != nil { 118 return err 119 } 120 121 sw.smu.Lock() 122 defer sw.smu.Unlock() 123 if so.Err != nil { 124 sw.stats.getLocked(so.Cookie).ListenFailed++ 125 return so.Err 126 } 127 sw.stats.getLocked(so.Cookie).Listened++ 128 return nil 129 } 130 131 // Accept wraps syscall.Accept. 132 func (sw *Switch) Accept(s int) (ns int, sa syscall.Sockaddr, err error) { 133 so := sw.sockso(s) 134 if so == nil { 135 return syscall.Accept(s) 136 } 137 sw.fmu.RLock() 138 f, _ := sw.fltab[FilterAccept] 139 sw.fmu.RUnlock() 140 141 af, err := f.apply(so) 142 if err != nil { 143 return -1, nil, err 144 } 145 ns, sa, so.Err = syscall.Accept(s) 146 if err = af.apply(so); err != nil { 147 if so.Err == nil { 148 syscall.Close(ns) 149 } 150 return -1, nil, err 151 } 152 153 sw.smu.Lock() 154 defer sw.smu.Unlock() 155 if so.Err != nil { 156 sw.stats.getLocked(so.Cookie).AcceptFailed++ 157 return -1, nil, so.Err 158 } 159 nso := sw.addLocked(ns, so.Cookie.Family(), so.Cookie.Type(), so.Cookie.Protocol()) 160 sw.stats.getLocked(nso.Cookie).Accepted++ 161 return ns, sa, nil 162 } 163 164 // GetsockoptInt wraps syscall.GetsockoptInt. 165 func (sw *Switch) GetsockoptInt(s, level, opt int) (soerr int, err error) { 166 so := sw.sockso(s) 167 if so == nil { 168 return syscall.GetsockoptInt(s, level, opt) 169 } 170 sw.fmu.RLock() 171 f, _ := sw.fltab[FilterGetsockoptInt] 172 sw.fmu.RUnlock() 173 174 af, err := f.apply(so) 175 if err != nil { 176 return -1, err 177 } 178 soerr, so.Err = syscall.GetsockoptInt(s, level, opt) 179 so.SocketErr = syscall.Errno(soerr) 180 if err = af.apply(so); err != nil { 181 return -1, err 182 } 183 184 if so.Err != nil { 185 return -1, so.Err 186 } 187 if opt == syscall.SO_ERROR && (so.SocketErr == syscall.Errno(0) || so.SocketErr == syscall.EISCONN) { 188 sw.smu.Lock() 189 sw.stats.getLocked(so.Cookie).Connected++ 190 sw.smu.Unlock() 191 } 192 return soerr, nil 193 } 194