56 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			56 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| 
								 | 
							
								package p2p
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import (
							 | 
						||
| 
								 | 
							
									"fmt"
							 | 
						||
| 
								 | 
							
									"net"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									natpmp "github.com/jackpal/go-nat-pmp"
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// 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
							 | 
						||
| 
								 | 
							
								}
							 |