]> Cypherpunks.ru repositories - gostls13.git/blob - src/net/rawconn_windows_test.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / src / net / rawconn_windows_test.go
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         return n, operr
30 }
31
32 func writeRawConn(c syscall.RawConn, b []byte) error {
33         var operr error
34         err := c.Write(func(s uintptr) bool {
35                 var written uint32
36                 var buf syscall.WSABuf
37                 buf.Buf = &b[0]
38                 buf.Len = uint32(len(b))
39                 operr = syscall.WSASend(syscall.Handle(s), &buf, 1, &written, 0, nil, nil)
40                 return true
41         })
42         if err != nil {
43                 return err
44         }
45         return operr
46 }
47
48 func controlRawConn(c syscall.RawConn, addr Addr) error {
49         var operr error
50         fn := func(s uintptr) {
51                 var v, l int32
52                 l = int32(unsafe.Sizeof(v))
53                 operr = syscall.Getsockopt(syscall.Handle(s), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, (*byte)(unsafe.Pointer(&v)), &l)
54                 if operr != nil {
55                         return
56                 }
57                 switch addr := addr.(type) {
58                 case *TCPAddr:
59                         // There's no guarantee that IP-level socket
60                         // options work well with dual stack sockets.
61                         // A simple solution would be to take a look
62                         // at the bound address to the raw connection
63                         // and to classify the address family of the
64                         // underlying socket by the bound address:
65                         //
66                         // - When IP.To16() != nil and IP.To4() == nil,
67                         //   we can assume that the raw connection
68                         //   consists of an IPv6 socket using only
69                         //   IPv6 addresses.
70                         //
71                         // - When IP.To16() == nil and IP.To4() != nil,
72                         //   the raw connection consists of an IPv4
73                         //   socket using only IPv4 addresses.
74                         //
75                         // - Otherwise, the raw connection is a dual
76                         //   stack socket, an IPv6 socket using IPv6
77                         //   addresses including IPv4-mapped or
78                         //   IPv4-embedded IPv6 addresses.
79                         if addr.IP.To16() != nil && addr.IP.To4() == nil {
80                                 operr = syscall.SetsockoptInt(syscall.Handle(s), syscall.IPPROTO_IPV6, syscall.IPV6_UNICAST_HOPS, 1)
81                         } else if addr.IP.To16() == nil && addr.IP.To4() != nil {
82                                 operr = syscall.SetsockoptInt(syscall.Handle(s), syscall.IPPROTO_IP, syscall.IP_TTL, 1)
83                         }
84                 }
85         }
86         if err := c.Control(fn); err != nil {
87                 return err
88         }
89         return operr
90 }
91
92 func controlOnConnSetup(network string, address string, c syscall.RawConn) error {
93         var operr error
94         var fn func(uintptr)
95         switch network {
96         case "tcp", "udp", "ip":
97                 return errors.New("ambiguous network: " + network)
98         default:
99                 switch network[len(network)-1] {
100                 case '4':
101                         fn = func(s uintptr) {
102                                 operr = syscall.SetsockoptInt(syscall.Handle(s), syscall.IPPROTO_IP, syscall.IP_TTL, 1)
103                         }
104                 case '6':
105                         fn = func(s uintptr) {
106                                 operr = syscall.SetsockoptInt(syscall.Handle(s), syscall.IPPROTO_IPV6, syscall.IPV6_UNICAST_HOPS, 1)
107                         }
108                 default:
109                         return errors.New("unknown network: " + network)
110                 }
111         }
112         if err := c.Control(fn); err != nil {
113                 return err
114         }
115         return operr
116 }