github.com/rsc/go@v0.0.0-20150416155037-e040fd465409/src/net/internal/socktest/sys_unix.go (about)

     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  	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 -1, 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.Close(s)
    26  		}
    27  		return -1, 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 -1, 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  // Close wraps syscall.Close.
    42  func (sw *Switch) Close(s int) (err error) {
    43  	so := sw.sockso(s)
    44  	if so == nil {
    45  		return syscall.Close(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.Close(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 int, 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  // Listen wraps syscall.Listen.
   101  func (sw *Switch) Listen(s, backlog int) (err error) {
   102  	so := sw.sockso(s)
   103  	if so == nil {
   104  		return syscall.Listen(s, backlog)
   105  	}
   106  	sw.fmu.RLock()
   107  	f, _ := sw.fltab[FilterListen]
   108  	sw.fmu.RUnlock()
   109  
   110  	af, err := f.apply(so)
   111  	if err != nil {
   112  		return err
   113  	}
   114  	so.Err = syscall.Listen(s, backlog)
   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).ListenFailed++
   123  		return so.Err
   124  	}
   125  	sw.stats.getLocked(so.Cookie).Listened++
   126  	return nil
   127  }
   128  
   129  // Accept wraps syscall.Accept.
   130  func (sw *Switch) Accept(s int) (ns int, sa syscall.Sockaddr, err error) {
   131  	so := sw.sockso(s)
   132  	if so == nil {
   133  		return syscall.Accept(s)
   134  	}
   135  	sw.fmu.RLock()
   136  	f, _ := sw.fltab[FilterAccept]
   137  	sw.fmu.RUnlock()
   138  
   139  	af, err := f.apply(so)
   140  	if err != nil {
   141  		return -1, nil, err
   142  	}
   143  	ns, sa, so.Err = syscall.Accept(s)
   144  	if err = af.apply(so); err != nil {
   145  		if so.Err == nil {
   146  			syscall.Close(ns)
   147  		}
   148  		return -1, nil, err
   149  	}
   150  
   151  	sw.smu.Lock()
   152  	defer sw.smu.Unlock()
   153  	if so.Err != nil {
   154  		sw.stats.getLocked(so.Cookie).AcceptFailed++
   155  		return -1, nil, so.Err
   156  	}
   157  	nso := sw.addLocked(ns, so.Cookie.Family(), so.Cookie.Type(), so.Cookie.Protocol())
   158  	sw.stats.getLocked(nso.Cookie).Accepted++
   159  	return ns, sa, nil
   160  }
   161  
   162  // GetsockoptInt wraps syscall.GetsockoptInt.
   163  func (sw *Switch) GetsockoptInt(s, level, opt int) (soerr int, err error) {
   164  	so := sw.sockso(s)
   165  	if so == nil {
   166  		return syscall.GetsockoptInt(s, level, opt)
   167  	}
   168  	sw.fmu.RLock()
   169  	f, _ := sw.fltab[FilterGetsockoptInt]
   170  	sw.fmu.RUnlock()
   171  
   172  	af, err := f.apply(so)
   173  	if err != nil {
   174  		return -1, err
   175  	}
   176  	soerr, so.Err = syscall.GetsockoptInt(s, level, opt)
   177  	so.SocketErr = syscall.Errno(soerr)
   178  	if err = af.apply(so); err != nil {
   179  		return -1, err
   180  	}
   181  
   182  	if so.Err != nil {
   183  		return -1, so.Err
   184  	}
   185  	if opt == syscall.SO_ERROR && (so.SocketErr == syscall.Errno(0) || so.SocketErr == syscall.EISCONN) {
   186  		sw.smu.Lock()
   187  		sw.stats.getLocked(so.Cookie).Connected++
   188  		sw.smu.Unlock()
   189  	}
   190  	return soerr, nil
   191  }