...
Run Format

Source file src/net/rawconn_windows_test.go

Documentation: net

     1  // Copyright 2017 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 net
     6  
     7  import (
     8  	"errors"
     9  	"syscall"
    10  	"unsafe"
    11  )
    12  
    13  func readRawConn(c syscall.RawConn, b []byte) (int, error) {
    14  	var operr error
    15  	var n int
    16  	err := c.Read(func(s uintptr) bool {
    17  		var read uint32
    18  		var flags uint32
    19  		var buf syscall.WSABuf
    20  		buf.Buf = &b[0]
    21  		buf.Len = uint32(len(b))
    22  		operr = syscall.WSARecv(syscall.Handle(s), &buf, 1, &read, &flags, nil, nil)
    23  		n = int(read)
    24  		return true
    25  	})
    26  	if err != nil {
    27  		return n, err
    28  	}
    29  	if operr != nil {
    30  		return n, operr
    31  	}
    32  	return n, nil
    33  }
    34  
    35  func writeRawConn(c syscall.RawConn, b []byte) error {
    36  	var operr error
    37  	err := c.Write(func(s uintptr) bool {
    38  		var written uint32
    39  		var buf syscall.WSABuf
    40  		buf.Buf = &b[0]
    41  		buf.Len = uint32(len(b))
    42  		operr = syscall.WSASend(syscall.Handle(s), &buf, 1, &written, 0, nil, nil)
    43  		return true
    44  	})
    45  	if err != nil {
    46  		return err
    47  	}
    48  	if operr != nil {
    49  		return operr
    50  	}
    51  	return nil
    52  }
    53  
    54  func controlRawConn(c syscall.RawConn, addr Addr) error {
    55  	var operr error
    56  	fn := func(s uintptr) {
    57  		var v, l int32
    58  		l = int32(unsafe.Sizeof(v))
    59  		operr = syscall.Getsockopt(syscall.Handle(s), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, (*byte)(unsafe.Pointer(&v)), &l)
    60  		if operr != nil {
    61  			return
    62  		}
    63  		switch addr := addr.(type) {
    64  		case *TCPAddr:
    65  			// There's no guarantee that IP-level socket
    66  			// options work well with dual stack sockets.
    67  			// A simple solution would be to take a look
    68  			// at the bound address to the raw connection
    69  			// and to classify the address family of the
    70  			// underlying socket by the bound address:
    71  			//
    72  			// - When IP.To16() != nil and IP.To4() == nil,
    73  			//   we can assume that the raw connection
    74  			//   consists of an IPv6 socket using only
    75  			//   IPv6 addresses.
    76  			//
    77  			// - When IP.To16() == nil and IP.To4() != nil,
    78  			//   the raw connection consists of an IPv4
    79  			//   socket using only IPv4 addresses.
    80  			//
    81  			// - Otherwise, the raw connection is a dual
    82  			//   stack socket, an IPv6 socket using IPv6
    83  			//   addresses including IPv4-mapped or
    84  			//   IPv4-embedded IPv6 addresses.
    85  			if addr.IP.To16() != nil && addr.IP.To4() == nil {
    86  				operr = syscall.SetsockoptInt(syscall.Handle(s), syscall.IPPROTO_IPV6, syscall.IPV6_UNICAST_HOPS, 1)
    87  			} else if addr.IP.To16() == nil && addr.IP.To4() != nil {
    88  				operr = syscall.SetsockoptInt(syscall.Handle(s), syscall.IPPROTO_IP, syscall.IP_TTL, 1)
    89  			}
    90  		}
    91  	}
    92  	if err := c.Control(fn); err != nil {
    93  		return err
    94  	}
    95  	if operr != nil {
    96  		return operr
    97  	}
    98  	return nil
    99  }
   100  
   101  func controlOnConnSetup(network string, address string, c syscall.RawConn) error {
   102  	var operr error
   103  	var fn func(uintptr)
   104  	switch network {
   105  	case "tcp", "udp", "ip":
   106  		return errors.New("ambiguous network: " + network)
   107  	default:
   108  		switch network[len(network)-1] {
   109  		case '4':
   110  			fn = func(s uintptr) {
   111  				operr = syscall.SetsockoptInt(syscall.Handle(s), syscall.IPPROTO_IP, syscall.IP_TTL, 1)
   112  			}
   113  		case '6':
   114  			fn = func(s uintptr) {
   115  				operr = syscall.SetsockoptInt(syscall.Handle(s), syscall.IPPROTO_IPV6, syscall.IPV6_UNICAST_HOPS, 1)
   116  			}
   117  		default:
   118  			return errors.New("unknown network: " + network)
   119  		}
   120  	}
   121  	if err := c.Control(fn); err != nil {
   122  		return err
   123  	}
   124  	if operr != nil {
   125  		return operr
   126  	}
   127  	return nil
   128  }
   129  

View as plain text