This commit is contained in:
Sudo-Ivan
2024-12-30 12:58:43 -06:00
parent 7ef7e60a87
commit 7a7ce84778
14 changed files with 919 additions and 207 deletions

View File

@@ -21,7 +21,10 @@ type Interface interface {
GetMode() common.InterfaceMode
IsOnline() bool
IsDetached() bool
IsEnabled() bool
Detach()
Enable()
Disable()
Send(data []byte, addr string) error
SetPacketCallback(common.PacketCallback)
GetPacketCallback() common.PacketCallback
@@ -33,12 +36,25 @@ type BaseInterface struct {
mode common.InterfaceMode
ifType common.InterfaceType
online bool
enabled bool
detached bool
mtu int
mutex sync.RWMutex
packetCallback common.PacketCallback
}
func NewBaseInterface(name string, ifType common.InterfaceType, enabled bool) BaseInterface {
return BaseInterface{
name: name,
mode: common.IF_MODE_FULL,
ifType: ifType,
online: false,
enabled: enabled,
detached: false,
mtu: common.DEFAULT_MTU,
}
}
func (i *BaseInterface) SetPacketCallback(callback common.PacketCallback) {
i.Mutex.Lock()
defer i.Mutex.Unlock()
@@ -136,5 +152,21 @@ func (i *BaseInterface) GetConn() net.Conn {
}
func (i *BaseInterface) IsEnabled() bool {
return i.Online && !i.Detached
i.mutex.RLock()
defer i.mutex.RUnlock()
return i.enabled && i.online && !i.detached
}
func (i *BaseInterface) Enable() {
i.mutex.Lock()
defer i.mutex.Unlock()
i.enabled = true
i.online = true
}
func (i *BaseInterface) Disable() {
i.mutex.Lock()
defer i.mutex.Unlock()
i.enabled = false
i.online = false
}

View File

@@ -44,85 +44,56 @@ type TCPClientInterface struct {
packetCallback common.PacketCallback
mutex sync.RWMutex
detached bool
enabled bool
}
func NewTCPClient(name string, targetAddr string, targetPort int, kissFraming bool, i2pTunneled bool) (*TCPClientInterface, error) {
func NewTCPClient(name string, targetHost string, targetPort int, kissFraming bool, i2pTunneled bool, enabled bool) (*TCPClientInterface, error) {
tc := &TCPClientInterface{
BaseInterface: BaseInterface{
name: name,
mode: common.IF_MODE_FULL,
ifType: common.IF_TYPE_TCP,
online: false,
mtu: 1064,
detached: false,
},
targetAddr: targetAddr,
targetPort: targetPort,
kissFraming: kissFraming,
i2pTunneled: i2pTunneled,
initiator: true,
BaseInterface: NewBaseInterface(name, common.IF_TYPE_TCP, enabled),
targetAddr: targetHost,
targetPort: targetPort,
kissFraming: kissFraming,
i2pTunneled: i2pTunneled,
initiator: true,
enabled: enabled,
}
if err := tc.connect(true); err != nil {
go tc.reconnect()
} else {
go tc.readLoop()
if enabled {
addr := fmt.Sprintf("%s:%d", targetHost, targetPort)
conn, err := net.Dial("tcp", addr)
if err != nil {
return nil, err
}
tc.conn = conn
tc.online = true
}
return tc, nil
}
func (tc *TCPClientInterface) connect(initial bool) error {
func (tc *TCPClientInterface) Start() error {
tc.mutex.Lock()
defer tc.mutex.Unlock()
if !tc.enabled {
return fmt.Errorf("interface not enabled")
}
if tc.conn != nil {
tc.online = true
return nil
}
addr := fmt.Sprintf("%s:%d", tc.targetAddr, tc.targetPort)
conn, err := net.DialTimeout("tcp", addr, time.Second*INITIAL_TIMEOUT)
conn, err := net.Dial("tcp", addr)
if err != nil {
if initial {
return fmt.Errorf("initial connection failed: %v", err)
}
return err
}
tc.conn = conn
tc.Online = true
tc.writing = false
tc.neverConnected = false
// Set TCP options
if tcpConn, ok := conn.(*net.TCPConn); ok {
tcpConn.SetNoDelay(true)
tcpConn.SetKeepAlive(true)
tcpConn.SetKeepAlivePeriod(time.Second * TCP_PROBE_INTERVAL)
}
tc.online = true
return nil
}
func (tc *TCPClientInterface) reconnect() {
if tc.initiator && !tc.reconnecting {
tc.reconnecting = true
attempts := 0
for !tc.Online {
time.Sleep(time.Second * RECONNECT_WAIT)
attempts++
if tc.maxReconnectTries > 0 && attempts > tc.maxReconnectTries {
tc.teardown()
break
}
if err := tc.connect(false); err != nil {
continue
}
go tc.readLoop()
break
}
tc.reconnecting = false
}
}
func (tc *TCPClientInterface) readLoop() {
buffer := make([]byte, tc.MTU)
inFrame := false
@@ -281,7 +252,9 @@ func (tc *TCPClientInterface) SetPacketCallback(cb common.PacketCallback) {
}
func (tc *TCPClientInterface) IsEnabled() bool {
return tc.Online
tc.mutex.RLock()
defer tc.mutex.RUnlock()
return tc.enabled && tc.online && !tc.detached
}
func (tc *TCPClientInterface) GetName() string {
@@ -306,17 +279,68 @@ func (tc *TCPClientInterface) IsOnline() bool {
return tc.online
}
func (tc *TCPClientInterface) reconnect() {
tc.mutex.Lock()
if tc.reconnecting {
tc.mutex.Unlock()
return
}
tc.reconnecting = true
tc.mutex.Unlock()
retries := 0
for retries < tc.maxReconnectTries {
tc.teardown()
addr := fmt.Sprintf("%s:%d", tc.targetAddr, tc.targetPort)
conn, err := net.Dial("tcp", addr)
if err == nil {
tc.mutex.Lock()
tc.conn = conn
tc.online = true
tc.neverConnected = false
tc.reconnecting = false
tc.mutex.Unlock()
// Restart read loop
go tc.readLoop()
return
}
retries++
// Wait before retrying
select {
case <-time.After(RECONNECT_WAIT * time.Second):
continue
}
}
// Failed to reconnect after max retries
tc.mutex.Lock()
tc.reconnecting = false
tc.mutex.Unlock()
tc.teardown()
}
func (tc *TCPClientInterface) Enable() {
tc.mutex.Lock()
defer tc.mutex.Unlock()
tc.online = true
}
func (tc *TCPClientInterface) Disable() {
tc.mutex.Lock()
defer tc.mutex.Unlock()
tc.online = false
}
type TCPServerInterface struct {
BaseInterface
listener net.Listener
connections map[string]net.Conn
mutex sync.RWMutex
bindAddr string
bindPort int
preferIPv6 bool
spawned bool
port int
host string
kissFraming bool
i2pTunneled bool
packetCallback common.PacketCallback
@@ -387,3 +411,15 @@ func (ts *TCPServerInterface) IsOnline() bool {
defer ts.mutex.RUnlock()
return ts.online
}
func (ts *TCPServerInterface) Enable() {
ts.mutex.Lock()
defer ts.mutex.Unlock()
ts.online = true
}
func (ts *TCPServerInterface) Disable() {
ts.mutex.Lock()
defer ts.mutex.Unlock()
ts.online = false
}

View File

@@ -2,6 +2,7 @@ package interfaces
import (
"fmt"
"log"
"net"
"sync"
@@ -19,9 +20,10 @@ type UDPInterface struct {
rxBytes uint64
mtu int
bitrate int
enabled bool
}
func NewUDPInterface(name string, addr string, target string) (*UDPInterface, error) {
func NewUDPInterface(name string, addr string, target string, enabled bool) (*UDPInterface, error) {
udpAddr, err := net.ResolveUDPAddr("udp", addr)
if err != nil {
return nil, err
@@ -36,17 +38,12 @@ func NewUDPInterface(name string, addr string, target string) (*UDPInterface, er
}
ui := &UDPInterface{
BaseInterface: BaseInterface{
name: name,
mode: common.IF_MODE_FULL,
ifType: common.IF_TYPE_UDP,
online: false,
mtu: common.DEFAULT_MTU,
detached: false,
},
addr: udpAddr,
targetAddr: targetAddr,
readBuffer: make([]byte, common.DEFAULT_MTU),
BaseInterface: NewBaseInterface(name, common.IF_TYPE_UDP, enabled),
addr: udpAddr,
targetAddr: targetAddr,
readBuffer: make([]byte, common.DEFAULT_MTU),
mtu: common.DEFAULT_MTU,
enabled: enabled,
}
return ui, nil
@@ -86,29 +83,16 @@ func (ui *UDPInterface) Detach() {
}
func (ui *UDPInterface) Send(data []byte, addr string) error {
if !ui.IsOnline() {
return fmt.Errorf("interface offline")
if !ui.IsEnabled() {
return fmt.Errorf("interface not enabled")
}
targetAddr := ui.targetAddr
if addr != "" {
var err error
targetAddr, err = net.ResolveUDPAddr("udp", addr)
if err != nil {
return fmt.Errorf("invalid target address: %v", err)
}
}
if targetAddr == nil {
if ui.targetAddr == nil {
return fmt.Errorf("no target address configured")
}
_, err := ui.conn.WriteToUDP(data, targetAddr)
if err != nil {
return fmt.Errorf("UDP write failed: %v", err)
}
return nil
_, err := ui.conn.WriteTo(data, ui.targetAddr)
return err
}
func (ui *UDPInterface) SetPacketCallback(callback common.PacketCallback) {
@@ -173,3 +157,58 @@ func (ui *UDPInterface) GetMTU() int {
func (ui *UDPInterface) GetBitrate() int {
return ui.bitrate
}
func (ui *UDPInterface) Enable() {
ui.mutex.Lock()
defer ui.mutex.Unlock()
ui.online = true
}
func (ui *UDPInterface) Disable() {
ui.mutex.Lock()
defer ui.mutex.Unlock()
ui.online = false
}
func (ui *UDPInterface) Start() error {
conn, err := net.ListenUDP("udp", ui.addr)
if err != nil {
return err
}
ui.conn = conn
ui.online = true
return nil
}
func (ui *UDPInterface) readLoop() {
buffer := make([]byte, ui.mtu)
for {
if ui.IsDetached() {
return
}
n, addr, err := ui.conn.ReadFromUDP(buffer)
if err != nil {
if !ui.IsDetached() {
log.Printf("UDP read error: %v", err)
}
return
}
ui.mutex.Lock()
ui.rxBytes += uint64(n)
ui.mutex.Unlock()
log.Printf("Received %d bytes from %s", n, addr.String())
if callback := ui.GetPacketCallback(); callback != nil {
callback(buffer[:n], ui)
}
}
}
func (ui *UDPInterface) IsEnabled() bool {
ui.mutex.RLock()
defer ui.mutex.RUnlock()
return ui.enabled && ui.online && !ui.detached
}