mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-08-07 05:38:30 +02:00
Added UI for plugin system and upnp example
- Added wip UI for plugin tag system - Added upnp port forwarder plugin - Added error and fatal printout for plugins - Optimized UI flow for plugin context window - Added dev web server for plugin development purpose
This commit is contained in:
135
example/plugins/upnp/mod/upnpc/upnpc.go
Normal file
135
example/plugins/upnp/mod/upnpc/upnpc.go
Normal file
@@ -0,0 +1,135 @@
|
||||
package upnpc
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"gitlab.com/NebulousLabs/go-upnp"
|
||||
)
|
||||
|
||||
/*
|
||||
uPNP Module
|
||||
|
||||
This module handles uPNP Connections to the gateway router and create a port forward entry
|
||||
for the host system at the given port (set with -port paramter)
|
||||
*/
|
||||
|
||||
type UPnPClient struct {
|
||||
Connection *upnp.IGD //UPnP conenction object
|
||||
ExternalIP string //Storage of external IP address
|
||||
RequiredPorts []int //All the required ports will be recored
|
||||
PolicyNames sync.Map //Name for the required port nubmer
|
||||
}
|
||||
|
||||
// NewUPNPClient creates a new UPnPClient object
|
||||
func NewUPNPClient() (*UPnPClient, error) {
|
||||
//Create uPNP forwarding in the NAT router
|
||||
fmt.Println("Discovering UPnP router in Local Area Network...")
|
||||
d, err := upnp.Discover()
|
||||
if err != nil {
|
||||
return &UPnPClient{}, err
|
||||
}
|
||||
|
||||
// discover external IP
|
||||
ip, err := d.ExternalIP()
|
||||
if err != nil {
|
||||
return &UPnPClient{}, err
|
||||
}
|
||||
|
||||
//Create the final obejcts
|
||||
newUPnPObject := &UPnPClient{
|
||||
Connection: d,
|
||||
ExternalIP: ip,
|
||||
RequiredPorts: []int{},
|
||||
}
|
||||
|
||||
return newUPnPObject, nil
|
||||
}
|
||||
|
||||
// ForwardPort forwards a port to the host
|
||||
func (u *UPnPClient) ForwardPort(portNumber int, ruleName string) error {
|
||||
fmt.Println("UPnP forwarding new port: ", portNumber, "for "+ruleName+" service")
|
||||
|
||||
//Check if port already forwarded
|
||||
_, ok := u.PolicyNames.Load(portNumber)
|
||||
if ok {
|
||||
//Port already forward. Ignore this request
|
||||
return errors.New("port already forwarded")
|
||||
}
|
||||
|
||||
// forward a port
|
||||
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
|
||||
}
|
||||
|
||||
// ClosePort closes the port forwarding
|
||||
func (u *UPnPClient) ClosePort(portNumber int) error {
|
||||
//Check if port is opened
|
||||
portOpened := false
|
||||
newRequiredPort := []int{}
|
||||
for _, thisPort := range u.RequiredPorts {
|
||||
if thisPort != portNumber {
|
||||
newRequiredPort = append(newRequiredPort, thisPort)
|
||||
} else {
|
||||
portOpened = true
|
||||
}
|
||||
}
|
||||
|
||||
if portOpened {
|
||||
//Update the port list
|
||||
u.RequiredPorts = newRequiredPort
|
||||
|
||||
// Close the port
|
||||
fmt.Println("Closing UPnP Port Forward: ", portNumber)
|
||||
err := u.Connection.Clear(uint16(portNumber))
|
||||
|
||||
//Delete the name registry
|
||||
u.PolicyNames.Delete(portNumber)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Renew forward rules, prevent router lease time from flushing the Upnp config
|
||||
func (u *UPnPClient) RenewForwardRules() {
|
||||
if u.Connection == nil {
|
||||
//UPnP router gone
|
||||
return
|
||||
}
|
||||
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))
|
||||
}
|
||||
fmt.Println("UPnP Port Forward rule renew completed")
|
||||
}
|
||||
|
||||
func (u *UPnPClient) Close() error {
|
||||
//Shutdown the default UPnP Object
|
||||
if u != nil {
|
||||
for _, portNumber := range u.RequiredPorts {
|
||||
err := u.Connection.Clear(uint16(portNumber))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
Reference in New Issue
Block a user