fmt
This commit is contained in:
36
SAMConn.go
36
SAMConn.go
@ -7,64 +7,60 @@ import (
|
||||
"github.com/go-i2p/i2pkeys"
|
||||
)
|
||||
|
||||
/*
|
||||
import (
|
||||
. "github.com/go-i2p/i2pkeys"
|
||||
)
|
||||
*/
|
||||
// SAMConn sets up a SAM connection.
|
||||
// Implements net.Conn
|
||||
type SAMConn struct {
|
||||
laddr i2pkeys.I2PAddr
|
||||
raddr i2pkeys.I2PAddr
|
||||
conn net.Conn
|
||||
net.Conn
|
||||
}
|
||||
|
||||
// Implements net.Conn
|
||||
// Read implements net.Conn
|
||||
func (sc *SAMConn) Read(buf []byte) (int, error) {
|
||||
n, err := sc.conn.Read(buf)
|
||||
n, err := sc.Conn.Read(buf)
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Implements net.Conn
|
||||
// Write Implements net.Conn
|
||||
func (sc *SAMConn) Write(buf []byte) (int, error) {
|
||||
n, err := sc.conn.Write(buf)
|
||||
n, err := sc.Conn.Write(buf)
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Implements net.Conn
|
||||
// Close Implements net.Conn
|
||||
func (sc *SAMConn) Close() error {
|
||||
return sc.conn.Close()
|
||||
return sc.Conn.Close()
|
||||
}
|
||||
|
||||
// LocalAddr Implements net.Conn
|
||||
func (sc *SAMConn) LocalAddr() net.Addr {
|
||||
return sc.localAddr()
|
||||
}
|
||||
|
||||
// Implements net.Conn
|
||||
func (sc *SAMConn) localAddr() i2pkeys.I2PAddr {
|
||||
return sc.laddr
|
||||
}
|
||||
|
||||
// RemoteAddr Implements net.Conn
|
||||
func (sc *SAMConn) RemoteAddr() net.Addr {
|
||||
return sc.remoteAddr()
|
||||
}
|
||||
|
||||
// Implements net.Conn
|
||||
func (sc *SAMConn) remoteAddr() i2pkeys.I2PAddr {
|
||||
return sc.raddr
|
||||
}
|
||||
|
||||
// Implements net.Conn
|
||||
// SetDeadline Implements net.Conn
|
||||
func (sc *SAMConn) SetDeadline(t time.Time) error {
|
||||
return sc.conn.SetDeadline(t)
|
||||
return sc.Conn.SetDeadline(t)
|
||||
}
|
||||
|
||||
// Implements net.Conn
|
||||
// SetReadDeadline Implements net.Conn
|
||||
func (sc *SAMConn) SetReadDeadline(t time.Time) error {
|
||||
return sc.conn.SetReadDeadline(t)
|
||||
return sc.Conn.SetReadDeadline(t)
|
||||
}
|
||||
|
||||
// Implements net.Conn
|
||||
// SetWriteDeadline Implements net.Conn
|
||||
func (sc *SAMConn) SetWriteDeadline(t time.Time) error {
|
||||
return sc.conn.SetWriteDeadline(t)
|
||||
return sc.Conn.SetWriteDeadline(t)
|
||||
}
|
||||
|
32
config.go
32
config.go
@ -60,6 +60,7 @@ type I2PConfig struct {
|
||||
AccessList []string
|
||||
}
|
||||
|
||||
// Sam returns the SAM address in the form of "host:port"
|
||||
func (f *I2PConfig) Sam() string {
|
||||
host := "127.0.0.1"
|
||||
port := "7656"
|
||||
@ -76,6 +77,7 @@ func (f *I2PConfig) Sam() string {
|
||||
return host + ":" + port
|
||||
}
|
||||
|
||||
// SetSAMAddress sets the SAM address from a string in the form of "host:port"
|
||||
func (f *I2PConfig) SetSAMAddress(addr string) {
|
||||
hp := strings.Split(addr, ":")
|
||||
if len(hp) == 1 {
|
||||
@ -92,6 +94,7 @@ func (f *I2PConfig) SetSAMAddress(addr string) {
|
||||
}).Debug("SAM address set")
|
||||
}
|
||||
|
||||
// ID returns the tunnel name in the form of "ID=name"
|
||||
func (f *I2PConfig) ID() string {
|
||||
if f.TunName == "" {
|
||||
b := make([]byte, 12)
|
||||
@ -104,6 +107,7 @@ func (f *I2PConfig) ID() string {
|
||||
return " ID=" + f.TunName + " "
|
||||
}
|
||||
|
||||
// Leasesetsettings returns the lease set settings in the form of "i2cp.leaseSetKey=key i2cp.leaseSetPrivateKey=key i2cp.leaseSetPrivateSigningKey=key"
|
||||
func (f *I2PConfig) Leasesetsettings() (string, string, string) {
|
||||
var r, s, t string
|
||||
if f.LeaseSetKey != "" {
|
||||
@ -123,6 +127,7 @@ func (f *I2PConfig) Leasesetsettings() (string, string, string) {
|
||||
return r, s, t
|
||||
}
|
||||
|
||||
// FromPort returns the from port setting in the form of "FROM_PORT=port"
|
||||
func (f *I2PConfig) FromPort() string {
|
||||
if f.samMax() < 3.1 {
|
||||
log.Debug("SAM version < 3.1, FromPort not applicable")
|
||||
@ -136,6 +141,7 @@ func (f *I2PConfig) FromPort() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// ToPort returns the to port setting in the form of "TO_PORT=port"
|
||||
func (f *I2PConfig) ToPort() string {
|
||||
if f.samMax() < 3.1 {
|
||||
log.Debug("SAM version < 3.1, ToPort not applicable")
|
||||
@ -149,6 +155,7 @@ func (f *I2PConfig) ToPort() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// SessionStyle returns the session style setting in the form of "STYLE=style"
|
||||
func (f *I2PConfig) SessionStyle() string {
|
||||
if f.Style != "" {
|
||||
log.WithField("style", f.Style).Debug("Session style set")
|
||||
@ -168,6 +175,7 @@ func (f *I2PConfig) samMax() float64 {
|
||||
return float64(i)
|
||||
}
|
||||
|
||||
// MinSAM returns the minimum SAM version required in major.minor form
|
||||
func (f *I2PConfig) MinSAM() string {
|
||||
if f.SamMin == "" {
|
||||
log.Debug("Using default MinSAM: 3.0")
|
||||
@ -177,6 +185,7 @@ func (f *I2PConfig) MinSAM() string {
|
||||
return f.SamMin
|
||||
}
|
||||
|
||||
// MaxSAM returns the maximum SAM version required in major.minor form
|
||||
func (f *I2PConfig) MaxSAM() string {
|
||||
if f.SamMax == "" {
|
||||
log.Debug("Using default MaxSAM: 3.1")
|
||||
@ -186,6 +195,7 @@ func (f *I2PConfig) MaxSAM() string {
|
||||
return f.SamMax
|
||||
}
|
||||
|
||||
// DestinationKey returns the destination key setting in the form of "DESTINATION=key"
|
||||
func (f *I2PConfig) DestinationKey() string {
|
||||
if &f.DestinationKeys != nil {
|
||||
log.WithField("destinationKey", f.DestinationKeys.String()).Debug("Destination key set")
|
||||
@ -195,6 +205,7 @@ func (f *I2PConfig) DestinationKey() string {
|
||||
return " DESTINATION=TRANSIENT "
|
||||
}
|
||||
|
||||
// SignatureType returns the signature type setting in the form of "SIGNATURE_TYPE=type"
|
||||
func (f *I2PConfig) SignatureType() string {
|
||||
if f.samMax() < 3.1 {
|
||||
log.Debug("SAM version < 3.1, SignatureType not applicable")
|
||||
@ -208,6 +219,7 @@ func (f *I2PConfig) SignatureType() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// EncryptLease returns the lease set encryption setting in the form of "i2cp.encryptLeaseSet=true"
|
||||
func (f *I2PConfig) EncryptLease() string {
|
||||
if f.EncryptLeaseSet == "true" {
|
||||
log.Debug("Lease set encryption enabled")
|
||||
@ -217,6 +229,7 @@ func (f *I2PConfig) EncryptLease() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Reliability returns the message reliability setting in the form of "i2cp.messageReliability=reliability"
|
||||
func (f *I2PConfig) Reliability() string {
|
||||
if f.MessageReliability != "" {
|
||||
log.WithField("reliability", f.MessageReliability).Debug("Message reliability set")
|
||||
@ -226,6 +239,7 @@ func (f *I2PConfig) Reliability() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Reduce returns the reduce idle settings in the form of "i2cp.reduceOnIdle=true i2cp.reduceIdleTime=time i2cp.reduceQuantity=quantity"
|
||||
func (f *I2PConfig) Reduce() string {
|
||||
if f.ReduceIdle == "true" {
|
||||
log.WithFields(logrus.Fields{
|
||||
@ -239,6 +253,7 @@ func (f *I2PConfig) Reduce() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Close returns the close idle settings in the form of "i2cp.closeOnIdle=true i2cp.closeIdleTime=time"
|
||||
func (f *I2PConfig) Close() string {
|
||||
if f.CloseIdle == "true" {
|
||||
log.WithFields(logrus.Fields{
|
||||
@ -251,6 +266,7 @@ func (f *I2PConfig) Close() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// DoZero returns the zero hop settings in the form of "inbound.allowZeroHop=true outbound.allowZeroHop=true fastRecieve=true"
|
||||
func (f *I2PConfig) DoZero() string {
|
||||
r := ""
|
||||
if f.InAllowZeroHop == "true" {
|
||||
@ -266,6 +282,7 @@ func (f *I2PConfig) DoZero() string {
|
||||
return r
|
||||
}
|
||||
|
||||
// Print returns the full config as a string
|
||||
func (f *I2PConfig) Print() []string {
|
||||
lsk, lspk, lspsk := f.Leasesetsettings()
|
||||
return []string{
|
||||
@ -292,6 +309,7 @@ func (f *I2PConfig) Print() []string {
|
||||
}
|
||||
}
|
||||
|
||||
// Accesslisttype returns the access list type
|
||||
func (f *I2PConfig) Accesslisttype() string {
|
||||
if f.AccessListType == "whitelist" {
|
||||
log.Debug("Access list type set to whitelist")
|
||||
@ -307,6 +325,7 @@ func (f *I2PConfig) Accesslisttype() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Accesslist returns the access list in the form of "i2cp.accessList=list"
|
||||
func (f *I2PConfig) Accesslist() string {
|
||||
if f.AccessListType != "" && len(f.AccessList) > 0 {
|
||||
r := ""
|
||||
@ -320,6 +339,7 @@ func (f *I2PConfig) Accesslist() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// LeaseSetEncryptionType returns the lease set encryption type in the form of "i2cp.leaseSetEncType=type"
|
||||
func (f *I2PConfig) LeaseSetEncryptionType() string {
|
||||
if f.LeaseSetEncryption == "" {
|
||||
log.Debug("Using default lease set encryption type: 4,0")
|
||||
@ -335,6 +355,9 @@ func (f *I2PConfig) LeaseSetEncryptionType() string {
|
||||
return "i2cp.leaseSetEncType=" + f.LeaseSetEncryption
|
||||
}
|
||||
|
||||
const DEFAULT_LEASESET_TYPE = "i2cp.leaseSetEncType=4"
|
||||
|
||||
// NewConfig returns a new config with default values or updates them with functional arguments
|
||||
func NewConfig(opts ...func(*I2PConfig) error) (*I2PConfig, error) {
|
||||
var config I2PConfig
|
||||
config.SamHost = "127.0.0.1"
|
||||
@ -366,6 +389,7 @@ func NewConfig(opts ...func(*I2PConfig) error) (*I2PConfig, error) {
|
||||
config.CloseIdle = "false"
|
||||
config.CloseIdleTime = "300000"
|
||||
config.MessageReliability = "none"
|
||||
config.LeaseSetEncryption = DEFAULT_LEASESET_TYPE
|
||||
for _, o := range opts {
|
||||
if err := o(&config); err != nil {
|
||||
return nil, err
|
||||
@ -374,10 +398,10 @@ func NewConfig(opts ...func(*I2PConfig) error) (*I2PConfig, error) {
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
// options map
|
||||
// Options a map of options
|
||||
type Options map[string]string
|
||||
|
||||
// obtain sam options as list of strings
|
||||
// AsList obtain sam options as list of strings
|
||||
func (opts Options) AsList() (ls []string) {
|
||||
for k, v := range opts {
|
||||
ls = append(ls, fmt.Sprintf("%s=%s", k, v))
|
||||
@ -393,7 +417,7 @@ type Config struct {
|
||||
Keyfile string
|
||||
}
|
||||
|
||||
// create new sam connector from config with a stream session
|
||||
// StreamSession create new sam connector from config with a stream session
|
||||
func (cfg *Config) StreamSession() (session *StreamSession, err error) {
|
||||
// connect
|
||||
var s *SAM
|
||||
@ -410,7 +434,7 @@ func (cfg *Config) StreamSession() (session *StreamSession, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// create new sam datagram session from config
|
||||
// DatagramSession create new sam datagram session from config
|
||||
func (cfg *Config) DatagramSession() (session *DatagramSession, err error) {
|
||||
// connect
|
||||
var s *SAM
|
||||
|
17
datagram.go
17
datagram.go
@ -95,7 +95,7 @@ func (s *DatagramSession) B32() string {
|
||||
return b32
|
||||
}
|
||||
|
||||
func (s *DatagramSession) Dial(net string, addr string) (*DatagramSession, error) {
|
||||
func (s *DatagramSession) Dial(net, addr string) (*DatagramSession, error) {
|
||||
log.WithFields(logrus.Fields{
|
||||
"net": net,
|
||||
"addr": addr,
|
||||
@ -194,6 +194,11 @@ func (s *DatagramSession) Read(b []byte) (n int, err error) {
|
||||
return rint, rerr
|
||||
}
|
||||
|
||||
const (
|
||||
MAX_DATAGRAM_SIZE = 31744 // Max reliable size
|
||||
RECOMMENDED_SIZE = 11264 // 11KB recommended max
|
||||
)
|
||||
|
||||
// Sends one signed datagram to the destination specified. At the time of
|
||||
// writing, maximum size is 31 kilobyte, but this may change in the future.
|
||||
// Implements net.PacketConn.
|
||||
@ -202,8 +207,14 @@ func (s *DatagramSession) WriteTo(b []byte, addr net.Addr) (n int, err error) {
|
||||
"addr": addr,
|
||||
"datagramLen": len(b),
|
||||
}).Debug("Writing datagram")
|
||||
if len(b) > MAX_DATAGRAM_SIZE {
|
||||
return 0, errors.New("datagram exceeds maximum size")
|
||||
}
|
||||
if len(b) > RECOMMENDED_SIZE {
|
||||
log.Warning("datagram exceeds recommended size of 11KB")
|
||||
}
|
||||
if s.DatagramOptions != nil {
|
||||
return s.WriteToWithOptions(b, addr.(i2pkeys.I2PAddr))
|
||||
return s.writeToWithOptions(b, addr.(i2pkeys.I2PAddr))
|
||||
}
|
||||
header := []byte("3.1 " + s.id + " " + addr.String() + "\n")
|
||||
msg := append(header, b...)
|
||||
@ -223,7 +234,7 @@ type DatagramOptions struct {
|
||||
SendLeaseset bool
|
||||
}
|
||||
|
||||
func (s *DatagramSession) WriteToWithOptions(b []byte, addr i2pkeys.I2PAddr) (n int, err error) {
|
||||
func (s *DatagramSession) writeToWithOptions(b []byte, addr i2pkeys.I2PAddr) (n int, err error) {
|
||||
var header bytes.Buffer
|
||||
header.WriteString(fmt.Sprintf("3.3 %s %s", s.id, addr.String()))
|
||||
|
||||
|
@ -110,7 +110,7 @@ func (sam *PrimarySession) DialTCP(network string, laddr, raddr net.Addr) (net.C
|
||||
return ts.Dial(network, raddr.String())
|
||||
}
|
||||
|
||||
func (sam *PrimarySession) DialTCPI2P(network string, laddr, raddr string) (net.Conn, error) {
|
||||
func (sam *PrimarySession) DialTCPI2P(network, laddr, raddr string) (net.Conn, error) {
|
||||
log.WithFields(logrus.Fields{"network": network, "laddr": laddr, "raddr": raddr}).Debug("DialTCPI2P() called")
|
||||
ts, ok := sam.stsess[network+raddr[0:4]]
|
||||
var err error
|
||||
@ -195,7 +195,7 @@ func (sam *SAM) NewPrimarySession(id string, keys i2pkeys.I2PKeys, options []str
|
||||
return sam.newPrimarySession(PrimarySessionSwitch, id, keys, options)
|
||||
}
|
||||
|
||||
func (sam *SAM) newPrimarySession(primarySessionSwitch string, id string, keys i2pkeys.I2PKeys, options []string) (*PrimarySession, error) {
|
||||
func (sam *SAM) newPrimarySession(primarySessionSwitch, id string, keys i2pkeys.I2PKeys, options []string) (*PrimarySession, error) {
|
||||
log.WithFields(logrus.Fields{
|
||||
"primarySessionSwitch": primarySessionSwitch,
|
||||
"id": id,
|
||||
|
27
sam3.go
27
sam3.go
@ -24,6 +24,7 @@ func init() {
|
||||
}
|
||||
|
||||
// Used for controlling I2Ps SAMv3.
|
||||
// This implements the "Control Socket" for all connections.
|
||||
type SAM struct {
|
||||
address string
|
||||
conn net.Conn
|
||||
@ -177,9 +178,15 @@ func (sam *SAM) EnsureKeyfile(fname string) (keys i2pkeys.I2PKeys, err error) {
|
||||
// Creates the I2P-equivalent of an IP address, that is unique and only the one
|
||||
// who has the private keys can send messages from. The public keys are the I2P
|
||||
// desination (the address) that anyone can send messages to.
|
||||
|
||||
// Add constant for recommended sig type
|
||||
const (
|
||||
DEFAULT_SIG_TYPE = "SIGNATURE_TYPE=7" // EdDSA_SHA512_Ed25519
|
||||
)
|
||||
|
||||
func (sam *SAM) NewKeys(sigType ...string) (i2pkeys.I2PKeys, error) {
|
||||
log.WithField("sigType", sigType).Debug("Generating new keys")
|
||||
sigtmp := ""
|
||||
sigtmp := DEFAULT_SIG_TYPE
|
||||
if len(sigType) > 0 {
|
||||
sigtmp = sigType[0]
|
||||
}
|
||||
@ -228,12 +235,12 @@ func (sam *SAM) Lookup(name string) (i2pkeys.I2PAddr, error) {
|
||||
// I2CP/streaminglib-options as specified. Extra arguments can be specified by
|
||||
// setting extra to something else than []string{}.
|
||||
// This sam3 instance is now a session
|
||||
func (sam *SAM) newGenericSession(style, id string, keys i2pkeys.I2PKeys, options []string, extras []string) (net.Conn, error) {
|
||||
func (sam *SAM) newGenericSession(style, id string, keys i2pkeys.I2PKeys, options, extras []string) (net.Conn, error) {
|
||||
log.WithFields(logrus.Fields{"style": style, "id": id}).Debug("Creating new generic session")
|
||||
return sam.newGenericSessionWithSignature(style, id, keys, Sig_NONE, options, extras)
|
||||
}
|
||||
|
||||
func (sam *SAM) newGenericSessionWithSignature(style, id string, keys i2pkeys.I2PKeys, sigType string, options []string, extras []string) (net.Conn, error) {
|
||||
func (sam *SAM) newGenericSessionWithSignature(style, id string, keys i2pkeys.I2PKeys, sigType string, options, extras []string) (net.Conn, error) {
|
||||
log.WithFields(logrus.Fields{"style": style, "id": id, "sigType": sigType}).Debug("Creating new generic session with signature")
|
||||
return sam.newGenericSessionWithSignatureAndPorts(style, id, "0", "0", keys, sigType, options, extras)
|
||||
}
|
||||
@ -243,7 +250,7 @@ func (sam *SAM) newGenericSessionWithSignature(style, id string, keys i2pkeys.I2
|
||||
// I2CP/streaminglib-options as specified. Extra arguments can be specified by
|
||||
// setting extra to something else than []string{}.
|
||||
// This sam3 instance is now a session
|
||||
func (sam *SAM) newGenericSessionWithSignatureAndPorts(style, id, from, to string, keys i2pkeys.I2PKeys, sigType string, options []string, extras []string) (net.Conn, error) {
|
||||
func (sam *SAM) newGenericSessionWithSignatureAndPorts(style, id, from, to string, keys i2pkeys.I2PKeys, sigType string, options, extras []string) (net.Conn, error) {
|
||||
log.WithFields(logrus.Fields{"style": style, "id": id, "from": from, "to": to, "sigType": sigType}).Debug("Creating new generic session with signature and ports")
|
||||
|
||||
optStr := GenerateOptionString(options)
|
||||
@ -315,8 +322,18 @@ func (sam *SAM) newGenericSessionWithSignatureAndPorts(style, id, from, to strin
|
||||
}
|
||||
}
|
||||
|
||||
// close this sam session
|
||||
// Close this sam session
|
||||
func (sam *SAM) Close() error {
|
||||
log.Debug("Closing SAM session")
|
||||
return sam.conn.Close()
|
||||
}
|
||||
|
||||
// CloseNotify the socket with a QUIT message
|
||||
func (sam *SAM) CloseNotify() error {
|
||||
log.Debug("Quitting SAM session")
|
||||
_, err := sam.conn.Write([]byte("QUIT\n"))
|
||||
if err != nil {
|
||||
return fmt.Errorf("close notification failed: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -115,6 +115,18 @@ func (l *StreamListener) AcceptI2P() (*SAMConn, error) {
|
||||
if strings.HasPrefix(line, "STREAM STATUS RESULT=OK") {
|
||||
// we gud read destination line
|
||||
destline, err := rd.ReadString(10)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return nil, errors.New("connection closed after OK")
|
||||
}
|
||||
return nil, errors.New("error reading destination: " + err.Error())
|
||||
}
|
||||
|
||||
// Validate destination format
|
||||
dest := ExtractDest(destline)
|
||||
if !strings.HasPrefix(dest, "DEST=") {
|
||||
return nil, errors.New("invalid destination format")
|
||||
}
|
||||
if err == nil {
|
||||
dest := ExtractDest(destline)
|
||||
l.session.from = ExtractPairString(destline, "FROM_PORT")
|
||||
@ -129,7 +141,7 @@ func (l *StreamListener) AcceptI2P() (*SAMConn, error) {
|
||||
return &SAMConn{
|
||||
laddr: l.laddr,
|
||||
raddr: i2pkeys.I2PAddr(dest),
|
||||
conn: s.conn,
|
||||
Conn: s.conn,
|
||||
}, nil
|
||||
} else {
|
||||
log.WithError(err).Error("Failed to read destination line")
|
||||
|
Reference in New Issue
Block a user