mirror of
https://github.com/go-i2p/go-sam-go.git
synced 2025-07-03 17:59:44 -04:00
Simplify common.NewSAM
This commit is contained in:
@ -3,7 +3,6 @@ package common
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -11,51 +10,59 @@ import (
|
|||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultSAMHost = "127.0.0.1"
|
||||||
|
defaultSAMPort = 7656
|
||||||
|
)
|
||||||
|
|
||||||
// Sam returns the SAM bridge address as a string in the format "host:port"
|
// Sam returns the SAM bridge address as a string in the format "host:port"
|
||||||
func (f *I2PConfig) Sam() string {
|
func (f *I2PConfig) Sam() string {
|
||||||
// Set default values
|
host := f.SamHost
|
||||||
host := "127.0.0.1"
|
if host == "" {
|
||||||
port := 7656
|
host = defaultSAMHost
|
||||||
|
|
||||||
// Override defaults if config values are set
|
|
||||||
if f.SamHost != "" {
|
|
||||||
host = f.SamHost
|
|
||||||
}
|
|
||||||
if f.SamPort != 0 {
|
|
||||||
port = f.SamPort
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log the SAM address being constructed
|
port := f.SamPort
|
||||||
log.WithFields(logrus.Fields{
|
if port == 0 {
|
||||||
"host": host,
|
port = defaultSAMPort
|
||||||
"port": port,
|
}
|
||||||
}).Debug("SAM address constructed")
|
|
||||||
|
|
||||||
// Return formatted SAM address
|
return fmt.Sprintf("%s:%d", host, port)
|
||||||
return net.JoinHostPort(host, strconv.Itoa(port))
|
}
|
||||||
|
|
||||||
|
// SAMAddress returns the SAM bridge address in the format "host:port"
|
||||||
|
// This is a convenience method that uses the Sam() function to get the address.
|
||||||
|
// It is used to provide a consistent interface for retrieving the SAM address.
|
||||||
|
func (f *I2PConfig) SAMAddress() string {
|
||||||
|
// Return the SAM address in the format "host:port"
|
||||||
|
return f.Sam()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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) {
|
||||||
if addr == "" {
|
if addr == "" {
|
||||||
f.SamHost = "127.0.0.1"
|
f.SamHost = defaultSAMHost
|
||||||
f.SamPort = 7656
|
f.SamPort = defaultSAMPort
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
host, port, err := net.SplitHostPort(addr)
|
host, portStr, err := SplitHostPort(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Only set host if it looks valid
|
log.WithError(err).Warn("Failed to parse SAM address, using defaults")
|
||||||
if net.ParseIP(addr) != nil || !strings.Contains(addr, ":") {
|
f.SamHost = defaultSAMHost
|
||||||
f.SamHost = addr
|
f.SamPort = defaultSAMPort
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
f.SamHost = host
|
f.SamHost = host
|
||||||
if p, err := strconv.Atoi(port); err == nil && p > 0 && p < 65536 {
|
|
||||||
f.SamPort = p
|
port, err := strconv.Atoi(portStr)
|
||||||
|
if err != nil || port < 1 || port > 65535 {
|
||||||
|
log.WithField("port", portStr).Warn("Invalid port, setting to 7656")
|
||||||
|
f.SamPort = defaultSAMPort
|
||||||
|
} else {
|
||||||
|
f.SamPort = port
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,13 +27,13 @@ func TestSetSAMAddress_Cases(t *testing.T) {
|
|||||||
name: "invalid port uses default",
|
name: "invalid port uses default",
|
||||||
addr: "localhost:99999",
|
addr: "localhost:99999",
|
||||||
wantHost: "localhost",
|
wantHost: "localhost",
|
||||||
wantPort: 0,
|
wantPort: 7656, // Default port
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "just IP address",
|
name: "just IP address",
|
||||||
addr: "192.168.1.1",
|
addr: "192.168.1.1",
|
||||||
wantHost: "192.168.1.1",
|
wantHost: "192.168.1.1",
|
||||||
wantPort: 0,
|
wantPort: 7656,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,68 +7,55 @@ import (
|
|||||||
"github.com/samber/oops"
|
"github.com/samber/oops"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Creates a new controller for the I2P routers SAM bridge.
|
// NewSAM creates a new SAM instance by connecting to the specified address,
|
||||||
func OldNewSAM(address string) (*SAM, error) {
|
// performing the hello handshake, and initializing the SAM resolver.
|
||||||
log.WithField("address", address).Debug("Creating new SAM instance")
|
// It returns a pointer to the SAM instance or an error if any step fails.
|
||||||
var s SAM
|
// This function combines connection establishment and hello handshake into a single step,
|
||||||
// TODO: clean this up by refactoring the connection setup and error handling logic
|
// eliminating the need for separate helper functions.
|
||||||
conn, err := net.Dial("tcp", address)
|
// It also initializes the SAM resolver directly after the connection is established.
|
||||||
if err != nil {
|
// The SAM instance is ready to use for further operations like session creation or name resolution.
|
||||||
log.WithError(err).Error("Failed to dial SAM address")
|
|
||||||
return nil, oops.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, oops.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, oops.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
|
|
||||||
resolver, err := NewSAMResolver(&s)
|
|
||||||
s.SAMResolver = *resolver
|
|
||||||
if err != nil {
|
|
||||||
log.WithError(err).Error("Failed to create SAM resolver")
|
|
||||||
return nil, oops.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, oops.Errorf("That SAM bridge does not support SAMv3.")
|
|
||||||
} else {
|
|
||||||
log.WithField("response", string(buf[:n])).Error("Unexpected SAM response")
|
|
||||||
conn.Close()
|
|
||||||
return nil, oops.Errorf("%s", string(buf[:n]))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewSAM(address string) (*SAM, error) {
|
func NewSAM(address string) (*SAM, error) {
|
||||||
logger := log.WithField("address", address)
|
logger := log.WithField("address", address)
|
||||||
logger.Debug("Creating new SAM instance")
|
logger.Debug("Creating new SAM instance")
|
||||||
|
|
||||||
conn, err := connectToSAM(address)
|
// Inline connection establishment - eliminates connectToSAM helper
|
||||||
|
conn, err := net.Dial("tcp", address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Error("Failed to connect to SAM bridge")
|
logger.WithError(err).Error("Failed to connect to SAM bridge")
|
||||||
return nil, err
|
return nil, oops.Errorf("failed to connect to SAM bridge at %s: %w", address, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
s := &SAM{
|
s := &SAM{
|
||||||
Conn: conn,
|
Conn: conn,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = sendHelloAndValidate(conn, s); err != nil {
|
// Inline hello handshake - eliminates sendHelloAndValidate helper
|
||||||
logger.WithError(err).Error("Failed to send hello and validate SAM connection")
|
if _, err := conn.Write(s.SAMEmit.HelloBytes()); err != nil {
|
||||||
|
logger.WithError(err).Error("Failed to send hello message")
|
||||||
conn.Close()
|
conn.Close()
|
||||||
return nil, err
|
return nil, oops.Errorf("failed to send hello message: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := make([]byte, 256)
|
||||||
|
n, err := conn.Read(buf)
|
||||||
|
if err != nil {
|
||||||
|
logger.WithError(err).Error("Failed to read SAM response")
|
||||||
|
conn.Close()
|
||||||
|
return nil, oops.Errorf("failed to read SAM response: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
response := string(buf[:n])
|
||||||
|
switch {
|
||||||
|
case strings.Contains(response, HELLO_REPLY_OK):
|
||||||
|
logger.Debug("SAM hello successful")
|
||||||
|
case response == HELLO_REPLY_NOVERSION:
|
||||||
|
logger.Error("SAM bridge does not support SAMv3")
|
||||||
|
conn.Close()
|
||||||
|
return nil, oops.Errorf("SAM bridge does not support SAMv3")
|
||||||
|
default:
|
||||||
|
logger.WithField("response", response).Error("Unexpected SAM response")
|
||||||
|
conn.Close()
|
||||||
|
return nil, oops.Errorf("unexpected SAM response: %s", response)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.SAMEmit.I2PConfig.SetSAMAddress(address)
|
s.SAMEmit.I2PConfig.SetSAMAddress(address)
|
||||||
|
Reference in New Issue
Block a user