Source file src/net/internal/socktest/sys_unix.go

     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  //go:build unix || (js && wasm) || wasip1
     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  

View as plain text