work on new constructors

This commit is contained in:
eyedeekay
2025-02-17 22:23:20 -05:00
parent c1d7c642b4
commit e279e7c011
7 changed files with 114 additions and 64 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
review.md
SAMv3.md

2
Makefile Normal file
View File

@ -0,0 +1,2 @@
fmt:
find . -name '*.go' -exec gofumpt -w -s -extra {} \;

View File

@ -13,49 +13,6 @@ import (
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
// Creates a new controller for the I2P routers SAM bridge.
func OldNewSAM(address string) (*SAM, error) {
log.WithField("address", address).Debug("Creating new SAM instance")
var s SAM
// TODO: clean this up by refactoring the connection setup and error handling logic
conn, err := net.Dial("tcp", address)
if err != nil {
log.WithError(err).Error("Failed to dial SAM address")
return nil, fmt.Errorf("error dialing to address '%s': %w", address, err)
}
if _, err := conn.Write(s.SAMEmit.HelloBytes()); err != nil {
log.WithError(err).Error("Failed to write hello message")
conn.Close()
return nil, fmt.Errorf("error writing to address '%s': %w", address, err)
}
buf := make([]byte, 256)
n, err := conn.Read(buf)
if err != nil {
log.WithError(err).Error("Failed to read SAM response")
conn.Close()
return nil, fmt.Errorf("error reading onto buffer: %w", err)
}
if strings.Contains(string(buf[:n]), HELLO_REPLY_OK) {
log.Debug("SAM hello successful")
s.SAMEmit.I2PConfig.SetSAMAddress(address)
s.Conn = conn
s.SAMResolver, err = NewSAMResolver(&s)
if err != nil {
log.WithError(err).Error("Failed to create SAM resolver")
return nil, fmt.Errorf("error creating resolver: %w", err)
}
return &s, nil
} else if string(buf[:n]) == HELLO_REPLY_NOVERSION {
log.Error("SAM bridge does not support SAMv3")
conn.Close()
return nil, fmt.Errorf("That SAM bridge does not support SAMv3.")
} else {
log.WithField("response", string(buf[:n])).Error("Unexpected SAM response")
conn.Close()
return nil, fmt.Errorf("%s", string(buf[:n]))
}
}
func (sam *SAM) Keys() (k *i2pkeys.I2PKeys) { func (sam *SAM) Keys() (k *i2pkeys.I2PKeys) {
// TODO: copy them? // TODO: copy them?
log.Debug("Retrieving SAM keys") log.Debug("Retrieving SAM keys")
@ -71,6 +28,7 @@ func (sam *SAM) ReadKeys(r io.Reader) (err error) {
if err == nil { if err == nil {
log.Debug("Keys loaded successfully") log.Debug("Keys loaded successfully")
sam.SAMEmit.I2PConfig.DestinationKeys = &keys sam.SAMEmit.I2PConfig.DestinationKeys = &keys
return
} }
log.WithError(err).Error("Failed to load keys") log.WithError(err).Error("Failed to load keys")
return return

View File

@ -38,25 +38,25 @@ func (f *I2PConfig) Sam() string {
// SetSAMAddress sets the SAM bridge host and port from a combined address string. // SetSAMAddress sets the SAM bridge host and port from a combined address string.
// If no address is provided, it sets default values for the host and port. // If no address is provided, it sets default values for the host and port.
func (f *I2PConfig) SetSAMAddress(addr string) { func (f *I2PConfig) SetSAMAddress(addr string) {
// Set default values if addr == "" {
f.SamHost = "127.0.0.1" f.SamHost = "127.0.0.1"
f.SamPort = 7656 f.SamPort = 7656
return
// Split address into host and port components
host, port, err := net.SplitHostPort(addr)
if err != nil {
// If error occurs, assume only host is provided
f.SamHost = addr
} else {
f.SamHost = host
f.SamPort, _ = strconv.Atoi(port)
} }
// Log the configured SAM address host, port, err := net.SplitHostPort(addr)
log.WithFields(logrus.Fields{ if err != nil {
"host": f.SamHost, // Only set host if it looks valid
"port": f.SamPort, if net.ParseIP(addr) != nil || !strings.Contains(addr, ":") {
}).Debug("SAM address set") f.SamHost = addr
}
return
}
f.SamHost = host
if p, err := strconv.Atoi(port); err == nil && p > 0 && p < 65536 {
f.SamPort = p
}
} }
// ID returns the tunnel name as a formatted string. If no tunnel name is set, // ID returns the tunnel name as a formatted string. If no tunnel name is set,

81
common/new.go Normal file
View File

@ -0,0 +1,81 @@
package common
import (
"fmt"
"net"
"strings"
)
// Creates a new controller for the I2P routers SAM bridge.
func OldNewSAM(address string) (*SAM, error) {
log.WithField("address", address).Debug("Creating new SAM instance")
var s SAM
// TODO: clean this up by refactoring the connection setup and error handling logic
conn, err := net.Dial("tcp", address)
if err != nil {
log.WithError(err).Error("Failed to dial SAM address")
return nil, fmt.Errorf("error dialing to address '%s': %w", address, err)
}
if _, err := conn.Write(s.SAMEmit.HelloBytes()); err != nil {
log.WithError(err).Error("Failed to write hello message")
conn.Close()
return nil, fmt.Errorf("error writing to address '%s': %w", address, err)
}
buf := make([]byte, 256)
n, err := conn.Read(buf)
if err != nil {
log.WithError(err).Error("Failed to read SAM response")
conn.Close()
return nil, fmt.Errorf("error reading onto buffer: %w", err)
}
if strings.Contains(string(buf[:n]), HELLO_REPLY_OK) {
log.Debug("SAM hello successful")
s.SAMEmit.I2PConfig.SetSAMAddress(address)
s.Conn = conn
s.SAMResolver, err = NewSAMResolver(&s)
if err != nil {
log.WithError(err).Error("Failed to create SAM resolver")
return nil, fmt.Errorf("error creating resolver: %w", err)
}
return &s, nil
} else if string(buf[:n]) == HELLO_REPLY_NOVERSION {
log.Error("SAM bridge does not support SAMv3")
conn.Close()
return nil, fmt.Errorf("That SAM bridge does not support SAMv3.")
} else {
log.WithField("response", string(buf[:n])).Error("Unexpected SAM response")
conn.Close()
return nil, fmt.Errorf("%s", string(buf[:n]))
}
}
func NewSAM(address string) (*SAM, error) {
logger := log.WithField("address", address)
logger.Debug("Creating new SAM instance")
conn, err := connectToSAM(address)
if err != nil {
return nil, err
}
defer func() {
if err != nil {
conn.Close()
}
}()
s := &SAM{
Conn: conn,
}
if err = sendHelloAndValidate(conn, s); err != nil {
return nil, err
}
s.SAMEmit.I2PConfig.SetSAMAddress(address)
if s.SAMResolver, err = NewSAMResolver(s); err != nil {
return nil, fmt.Errorf("failed to create SAM resolver: %w", err)
}
return s, nil
}

View File

@ -1,8 +1,10 @@
package common package common
import ( import (
"context"
"fmt" "fmt"
"net" "net"
"time"
"github.com/go-i2p/i2pkeys" "github.com/go-i2p/i2pkeys"
) )
@ -64,6 +66,11 @@ type SAM struct {
SAMEmit SAMEmit
*SAMResolver *SAMResolver
net.Conn net.Conn
// Timeout for SAM connections
Timeout time.Duration
// Context for control of lifecycle
Context context.Context
} }
type SAMResolver struct { type SAMResolver struct {

View File

@ -37,11 +37,12 @@ func SplitHostPort(hostport string) (string, string, error) {
return host, port, nil return host, port, nil
} }
var randSource = rand.NewSource(time.Now().UnixNano())
var randGen = rand.New(randSource)
func RandPort() string { func RandPort() string {
for { for {
s := rand.NewSource(time.Now().UnixNano()) p := randGen.Intn(55534) + 10000
r := rand.New(s)
p := r.Intn(55534) + 10000
port := strconv.Itoa(p) port := strconv.Itoa(p)
if l, e := net.Listen("tcp", net.JoinHostPort("localhost", port)); e != nil { if l, e := net.Listen("tcp", net.JoinHostPort("localhost", port)); e != nil {
continue continue
@ -54,6 +55,5 @@ func RandPort() string {
return strconv.Itoa(l.Addr().(*net.UDPAddr).Port) return strconv.Itoa(l.Addr().(*net.UDPAddr).Port)
} }
} }
} }
} }