]> Cypherpunks repositories - gostls13.git/commitdiff
net/internal/socktest: add hook for Listen, failed system call counters
authorMikio Hara <mikioh.mikioh@gmail.com>
Wed, 8 Apr 2015 11:13:36 +0000 (20:13 +0900)
committerMikio Hara <mikioh.mikioh@gmail.com>
Wed, 15 Apr 2015 11:03:50 +0000 (11:03 +0000)
Change-Id: Icaac9a48a3b9a3c5542235162e21ab8303592965
Reviewed-on: https://go-review.googlesource.com/8641
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/net/internal/socktest/switch.go
src/net/internal/socktest/switch_posix.go [new file with mode: 0644]
src/net/internal/socktest/switch_stub.go
src/net/internal/socktest/sys_cloexec.go
src/net/internal/socktest/sys_unix.go
src/net/internal/socktest/sys_windows.go

index 539819160ea3b90c3b2c1313d0478f01cbbb600b..5e558a2de327dfdcfcb1d45436677f6bae515073 100644 (file)
@@ -5,7 +5,10 @@
 // Package socktest provides utilities for socket testing.
 package socktest
 
-import "sync"
+import (
+       "fmt"
+       "sync"
+)
 
 func switchInit(sw *Switch) {
        sw.fltab = make(map[FilterType]Filter)
@@ -70,7 +73,11 @@ func cookie(family, sotype, proto int) Cookie {
 type Status struct {
        Cookie    Cookie
        Err       error // error status of socket system call
-       SocketErr int   // error status of socket by SO_ERROR
+       SocketErr error // error status of socket by SO_ERROR
+}
+
+func (so Status) String() string {
+       return fmt.Sprintf("(%s, %s, %s): syscallerr=%v, socketerr=%v", familyString(so.Cookie.Family()), typeString(so.Cookie.Type()), protocolString(so.Cookie.Protocol()), so.Err, so.SocketErr)
 }
 
 // A Stat represents a per-cookie socket statistics.
@@ -80,9 +87,20 @@ type Stat struct {
        Protocol int // protocol number
 
        Opened    uint64 // number of sockets opened
-       Accepted  uint64 // number of sockets accepted
        Connected uint64 // number of sockets connected
+       Listened  uint64 // number of sockets listened
+       Accepted  uint64 // number of sockets accepted
        Closed    uint64 // number of sockets closed
+
+       OpenFailed    uint64 // number of sockets open failed
+       ConnectFailed uint64 // number of sockets connect failed
+       ListenFailed  uint64 // number of sockets listen failed
+       AcceptFailed  uint64 // number of sockets accept failed
+       CloseFailed   uint64 // number of sockets close failed
+}
+
+func (st Stat) String() string {
+       return fmt.Sprintf("(%s, %s, %s): opened=%d, connected=%d, listened=%d, accepted=%d, closed=%d, openfailed=%d, connectfailed=%d, listenfailed=%d, acceptfailed=%d, closefailed=%d", familyString(st.Family), typeString(st.Type), protocolString(st.Protocol), st.Opened, st.Connected, st.Listened, st.Accepted, st.Closed, st.OpenFailed, st.ConnectFailed, st.ListenFailed, st.AcceptFailed, st.CloseFailed)
 }
 
 type stats map[Cookie]*Stat
@@ -101,8 +119,9 @@ type FilterType int
 
 const (
        FilterSocket        FilterType = iota // for Socket
-       FilterAccept                          // for Accept or Accept4
        FilterConnect                         // for Connect or ConnectEx
+       FilterListen                          // for Listen
+       FilterAccept                          // for Accept or Accept4
        FilterGetsockoptInt                   // for GetsockoptInt
        FilterClose                           // for Close or Closesocket
 )
diff --git a/src/net/internal/socktest/switch_posix.go b/src/net/internal/socktest/switch_posix.go
new file mode 100644 (file)
index 0000000..863edef
--- /dev/null
@@ -0,0 +1,58 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !plan9
+
+package socktest
+
+import (
+       "fmt"
+       "syscall"
+)
+
+func familyString(family int) string {
+       switch family {
+       case syscall.AF_INET:
+               return "inet4"
+       case syscall.AF_INET6:
+               return "inet6"
+       case syscall.AF_UNIX:
+               return "local"
+       default:
+               return fmt.Sprintf("%d", family)
+       }
+}
+
+func typeString(sotype int) string {
+       var s string
+       switch sotype & 0xff {
+       case syscall.SOCK_STREAM:
+               s = "stream"
+       case syscall.SOCK_DGRAM:
+               s = "datagram"
+       case syscall.SOCK_RAW:
+               s = "raw"
+       case syscall.SOCK_SEQPACKET:
+               s = "seqpacket"
+       default:
+               s = fmt.Sprintf("%d", sotype&0xff)
+       }
+       if flags := uint(sotype) & ^uint(0xff); flags != 0 {
+               s += fmt.Sprintf("|%#x", flags)
+       }
+       return s
+}
+
+func protocolString(proto int) string {
+       switch proto {
+       case 0:
+               return "default"
+       case syscall.IPPROTO_TCP:
+               return "tcp"
+       case syscall.IPPROTO_UDP:
+               return "udp"
+       default:
+               return fmt.Sprintf("%d", proto)
+       }
+}
index be97628a00b0d0499484ed7e201dda27ac72b3a9..28ce72cb855a6e1769326cee1b56d585439dd23c 100644 (file)
@@ -8,3 +8,9 @@ package socktest
 
 // Sockets maps a socket descriptor to the status of socket.
 type Sockets map[int]Status
+
+func familyString(family int) string { return "<nil>" }
+
+func typeString(sotype int) string { return "<nil>" }
+
+func protocolString(proto int) string { return "<nil>" }
index 61cb6aec088f67c60e0ac3b1afa56c49e88cef21..340ff071e7ec610d0a0c82501286b854f79cc98e 100644 (file)
@@ -30,12 +30,13 @@ func (sw *Switch) Accept4(s, flags int) (ns int, sa syscall.Sockaddr, err error)
                return -1, nil, err
        }
 
+       sw.smu.Lock()
+       defer sw.smu.Unlock()
        if so.Err != nil {
+               sw.stats.getLocked(so.Cookie).AcceptFailed++
                return -1, nil, so.Err
        }
-       sw.smu.Lock()
        nso := sw.addLocked(ns, so.Cookie.Family(), so.Cookie.Type(), so.Cookie.Protocol())
        sw.stats.getLocked(nso.Cookie).Accepted++
-       sw.smu.Unlock()
        return ns, sa, nil
 }
index b128c019ae55641078e183c9852b6834293e0cf2..4089f8cea2368e8fd3f5de499dd998e86ebf72e4 100644 (file)
@@ -27,13 +27,14 @@ func (sw *Switch) Socket(family, sotype, proto int) (s int, err error) {
                return -1, err
        }
 
+       sw.smu.Lock()
+       defer sw.smu.Unlock()
        if so.Err != nil {
+               sw.stats.getLocked(so.Cookie).OpenFailed++
                return -1, so.Err
        }
-       sw.smu.Lock()
        nso := sw.addLocked(s, family, sotype, proto)
        sw.stats.getLocked(nso.Cookie).Opened++
-       sw.smu.Unlock()
        return s, nil
 }
 
@@ -56,13 +57,14 @@ func (sw *Switch) Close(s int) (err error) {
                return err
        }
 
+       sw.smu.Lock()
+       defer sw.smu.Unlock()
        if so.Err != nil {
+               sw.stats.getLocked(so.Cookie).CloseFailed++
                return so.Err
        }
-       sw.smu.Lock()
        delete(sw.sotab, s)
        sw.stats.getLocked(so.Cookie).Closed++
-       sw.smu.Unlock()
        return nil
 }
 
@@ -85,12 +87,42 @@ func (sw *Switch) Connect(s int, sa syscall.Sockaddr) (err error) {
                return err
        }
 
+       sw.smu.Lock()
+       defer sw.smu.Unlock()
        if so.Err != nil {
+               sw.stats.getLocked(so.Cookie).ConnectFailed++
                return so.Err
        }
-       sw.smu.Lock()
        sw.stats.getLocked(so.Cookie).Connected++
-       sw.smu.Unlock()
+       return nil
+}
+
+// Listen wraps syscall.Listen.
+func (sw *Switch) Listen(s, backlog int) (err error) {
+       so := sw.sockso(s)
+       if so == nil {
+               return syscall.Listen(s, backlog)
+       }
+       sw.fmu.RLock()
+       f, _ := sw.fltab[FilterListen]
+       sw.fmu.RUnlock()
+
+       af, err := f.apply(so)
+       if err != nil {
+               return err
+       }
+       so.Err = syscall.Listen(s, backlog)
+       if err = af.apply(so); err != nil {
+               return err
+       }
+
+       sw.smu.Lock()
+       defer sw.smu.Unlock()
+       if so.Err != nil {
+               sw.stats.getLocked(so.Cookie).ListenFailed++
+               return so.Err
+       }
+       sw.stats.getLocked(so.Cookie).Listened++
        return nil
 }
 
@@ -116,13 +148,14 @@ func (sw *Switch) Accept(s int) (ns int, sa syscall.Sockaddr, err error) {
                return -1, nil, err
        }
 
+       sw.smu.Lock()
+       defer sw.smu.Unlock()
        if so.Err != nil {
+               sw.stats.getLocked(so.Cookie).AcceptFailed++
                return -1, nil, so.Err
        }
-       sw.smu.Lock()
        nso := sw.addLocked(ns, so.Cookie.Family(), so.Cookie.Type(), so.Cookie.Protocol())
        sw.stats.getLocked(nso.Cookie).Accepted++
-       sw.smu.Unlock()
        return ns, sa, nil
 }
 
@@ -140,7 +173,8 @@ func (sw *Switch) GetsockoptInt(s, level, opt int) (soerr int, err error) {
        if err != nil {
                return -1, err
        }
-       so.SocketErr, so.Err = syscall.GetsockoptInt(s, level, opt)
+       soerr, so.Err = syscall.GetsockoptInt(s, level, opt)
+       so.SocketErr = syscall.Errno(soerr)
        if err = af.apply(so); err != nil {
                return -1, err
        }
@@ -148,10 +182,10 @@ func (sw *Switch) GetsockoptInt(s, level, opt int) (soerr int, err error) {
        if so.Err != nil {
                return -1, so.Err
        }
-       if opt == syscall.SO_ERROR && (so.SocketErr == 0 || syscall.Errno(so.SocketErr) == syscall.EISCONN) {
+       if opt == syscall.SO_ERROR && (so.SocketErr == syscall.Errno(0) || so.SocketErr == syscall.EISCONN) {
                sw.smu.Lock()
                sw.stats.getLocked(so.Cookie).Connected++
                sw.smu.Unlock()
        }
-       return so.SocketErr, nil
+       return soerr, nil
 }
index 30bac45512a2d284510c6241f5a5690958c7acf6..907e01b5a2e8d626a015b8d783fbaeede7088b66 100644 (file)
@@ -25,13 +25,14 @@ func (sw *Switch) Socket(family, sotype, proto int) (s syscall.Handle, err error
                return syscall.InvalidHandle, err
        }
 
+       sw.smu.Lock()
+       defer sw.smu.Unlock()
        if so.Err != nil {
+               sw.stats.getLocked(so.Cookie).OpenFailed++
                return syscall.InvalidHandle, so.Err
        }
-       sw.smu.Lock()
        nso := sw.addLocked(s, family, sotype, proto)
        sw.stats.getLocked(nso.Cookie).Opened++
-       sw.smu.Unlock()
        return s, nil
 }
 
@@ -54,13 +55,14 @@ func (sw *Switch) Closesocket(s syscall.Handle) (err error) {
                return err
        }
 
+       sw.smu.Lock()
+       defer sw.smu.Unlock()
        if so.Err != nil {
+               sw.stats.getLocked(so.Cookie).CloseFailed++
                return so.Err
        }
-       sw.smu.Lock()
        delete(sw.sotab, s)
        sw.stats.getLocked(so.Cookie).Closed++
-       sw.smu.Unlock()
        return nil
 }
 
@@ -83,12 +85,13 @@ func (sw *Switch) Connect(s syscall.Handle, sa syscall.Sockaddr) (err error) {
                return err
        }
 
+       sw.smu.Lock()
+       defer sw.smu.Unlock()
        if so.Err != nil {
+               sw.stats.getLocked(so.Cookie).ConnectFailed++
                return so.Err
        }
-       sw.smu.Lock()
        sw.stats.getLocked(so.Cookie).Connected++
-       sw.smu.Unlock()
        return nil
 }
 
@@ -111,11 +114,41 @@ func (sw *Switch) ConnectEx(s syscall.Handle, sa syscall.Sockaddr, b *byte, n ui
                return err
        }
 
+       sw.smu.Lock()
+       defer sw.smu.Unlock()
        if so.Err != nil {
+               sw.stats.getLocked(so.Cookie).ConnectFailed++
                return so.Err
        }
-       sw.smu.Lock()
        sw.stats.getLocked(so.Cookie).Connected++
-       sw.smu.Unlock()
+       return nil
+}
+
+// Listen wraps syscall.Listen.
+func (sw *Switch) Listen(s syscall.Handle, backlog int) (err error) {
+       so := sw.sockso(s)
+       if so == nil {
+               return syscall.Listen(s, backlog)
+       }
+       sw.fmu.RLock()
+       f, _ := sw.fltab[FilterListen]
+       sw.fmu.RUnlock()
+
+       af, err := f.apply(so)
+       if err != nil {
+               return err
+       }
+       so.Err = syscall.Listen(s, backlog)
+       if err = af.apply(so); err != nil {
+               return err
+       }
+
+       sw.smu.Lock()
+       defer sw.smu.Unlock()
+       if so.Err != nil {
+               sw.stats.getLocked(so.Cookie).ListenFailed++
+               return so.Err
+       }
+       sw.stats.getLocked(so.Cookie).Listened++
        return nil
 }