package sam3 import ( "fmt" "strconv" "strings" "time" "github.com/sirupsen/logrus" ) // Option is a SAMEmit Option type Option func(*SAMEmit) error // SetType sets the type of the forwarder server func SetType(s string) func(*SAMEmit) error { return func(c *SAMEmit) error { if s == "STREAM" { c.Style = s log.WithField("style", s).Debug("Set session style") return nil } else if s == "DATAGRAM" { c.Style = s log.WithField("style", s).Debug("Set session style") return nil } else if s == "RAW" { c.Style = s log.WithField("style", s).Debug("Set session style") return nil } log.WithField("style", s).Error("Invalid session style") return fmt.Errorf("Invalid session STYLE=%s, must be STREAM, DATAGRAM, or RAW", s) } } // SetSAMAddress sets the SAM address all-at-once func SetSAMAddress(s string) func(*SAMEmit) error { return func(c *SAMEmit) error { sp := strings.Split(s, ":") if len(sp) > 2 { log.WithField("address", s).Error("Invalid SAM address") return fmt.Errorf("Invalid address string: %s", sp) } if len(sp) == 2 { c.I2PConfig.SamPort = sp[1] } c.I2PConfig.SamHost = sp[0] log.WithFields(logrus.Fields{ "host": c.I2PConfig.SamHost, "port": c.I2PConfig.SamPort, }).Debug("Set SAM address") return nil } } // SetSAMHost sets the host of the SAMEmit's SAM bridge func SetSAMHost(s string) func(*SAMEmit) error { return func(c *SAMEmit) error { c.I2PConfig.SamHost = s log.WithField("host", s).Debug("Set SAM host") return nil } } // SetSAMPort sets the port of the SAMEmit's SAM bridge using a string func SetSAMPort(s string) func(*SAMEmit) error { return func(c *SAMEmit) error { port, err := strconv.Atoi(s) if err != nil { log.WithField("port", s).Error("Invalid SAM port: non-number") return fmt.Errorf("Invalid SAM Port %s; non-number", s) } if port < 65536 && port > -1 { c.I2PConfig.SamPort = s log.WithField("port", s).Debug("Set SAM port") return nil } log.WithField("port", port).Error("Invalid SAM port") return fmt.Errorf("Invalid port") } } // SetName sets the host of the SAMEmit's SAM bridge func SetName(s string) func(*SAMEmit) error { return func(c *SAMEmit) error { c.I2PConfig.SessionOptions.NickName = s log.WithField("name", s).Debug("Set tunnel name") return nil } } // SetInLength sets the number of hops inbound func SetInLength(u int) func(*SAMEmit) error { return func(c *SAMEmit) error { if u < 7 && u >= 0 { c.I2PConfig.InLength = u log.WithField("inLength", u).Debug("Set inbound tunnel length") return nil } log.WithField("inLength", u).Error("Invalid inbound tunnel length") return fmt.Errorf("Invalid inbound tunnel length") } } // SetOutLength sets the number of hops outbound func SetOutLength(u int) func(*SAMEmit) error { return func(c *SAMEmit) error { if u < 7 && u >= 0 { c.I2PConfig.OutLength = u log.WithField("outLength", u).Debug("Set outbound tunnel length") return nil } log.WithField("outLength", u).Error("Invalid outbound tunnel length") return fmt.Errorf("Invalid outbound tunnel length") } } // SetInVariance sets the variance of a number of hops inbound func SetInVariance(i int) func(*SAMEmit) error { return func(c *SAMEmit) error { if i < 7 && i > -7 { c.I2PConfig.InVariance = i log.WithField("inVariance", i).Debug("Set inbound tunnel variance") return nil } log.WithField("inVariance", i).Error("Invalid inbound tunnel variance") return fmt.Errorf("Invalid inbound tunnel length") } } // SetOutVariance sets the variance of a number of hops outbound func SetOutVariance(i int) func(*SAMEmit) error { return func(c *SAMEmit) error { if i < 7 && i > -7 { c.I2PConfig.OutVariance = i log.WithField("outVariance", i).Debug("Set outbound tunnel variance") return nil } log.WithField("outVariance", i).Error("Invalid outbound tunnel variance") return fmt.Errorf("Invalid outbound tunnel variance") } } // SetInQuantity sets the inbound tunnel quantity func SetInQuantity(u int) func(*SAMEmit) error { return func(c *SAMEmit) error { if u <= 16 && u > 0 { c.I2PConfig.InQuantity = u log.WithField("inQuantity", u).Debug("Set inbound tunnel quantity") return nil } log.WithField("inQuantity", u).Error("Invalid inbound tunnel quantity") return fmt.Errorf("Invalid inbound tunnel quantity") } } // SetOutQuantity sets the outbound tunnel quantity func SetOutQuantity(u int) func(*SAMEmit) error { return func(c *SAMEmit) error { if u <= 16 && u > 0 { c.I2PConfig.OutQuantity = u log.WithField("outQuantity", u).Debug("Set outbound tunnel quantity") return nil } log.WithField("outQuantity", u).Error("Invalid outbound tunnel quantity") return fmt.Errorf("Invalid outbound tunnel quantity") } } // SetInBackups sets the inbound tunnel backups func SetInBackups(u int) func(*SAMEmit) error { return func(c *SAMEmit) error { if u < 6 && u >= 0 { c.I2PConfig.InBackupQuantity = u log.WithField("inBackups", u).Debug("Set inbound tunnel backups") return nil } log.WithField("inBackups", u).Error("Invalid inbound tunnel backup quantity") return fmt.Errorf("Invalid inbound tunnel backup quantity") } } // SetOutBackups sets the inbound tunnel backups func SetOutBackups(u int) func(*SAMEmit) error { return func(c *SAMEmit) error { if u < 6 && u >= 0 { c.I2PConfig.OutBackupQuantity = u log.WithField("outBackups", u).Debug("Set outbound tunnel backups") return nil } log.WithField("outBackups", u).Error("Invalid outbound tunnel backup quantity") return fmt.Errorf("Invalid outbound tunnel backup quantity") } } // SetEncrypt tells the router to use an encrypted leaseset func SetEncrypt(b bool) func(*SAMEmit) error { return func(c *SAMEmit) error { c.I2PConfig.EncryptLeaseSet = b log.WithField("encrypt", b).Debug("Set lease set encryption") return nil } } // SetLeaseSetKey sets the host of the SAMEmit's SAM bridge func SetLeaseSetKey(s string) func(*SAMEmit) error { return func(c *SAMEmit) error { c.I2PConfig.LeaseSetKey = s log.WithField("leaseSetKey", s).Debug("Set lease set key") return nil } } // SetLeaseSetPrivateKey sets the host of the SAMEmit's SAM bridge func SetLeaseSetPrivateKey(s string) func(*SAMEmit) error { return func(c *SAMEmit) error { c.I2PConfig.LeaseSetPrivateKey = s log.WithField("leaseSetPrivateKey", s).Debug("Set lease set private key") return nil } } // SetLeaseSetPrivateSigningKey sets the host of the SAMEmit's SAM bridge func SetLeaseSetPrivateSigningKey(s string) func(*SAMEmit) error { return func(c *SAMEmit) error { c.I2PConfig.LeaseSetPrivateSigningKey = s log.WithField("leaseSetPrivateSigningKey", s).Debug("Set lease set private signing key") return nil } } // SetMessageReliability sets the host of the SAMEmit's SAM bridge func SetMessageReliability(s string) func(*SAMEmit) error { return func(c *SAMEmit) error { c.I2PConfig.TransportOptions.MessageReliability = s log.WithField("messageReliability", s).Debug("Set message reliability") return nil } } // SetAllowZeroIn tells the tunnel to accept zero-hop peers func SetAllowZeroIn(b bool) func(*SAMEmit) error { return func(c *SAMEmit) error { c.I2PConfig.InAllowZeroHop = b log.WithField("allowZeroIn", b).Debug("Set allow zero-hop inbound") return nil } } // SetAllowZeroOut tells the tunnel to accept zero-hop peers func SetAllowZeroOut(b bool) func(*SAMEmit) error { return func(c *SAMEmit) error { c.I2PConfig.OutAllowZeroHop = b log.WithField("allowZeroOut", b).Debug("Set allow zero-hop outbound") return nil } } // SetCompress tells clients to use compression func SetCompress(b bool) func(*SAMEmit) error { return func(c *SAMEmit) error { if b { c.I2PConfig.UseCompression = "true" return nil } c.I2PConfig.UseCompression = "false" log.WithField("compress", b).Debug("Set compression") return nil } } // SetFastRecieve tells clients to use compression func SetFastRecieve(b bool) func(*SAMEmit) error { return func(c *SAMEmit) error { if b { c.I2PConfig.TransportOptions.FastReceive = "true" return nil } c.I2PConfig.TransportOptions.FastReceive = "false" log.WithField("fastReceive", b).Debug("Set fast receive") return nil } } // SetReduceIdle tells the connection to reduce it's tunnels during extended idle time. func SetReduceIdle(b bool) func(*SAMEmit) error { return func(c *SAMEmit) error { c.I2PConfig.ReduceIdle = b log.WithField("reduceIdle", b).Debug("Set reduce idle") return nil } } // SetReduceIdleTime sets the time to wait before reducing tunnels to idle levels func SetReduceIdleTime(u int) func(*SAMEmit) error { return func(c *SAMEmit) error { c.I2PConfig.TransportOptions.ReduceIdleTimeout = 300000 if u >= 6 { idleTime := (u * 60) * 1000 c.I2PConfig.TransportOptions.ReduceIdleTimeout = time.Duration(idleTime) log.WithFields(logrus.Fields{ "minutes": u, "milliseconds": idleTime, }).Debug("Set reduce idle time") return nil } log.WithField("minutes", u).Error("Invalid reduce idle timeout") return fmt.Errorf("Invalid reduce idle timeout(Measured in minutes) %v", u) } } // SetReduceIdleTimeMs sets the time to wait before reducing tunnels to idle levels in milliseconds func SetReduceIdleTimeMs(u int) func(*SAMEmit) error { return func(c *SAMEmit) error { c.I2PConfig.TransportOptions.ReduceIdleTimeout = 300000 if u >= 300000 { c.I2PConfig.TransportOptions.ReduceIdleTimeout = time.Duration(u) log.WithField("reduceIdleTimeMs", u).Debug("Set reduce idle time in milliseconds") return nil } return fmt.Errorf("Invalid reduce idle timeout(Measured in milliseconds) %v", u) } } // SetReduceIdleQuantity sets minimum number of tunnels to reduce to during idle time func SetReduceIdleQuantity(u int) func(*SAMEmit) error { return func(c *SAMEmit) error { if u < 5 { c.I2PConfig.ReduceIdleQuantity = u log.WithField("reduceIdleQuantity", u).Debug("Set reduce idle quantity") return nil } log.WithField("quantity", u).Error("Invalid reduce tunnel quantity") return fmt.Errorf("Invalid reduce tunnel quantity") } } // SetCloseIdle tells the connection to close it's tunnels during extended idle time. func SetCloseIdle(b bool) func(*SAMEmit) error { return func(c *SAMEmit) error { c.I2PConfig.CloseIdle = b return nil } } // SetCloseIdleTime sets the time to wait before closing tunnels to idle levels func SetCloseIdleTime(u int) func(*SAMEmit) error { return func(c *SAMEmit) error { c.I2PConfig.TransportOptions.CloseIdleTimeout = 300000 if u >= 6 { idleTime := (u * 60) * 1000 c.I2PConfig.TransportOptions.CloseIdleTimeout = time.Duration(idleTime) log.WithFields(logrus.Fields{ "minutes": u, "milliseconds": idleTime, }).Debug("Set close idle time") return nil } log.WithField("minutes", u).Error("Invalid close idle timeout") return fmt.Errorf("Invalid close idle timeout(Measured in minutes) %v", u) } } // SetCloseIdleTimeMs sets the time to wait before closing tunnels to idle levels in milliseconds func SetCloseIdleTimeMs(u int) func(*SAMEmit) error { return func(c *SAMEmit) error { c.I2PConfig.TransportOptions.CloseIdleTimeout = 300000 if u >= 300000 { c.I2PConfig.TransportOptions.CloseIdleTimeout = time.Duration(u) log.WithField("closeIdleTimeMs", u).Debug("Set close idle time in milliseconds") return nil } return fmt.Errorf("Invalid close idle timeout(Measured in milliseconds) %v", u) } } // SetAccessListType tells the system to treat the AccessList as a whitelist func SetAccessListType(s string) func(*SAMEmit) error { return func(c *SAMEmit) error { if s == "whitelist" { c.I2PConfig.AccessListType = "whitelist" log.Debug("Set access list type to whitelist") return nil } else if s == "blacklist" { c.I2PConfig.AccessListType = "blacklist" log.Debug("Set access list type to blacklist") return nil } else if s == "none" { c.I2PConfig.AccessListType = "" log.Debug("Set access list type to none") return nil } else if s == "" { c.I2PConfig.AccessListType = "" log.Debug("Set access list type to none") return nil } return fmt.Errorf("Invalid Access list type(whitelist, blacklist, none)") } } // SetAccessList tells the system to treat the AccessList as a whitelist func SetAccessList(s []string) func(*SAMEmit) error { return func(c *SAMEmit) error { if len(s) > 0 { for _, a := range s { c.I2PConfig.AccessList = append(c.I2PConfig.AccessList, a) } log.WithField("accessList", s).Debug("Set access list") return nil } log.Debug("No access list set (empty list provided)") return nil } }