├── .github └── workflows │ ├── automerge.yml │ ├── go-check.yml │ ├── go-test.yml │ ├── release-check.yml │ ├── releaser.yml │ └── tagpush.yml ├── LICENSE ├── README.md ├── go.mod ├── go.sum ├── net ├── net.go ├── net_bsd.go ├── net_linux.go ├── net_test.go └── net_windows.go ├── sockaddr.go ├── sockaddr_bsd.go ├── sockaddr_linux.go ├── sockaddr_platform.go ├── sockaddr_windows.go └── version.json /.github/workflows/automerge.yml: -------------------------------------------------------------------------------- 1 | # File managed by web3-bot. DO NOT EDIT. 2 | # See https://github.com/protocol/.github/ for details. 3 | 4 | # Automatically merge pull requests opened by web3-bot, as soon as (and only if) all tests pass. 5 | # This reduces the friction associated with updating with our workflows. 6 | 7 | on: [ pull_request ] 8 | name: Automerge 9 | 10 | jobs: 11 | automerge-check: 12 | if: github.event.pull_request.user.login == 'web3-bot' 13 | runs-on: ubuntu-latest 14 | outputs: 15 | status: ${{ steps.should-automerge.outputs.status }} 16 | steps: 17 | - uses: actions/checkout@v2 18 | with: 19 | fetch-depth: 0 20 | - name: Check if we should automerge 21 | id: should-automerge 22 | run: | 23 | for commit in $(git rev-list --first-parent origin/${{ github.event.pull_request.base.ref }}..${{ github.event.pull_request.head.sha }}); do 24 | committer=$(git show --format=$'%ce' -s $commit) 25 | echo "Committer: $committer" 26 | if [[ "$committer" != "web3-bot@users.noreply.github.com" ]]; then 27 | echo "Commit $commit wasn't committed by web3-bot, but by $committer." 28 | echo "::set-output name=status::false" 29 | exit 30 | fi 31 | done 32 | echo "::set-output name=status::true" 33 | automerge: 34 | needs: automerge-check 35 | runs-on: ubuntu-latest 36 | # The check for the user is redundant here, as this job depends on the automerge-check job, 37 | # but it prevents this job from spinning up, just to be skipped shortly after. 38 | if: github.event.pull_request.user.login == 'web3-bot' && needs.automerge-check.outputs.status == 'true' 39 | steps: 40 | - name: Wait on tests 41 | uses: lewagon/wait-on-check-action@bafe56a6863672c681c3cf671f5e10b20abf2eaa # v0.2 42 | with: 43 | ref: ${{ github.event.pull_request.head.sha }} 44 | repo-token: ${{ secrets.GITHUB_TOKEN }} 45 | wait-interval: 10 46 | running-workflow-name: 'automerge' # the name of this job 47 | - name: Merge PR 48 | uses: pascalgn/automerge-action@741c311a47881be9625932b0a0de1b0937aab1ae # v0.13.1 49 | env: 50 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 51 | MERGE_LABELS: "" 52 | MERGE_METHOD: "squash" 53 | MERGE_DELETE_BRANCH: true 54 | -------------------------------------------------------------------------------- /.github/workflows/go-check.yml: -------------------------------------------------------------------------------- 1 | # File managed by web3-bot. DO NOT EDIT. 2 | # See https://github.com/protocol/.github/ for details. 3 | 4 | on: [push, pull_request] 5 | name: Go Checks 6 | 7 | jobs: 8 | unit: 9 | runs-on: ubuntu-latest 10 | name: All 11 | env: 12 | RUNGOGENERATE: false 13 | steps: 14 | - uses: actions/checkout@v2 15 | with: 16 | submodules: recursive 17 | - uses: actions/setup-go@v2 18 | with: 19 | go-version: "1.17.x" 20 | - name: Run repo-specific setup 21 | uses: ./.github/actions/go-check-setup 22 | if: hashFiles('./.github/actions/go-check-setup') != '' 23 | - name: Read config 24 | if: hashFiles('./.github/workflows/go-check-config.json') != '' 25 | run: | 26 | if jq -re .gogenerate ./.github/workflows/go-check-config.json; then 27 | echo "RUNGOGENERATE=true" >> $GITHUB_ENV 28 | fi 29 | - name: Install staticcheck 30 | run: go install honnef.co/go/tools/cmd/staticcheck@c8caa92bad8c27ae734c6725b8a04932d54a147b # 2021.1.2 (v0.2.2) 31 | - name: Check that go.mod is tidy 32 | uses: protocol/multiple-go-modules@v1.2 33 | with: 34 | run: | 35 | go mod tidy 36 | if [[ -n $(git ls-files --other --exclude-standard --directory -- go.sum) ]]; then 37 | echo "go.sum was added by go mod tidy" 38 | exit 1 39 | fi 40 | git diff --exit-code -- go.sum go.mod 41 | - name: gofmt 42 | if: ${{ success() || failure() }} # run this step even if the previous one failed 43 | run: | 44 | out=$(gofmt -s -l .) 45 | if [[ -n "$out" ]]; then 46 | echo $out | awk '{print "::error file=" $0 ",line=0,col=0::File is not gofmt-ed."}' 47 | exit 1 48 | fi 49 | - name: go vet 50 | if: ${{ success() || failure() }} # run this step even if the previous one failed 51 | uses: protocol/multiple-go-modules@v1.2 52 | with: 53 | run: go vet ./... 54 | - name: staticcheck 55 | if: ${{ success() || failure() }} # run this step even if the previous one failed 56 | uses: protocol/multiple-go-modules@v1.2 57 | with: 58 | run: | 59 | set -o pipefail 60 | staticcheck ./... | sed -e 's@\(.*\)\.go@./\1.go@g' 61 | - name: go generate 62 | uses: protocol/multiple-go-modules@v1.2 63 | if: (success() || failure()) && env.RUNGOGENERATE == 'true' 64 | with: 65 | run: | 66 | git clean -fd # make sure there aren't untracked files / directories 67 | go generate ./... 68 | # check if go generate modified or added any files 69 | if ! $(git add . && git diff-index HEAD --exit-code --quiet); then 70 | echo "go generated caused changes to the repository:" 71 | git status --short 72 | exit 1 73 | fi 74 | 75 | -------------------------------------------------------------------------------- /.github/workflows/go-test.yml: -------------------------------------------------------------------------------- 1 | # File managed by web3-bot. DO NOT EDIT. 2 | # See https://github.com/protocol/.github/ for details. 3 | 4 | on: [push, pull_request] 5 | name: Go Test 6 | 7 | jobs: 8 | unit: 9 | strategy: 10 | fail-fast: false 11 | matrix: 12 | os: [ "ubuntu", "windows", "macos" ] 13 | go: [ "1.16.x", "1.17.x" ] 14 | env: 15 | COVERAGES: "" 16 | runs-on: ${{ matrix.os }}-latest 17 | name: ${{ matrix.os}} (go ${{ matrix.go }}) 18 | steps: 19 | - uses: actions/checkout@v2 20 | with: 21 | submodules: recursive 22 | - uses: actions/setup-go@v2 23 | with: 24 | go-version: ${{ matrix.go }} 25 | - name: Go information 26 | run: | 27 | go version 28 | go env 29 | - name: Use msys2 on windows 30 | if: ${{ matrix.os == 'windows' }} 31 | shell: bash 32 | # The executable for msys2 is also called bash.cmd 33 | # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2019-Readme.md#shells 34 | # If we prepend its location to the PATH 35 | # subsequent 'shell: bash' steps will use msys2 instead of gitbash 36 | run: echo "C:/msys64/usr/bin" >> $GITHUB_PATH 37 | - name: Run repo-specific setup 38 | uses: ./.github/actions/go-test-setup 39 | if: hashFiles('./.github/actions/go-test-setup') != '' 40 | - name: Run tests 41 | uses: protocol/multiple-go-modules@v1.2 42 | with: 43 | # Use -coverpkg=./..., so that we include cross-package coverage. 44 | # If package ./A imports ./B, and ./A's tests also cover ./B, 45 | # this means ./B's coverage will be significantly higher than 0%. 46 | run: go test -v -coverprofile=module-coverage.txt -coverpkg=./... ./... 47 | - name: Run tests (32 bit) 48 | if: ${{ matrix.os != 'macos' }} # can't run 32 bit tests on OSX. 49 | uses: protocol/multiple-go-modules@v1.2 50 | env: 51 | GOARCH: 386 52 | with: 53 | run: go test -v ./... 54 | - name: Run tests with race detector 55 | if: ${{ matrix.os == 'ubuntu' }} # speed things up. Windows and OSX VMs are slow 56 | uses: protocol/multiple-go-modules@v1.2 57 | with: 58 | run: go test -v -race ./... 59 | - name: Collect coverage files 60 | shell: bash 61 | run: echo "COVERAGES=$(find . -type f -name 'module-coverage.txt' | tr -s '\n' ',' | sed 's/,$//')" >> $GITHUB_ENV 62 | - name: Upload coverage to Codecov 63 | uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 64 | with: 65 | files: '${{ env.COVERAGES }}' 66 | env_vars: OS=${{ matrix.os }}, GO=${{ matrix.go }} 67 | -------------------------------------------------------------------------------- /.github/workflows/release-check.yml: -------------------------------------------------------------------------------- 1 | # File managed by web3-bot. DO NOT EDIT. 2 | # See https://github.com/protocol/.github/ for details. 3 | 4 | name: Release Checker 5 | on: 6 | pull_request: 7 | paths: [ 'version.json' ] 8 | 9 | jobs: 10 | release-check: 11 | uses: protocol/.github/.github/workflows/release-check.yml@master 12 | -------------------------------------------------------------------------------- /.github/workflows/releaser.yml: -------------------------------------------------------------------------------- 1 | # File managed by web3-bot. DO NOT EDIT. 2 | # See https://github.com/protocol/.github/ for details. 3 | 4 | name: Releaser 5 | on: 6 | push: 7 | paths: [ 'version.json' ] 8 | 9 | jobs: 10 | releaser: 11 | uses: protocol/.github/.github/workflows/releaser.yml@master 12 | -------------------------------------------------------------------------------- /.github/workflows/tagpush.yml: -------------------------------------------------------------------------------- 1 | # File managed by web3-bot. DO NOT EDIT. 2 | # See https://github.com/protocol/.github/ for details. 3 | 4 | name: Tag Push Checker 5 | on: 6 | push: 7 | tags: 8 | - v* 9 | 10 | jobs: 11 | releaser: 12 | uses: protocol/.github/.github/workflows/tagpush.yml@master 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DEPRECATION NOTICE 2 | 3 | This repository is not maintained any longer. 4 | 5 | ## go-sockaddr - `{Raw,}Sockaddr` conversions 6 | 7 | See https://groups.google.com/d/msg/golang-nuts/B-meiFfkmH0/-TxP1r6zvk8J 8 | This package extracts unexported code from `golang.org/x/unix` to help in converting 9 | between: 10 | 11 | ```Go 12 | ${platform}.Sockaddr 13 | ${platform}.RawSockaddrAny 14 | C.struct_sockaddr_any 15 | net.*Addr 16 | ``` 17 | 18 | Godoc: 19 | 20 | - sockaddr - http://godoc.org/github.com/libp2p/go-sockaddr 21 | - sockaddr/net - http://godoc.org/github.com/libp2p/go-sockaddr/net 22 | 23 | --- 24 | 25 | The last gx published version of this module was: 1.0.3: QmNzEyX7vjWiqinyLeavcAF1oegav6dZ1aQpAkYvG9m5Ze 26 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/libp2p/go-sockaddr 2 | 3 | require golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e 4 | 5 | go 1.16 6 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e h1:ZytStCyV048ZqDsWHiYDdoI2Vd4msMcrDECFxS+tL9c= 2 | golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 3 | -------------------------------------------------------------------------------- /net/net.go: -------------------------------------------------------------------------------- 1 | // Package sockaddrnet provides conversions between net.Addr and Sockaddr 2 | // Deprecated: This package is not maintained any longer. 3 | package sockaddrnet 4 | 5 | import ( 6 | "net" 7 | ) 8 | 9 | // NetAddrAF returns the unix AF_* type for a given net.Addr 10 | // returns AF_UNSPEC if unknown 11 | func NetAddrAF(addr net.Addr) int { 12 | switch addr := addr.(type) { 13 | case *net.IPAddr: 14 | return IPAF(addr.IP) 15 | 16 | case *net.TCPAddr: 17 | return IPAF(addr.IP) 18 | 19 | case *net.UDPAddr: 20 | return IPAF(addr.IP) 21 | 22 | case *net.UnixAddr: 23 | return AF_UNIX 24 | 25 | default: 26 | return AF_UNSPEC 27 | } 28 | } 29 | 30 | // IPAF returns the unix AF_* type for a given IP address 31 | // returns AF_UNSPEC if unknown 32 | func IPAF(ip net.IP) int { 33 | switch { 34 | case ip.To4() != nil: 35 | return AF_INET 36 | 37 | case ip.To16() != nil: 38 | return AF_INET6 39 | 40 | default: 41 | return AF_UNSPEC 42 | } 43 | } 44 | 45 | // NetAddrIPPROTO returns the unix IPPROTO_* type for a given net.Addr 46 | // returns -1 if protocol unknown 47 | func NetAddrIPPROTO(addr net.Addr) int { 48 | switch addr := addr.(type) { 49 | case *net.IPAddr: 50 | switch { 51 | default: 52 | return IPPROTO_IP 53 | 54 | case addr.IP.To4() != nil: 55 | return IPPROTO_IPV4 56 | 57 | case addr.IP.To16() != nil: 58 | return IPPROTO_IPV6 59 | } 60 | 61 | case *net.TCPAddr: 62 | return IPPROTO_TCP 63 | 64 | case *net.UDPAddr: 65 | return IPPROTO_UDP 66 | 67 | default: 68 | return -1 69 | } 70 | } 71 | 72 | // NetAddrSOCK returns the unix SOCK_* type for a given net.Addr 73 | // returns 0 if type unknown 74 | func NetAddrSOCK(addr net.Addr) int { 75 | switch addr := addr.(type) { 76 | case *net.IPAddr: 77 | return SOCK_DGRAM 78 | case *net.TCPAddr: 79 | return SOCK_STREAM 80 | case *net.UDPAddr: 81 | return SOCK_DGRAM 82 | case *net.UnixAddr: 83 | switch addr.Net { 84 | default: 85 | return 0 86 | case "unix": 87 | return SOCK_STREAM 88 | case "unixgram": 89 | return SOCK_DGRAM 90 | case "unixpacket": 91 | return SOCK_SEQPACKET 92 | } 93 | default: 94 | return 0 95 | } 96 | } 97 | 98 | // NetAddrToSockaddr converts a net.Addr to a Sockaddr. 99 | // Returns nil if the input is invalid or conversion is not possible. 100 | func NetAddrToSockaddr(addr net.Addr) Sockaddr { 101 | switch addr := addr.(type) { 102 | case *net.IPAddr: 103 | return IPAddrToSockaddr(addr) 104 | case *net.TCPAddr: 105 | return TCPAddrToSockaddr(addr) 106 | case *net.UDPAddr: 107 | return UDPAddrToSockaddr(addr) 108 | case *net.UnixAddr: 109 | sa, _ := UnixAddrToSockaddr(addr) 110 | return sa 111 | default: 112 | return nil 113 | } 114 | } 115 | 116 | // IPAndZoneToSockaddr converts a net.IP (with optional IPv6 Zone) to a Sockaddr 117 | // Returns nil if conversion fails. 118 | func IPAndZoneToSockaddr(ip net.IP, zone string) Sockaddr { 119 | // Unspecified? 120 | if ip == nil { 121 | if zone != "" { 122 | return &SockaddrInet6{ZoneId: uint32(IP6ZoneToInt(zone))} 123 | } 124 | return new(SockaddrInet4) 125 | } 126 | 127 | // Valid IPv4? 128 | if ip4 := ip.To4(); ip4 != nil && zone == "" { 129 | var buf [4]byte 130 | copy(buf[:], ip4) // last 4 bytes 131 | return &SockaddrInet4{Addr: buf} 132 | } 133 | 134 | // Valid IPv6 address? 135 | if ip6 := ip.To16(); ip6 != nil { 136 | var buf [16]byte 137 | copy(buf[:], ip6) 138 | return &SockaddrInet6{Addr: buf, ZoneId: uint32(IP6ZoneToInt(zone))} 139 | } 140 | 141 | return nil 142 | } 143 | 144 | // IPAddrToSockaddr converts a net.IPAddr to a Sockaddr. 145 | // Returns nil if conversion fails. 146 | func IPAddrToSockaddr(addr *net.IPAddr) Sockaddr { 147 | return IPAndZoneToSockaddr(addr.IP, addr.Zone) 148 | } 149 | 150 | // TCPAddrToSockaddr converts a net.TCPAddr to a Sockaddr. 151 | // Returns nil if conversion fails. 152 | func TCPAddrToSockaddr(addr *net.TCPAddr) Sockaddr { 153 | sa := IPAndZoneToSockaddr(addr.IP, addr.Zone) 154 | switch sa := sa.(type) { 155 | case *SockaddrInet4: 156 | sa.Port = addr.Port 157 | return sa 158 | case *SockaddrInet6: 159 | sa.Port = addr.Port 160 | return sa 161 | default: 162 | return nil 163 | } 164 | } 165 | 166 | // UDPAddrToSockaddr converts a net.UDPAddr to a Sockaddr. 167 | // Returns nil if conversion fails. 168 | func UDPAddrToSockaddr(addr *net.UDPAddr) Sockaddr { 169 | sa := IPAndZoneToSockaddr(addr.IP, addr.Zone) 170 | switch sa := sa.(type) { 171 | case *SockaddrInet4: 172 | sa.Port = addr.Port 173 | return sa 174 | case *SockaddrInet6: 175 | sa.Port = addr.Port 176 | return sa 177 | default: 178 | return nil 179 | } 180 | } 181 | 182 | // UnixAddrToSockaddr converts a net.UnixAddr to a Sockaddr, and returns 183 | // the type (unix.SOCK_STREAM, unix.SOCK_DGRAM, unix.SOCK_SEQPACKET) 184 | // Returns (nil, 0) if conversion fails. 185 | func UnixAddrToSockaddr(addr *net.UnixAddr) (Sockaddr, int) { 186 | t := 0 187 | switch addr.Net { 188 | case "unix": 189 | t = SOCK_STREAM 190 | case "unixgram": 191 | t = SOCK_DGRAM 192 | case "unixpacket": 193 | t = SOCK_SEQPACKET 194 | default: 195 | return nil, 0 196 | } 197 | return &SockaddrUnix{Name: addr.Name}, t 198 | } 199 | 200 | // SockaddrToIPAndZone converts a Sockaddr to a net.IP (with optional IPv6 Zone) 201 | // Returns nil if conversion fails. 202 | func SockaddrToIPAndZone(sa Sockaddr) (net.IP, string) { 203 | switch sa := sa.(type) { 204 | case *SockaddrInet4: 205 | ip := make([]byte, 16) 206 | // V4InV6Prefix 207 | ip[10] = 0xff 208 | ip[11] = 0xff 209 | copy(ip[12:16], sa.Addr[:]) 210 | return ip, "" 211 | 212 | case *SockaddrInet6: 213 | ip := make([]byte, 16) 214 | copy(ip, sa.Addr[:]) 215 | return ip, IP6ZoneToString(int(sa.ZoneId)) 216 | } 217 | return nil, "" 218 | } 219 | 220 | // SockaddrToIPAddr converts a Sockaddr to a net.IPAddr 221 | // Returns nil if conversion fails. 222 | func SockaddrToIPAddr(sa Sockaddr) *net.IPAddr { 223 | ip, zone := SockaddrToIPAndZone(sa) 224 | switch sa.(type) { 225 | case *SockaddrInet4: 226 | return &net.IPAddr{IP: ip} 227 | case *SockaddrInet6: 228 | return &net.IPAddr{IP: ip, Zone: zone} 229 | } 230 | return nil 231 | } 232 | 233 | // SockaddrToTCPAddr converts a Sockaddr to a net.TCPAddr 234 | // Returns nil if conversion fails. 235 | func SockaddrToTCPAddr(sa Sockaddr) *net.TCPAddr { 236 | ip, zone := SockaddrToIPAndZone(sa) 237 | switch sa := sa.(type) { 238 | case *SockaddrInet4: 239 | return &net.TCPAddr{IP: ip, Port: sa.Port} 240 | case *SockaddrInet6: 241 | return &net.TCPAddr{IP: ip, Port: sa.Port, Zone: zone} 242 | } 243 | return nil 244 | } 245 | 246 | // SockaddrToUDPAddr converts a Sockaddr to a net.UDPAddr 247 | // Returns nil if conversion fails. 248 | func SockaddrToUDPAddr(sa Sockaddr) *net.UDPAddr { 249 | ip, zone := SockaddrToIPAndZone(sa) 250 | switch sa := sa.(type) { 251 | case *SockaddrInet4: 252 | return &net.UDPAddr{IP: ip, Port: sa.Port} 253 | case *SockaddrInet6: 254 | return &net.UDPAddr{IP: ip, Port: sa.Port, Zone: zone} 255 | } 256 | return nil 257 | } 258 | 259 | // from: go/src/pkg/net/unixsock_posix.go 260 | 261 | // SockaddrToUnixAddr converts a Sockaddr to a net.UnixAddr 262 | // Returns nil if conversion fails. 263 | func SockaddrToUnixAddr(sa Sockaddr) *net.UnixAddr { 264 | if s, ok := sa.(*SockaddrUnix); ok { 265 | return &net.UnixAddr{Name: s.Name, Net: "unix"} 266 | } 267 | return nil 268 | } 269 | 270 | // SockaddrToUnixgramAddr converts a Sockaddr to a net.UnixAddr 271 | // Returns nil if conversion fails. 272 | func SockaddrToUnixgramAddr(sa Sockaddr) *net.UnixAddr { 273 | if s, ok := sa.(*SockaddrUnix); ok { 274 | return &net.UnixAddr{Name: s.Name, Net: "unixgram"} 275 | } 276 | return nil 277 | } 278 | 279 | // SockaddrToUnixpacketAddr converts a Sockaddr to a net.UnixAddr 280 | // Returns nil if conversion fails. 281 | func SockaddrToUnixpacketAddr(sa Sockaddr) *net.UnixAddr { 282 | if s, ok := sa.(*SockaddrUnix); ok { 283 | return &net.UnixAddr{Name: s.Name, Net: "unixpacket"} 284 | } 285 | return nil 286 | } 287 | 288 | // from: go/src/pkg/net/ipsock.go 289 | 290 | // IP6ZoneToString converts an IP6 Zone unix int to a net string 291 | // returns "" if zone is 0 292 | func IP6ZoneToString(zone int) string { 293 | if zone == 0 { 294 | return "" 295 | } 296 | if ifi, err := net.InterfaceByIndex(zone); err == nil { 297 | return ifi.Name 298 | } 299 | return itod(uint(zone)) 300 | } 301 | 302 | // IP6ZoneToInt converts an IP6 Zone net string to a unix int 303 | // returns 0 if zone is "" 304 | func IP6ZoneToInt(zone string) int { 305 | if zone == "" { 306 | return 0 307 | } 308 | if ifi, err := net.InterfaceByName(zone); err == nil { 309 | return ifi.Index 310 | } 311 | n, _, _ := dtoi(zone, 0) 312 | return n 313 | } 314 | 315 | // from: go/src/pkg/net/parse.go 316 | 317 | // Convert i to decimal string. 318 | func itod(i uint) string { 319 | if i == 0 { 320 | return "0" 321 | } 322 | 323 | // Assemble decimal in reverse order. 324 | var b [32]byte 325 | bp := len(b) 326 | for ; i > 0; i /= 10 { 327 | bp-- 328 | b[bp] = byte(i%10) + '0' 329 | } 330 | 331 | return string(b[bp:]) 332 | } 333 | 334 | // Bigger than we need, not too big to worry about overflow 335 | const big = 0xFFFFFF 336 | 337 | // Decimal to integer starting at &s[i0]. 338 | // Returns number, new offset, success. 339 | func dtoi(s string, i0 int) (n int, i int, ok bool) { 340 | n = 0 341 | for i = i0; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ { 342 | n = n*10 + int(s[i]-'0') 343 | if n >= big { 344 | return 0, i, false 345 | } 346 | } 347 | if i == i0 { 348 | return 0, i, false 349 | } 350 | return n, i, true 351 | } 352 | -------------------------------------------------------------------------------- /net/net_bsd.go: -------------------------------------------------------------------------------- 1 | //go:build darwin || dragonfly || freebsd || netbsd || openbsd 2 | // +build darwin dragonfly freebsd netbsd openbsd 3 | 4 | package sockaddrnet 5 | 6 | import ( 7 | "golang.org/x/sys/unix" 8 | ) 9 | 10 | const ( 11 | AF_INET = unix.AF_INET 12 | AF_INET6 = unix.AF_INET6 13 | AF_UNIX = unix.AF_UNIX 14 | AF_UNSPEC = unix.AF_UNSPEC 15 | 16 | IPPROTO_IP = unix.IPPROTO_IP 17 | IPPROTO_IPV4 = unix.IPPROTO_IPV4 18 | IPPROTO_IPV6 = unix.IPPROTO_IPV6 19 | IPPROTO_TCP = unix.IPPROTO_TCP 20 | IPPROTO_UDP = unix.IPPROTO_UDP 21 | 22 | SOCK_DGRAM = unix.SOCK_DGRAM 23 | SOCK_STREAM = unix.SOCK_STREAM 24 | SOCK_SEQPACKET = unix.SOCK_SEQPACKET 25 | ) 26 | 27 | type Sockaddr = unix.Sockaddr 28 | type SockaddrInet4 = unix.SockaddrInet4 29 | type SockaddrInet6 = unix.SockaddrInet6 30 | type SockaddrUnix = unix.SockaddrUnix 31 | type RawSockaddrAny = unix.RawSockaddrAny 32 | -------------------------------------------------------------------------------- /net/net_linux.go: -------------------------------------------------------------------------------- 1 | package sockaddrnet 2 | 3 | import ( 4 | "golang.org/x/sys/unix" 5 | ) 6 | 7 | const ( 8 | AF_INET = unix.AF_INET 9 | AF_INET6 = unix.AF_INET6 10 | AF_UNIX = unix.AF_UNIX 11 | AF_UNSPEC = unix.AF_UNSPEC 12 | 13 | IPPROTO_IP = unix.IPPROTO_IP 14 | IPPROTO_IPV4 = unix.IPPROTO_IPIP 15 | IPPROTO_IPV6 = unix.IPPROTO_IPV6 16 | IPPROTO_TCP = unix.IPPROTO_TCP 17 | IPPROTO_UDP = unix.IPPROTO_UDP 18 | 19 | SOCK_DGRAM = unix.SOCK_DGRAM 20 | SOCK_STREAM = unix.SOCK_STREAM 21 | SOCK_SEQPACKET = unix.SOCK_SEQPACKET 22 | ) 23 | 24 | type Sockaddr = unix.Sockaddr 25 | type SockaddrInet4 = unix.SockaddrInet4 26 | type SockaddrInet6 = unix.SockaddrInet6 27 | type SockaddrUnix = unix.SockaddrUnix 28 | type RawSockaddrAny = unix.RawSockaddrAny 29 | -------------------------------------------------------------------------------- /net/net_test.go: -------------------------------------------------------------------------------- 1 | package sockaddrnet 2 | 3 | import ( 4 | "bytes" 5 | "net" 6 | "testing" 7 | ) 8 | 9 | func assertIPEq(t *testing.T, ip net.IP, sa Sockaddr) { 10 | switch s := sa.(type) { 11 | case *SockaddrInet4: 12 | if !bytes.Equal(s.Addr[:], ip.To4()) { 13 | t.Error("IPs not equal") 14 | } 15 | case *SockaddrInet6: 16 | if !bytes.Equal(s.Addr[:], ip.To16()) { 17 | t.Error("IPs not equal") 18 | } 19 | default: 20 | t.Error("not a known sockaddr") 21 | } 22 | } 23 | 24 | func subtestIPSockaddr(t *testing.T, ip net.IP) { 25 | assertIPEq(t, ip, IPAndZoneToSockaddr(ip, "")) 26 | } 27 | 28 | func TestIPAndZoneToSockaddr(t *testing.T) { 29 | subtestIPSockaddr(t, net.ParseIP("127.0.0.1")) 30 | subtestIPSockaddr(t, net.IPv4zero) 31 | subtestIPSockaddr(t, net.IP(net.IPv4zero.To4())) 32 | subtestIPSockaddr(t, net.IPv6unspecified) 33 | assertIPEq(t, net.IPv4zero, IPAndZoneToSockaddr(nil, "")) 34 | } 35 | -------------------------------------------------------------------------------- /net/net_windows.go: -------------------------------------------------------------------------------- 1 | package sockaddrnet 2 | 3 | import ( 4 | "golang.org/x/sys/windows" 5 | ) 6 | 7 | const ( 8 | AF_INET = windows.AF_INET 9 | AF_INET6 = windows.AF_INET6 10 | AF_UNIX = windows.AF_UNIX 11 | AF_UNSPEC = windows.AF_UNSPEC 12 | 13 | IPPROTO_IP = windows.IPPROTO_IP 14 | IPPROTO_IPV4 = 0x4 // windows.IPPROTO_IPV4 (missing) 15 | IPPROTO_IPV6 = windows.IPPROTO_IPV6 16 | IPPROTO_TCP = windows.IPPROTO_TCP 17 | IPPROTO_UDP = windows.IPPROTO_UDP 18 | 19 | SOCK_DGRAM = windows.SOCK_DGRAM 20 | SOCK_STREAM = windows.SOCK_STREAM 21 | SOCK_SEQPACKET = windows.SOCK_SEQPACKET 22 | ) 23 | 24 | type Sockaddr = windows.Sockaddr 25 | type SockaddrInet4 = windows.SockaddrInet4 26 | type SockaddrInet6 = windows.SockaddrInet6 27 | type SockaddrUnix = windows.SockaddrUnix 28 | type RawSockaddrAny = windows.RawSockaddrAny 29 | -------------------------------------------------------------------------------- /sockaddr.go: -------------------------------------------------------------------------------- 1 | // Deprecated: This package is not maintained any longer. 2 | package sockaddr 3 | 4 | import ( 5 | sockaddrnet "github.com/libp2p/go-sockaddr/net" 6 | ) 7 | 8 | // Socklen is a type for the length of a sockaddr. 9 | type Socklen uint 10 | 11 | // SockaddrToAny converts a Sockaddr into a RawSockaddrAny 12 | // The implementation is platform dependent. 13 | func SockaddrToAny(sa sockaddrnet.Sockaddr) (*sockaddrnet.RawSockaddrAny, Socklen, error) { 14 | return sockaddrToAny(sa) 15 | } 16 | 17 | // SockaddrToAny converts a RawSockaddrAny into a Sockaddr 18 | // The implementation is platform dependent. 19 | func AnyToSockaddr(rsa *sockaddrnet.RawSockaddrAny) (sockaddrnet.Sockaddr, error) { 20 | return anyToSockaddr(rsa) 21 | } 22 | -------------------------------------------------------------------------------- /sockaddr_bsd.go: -------------------------------------------------------------------------------- 1 | //go:build darwin || dragonfly || freebsd || netbsd || openbsd 2 | // +build darwin dragonfly freebsd netbsd openbsd 3 | 4 | package sockaddr 5 | 6 | import ( 7 | "syscall" 8 | "unsafe" 9 | 10 | "golang.org/x/sys/unix" 11 | ) 12 | 13 | func sockaddrToAny(sa unix.Sockaddr) (*unix.RawSockaddrAny, Socklen, error) { 14 | if sa == nil { 15 | return nil, 0, syscall.EINVAL 16 | } 17 | 18 | switch sa := sa.(type) { 19 | case *unix.SockaddrInet4: 20 | if sa.Port < 0 || sa.Port > 0xFFFF { 21 | return nil, 0, syscall.EINVAL 22 | } 23 | var raw unix.RawSockaddrInet4 24 | raw.Len = unix.SizeofSockaddrInet4 25 | raw.Family = unix.AF_INET 26 | p := (*[2]byte)(unsafe.Pointer(&raw.Port)) 27 | p[0] = byte(sa.Port >> 8) 28 | p[1] = byte(sa.Port) 29 | for i := 0; i < len(sa.Addr); i++ { 30 | raw.Addr[i] = sa.Addr[i] 31 | } 32 | return (*unix.RawSockaddrAny)(unsafe.Pointer(&raw)), Socklen(raw.Len), nil 33 | 34 | case *unix.SockaddrInet6: 35 | if sa.Port < 0 || sa.Port > 0xFFFF { 36 | return nil, 0, syscall.EINVAL 37 | } 38 | var raw unix.RawSockaddrInet6 39 | raw.Len = unix.SizeofSockaddrInet6 40 | raw.Family = unix.AF_INET6 41 | p := (*[2]byte)(unsafe.Pointer(&raw.Port)) 42 | p[0] = byte(sa.Port >> 8) 43 | p[1] = byte(sa.Port) 44 | raw.Scope_id = sa.ZoneId 45 | for i := 0; i < len(sa.Addr); i++ { 46 | raw.Addr[i] = sa.Addr[i] 47 | } 48 | return (*unix.RawSockaddrAny)(unsafe.Pointer(&raw)), Socklen(raw.Len), nil 49 | 50 | case *unix.SockaddrUnix: 51 | name := sa.Name 52 | n := len(name) 53 | var raw unix.RawSockaddrUnix 54 | if n >= len(raw.Path) || n == 0 { 55 | return nil, 0, syscall.EINVAL 56 | } 57 | raw.Len = byte(3 + n) // 2 for Family, Len; 1 for NUL 58 | raw.Family = unix.AF_UNIX 59 | for i := 0; i < n; i++ { 60 | raw.Path[i] = int8(name[i]) 61 | } 62 | return (*unix.RawSockaddrAny)(unsafe.Pointer(&raw)), Socklen(raw.Len), nil 63 | 64 | case *unix.SockaddrDatalink: 65 | if sa.Index == 0 { 66 | return nil, 0, syscall.EINVAL 67 | } 68 | var raw unix.RawSockaddrDatalink 69 | raw.Len = sa.Len 70 | raw.Family = unix.AF_LINK 71 | raw.Index = sa.Index 72 | raw.Type = sa.Type 73 | raw.Nlen = sa.Nlen 74 | raw.Alen = sa.Alen 75 | raw.Slen = sa.Slen 76 | for i := 0; i < len(raw.Data); i++ { 77 | raw.Data[i] = sa.Data[i] 78 | } 79 | return (*unix.RawSockaddrAny)(unsafe.Pointer(&raw)), unix.SizeofSockaddrDatalink, nil 80 | } 81 | return nil, 0, syscall.EAFNOSUPPORT 82 | } 83 | 84 | func anyToSockaddr(rsa *unix.RawSockaddrAny) (unix.Sockaddr, error) { 85 | if rsa == nil { 86 | return nil, syscall.EINVAL 87 | } 88 | 89 | switch rsa.Addr.Family { 90 | case unix.AF_LINK: 91 | pp := (*unix.RawSockaddrDatalink)(unsafe.Pointer(rsa)) 92 | sa := new(unix.SockaddrDatalink) 93 | sa.Len = pp.Len 94 | sa.Family = pp.Family 95 | sa.Index = pp.Index 96 | sa.Type = pp.Type 97 | sa.Nlen = pp.Nlen 98 | sa.Alen = pp.Alen 99 | sa.Slen = pp.Slen 100 | for i := 0; i < len(sa.Data); i++ { 101 | sa.Data[i] = pp.Data[i] 102 | } 103 | return sa, nil 104 | 105 | case unix.AF_UNIX: 106 | pp := (*unix.RawSockaddrUnix)(unsafe.Pointer(rsa)) 107 | if pp.Len < 3 || pp.Len > unix.SizeofSockaddrUnix { 108 | return nil, syscall.EINVAL 109 | } 110 | sa := new(unix.SockaddrUnix) 111 | n := int(pp.Len) - 3 // subtract leading Family, Len, terminating NUL 112 | for i := 0; i < n; i++ { 113 | if pp.Path[i] == 0 { 114 | // found early NUL; assume Len is overestimating 115 | n = i 116 | break 117 | } 118 | } 119 | bytes := (*[10000]byte)(unsafe.Pointer(&pp.Path[0]))[0:n] 120 | sa.Name = string(bytes) 121 | return sa, nil 122 | 123 | case unix.AF_INET: 124 | pp := (*unix.RawSockaddrInet4)(unsafe.Pointer(rsa)) 125 | sa := new(unix.SockaddrInet4) 126 | p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 127 | sa.Port = int(p[0])<<8 + int(p[1]) 128 | for i := 0; i < len(sa.Addr); i++ { 129 | sa.Addr[i] = pp.Addr[i] 130 | } 131 | return sa, nil 132 | 133 | case unix.AF_INET6: 134 | pp := (*unix.RawSockaddrInet6)(unsafe.Pointer(rsa)) 135 | sa := new(unix.SockaddrInet6) 136 | p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 137 | sa.Port = int(p[0])<<8 + int(p[1]) 138 | sa.ZoneId = pp.Scope_id 139 | for i := 0; i < len(sa.Addr); i++ { 140 | sa.Addr[i] = pp.Addr[i] 141 | } 142 | return sa, nil 143 | } 144 | return nil, syscall.EAFNOSUPPORT 145 | } 146 | -------------------------------------------------------------------------------- /sockaddr_linux.go: -------------------------------------------------------------------------------- 1 | package sockaddr 2 | 3 | import ( 4 | "syscall" 5 | "unsafe" 6 | 7 | "golang.org/x/sys/unix" 8 | ) 9 | 10 | func sockaddrToAny(sa unix.Sockaddr) (*unix.RawSockaddrAny, Socklen, error) { 11 | if sa == nil { 12 | return nil, 0, syscall.EINVAL 13 | } 14 | 15 | switch sa := sa.(type) { 16 | case *unix.SockaddrInet4: 17 | if sa.Port < 0 || sa.Port > 0xFFFF { 18 | return nil, 0, syscall.EINVAL 19 | } 20 | var raw unix.RawSockaddrInet4 21 | raw.Family = unix.AF_INET 22 | p := (*[2]byte)(unsafe.Pointer(&raw.Port)) 23 | p[0] = byte(sa.Port >> 8) 24 | p[1] = byte(sa.Port) 25 | for i := 0; i < len(sa.Addr); i++ { 26 | raw.Addr[i] = sa.Addr[i] 27 | } 28 | return (*unix.RawSockaddrAny)(unsafe.Pointer(&raw)), unix.SizeofSockaddrInet4, nil 29 | 30 | case *unix.SockaddrInet6: 31 | if sa.Port < 0 || sa.Port > 0xFFFF { 32 | return nil, 0, syscall.EINVAL 33 | } 34 | var raw unix.RawSockaddrInet6 35 | raw.Family = unix.AF_INET6 36 | p := (*[2]byte)(unsafe.Pointer(&raw.Port)) 37 | p[0] = byte(sa.Port >> 8) 38 | p[1] = byte(sa.Port) 39 | raw.Scope_id = sa.ZoneId 40 | for i := 0; i < len(sa.Addr); i++ { 41 | raw.Addr[i] = sa.Addr[i] 42 | } 43 | return (*unix.RawSockaddrAny)(unsafe.Pointer(&raw)), unix.SizeofSockaddrInet6, nil 44 | 45 | case *unix.SockaddrUnix: 46 | name := sa.Name 47 | n := len(name) 48 | var raw unix.RawSockaddrUnix 49 | if n >= len(raw.Path) { 50 | return nil, 0, syscall.EINVAL 51 | } 52 | raw.Family = unix.AF_UNIX 53 | for i := 0; i < n; i++ { 54 | raw.Path[i] = int8(name[i]) 55 | } 56 | // length is family (uint16), name, NUL. 57 | sl := Socklen(2) 58 | if n > 0 { 59 | sl += Socklen(n) + 1 60 | } 61 | if raw.Path[0] == '@' { 62 | raw.Path[0] = 0 63 | // Don't count trailing NUL for abstract address. 64 | sl-- 65 | } 66 | return (*unix.RawSockaddrAny)(unsafe.Pointer(&raw)), sl, nil 67 | 68 | case *unix.SockaddrLinklayer: 69 | if sa.Ifindex < 0 || sa.Ifindex > 0x7fffffff { 70 | return nil, 0, syscall.EINVAL 71 | } 72 | var raw unix.RawSockaddrLinklayer 73 | raw.Family = unix.AF_PACKET 74 | raw.Protocol = sa.Protocol 75 | raw.Ifindex = int32(sa.Ifindex) 76 | raw.Hatype = sa.Hatype 77 | raw.Pkttype = sa.Pkttype 78 | raw.Halen = sa.Halen 79 | for i := 0; i < len(sa.Addr); i++ { 80 | raw.Addr[i] = sa.Addr[i] 81 | } 82 | return (*unix.RawSockaddrAny)(unsafe.Pointer(&raw)), unix.SizeofSockaddrLinklayer, nil 83 | } 84 | return nil, 0, syscall.EAFNOSUPPORT 85 | } 86 | 87 | func anyToSockaddr(rsa *unix.RawSockaddrAny) (unix.Sockaddr, error) { 88 | if rsa == nil { 89 | return nil, syscall.EINVAL 90 | } 91 | 92 | switch rsa.Addr.Family { 93 | case unix.AF_NETLINK: 94 | pp := (*unix.RawSockaddrNetlink)(unsafe.Pointer(rsa)) 95 | sa := new(unix.SockaddrNetlink) 96 | sa.Family = pp.Family 97 | sa.Pad = pp.Pad 98 | sa.Pid = pp.Pid 99 | sa.Groups = pp.Groups 100 | return sa, nil 101 | 102 | case unix.AF_PACKET: 103 | pp := (*unix.RawSockaddrLinklayer)(unsafe.Pointer(rsa)) 104 | sa := new(unix.SockaddrLinklayer) 105 | sa.Protocol = pp.Protocol 106 | sa.Ifindex = int(pp.Ifindex) 107 | sa.Hatype = pp.Hatype 108 | sa.Pkttype = pp.Pkttype 109 | sa.Halen = pp.Halen 110 | for i := 0; i < len(sa.Addr); i++ { 111 | sa.Addr[i] = pp.Addr[i] 112 | } 113 | return sa, nil 114 | 115 | case unix.AF_UNIX: 116 | pp := (*unix.RawSockaddrUnix)(unsafe.Pointer(rsa)) 117 | sa := new(unix.SockaddrUnix) 118 | if pp.Path[0] == 0 { 119 | // "Abstract" Unix domain socket. 120 | // Rewrite leading NUL as @ for textual display. 121 | // (This is the standard convention.) 122 | // Not friendly to overwrite in place, 123 | // but the callers below don't care. 124 | pp.Path[0] = '@' 125 | } 126 | 127 | // Assume path ends at NUL. 128 | // This is not technically the Linux semantics for 129 | // abstract Unix domain sockets--they are supposed 130 | // to be uninterpreted fixed-size binary blobs--but 131 | // everyone uses this convention. 132 | n := 0 133 | for n < len(pp.Path) && pp.Path[n] != 0 { 134 | n++ 135 | } 136 | bytes := (*[10000]byte)(unsafe.Pointer(&pp.Path[0]))[0:n] 137 | sa.Name = string(bytes) 138 | return sa, nil 139 | 140 | case unix.AF_INET: 141 | pp := (*unix.RawSockaddrInet4)(unsafe.Pointer(rsa)) 142 | sa := new(unix.SockaddrInet4) 143 | p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 144 | sa.Port = int(p[0])<<8 + int(p[1]) 145 | for i := 0; i < len(sa.Addr); i++ { 146 | sa.Addr[i] = pp.Addr[i] 147 | } 148 | return sa, nil 149 | 150 | case unix.AF_INET6: 151 | pp := (*unix.RawSockaddrInet6)(unsafe.Pointer(rsa)) 152 | sa := new(unix.SockaddrInet6) 153 | p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 154 | sa.Port = int(p[0])<<8 + int(p[1]) 155 | sa.ZoneId = pp.Scope_id 156 | for i := 0; i < len(sa.Addr); i++ { 157 | sa.Addr[i] = pp.Addr[i] 158 | } 159 | return sa, nil 160 | } 161 | return nil, syscall.EAFNOSUPPORT 162 | } 163 | -------------------------------------------------------------------------------- /sockaddr_platform.go: -------------------------------------------------------------------------------- 1 | package sockaddr 2 | 3 | // import ( 4 | // "unix" 5 | // "unsafe" 6 | // ) 7 | 8 | // func sockaddrToAny(sa unix.Sockaddr) (*unix.RawSockaddrAny, Socklen, error) { 9 | // if sa == nil { 10 | // return nil, 0, unix.EINVAL 11 | // } 12 | 13 | // switch sa.(type) { 14 | // case *unix.SockaddrInet4: 15 | // case *unix.SockaddrInet6: 16 | // case *unix.SockaddrUnix: 17 | // case *unix.SockaddrDatalink: 18 | // } 19 | // return nil, 0, unix.EAFNOSUPPORT 20 | // } 21 | 22 | // func anyToSockaddr(rsa *unix.RawSockaddrAny) (unix.Sockaddr, error) { 23 | // if rsa == nil { 24 | // return nil, 0, unix.EINVAL 25 | // } 26 | 27 | // switch rsa.Addr.Family { 28 | // case unix.AF_NETLINK: 29 | // case unix.AF_PACKET: 30 | // case unix.AF_UNIX: 31 | // case unix.AF_INET: 32 | // case unix.AF_INET6: 33 | // } 34 | // return nil, unix.EAFNOSUPPORT 35 | // } 36 | -------------------------------------------------------------------------------- /sockaddr_windows.go: -------------------------------------------------------------------------------- 1 | package sockaddr 2 | 3 | import ( 4 | "syscall" 5 | "unsafe" 6 | 7 | "golang.org/x/sys/windows" 8 | ) 9 | 10 | func sockaddrToAny(sa windows.Sockaddr) (*windows.RawSockaddrAny, Socklen, error) { 11 | if sa == nil { 12 | return nil, 0, syscall.EINVAL 13 | } 14 | 15 | switch sa := sa.(type) { 16 | case *windows.SockaddrInet4: 17 | if sa.Port < 0 || sa.Port > 0xFFFF { 18 | return nil, 0, syscall.EINVAL 19 | } 20 | 21 | raw := new(windows.RawSockaddrAny) 22 | raw.Addr.Family = windows.AF_INET 23 | raw4 := (*windows.RawSockaddrInet4)(unsafe.Pointer(raw)) 24 | p := (*[2]byte)(unsafe.Pointer(&raw4.Port)) 25 | p[0] = byte(sa.Port >> 8) 26 | p[1] = byte(sa.Port) 27 | for i := 0; i < len(sa.Addr); i++ { 28 | raw4.Addr[i] = sa.Addr[i] 29 | } 30 | return raw, Socklen(unsafe.Sizeof(*raw4)), nil 31 | 32 | case *windows.SockaddrInet6: 33 | if sa.Port < 0 || sa.Port > 0xFFFF { 34 | return nil, 0, syscall.EINVAL 35 | } 36 | 37 | raw := new(windows.RawSockaddrAny) 38 | raw.Addr.Family = windows.AF_INET6 39 | raw6 := (*windows.RawSockaddrInet6)(unsafe.Pointer(raw)) 40 | p := (*[2]byte)(unsafe.Pointer(&raw6.Port)) 41 | p[0] = byte(sa.Port >> 8) 42 | p[1] = byte(sa.Port) 43 | raw6.Scope_id = sa.ZoneId 44 | for i := 0; i < len(sa.Addr); i++ { 45 | raw6.Addr[i] = sa.Addr[i] 46 | } 47 | return raw, Socklen(unsafe.Sizeof(*raw6)), nil 48 | 49 | case *windows.SockaddrUnix: 50 | return nil, 0, syscall.EWINDOWS 51 | } 52 | return nil, 0, syscall.EAFNOSUPPORT 53 | } 54 | 55 | func anyToSockaddr(rsa *windows.RawSockaddrAny) (windows.Sockaddr, error) { 56 | if rsa == nil { 57 | return nil, syscall.EINVAL 58 | } 59 | 60 | switch rsa.Addr.Family { 61 | case windows.AF_UNIX: 62 | return nil, syscall.EWINDOWS 63 | 64 | case windows.AF_INET: 65 | pp := (*windows.RawSockaddrInet4)(unsafe.Pointer(rsa)) 66 | sa := new(windows.SockaddrInet4) 67 | p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 68 | sa.Port = int(p[0])<<8 + int(p[1]) 69 | for i := 0; i < len(sa.Addr); i++ { 70 | sa.Addr[i] = pp.Addr[i] 71 | } 72 | return sa, nil 73 | 74 | case windows.AF_INET6: 75 | pp := (*windows.RawSockaddrInet6)(unsafe.Pointer(rsa)) 76 | sa := new(windows.SockaddrInet6) 77 | p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 78 | sa.Port = int(p[0])<<8 + int(p[1]) 79 | sa.ZoneId = pp.Scope_id 80 | for i := 0; i < len(sa.Addr); i++ { 81 | sa.Addr[i] = pp.Addr[i] 82 | } 83 | return sa, nil 84 | } 85 | return nil, syscall.EAFNOSUPPORT 86 | } 87 | -------------------------------------------------------------------------------- /version.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "v0.2.0" 3 | } 4 | --------------------------------------------------------------------------------