Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
3f503ffc
Commit
3f503ffc
authored
Feb 02, 2014
by
obscuren
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implemented support for UPnP
parent
ae0d4eb7
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
180 additions
and
123 deletions
+180
-123
ethereum.go
ethereum.go
+62
-0
nat.go
nat.go
+12
-0
natpmp.go
natpmp.go
+54
-0
natupnp.go
natupnp.go
+52
-123
No files found.
ethereum.go
View file @
3f503ffc
...
@@ -8,6 +8,7 @@ import (
...
@@ -8,6 +8,7 @@ import (
"github.com/ethereum/ethwire-go"
"github.com/ethereum/ethwire-go"
"log"
"log"
"net"
"net"
"strconv"
"sync"
"sync"
"sync/atomic"
"sync/atomic"
"time"
"time"
...
@@ -29,6 +30,7 @@ const (
...
@@ -29,6 +30,7 @@ const (
type
Ethereum
struct
{
type
Ethereum
struct
{
// Channel for shutting down the ethereum
// Channel for shutting down the ethereum
shutdownChan
chan
bool
shutdownChan
chan
bool
quit
chan
bool
// DB interface
// DB interface
//db *ethdb.LDBDatabase
//db *ethdb.LDBDatabase
db
*
ethdb
.
MemDatabase
db
*
ethdb
.
MemDatabase
...
@@ -48,6 +50,8 @@ type Ethereum struct {
...
@@ -48,6 +50,8 @@ type Ethereum struct {
// Capabilities for outgoing peers
// Capabilities for outgoing peers
serverCaps
Caps
serverCaps
Caps
nat
NAT
}
}
func
New
(
caps
Caps
)
(
*
Ethereum
,
error
)
{
func
New
(
caps
Caps
)
(
*
Ethereum
,
error
)
{
...
@@ -57,15 +61,30 @@ func New(caps Caps) (*Ethereum, error) {
...
@@ -57,15 +61,30 @@ func New(caps Caps) (*Ethereum, error) {
return
nil
,
err
return
nil
,
err
}
}
/*
gateway := net.ParseIP("192.168.192.1")
nat := NewNatPMP(gateway)
port, err := nat.AddPortMapping("tcp", 30303, 30303, "", 60)
log.Println(port, err)
*/
nat
,
err
:=
Discover
()
if
err
!=
nil
{
log
.
Println
(
"UPnP failed"
,
err
)
return
nil
,
err
}
ethutil
.
Config
.
Db
=
db
ethutil
.
Config
.
Db
=
db
nonce
,
_
:=
ethutil
.
RandomUint64
()
nonce
,
_
:=
ethutil
.
RandomUint64
()
ethereum
:=
&
Ethereum
{
ethereum
:=
&
Ethereum
{
shutdownChan
:
make
(
chan
bool
),
shutdownChan
:
make
(
chan
bool
),
quit
:
make
(
chan
bool
),
db
:
db
,
db
:
db
,
peers
:
list
.
New
(),
peers
:
list
.
New
(),
Nonce
:
nonce
,
Nonce
:
nonce
,
serverCaps
:
caps
,
serverCaps
:
caps
,
nat
:
nat
,
}
}
ethereum
.
TxPool
=
ethchain
.
NewTxPool
()
ethereum
.
TxPool
=
ethchain
.
NewTxPool
()
ethereum
.
TxPool
.
Speaker
=
ethereum
ethereum
.
TxPool
.
Speaker
=
ethereum
...
@@ -217,6 +236,8 @@ func (s *Ethereum) Start() {
...
@@ -217,6 +236,8 @@ func (s *Ethereum) Start() {
go
s
.
peerHandler
(
ln
)
go
s
.
peerHandler
(
ln
)
}
}
go
s
.
upnpUpdateThread
()
// Start the reaping processes
// Start the reaping processes
go
s
.
ReapDeadPeerHandler
()
go
s
.
ReapDeadPeerHandler
()
...
@@ -245,6 +266,8 @@ func (s *Ethereum) Stop() {
...
@@ -245,6 +266,8 @@ func (s *Ethereum) Stop() {
p
.
Stop
()
p
.
Stop
()
})
})
close
(
s
.
quit
)
s
.
shutdownChan
<-
true
s
.
shutdownChan
<-
true
s
.
TxPool
.
Stop
()
s
.
TxPool
.
Stop
()
...
@@ -254,3 +277,42 @@ func (s *Ethereum) Stop() {
...
@@ -254,3 +277,42 @@ func (s *Ethereum) Stop() {
func
(
s
*
Ethereum
)
WaitForShutdown
()
{
func
(
s
*
Ethereum
)
WaitForShutdown
()
{
<-
s
.
shutdownChan
<-
s
.
shutdownChan
}
}
func
(
s
*
Ethereum
)
upnpUpdateThread
()
{
// Go off immediately to prevent code duplication, thereafter we renew
// lease every 15 minutes.
timer
:=
time
.
NewTimer
(
0
*
time
.
Second
)
lport
,
_
:=
strconv
.
ParseInt
(
"30303"
,
10
,
16
)
first
:=
true
out
:
for
{
select
{
case
<-
timer
.
C
:
listenPort
,
err
:=
s
.
nat
.
AddPortMapping
(
"TCP"
,
int
(
lport
),
int
(
lport
),
"eth listen port"
,
20
*
60
)
if
err
!=
nil
{
log
.
Println
(
"can't add UPnP port mapping:"
,
err
)
break
out
}
if
first
&&
err
==
nil
{
externalip
,
err
:=
s
.
nat
.
GetExternalAddress
()
if
err
!=
nil
{
log
.
Println
(
"UPnP can't get external address:"
,
err
)
continue
out
}
log
.
Println
(
"Successfully bound via UPnP to"
,
externalip
,
listenPort
)
first
=
false
}
timer
.
Reset
(
time
.
Minute
*
15
)
case
<-
s
.
quit
:
break
out
}
}
timer
.
Stop
()
if
err
:=
s
.
nat
.
DeletePortMapping
(
"TCP"
,
int
(
lport
),
int
(
lport
));
err
!=
nil
{
log
.
Println
(
"unable to remove UPnP port mapping:"
,
err
)
}
else
{
log
.
Println
(
"succesfully disestablished UPnP port mapping"
)
}
}
nat.go
0 → 100644
View file @
3f503ffc
package
eth
import
(
"net"
)
// protocol is either "udp" or "tcp"
type
NAT
interface
{
GetExternalAddress
()
(
addr
net
.
IP
,
err
error
)
AddPortMapping
(
protocol
string
,
externalPort
,
internalPort
int
,
description
string
,
timeout
int
)
(
mappedExternalPort
int
,
err
error
)
DeletePortMapping
(
protocol
string
,
externalPort
,
internalPort
int
)
(
err
error
)
}
natpmp.go
0 → 100644
View file @
3f503ffc
package
eth
import
(
natpmp
"code.google.com/p/go-nat-pmp"
"fmt"
"net"
)
// Adapt the NAT-PMP protocol to the NAT interface
// TODO:
// + Register for changes to the external address.
// + Re-register port mapping when router reboots.
// + A mechanism for keeping a port mapping registered.
type
natPMPClient
struct
{
client
*
natpmp
.
Client
}
func
NewNatPMP
(
gateway
net
.
IP
)
(
nat
NAT
)
{
return
&
natPMPClient
{
natpmp
.
NewClient
(
gateway
)}
}
func
(
n
*
natPMPClient
)
GetExternalAddress
()
(
addr
net
.
IP
,
err
error
)
{
response
,
err
:=
n
.
client
.
GetExternalAddress
()
if
err
!=
nil
{
return
}
ip
:=
response
.
ExternalIPAddress
addr
=
net
.
IPv4
(
ip
[
0
],
ip
[
1
],
ip
[
2
],
ip
[
3
])
return
}
func
(
n
*
natPMPClient
)
AddPortMapping
(
protocol
string
,
externalPort
,
internalPort
int
,
description
string
,
timeout
int
)
(
mappedExternalPort
int
,
err
error
)
{
if
timeout
<=
0
{
err
=
fmt
.
Errorf
(
"timeout must not be <= 0"
)
return
}
// Note order of port arguments is switched between our AddPortMapping and the client's AddPortMapping.
response
,
err
:=
n
.
client
.
AddPortMapping
(
protocol
,
internalPort
,
externalPort
,
timeout
)
if
err
!=
nil
{
return
}
mappedExternalPort
=
int
(
response
.
MappedExternalPort
)
return
}
func
(
n
*
natPMPClient
)
DeletePortMapping
(
protocol
string
,
externalPort
,
internalPort
int
)
(
err
error
)
{
// To destroy a mapping, send an add-port with
// an internalPort of the internal port to destroy, an external port of zero and a time of zero.
_
,
err
=
n
.
client
.
AddPortMapping
(
protocol
,
internalPort
,
0
,
0
)
return
}
upnp.go
→
nat
upnp.go
View file @
3f503ffc
package
eth
package
eth
// Upnp code taken from Taipei Torrent license is below:
// Copyright (c) 2010 Jack Palevich. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Just enough UPnP to be able to forward ports
// Just enough UPnP to be able to forward ports
//
//
...
@@ -44,27 +15,11 @@ import (
...
@@ -44,27 +15,11 @@ import (
"time"
"time"
)
)
// NAT is an interface representing a NAT traversal options for example UPNP or
// NAT-PMP. It provides methods to query and manipulate this traversal to allow
// access to services.
type
NAT
interface
{
// Get the external address from outside the NAT.
GetExternalAddress
()
(
addr
net
.
IP
,
err
error
)
// Add a port mapping for protocol ("udp" or "tcp") from externalport to
// internal port with description lasting for timeout.
AddPortMapping
(
protocol
string
,
externalPort
,
internalPort
int
,
description
string
,
timeout
int
)
(
mappedExternalPort
int
,
err
error
)
// Remove a previously added port mapping from externalport to
// internal port.
DeletePortMapping
(
protocol
string
,
externalPort
,
internalPort
int
)
(
err
error
)
}
type
upnpNAT
struct
{
type
upnpNAT
struct
{
serviceURL
string
serviceURL
string
ourIP
string
ourIP
string
}
}
// Discover searches the local network for a UPnP router returning a NAT
// for the network if so, nil if not.
func
Discover
()
(
nat
NAT
,
err
error
)
{
func
Discover
()
(
nat
NAT
,
err
error
)
{
ssdp
,
err
:=
net
.
ResolveUDPAddr
(
"udp4"
,
"239.255.255.250:1900"
)
ssdp
,
err
:=
net
.
ResolveUDPAddr
(
"udp4"
,
"239.255.255.250:1900"
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -77,7 +32,7 @@ func Discover() (nat NAT, err error) {
...
@@ -77,7 +32,7 @@ func Discover() (nat NAT, err error) {
socket
:=
conn
.
(
*
net
.
UDPConn
)
socket
:=
conn
.
(
*
net
.
UDPConn
)
defer
socket
.
Close
()
defer
socket
.
Close
()
err
=
socket
.
SetDeadline
(
time
.
Now
()
.
Add
(
3
*
time
.
Second
))
err
=
socket
.
SetDeadline
(
time
.
Now
()
.
Add
(
10
*
time
.
Second
))
if
err
!=
nil
{
if
err
!=
nil
{
return
return
}
}
...
@@ -134,7 +89,7 @@ func Discover() (nat NAT, err error) {
...
@@ -134,7 +89,7 @@ func Discover() (nat NAT, err error) {
nat
=
&
upnpNAT
{
serviceURL
:
serviceURL
,
ourIP
:
ourIP
}
nat
=
&
upnpNAT
{
serviceURL
:
serviceURL
,
ourIP
:
ourIP
}
return
return
}
}
err
=
errors
.
New
(
"UPnP port discovery failed"
)
err
=
errors
.
New
(
"UPnP port discovery failed
.
"
)
return
return
}
}
...
@@ -190,39 +145,38 @@ type root struct {
...
@@ -190,39 +145,38 @@ type root struct {
Device
device
Device
device
}
}
// getChildDevice searches the children of device for a device with the given
// type.
func
getChildDevice
(
d
*
device
,
deviceType
string
)
*
device
{
func
getChildDevice
(
d
*
device
,
deviceType
string
)
*
device
{
for
i
:=
range
d
.
DeviceList
.
Device
{
dl
:=
d
.
DeviceList
.
Device
if
d
.
DeviceList
.
Device
[
i
]
.
DeviceType
==
deviceType
{
for
i
:=
0
;
i
<
len
(
dl
);
i
++
{
return
&
d
.
DeviceList
.
Device
[
i
]
if
dl
[
i
]
.
DeviceType
==
deviceType
{
return
&
dl
[
i
]
}
}
}
}
return
nil
return
nil
}
}
// getChildDevice searches the service list of device for a service with the
// given type.
func
getChildService
(
d
*
device
,
serviceType
string
)
*
service
{
func
getChildService
(
d
*
device
,
serviceType
string
)
*
service
{
for
i
:=
range
d
.
ServiceList
.
Service
{
sl
:=
d
.
ServiceList
.
Service
if
d
.
ServiceList
.
Service
[
i
]
.
ServiceType
==
serviceType
{
for
i
:=
0
;
i
<
len
(
sl
);
i
++
{
return
&
d
.
ServiceList
.
Service
[
i
]
if
sl
[
i
]
.
ServiceType
==
serviceType
{
return
&
sl
[
i
]
}
}
}
}
return
nil
return
nil
}
}
// getOurIP returns a best guess at what the local IP is.
func
getOurIP
()
(
ip
string
,
err
error
)
{
func
getOurIP
()
(
ip
string
,
err
error
)
{
hostname
,
err
:=
os
.
Hostname
()
hostname
,
err
:=
os
.
Hostname
()
if
err
!=
nil
{
if
err
!=
nil
{
return
return
}
}
return
net
.
LookupCNAME
(
hostname
)
p
,
err
:=
net
.
LookupIP
(
hostname
)
if
err
!=
nil
&&
len
(
p
)
>
0
{
return
}
return
p
[
0
]
.
String
(),
nil
}
}
// getServiceURL parses the xml description at the given root url to find the
// url for the WANIPConnection service to be used for port forwarding.
func
getServiceURL
(
rootURL
string
)
(
url
string
,
err
error
)
{
func
getServiceURL
(
rootURL
string
)
(
url
string
,
err
error
)
{
r
,
err
:=
http
.
Get
(
rootURL
)
r
,
err
:=
http
.
Get
(
rootURL
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -235,34 +189,34 @@ func getServiceURL(rootURL string) (url string, err error) {
...
@@ -235,34 +189,34 @@ func getServiceURL(rootURL string) (url string, err error) {
}
}
var
root
root
var
root
root
err
=
xml
.
NewDecoder
(
r
.
Body
)
.
Decode
(
&
root
)
err
=
xml
.
NewDecoder
(
r
.
Body
)
.
Decode
(
&
root
)
if
err
!=
nil
{
if
err
!=
nil
{
return
return
}
}
a
:=
&
root
.
Device
a
:=
&
root
.
Device
if
a
.
DeviceType
!=
"urn:schemas-upnp-org:device:InternetGatewayDevice:1"
{
if
a
.
DeviceType
!=
"urn:schemas-upnp-org:device:InternetGatewayDevice:1"
{
err
=
errors
.
New
(
"
n
o InternetGatewayDevice"
)
err
=
errors
.
New
(
"
N
o InternetGatewayDevice"
)
return
return
}
}
b
:=
getChildDevice
(
a
,
"urn:schemas-upnp-org:device:WANDevice:1"
)
b
:=
getChildDevice
(
a
,
"urn:schemas-upnp-org:device:WANDevice:1"
)
if
b
==
nil
{
if
b
==
nil
{
err
=
errors
.
New
(
"
n
o WANDevice"
)
err
=
errors
.
New
(
"
N
o WANDevice"
)
return
return
}
}
c
:=
getChildDevice
(
b
,
"urn:schemas-upnp-org:device:WANConnectionDevice:1"
)
c
:=
getChildDevice
(
b
,
"urn:schemas-upnp-org:device:WANConnectionDevice:1"
)
if
c
==
nil
{
if
c
==
nil
{
err
=
errors
.
New
(
"
n
o WANConnectionDevice"
)
err
=
errors
.
New
(
"
N
o WANConnectionDevice"
)
return
return
}
}
d
:=
getChildService
(
c
,
"urn:schemas-upnp-org:service:WANIPConnection:1"
)
d
:=
getChildService
(
c
,
"urn:schemas-upnp-org:service:WANIPConnection:1"
)
if
d
==
nil
{
if
d
==
nil
{
err
=
errors
.
New
(
"
n
o WANIPConnection"
)
err
=
errors
.
New
(
"
N
o WANIPConnection"
)
return
return
}
}
url
=
combineURL
(
rootURL
,
d
.
ControlURL
)
url
=
combineURL
(
rootURL
,
d
.
ControlURL
)
return
return
}
}
// combineURL appends subURL onto rootURL.
func
combineURL
(
rootURL
,
subURL
string
)
string
{
func
combineURL
(
rootURL
,
subURL
string
)
string
{
protocolEnd
:=
"://"
protocolEnd
:=
"://"
protoEndIndex
:=
strings
.
Index
(
rootURL
,
protocolEnd
)
protoEndIndex
:=
strings
.
Index
(
rootURL
,
protocolEnd
)
...
@@ -271,24 +225,7 @@ func combineURL(rootURL, subURL string) string {
...
@@ -271,24 +225,7 @@ func combineURL(rootURL, subURL string) string {
return
rootURL
[
0
:
protoEndIndex
+
len
(
protocolEnd
)
+
rootIndex
]
+
subURL
return
rootURL
[
0
:
protoEndIndex
+
len
(
protocolEnd
)
+
rootIndex
]
+
subURL
}
}
// soapBody represents the <s:Body> element in a SOAP reply.
func
soapRequest
(
url
,
function
,
message
string
)
(
r
*
http
.
Response
,
err
error
)
{
// fields we don't care about are elided.
type
soapBody
struct
{
XMLName
xml
.
Name
`xml:"Body"`
Data
[]
byte
`xml:",innerxml"`
}
// soapEnvelope represents the <s:Envelope> element in a SOAP reply.
// fields we don't care about are elided.
type
soapEnvelope
struct
{
XMLName
xml
.
Name
`xml:"Envelope"`
Body
soapBody
`xml:"Body"`
}
// soapRequests performs a soap request with the given parameters and returns
// the xml replied stripped of the soap headers. in the case that the request is
// unsuccessful the an error is returned.
func
soapRequest
(
url
,
function
,
message
string
)
(
replyXML
[]
byte
,
err
error
)
{
fullMessage
:=
"<?xml version=
\"
1.0
\"
?>"
+
fullMessage
:=
"<?xml version=
\"
1.0
\"
?>"
+
"<s:Envelope xmlns:s=
\"
http://schemas.xmlsoap.org/soap/envelope/
\"
s:encodingStyle=
\"
http://schemas.xmlsoap.org/soap/encoding/
\"
>
\r\n
"
+
"<s:Envelope xmlns:s=
\"
http://schemas.xmlsoap.org/soap/envelope/
\"
s:encodingStyle=
\"
http://schemas.xmlsoap.org/soap/encoding/
\"
>
\r\n
"
+
"<s:Body>"
+
message
+
"</s:Body></s:Envelope>"
"<s:Body>"
+
message
+
"</s:Body></s:Envelope>"
...
@@ -305,10 +242,10 @@ func soapRequest(url, function, message string) (replyXML []byte, err error) {
...
@@ -305,10 +242,10 @@ func soapRequest(url, function, message string) (replyXML []byte, err error) {
req
.
Header
.
Set
(
"Cache-Control"
,
"no-cache"
)
req
.
Header
.
Set
(
"Cache-Control"
,
"no-cache"
)
req
.
Header
.
Set
(
"Pragma"
,
"no-cache"
)
req
.
Header
.
Set
(
"Pragma"
,
"no-cache"
)
r
,
err
:=
http
.
DefaultClient
.
Do
(
req
)
// log.Stderr("soapRequest ",
req)
if
err
!=
nil
{
//fmt.Println(fullMessage)
return
nil
,
err
}
r
,
err
=
http
.
DefaultClient
.
Do
(
req
)
if
r
.
Body
!=
nil
{
if
r
.
Body
!=
nil
{
defer
r
.
Body
.
Close
()
defer
r
.
Body
.
Close
()
}
}
...
@@ -319,45 +256,39 @@ func soapRequest(url, function, message string) (replyXML []byte, err error) {
...
@@ -319,45 +256,39 @@ func soapRequest(url, function, message string) (replyXML []byte, err error) {
r
=
nil
r
=
nil
return
return
}
}
var
reply
soapEnvelope
return
err
=
xml
.
NewDecoder
(
r
.
Body
)
.
Decode
(
&
reply
)
if
err
!=
nil
{
return
nil
,
err
}
return
reply
.
Body
.
Data
,
nil
}
}
// getExternalIPAddressResponse represents the XML response to a
type
statusInfo
struct
{
// GetExternalIPAddress SOAP request.
externalIpAddress
string
type
getExternalIPAddressResponse
struct
{
XMLName
xml
.
Name
`xml:"GetExternalIPAddressResponse"`
ExternalIPAddress
string
`xml:"NewExternalIPAddress"`
}
}
// GetExternalAddress implements the NAT interface by fetching the external IP
func
(
n
*
upnpNAT
)
getStatusInfo
()
(
info
statusInfo
,
err
error
)
{
// from the UPnP router.
func
(
n
*
upnpNAT
)
GetExternalAddress
()
(
addr
net
.
IP
,
err
error
)
{
message
:=
"<u:GetStatusInfo xmlns:u=
\"
urn:schemas-upnp-org:service:WANIPConnection:1
\"
>
\r\n
"
+
message
:=
"<u:GetExternalIPAddress xmlns:u=
\"
urn:schemas-upnp-org:service:WANIPConnection:1
\"
/>
\r\n
"
"</u:GetStatusInfo>"
response
,
err
:=
soapRequest
(
n
.
serviceURL
,
"GetExternalIPAddress"
,
message
)
if
err
!=
nil
{
return
nil
,
err
}
var
re
ply
getExternalIPAddress
Response
var
re
sponse
*
http
.
Response
err
=
xml
.
Unmarshal
(
response
,
&
reply
)
response
,
err
=
soapRequest
(
n
.
serviceURL
,
"GetStatusInfo"
,
message
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
}
}
addr
=
net
.
ParseIP
(
reply
.
ExternalIPAddress
)
// TODO: Write a soap reply parser. It has to eat the Body and envelope tags...
if
addr
==
nil
{
return
nil
,
errors
.
New
(
"unable to parse ip address"
)
response
.
Body
.
Close
()
return
}
func
(
n
*
upnpNAT
)
GetExternalAddress
()
(
addr
net
.
IP
,
err
error
)
{
info
,
err
:=
n
.
getStatusInfo
()
if
err
!=
nil
{
return
}
}
return
addr
,
nil
addr
=
net
.
ParseIP
(
info
.
externalIpAddress
)
return
}
}
// AddPortMapping implements the NAT interface by setting up a port forwarding
// from the UPnP router to the local machine with the given ports and protocol.
func
(
n
*
upnpNAT
)
AddPortMapping
(
protocol
string
,
externalPort
,
internalPort
int
,
description
string
,
timeout
int
)
(
mappedExternalPort
int
,
err
error
)
{
func
(
n
*
upnpNAT
)
AddPortMapping
(
protocol
string
,
externalPort
,
internalPort
int
,
description
string
,
timeout
int
)
(
mappedExternalPort
int
,
err
error
)
{
// A single concatenation would break ARM compilation.
// A single concatenation would break ARM compilation.
message
:=
"<u:AddPortMapping xmlns:u=
\"
urn:schemas-upnp-org:service:WANIPConnection:1
\"
>
\r\n
"
+
message
:=
"<u:AddPortMapping xmlns:u=
\"
urn:schemas-upnp-org:service:WANIPConnection:1
\"
>
\r\n
"
+
...
@@ -370,22 +301,19 @@ func (n *upnpNAT) AddPortMapping(protocol string, externalPort, internalPort int
...
@@ -370,22 +301,19 @@ func (n *upnpNAT) AddPortMapping(protocol string, externalPort, internalPort int
"</NewPortMappingDescription><NewLeaseDuration>"
+
strconv
.
Itoa
(
timeout
)
+
"</NewPortMappingDescription><NewLeaseDuration>"
+
strconv
.
Itoa
(
timeout
)
+
"</NewLeaseDuration></u:AddPortMapping>"
"</NewLeaseDuration></u:AddPortMapping>"
response
,
err
:=
soapRequest
(
n
.
serviceURL
,
"AddPortMapping"
,
message
)
var
response
*
http
.
Response
response
,
err
=
soapRequest
(
n
.
serviceURL
,
"AddPortMapping"
,
message
)
if
err
!=
nil
{
if
err
!=
nil
{
return
return
}
}
// TODO: check response to see if the port was forwarded
// TODO: check response to see if the port was forwarded
// If the port was not wildcard we don't get an reply with the port in
// log.Println(message, response)
// it. Not sure about wildcard yet. miniupnpc just checks for error
// codes here.
mappedExternalPort
=
externalPort
mappedExternalPort
=
externalPort
_
=
response
_
=
response
return
return
}
}
// AddPortMapping implements the NAT interface by removing up a port forwarding
// from the UPnP router to the local machine with the given ports and.
func
(
n
*
upnpNAT
)
DeletePortMapping
(
protocol
string
,
externalPort
,
internalPort
int
)
(
err
error
)
{
func
(
n
*
upnpNAT
)
DeletePortMapping
(
protocol
string
,
externalPort
,
internalPort
int
)
(
err
error
)
{
message
:=
"<u:DeletePortMapping xmlns:u=
\"
urn:schemas-upnp-org:service:WANIPConnection:1
\"
>
\r\n
"
+
message
:=
"<u:DeletePortMapping xmlns:u=
\"
urn:schemas-upnp-org:service:WANIPConnection:1
\"
>
\r\n
"
+
...
@@ -393,7 +321,8 @@ func (n *upnpNAT) DeletePortMapping(protocol string, externalPort, internalPort
...
@@ -393,7 +321,8 @@ func (n *upnpNAT) DeletePortMapping(protocol string, externalPort, internalPort
"</NewExternalPort><NewProtocol>"
+
protocol
+
"</NewProtocol>"
+
"</NewExternalPort><NewProtocol>"
+
protocol
+
"</NewProtocol>"
+
"</u:DeletePortMapping>"
"</u:DeletePortMapping>"
response
,
err
:=
soapRequest
(
n
.
serviceURL
,
"DeletePortMapping"
,
message
)
var
response
*
http
.
Response
response
,
err
=
soapRequest
(
n
.
serviceURL
,
"DeletePortMapping"
,
message
)
if
err
!=
nil
{
if
err
!=
nil
{
return
return
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment