Home | History | Annotate | Download | only in socktest
      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