mirror of
https://github.com/go-i2p/go-sam-go.git
synced 2025-07-03 17:59:44 -04:00
182 lines
5.0 KiB
Go
182 lines
5.0 KiB
Go
package common
|
|
|
|
import (
|
|
"fmt"
|
|
"math/rand"
|
|
"net"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/samber/oops"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
func IgnorePortError(err error) error {
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
if strings.Contains(err.Error(), "missing port in address") {
|
|
log.Debug("Ignoring 'missing port in address' error")
|
|
err = nil
|
|
}
|
|
return err
|
|
}
|
|
|
|
func SplitHostPort(hostport string) (string, string, error) {
|
|
host, port, err := net.SplitHostPort(hostport)
|
|
if err != nil {
|
|
if IgnorePortError(err) == nil {
|
|
log.WithField("host", hostport).Debug("Using full string as host, port set to 0")
|
|
host = hostport
|
|
port = "0"
|
|
}
|
|
}
|
|
log.WithFields(logrus.Fields{
|
|
"host": host,
|
|
"port": port,
|
|
}).Debug("Split host and port")
|
|
return host, port, nil
|
|
}
|
|
|
|
func ExtractPairString(input, value string) string {
|
|
log.WithFields(logrus.Fields{"input": input, "value": value}).Debug("ExtractPairString called")
|
|
parts := strings.Split(input, " ")
|
|
for _, part := range parts {
|
|
log.WithField("part", part).Debug("Checking part")
|
|
if strings.HasPrefix(part, value) {
|
|
kv := strings.SplitN(part, "=", 2)
|
|
if len(kv) == 2 {
|
|
log.WithFields(logrus.Fields{"key": kv[0], "value": kv[1]}).Debug("Pair extracted")
|
|
return kv[1]
|
|
}
|
|
}
|
|
}
|
|
log.WithFields(logrus.Fields{"input": input, "value": value}).Debug("No pair found")
|
|
return ""
|
|
}
|
|
|
|
func ExtractPairInt(input, value string) int {
|
|
rv, err := strconv.Atoi(ExtractPairString(input, value))
|
|
if err != nil {
|
|
log.WithFields(logrus.Fields{"input": input, "value": value}).Debug("No pair found")
|
|
return 0
|
|
}
|
|
log.WithField("result", rv).Debug("Pair extracted and converted to int")
|
|
return rv
|
|
}
|
|
|
|
func ExtractDest(input string) string {
|
|
log.WithField("input", input).Debug("ExtractDest called")
|
|
dest := strings.Split(input, " ")[0]
|
|
log.WithField("dest", dest).Debug("Destination extracted")
|
|
return dest
|
|
}
|
|
|
|
var (
|
|
randSource = rand.NewSource(time.Now().UnixNano())
|
|
randGen = rand.New(randSource)
|
|
)
|
|
|
|
func RandPort() (portNumber string, err error) {
|
|
maxAttempts := 30
|
|
for range maxAttempts {
|
|
p := randGen.Intn(55534) + 10000
|
|
port := strconv.Itoa(p)
|
|
if l, e := net.Listen("tcp", net.JoinHostPort("localhost", port)); e != nil {
|
|
continue
|
|
} else {
|
|
defer l.Close()
|
|
if l, e := net.Listen("udp", net.JoinHostPort("localhost", port)); e != nil {
|
|
continue
|
|
} else {
|
|
defer l.Close()
|
|
return strconv.Itoa(l.Addr().(*net.UDPAddr).Port), nil
|
|
}
|
|
}
|
|
}
|
|
|
|
return "", oops.Errorf("unable to find a pair of available tcp and udp ports in %v attempts", maxAttempts)
|
|
}
|
|
|
|
// generateRandomTunnelName creates a random 12-character tunnel name using lowercase letters.
|
|
// This function is deterministic for testing when a fixed seed is used.
|
|
func (f *I2PConfig) generateRandomTunnelName() string {
|
|
const (
|
|
nameLength = 12
|
|
letters = "abcdefghijklmnopqrstuvwxyz"
|
|
)
|
|
|
|
generator := rand.New(rand.NewSource(time.Now().UnixNano()))
|
|
name := make([]byte, nameLength)
|
|
|
|
for i := range name {
|
|
name[i] = letters[generator.Intn(len(letters))]
|
|
}
|
|
|
|
return string(name)
|
|
}
|
|
|
|
// validateEncryptionTypes checks that all comma-separated values are valid integers
|
|
func (f *I2PConfig) validateEncryptionTypes(encTypes string) error {
|
|
for _, s := range strings.Split(encTypes, ",") {
|
|
trimmed := strings.TrimSpace(s)
|
|
if trimmed == "" {
|
|
return fmt.Errorf("empty encryption type")
|
|
}
|
|
if _, err := strconv.Atoi(trimmed); err != nil {
|
|
return fmt.Errorf("invalid encryption type '%s': %w", trimmed, err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// formatLeaseSetEncryptionType creates the formatted configuration string
|
|
func (f *I2PConfig) formatLeaseSetEncryptionType(encType string) string {
|
|
log.WithField("leaseSetEncType", encType).Debug("Lease set encryption type set")
|
|
return fmt.Sprintf("i2cp.leaseSetEncType=%s", encType)
|
|
}
|
|
|
|
// collectTunnelSettings returns all tunnel-related configuration strings
|
|
func (f *I2PConfig) collectTunnelSettings() []string {
|
|
return []string{
|
|
f.InboundLength(),
|
|
f.OutboundLength(),
|
|
f.InboundLengthVariance(),
|
|
f.OutboundLengthVariance(),
|
|
f.InboundBackupQuantity(),
|
|
f.OutboundBackupQuantity(),
|
|
f.InboundQuantity(),
|
|
f.OutboundQuantity(),
|
|
}
|
|
}
|
|
|
|
// collectConnectionSettings returns all connection behavior configuration strings
|
|
func (f *I2PConfig) collectConnectionSettings() []string {
|
|
return []string{
|
|
f.UsingCompression(),
|
|
f.DoZero(), // Zero hop settings
|
|
f.Reduce(), // Reduce idle settings
|
|
f.Close(), // Close idle settings
|
|
f.Reliability(), // Message reliability
|
|
}
|
|
}
|
|
|
|
// collectLeaseSetSettings returns all lease set configuration strings
|
|
func (f *I2PConfig) collectLeaseSetSettings() []string {
|
|
lsk, lspk, lspsk := f.LeaseSetSettings()
|
|
return []string{
|
|
f.EncryptLease(), // Lease encryption
|
|
lsk, lspk, lspsk, // Lease set keys
|
|
f.LeaseSetEncryptionType(), // Lease set encryption type
|
|
}
|
|
}
|
|
|
|
// collectAccessSettings returns all access control configuration strings
|
|
func (f *I2PConfig) collectAccessSettings() []string {
|
|
return []string{
|
|
f.Accesslisttype(), // Access list type
|
|
f.Accesslist(), // Access list
|
|
}
|
|
}
|