libgo: update to Go 1.11
[official-gcc.git] / libgo / go / net / rawconn_windows_test.go
blob2774c97e5c82e37937f8f23efab4ad9a2b76e780
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.
5 package net
7 import (
8 "errors"
9 "syscall"
10 "unsafe"
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
26 if err != nil {
27 return n, err
29 if operr != nil {
30 return n, operr
32 return n, nil
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
45 if err != nil {
46 return err
48 if operr != nil {
49 return operr
51 return nil
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
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:
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.
77 // - When IP.To16() == nil and IP.To4() != nil,
78 // the raw connection consists of an IPv4
79 // socket using only IPv4 addresses.
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)
92 if err := c.Control(fn); err != nil {
93 return err
95 if operr != nil {
96 return operr
98 return nil
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)
113 case '6':
114 fn = func(s uintptr) {
115 operr = syscall.SetsockoptInt(syscall.Handle(s), syscall.IPPROTO_IPV6, syscall.IPV6_UNICAST_HOPS, 1)
117 default:
118 return errors.New("unknown network: " + network)
121 if err := c.Control(fn); err != nil {
122 return err
124 if operr != nil {
125 return operr
127 return nil