123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- package upnp
- import (
- "errors"
- "log"
- "sync"
- "time"
- "gitlab.com/NebulousLabs/go-upnp"
- )
- type UPnPClient struct {
- Connection *upnp.IGD
- ExternalIP string
- RequiredPorts []int
- PolicyNames sync.Map
- }
- func NewUPNPClient() (*UPnPClient, error) {
-
- log.Println("Discovering UPnP router in Local Area Network...")
- d, err := upnp.Discover()
- if err != nil {
- return &UPnPClient{}, err
- }
-
- ip, err := d.ExternalIP()
- if err != nil {
- return &UPnPClient{}, err
- }
-
- newUPnPObject := &UPnPClient{
- Connection: d,
- ExternalIP: ip,
- RequiredPorts: []int{},
- }
- return newUPnPObject, nil
- }
- func (u *UPnPClient) ForwardPort(portNumber int, ruleName string) error {
- log.Println("UPnP forwarding new port: ", portNumber, "for "+ruleName+" service")
-
- _, ok := u.PolicyNames.Load(portNumber)
- if ok {
-
- return errors.New("Port already forwarded")
- }
-
- err := u.Connection.Forward(uint16(portNumber), ruleName)
- if err != nil {
- return err
- }
- u.RequiredPorts = append(u.RequiredPorts, portNumber)
- u.PolicyNames.Store(portNumber, ruleName)
- return nil
- }
- func (u *UPnPClient) ClosePort(portNumber int) error {
-
- portOpened := false
- newRequiredPort := []int{}
- for _, thisPort := range u.RequiredPorts {
- if thisPort != portNumber {
- newRequiredPort = append(newRequiredPort, thisPort)
- } else {
- portOpened = true
- }
- }
- if portOpened {
-
- u.RequiredPorts = newRequiredPort
-
- log.Println("Closing UPnP Port Forward: ", portNumber)
- err := u.Connection.Clear(uint16(portNumber))
-
- u.PolicyNames.Delete(portNumber)
- if err != nil {
- log.Println(err)
- return err
- }
- }
- return nil
- }
- func (u *UPnPClient) RenewForwardRules() {
- portsToRenew := u.RequiredPorts
- for _, thisPort := range portsToRenew {
- ruleName, ok := u.PolicyNames.Load(thisPort)
- if !ok {
- continue
- }
- u.ClosePort(thisPort)
- time.Sleep(100 * time.Millisecond)
- u.ForwardPort(thisPort, ruleName.(string))
- }
- log.Println("UPnP Port Forward rule renew completed")
- }
- func (u *UPnPClient) Close() {
-
- if u != nil {
- for _, portNumber := range u.RequiredPorts {
- err := u.Connection.Clear(uint16(portNumber))
- if err != nil {
- log.Println(err)
- }
- }
- }
- }
|