aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/jackpal
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/jackpal')
-rw-r--r--vendor/github.com/jackpal/go-nat-pmp/.travis.yml13
-rw-r--r--vendor/github.com/jackpal/go-nat-pmp/LICENSE13
-rw-r--r--vendor/github.com/jackpal/go-nat-pmp/README.md52
-rw-r--r--vendor/github.com/jackpal/go-nat-pmp/natpmp.go153
-rw-r--r--vendor/github.com/jackpal/go-nat-pmp/network.go89
-rw-r--r--vendor/github.com/jackpal/go-nat-pmp/recorder.go19
6 files changed, 339 insertions, 0 deletions
diff --git a/vendor/github.com/jackpal/go-nat-pmp/.travis.yml b/vendor/github.com/jackpal/go-nat-pmp/.travis.yml
new file mode 100644
index 000000000..9c3f6547d
--- /dev/null
+++ b/vendor/github.com/jackpal/go-nat-pmp/.travis.yml
@@ -0,0 +1,13 @@
+language: go
+
+go:
+ - 1.6.2
+ - tip
+
+allowed_failures:
+ - go: tip
+
+install:
+ - go get -d -v ./... && go install -race -v ./...
+
+script: go test -race -v ./...
diff --git a/vendor/github.com/jackpal/go-nat-pmp/LICENSE b/vendor/github.com/jackpal/go-nat-pmp/LICENSE
new file mode 100644
index 000000000..249514b0f
--- /dev/null
+++ b/vendor/github.com/jackpal/go-nat-pmp/LICENSE
@@ -0,0 +1,13 @@
+ Copyright 2013 John Howard Palevich
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/github.com/jackpal/go-nat-pmp/README.md b/vendor/github.com/jackpal/go-nat-pmp/README.md
new file mode 100644
index 000000000..3ca687f0b
--- /dev/null
+++ b/vendor/github.com/jackpal/go-nat-pmp/README.md
@@ -0,0 +1,52 @@
+go-nat-pmp
+==========
+
+A Go language client for the NAT-PMP internet protocol for port mapping and discovering the external
+IP address of a firewall.
+
+NAT-PMP is supported by Apple brand routers and open source routers like Tomato and DD-WRT.
+
+See http://tools.ietf.org/html/draft-cheshire-nat-pmp-03
+
+
+[![Build Status](https://travis-ci.org/jackpal/go-nat-pmp.svg)](https://travis-ci.org/jackpal/go-nat-pmp)
+
+Get the package
+---------------
+
+ go get -u github.com/jackpal/go-nat-pmp
+
+Usage
+-----
+
+ import (
+ "github.com/jackpal/gateway"
+ natpmp "github.com/jackpal/go-nat-pmp"
+ )
+
+ gatewayIP, err = gateway.DiscoverGateway()
+ if err != nil {
+ return
+ }
+
+ client := natpmp.NewClient(gatewayIP)
+ response, err := client.GetExternalAddress()
+ if err != nil {
+ return
+ }
+ print("External IP address:", response.ExternalIPAddress)
+
+Clients
+-------
+
+This library is used in the Taipei Torrent BitTorrent client http://github.com/jackpal/Taipei-Torrent
+
+Complete documentation
+----------------------
+
+ http://godoc.org/github.com/jackpal/go-nat-pmp
+
+License
+-------
+
+This project is licensed under the Apache License 2.0.
diff --git a/vendor/github.com/jackpal/go-nat-pmp/natpmp.go b/vendor/github.com/jackpal/go-nat-pmp/natpmp.go
new file mode 100644
index 000000000..5ca7680e4
--- /dev/null
+++ b/vendor/github.com/jackpal/go-nat-pmp/natpmp.go
@@ -0,0 +1,153 @@
+package natpmp
+
+import (
+ "fmt"
+ "net"
+ "time"
+)
+
+// Implement the NAT-PMP protocol, typically supported by Apple routers and open source
+// routers such as DD-WRT and Tomato.
+//
+// See http://tools.ietf.org/html/draft-cheshire-nat-pmp-03
+//
+// Usage:
+//
+// client := natpmp.NewClient(gatewayIP)
+// response, err := client.GetExternalAddress()
+
+// The recommended mapping lifetime for AddPortMapping
+const RECOMMENDED_MAPPING_LIFETIME_SECONDS = 3600
+
+// Interface used to make remote procedure calls.
+type caller interface {
+ call(msg []byte, timeout time.Duration) (result []byte, err error)
+}
+
+// Client is a NAT-PMP protocol client.
+type Client struct {
+ caller caller
+ timeout time.Duration
+}
+
+// Create a NAT-PMP client for the NAT-PMP server at the gateway.
+// Uses default timeout which is around 128 seconds.
+func NewClient(gateway net.IP) (nat *Client) {
+ return &Client{&network{gateway}, 0}
+}
+
+// Create a NAT-PMP client for the NAT-PMP server at the gateway, with a timeout.
+// Timeout defines the total amount of time we will keep retrying before giving up.
+func NewClientWithTimeout(gateway net.IP, timeout time.Duration) (nat *Client) {
+ return &Client{&network{gateway}, timeout}
+}
+
+// Results of the NAT-PMP GetExternalAddress operation.
+type GetExternalAddressResult struct {
+ SecondsSinceStartOfEpoc uint32
+ ExternalIPAddress [4]byte
+}
+
+// Get the external address of the router.
+func (n *Client) GetExternalAddress() (result *GetExternalAddressResult, err error) {
+ msg := make([]byte, 2)
+ msg[0] = 0 // Version 0
+ msg[1] = 0 // OP Code 0
+ response, err := n.rpc(msg, 12)
+ if err != nil {
+ return
+ }
+ result = &GetExternalAddressResult{}
+ result.SecondsSinceStartOfEpoc = readNetworkOrderUint32(response[4:8])
+ copy(result.ExternalIPAddress[:], response[8:12])
+ return
+}
+
+// Results of the NAT-PMP AddPortMapping operation
+type AddPortMappingResult struct {
+ SecondsSinceStartOfEpoc uint32
+ InternalPort uint16
+ MappedExternalPort uint16
+ PortMappingLifetimeInSeconds uint32
+}
+
+// Add (or delete) a port mapping. To delete a mapping, set the requestedExternalPort and lifetime to 0
+func (n *Client) AddPortMapping(protocol string, internalPort, requestedExternalPort int, lifetime int) (result *AddPortMappingResult, err error) {
+ var opcode byte
+ if protocol == "udp" {
+ opcode = 1
+ } else if protocol == "tcp" {
+ opcode = 2
+ } else {
+ err = fmt.Errorf("unknown protocol %v", protocol)
+ return
+ }
+ msg := make([]byte, 12)
+ msg[0] = 0 // Version 0
+ msg[1] = opcode
+ writeNetworkOrderUint16(msg[4:6], uint16(internalPort))
+ writeNetworkOrderUint16(msg[6:8], uint16(requestedExternalPort))
+ writeNetworkOrderUint32(msg[8:12], uint32(lifetime))
+ response, err := n.rpc(msg, 16)
+ if err != nil {
+ return
+ }
+ result = &AddPortMappingResult{}
+ result.SecondsSinceStartOfEpoc = readNetworkOrderUint32(response[4:8])
+ result.InternalPort = readNetworkOrderUint16(response[8:10])
+ result.MappedExternalPort = readNetworkOrderUint16(response[10:12])
+ result.PortMappingLifetimeInSeconds = readNetworkOrderUint32(response[12:16])
+ return
+}
+
+func (n *Client) rpc(msg []byte, resultSize int) (result []byte, err error) {
+ result, err = n.caller.call(msg, n.timeout)
+ if err != nil {
+ return
+ }
+ err = protocolChecks(msg, resultSize, result)
+ return
+}
+
+func protocolChecks(msg []byte, resultSize int, result []byte) (err error) {
+ if len(result) != resultSize {
+ err = fmt.Errorf("unexpected result size %d, expected %d", len(result), resultSize)
+ return
+ }
+ if result[0] != 0 {
+ err = fmt.Errorf("unknown protocol version %d", result[0])
+ return
+ }
+ expectedOp := msg[1] | 0x80
+ if result[1] != expectedOp {
+ err = fmt.Errorf("Unexpected opcode %d. Expected %d", result[1], expectedOp)
+ return
+ }
+ resultCode := readNetworkOrderUint16(result[2:4])
+ if resultCode != 0 {
+ err = fmt.Errorf("Non-zero result code %d", resultCode)
+ return
+ }
+ // If we got here the RPC is good.
+ return
+}
+
+func writeNetworkOrderUint16(buf []byte, d uint16) {
+ buf[0] = byte(d >> 8)
+ buf[1] = byte(d)
+}
+
+func writeNetworkOrderUint32(buf []byte, d uint32) {
+ buf[0] = byte(d >> 24)
+ buf[1] = byte(d >> 16)
+ buf[2] = byte(d >> 8)
+ buf[3] = byte(d)
+}
+
+func readNetworkOrderUint16(buf []byte) uint16 {
+ return (uint16(buf[0]) << 8) | uint16(buf[1])
+}
+
+func readNetworkOrderUint32(buf []byte) uint32 {
+ return (uint32(buf[0]) << 24) | (uint32(buf[1]) << 16) | (uint32(buf[2]) << 8) | uint32(buf[3])
+}
diff --git a/vendor/github.com/jackpal/go-nat-pmp/network.go b/vendor/github.com/jackpal/go-nat-pmp/network.go
new file mode 100644
index 000000000..c42b4fee9
--- /dev/null
+++ b/vendor/github.com/jackpal/go-nat-pmp/network.go
@@ -0,0 +1,89 @@
+package natpmp
+
+import (
+ "fmt"
+ "net"
+ "time"
+)
+
+const nAT_PMP_PORT = 5351
+const nAT_TRIES = 9
+const nAT_INITIAL_MS = 250
+
+// A caller that implements the NAT-PMP RPC protocol.
+type network struct {
+ gateway net.IP
+}
+
+func (n *network) call(msg []byte, timeout time.Duration) (result []byte, err error) {
+ var server net.UDPAddr
+ server.IP = n.gateway
+ server.Port = nAT_PMP_PORT
+ conn, err := net.DialUDP("udp", nil, &server)
+ if err != nil {
+ return
+ }
+ defer conn.Close()
+
+ // 16 bytes is the maximum result size.
+ result = make([]byte, 16)
+
+ var finalTimeout time.Time
+ if timeout != 0 {
+ finalTimeout = time.Now().Add(timeout)
+ }
+
+ needNewDeadline := true
+
+ var tries uint
+ for tries = 0; (tries < nAT_TRIES && finalTimeout.IsZero()) || time.Now().Before(finalTimeout); {
+ if needNewDeadline {
+ nextDeadline := time.Now().Add((nAT_INITIAL_MS << tries) * time.Millisecond)
+ err = conn.SetDeadline(minTime(nextDeadline, finalTimeout))
+ if err != nil {
+ return
+ }
+ needNewDeadline = false
+ }
+ _, err = conn.Write(msg)
+ if err != nil {
+ return
+ }
+ var bytesRead int
+ var remoteAddr *net.UDPAddr
+ bytesRead, remoteAddr, err = conn.ReadFromUDP(result)
+ if err != nil {
+ if err.(net.Error).Timeout() {
+ tries++
+ needNewDeadline = true
+ continue
+ }
+ return
+ }
+ if !remoteAddr.IP.Equal(n.gateway) {
+ // Ignore this packet.
+ // Continue without increasing retransmission timeout or deadline.
+ continue
+ }
+ // Trim result to actual number of bytes received
+ if bytesRead < len(result) {
+ result = result[:bytesRead]
+ }
+ return
+ }
+ err = fmt.Errorf("Timed out trying to contact gateway")
+ return
+}
+
+func minTime(a, b time.Time) time.Time {
+ if a.IsZero() {
+ return b
+ }
+ if b.IsZero() {
+ return a
+ }
+ if a.Before(b) {
+ return a
+ }
+ return b
+}
diff --git a/vendor/github.com/jackpal/go-nat-pmp/recorder.go b/vendor/github.com/jackpal/go-nat-pmp/recorder.go
new file mode 100644
index 000000000..845703672
--- /dev/null
+++ b/vendor/github.com/jackpal/go-nat-pmp/recorder.go
@@ -0,0 +1,19 @@
+package natpmp
+
+import "time"
+
+type callObserver interface {
+ observeCall(msg []byte, result []byte, err error)
+}
+
+// A caller that records the RPC call.
+type recorder struct {
+ child caller
+ observer callObserver
+}
+
+func (n *recorder) call(msg []byte, timeout time.Duration) (result []byte, err error) {
+ result, err = n.child.call(msg, timeout)
+ n.observer.observeCall(msg, result, err)
+ return
+}