Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
0e87ddfa4b | ||
![]() |
9e3532c81b | ||
![]() |
ca8d8688cb | ||
![]() |
ef67dc1e44 | ||
![]() |
9a162e9502 | ||
![]() |
31b8d62f04 | ||
![]() |
d191b3404e | ||
![]() |
1de06ec9b9 | ||
![]() |
ed814a2fc6 | ||
![]() |
746084e65f | ||
![]() |
1a55eb6e90 |
2
Makefile
2
Makefile
@@ -1,6 +1,6 @@
|
||||
|
||||
USER_GH=eyedeekay
|
||||
VERSION=0.33.001
|
||||
VERSION=0.33.01
|
||||
packagename=sam3
|
||||
|
||||
echo:
|
||||
|
15
README.md
15
README.md
@@ -23,7 +23,7 @@ This library is much better than ccondom (that use BOB), much more stable and mu
|
||||
|
||||
**Does not work:**
|
||||
|
||||
* Everything works! :D
|
||||
* Stream Forwarding
|
||||
* Probably needs some real-world testing
|
||||
|
||||
## Documentation ##
|
||||
@@ -38,16 +38,17 @@ This library is much better than ccondom (that use BOB), much more stable and mu
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/majestrate/i2p-tools/sam3"
|
||||
"github.com/eyedeekay/sam3"
|
||||
"github.com/eyedeekay/sam3/i2pkeys"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const yoursam = "127.0.0.1:7656" // sam bridge
|
||||
|
||||
func client(server I2PAddr) {
|
||||
sam, _ := NewSAM(yoursam)
|
||||
func client(server i2pkeys.I2PAddr) {
|
||||
sam, _ := sam3.NewSAM(yoursam)
|
||||
keys, _ := sam.NewKeys()
|
||||
stream, _ := sam.NewStreamSession("clientTun", keys, Options_Small)
|
||||
stream, _ := sam.NewStreamSession("clientTun", keys, sam3.Options_Small)
|
||||
fmt.Println("Client: Connecting to " + server.Base32())
|
||||
conn, _ := stream.DialI2P(server)
|
||||
conn.Write([]byte("Hello world!"))
|
||||
@@ -57,11 +58,9 @@ func client(server I2PAddr) {
|
||||
func main() {
|
||||
sam, _ := NewSAM(yoursam)
|
||||
keys, _ := sam.NewKeys()
|
||||
stream, _ := sam.NewStreamSession("serverTun", keys, Options_Medium)
|
||||
stream, _ := sam.NewStreamSession("serverTun", keys, sam3.Options_Medium)
|
||||
listener, _ := stream.Listen()
|
||||
go client(keys.Addr())
|
||||
stream, _ := sam.NewStreamSession("serverTun", keys, Options_Medium)
|
||||
listener, _ := stream.Listen()
|
||||
conn, _ := listener.Accept()
|
||||
buf := make([]byte, 4096)
|
||||
n, _ := conn.Read(buf)
|
||||
|
@@ -1,9 +1,10 @@
|
||||
package sam3
|
||||
|
||||
import (
|
||||
"github.com/eyedeekay/sam3/i2pkeys"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/eyedeekay/sam3/i2pkeys"
|
||||
)
|
||||
|
||||
/*
|
||||
|
@@ -84,7 +84,13 @@ func (s *DatagramSession) DialRemote(net, addr string) (net.PacketConn, error) {
|
||||
}
|
||||
|
||||
func (s *DatagramSession) DialI2PRemote(net string, addr net.Addr) (*DatagramSession, error) {
|
||||
s.remoteAddr = addr.(*i2pkeys.I2PAddr)
|
||||
switch addr.(type) {
|
||||
case *i2pkeys.I2PAddr:
|
||||
s.remoteAddr = addr.(*i2pkeys.I2PAddr)
|
||||
case i2pkeys.I2PAddr:
|
||||
i2paddr := addr.(i2pkeys.I2PAddr)
|
||||
s.remoteAddr = &i2paddr
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
|
147
helper/helper.go
147
helper/helper.go
@@ -1,7 +1,6 @@
|
||||
package sam
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
@@ -25,10 +24,11 @@ func I2PListener(name, samaddr, keyspath string) (*sam3.StreamListener, error) {
|
||||
if keyspath != "" {
|
||||
err = ioutil.WriteFile(keyspath+".i2p.public.txt", []byte(listener.Keys().Addr().Base32()), 0644)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error storing I2P base32 address in adjacent text file, %s", err)
|
||||
log.Fatalf("error storing I2P base32 address in adjacent text file, %s", err)
|
||||
}
|
||||
}
|
||||
return listener.Listen() //, err
|
||||
log.Printf("Listening on: %s", listener.Addr().Base32())
|
||||
return listener.Listen()
|
||||
}
|
||||
|
||||
// I2PStreamSession is a convenience function which returns a sam3.StreamSession instead
|
||||
@@ -38,38 +38,11 @@ func I2PStreamSession(name, samaddr, keyspath string) (*sam3.StreamSession, erro
|
||||
log.Printf("Starting and registering I2P session...")
|
||||
sam, err := sam3.NewSAM(samaddr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error connecting to SAM to %s: %s", samaddr, err)
|
||||
log.Fatalf("error connecting to SAM to %s: %s", samaddr, err)
|
||||
}
|
||||
var keys *i2pkeys.I2PKeys
|
||||
if keyspath != "" {
|
||||
if _, err := os.Stat(keyspath + ".i2p.private"); os.IsNotExist(err) {
|
||||
f, err := os.Create(keyspath + ".i2p.private")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to open I2P keyfile for writing: %s", err)
|
||||
}
|
||||
defer f.Close()
|
||||
tkeys, err := sam.NewKeys()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to generate I2P Keys, %s", err)
|
||||
}
|
||||
keys = &tkeys
|
||||
err = i2pkeys.StoreKeysIncompat(*keys, f)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to save newly generated I2P Keys, %s", err)
|
||||
}
|
||||
} else {
|
||||
tkeys, err := i2pkeys.LoadKeys(keyspath + ".i2p.private")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to load I2P Keys: %e", err)
|
||||
}
|
||||
keys = &tkeys
|
||||
}
|
||||
} else {
|
||||
tkeys, err := sam.NewKeys()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to generate I2P Keys, %s", err)
|
||||
}
|
||||
keys = &tkeys
|
||||
keys, err := GenerateOrLoadKeys(keyspath, sam)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stream, err := sam.NewStreamSession(name, *keys, sam3.Options_Medium)
|
||||
return stream, err
|
||||
@@ -81,38 +54,11 @@ func I2PDatagramSession(name, samaddr, keyspath string) (*sam3.DatagramSession,
|
||||
log.Printf("Starting and registering I2P session...")
|
||||
sam, err := sam3.NewSAM(samaddr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error connecting to SAM to %s: %s", samaddr, err)
|
||||
log.Fatalf("error connecting to SAM to %s: %s", samaddr, err)
|
||||
}
|
||||
var keys *i2pkeys.I2PKeys
|
||||
if keyspath != "" {
|
||||
if _, err := os.Stat(keyspath + ".i2p.private"); os.IsNotExist(err) {
|
||||
f, err := os.Create(keyspath + ".i2p.private")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to open I2P keyfile for writing: %s", err)
|
||||
}
|
||||
defer f.Close()
|
||||
tkeys, err := sam.NewKeys()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to generate I2P Keys, %s", err)
|
||||
}
|
||||
keys = &tkeys
|
||||
err = i2pkeys.StoreKeysIncompat(*keys, f)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to save newly generated I2P Keys, %s", err)
|
||||
}
|
||||
} else {
|
||||
tkeys, err := i2pkeys.LoadKeys(keyspath + ".i2p.private")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to load I2P Keys: %e", err)
|
||||
}
|
||||
keys = &tkeys
|
||||
}
|
||||
} else {
|
||||
tkeys, err := sam.NewKeys()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to generate I2P Keys, %s", err)
|
||||
}
|
||||
keys = &tkeys
|
||||
keys, err := GenerateOrLoadKeys(keyspath, sam)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gram, err := sam.NewDatagramSession(name, *keys, sam3.Options_Medium, 0)
|
||||
return gram, err
|
||||
@@ -124,39 +70,48 @@ func I2PPrimarySession(name, samaddr, keyspath string) (*sam3.PrimarySession, er
|
||||
log.Printf("Starting and registering I2P session...")
|
||||
sam, err := sam3.NewSAM(samaddr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error connecting to SAM to %s: %s", samaddr, err)
|
||||
log.Fatalf("error connecting to SAM to %s: %s", samaddr, err)
|
||||
}
|
||||
var keys *i2pkeys.I2PKeys
|
||||
if keyspath != "" {
|
||||
if _, err := os.Stat(keyspath + ".i2p.private"); os.IsNotExist(err) {
|
||||
f, err := os.Create(keyspath + ".i2p.private")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to open I2P keyfile for writing: %s", err)
|
||||
}
|
||||
defer f.Close()
|
||||
tkeys, err := sam.NewKeys()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to generate I2P Keys, %s", err)
|
||||
}
|
||||
keys = &tkeys
|
||||
err = i2pkeys.StoreKeysIncompat(*keys, f)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to save newly generated I2P Keys, %s", err)
|
||||
}
|
||||
} else {
|
||||
tkeys, err := i2pkeys.LoadKeys(keyspath + ".i2p.private")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to load I2P Keys: %e", err)
|
||||
}
|
||||
keys = &tkeys
|
||||
}
|
||||
} else {
|
||||
tkeys, err := sam.NewKeys()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to generate I2P Keys, %s", err)
|
||||
}
|
||||
keys = &tkeys
|
||||
keys, err := GenerateOrLoadKeys(keyspath, sam)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gram, err := sam.NewPrimarySession(name, *keys, sam3.Options_Medium)
|
||||
return gram, err
|
||||
}
|
||||
|
||||
func GenerateOrLoadKeys(keyspath string, sam *sam3.SAM) (keys *i2pkeys.I2PKeys, err error) {
|
||||
if sam == nil {
|
||||
sam, err = sam3.NewSAM("127.0.0.1:7657")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if _, err := os.Stat(keyspath + ".i2p.private"); os.IsNotExist(err) {
|
||||
f, err := os.Create(keyspath + ".i2p.private")
|
||||
if err != nil {
|
||||
log.Fatalf("unable to open I2P keyfile for writing: %s", err)
|
||||
}
|
||||
defer f.Close()
|
||||
tkeys, err := sam.NewKeys()
|
||||
if err != nil {
|
||||
log.Fatalf("unable to generate I2P Keys, %s", err)
|
||||
}
|
||||
keys = &tkeys
|
||||
err = i2pkeys.StoreKeysIncompat(*keys, f)
|
||||
if err != nil {
|
||||
log.Fatalf("unable to save newly generated I2P Keys, %s", err)
|
||||
}
|
||||
} else {
|
||||
tkeys, err := i2pkeys.LoadKeys(keyspath + ".i2p.private")
|
||||
if err != nil {
|
||||
log.Fatalf("unable to load I2P Keys: %e", err)
|
||||
}
|
||||
keys = &tkeys
|
||||
}
|
||||
return keys, nil
|
||||
}
|
||||
|
||||
func GenerateKeys(keyspath string) (keys *i2pkeys.I2PKeys, err error) {
|
||||
return GenerateOrLoadKeys(keyspath, nil)
|
||||
}
|
||||
|
@@ -21,8 +21,6 @@ var (
|
||||
i2pB32enc *base32.Encoding = base32.NewEncoding("abcdefghijklmnopqrstuvwxyz234567")
|
||||
)
|
||||
|
||||
var FakePort = false
|
||||
|
||||
// The public and private keys associated with an I2P destination. I2P hides the
|
||||
// details of exactly what this is, so treat them as blobs, but generally: One
|
||||
// pair of DSA keys, one pair of ElGamal keys, and sometimes (almost never) also
|
||||
@@ -281,14 +279,7 @@ func (addr I2PAddr) Bytes() []byte {
|
||||
// performing a Lookup(). Lookup only works if you are using the I2PAddr from
|
||||
// which the b32 address was generated.
|
||||
func (addr I2PAddr) Base32() (str string) {
|
||||
return addr.DestHash().String() + addr.Port()
|
||||
}
|
||||
|
||||
func (addr I2PAddr) Port() (str string) {
|
||||
if FakePort {
|
||||
return ":8080"
|
||||
}
|
||||
return ""
|
||||
return addr.DestHash().String()
|
||||
}
|
||||
|
||||
func (addr I2PAddr) DestHash() (h I2PDestHash) {
|
||||
|
71
primary.go
71
primary.go
@@ -33,8 +33,8 @@ type PrimarySession struct {
|
||||
Deadline time.Time
|
||||
sigType string
|
||||
Config SAMEmit
|
||||
stsess *StreamSession
|
||||
dgsess *DatagramSession
|
||||
stsess map[string]*StreamSession
|
||||
dgsess map[string]*DatagramSession
|
||||
// from string
|
||||
// to string
|
||||
}
|
||||
@@ -62,12 +62,10 @@ func (ss *PrimarySession) Close() error {
|
||||
|
||||
// Returns the I2P destination (the address) of the stream session
|
||||
func (ss *PrimarySession) Addr() i2pkeys.I2PAddr {
|
||||
// fmt.Println("LOCAL ADDR")
|
||||
return ss.keys.Addr()
|
||||
}
|
||||
|
||||
func (ss *PrimarySession) LocalAddr() net.Addr {
|
||||
// fmt.Println("LOCAL ADDR")
|
||||
aa := ss.keys.Addr()
|
||||
return &aa
|
||||
}
|
||||
@@ -89,58 +87,58 @@ func (sam *PrimarySession) Dial(network, addr string) (net.Conn, error) {
|
||||
|
||||
// DialTCP implements x/dialer
|
||||
func (sam *PrimarySession) DialTCP(network string, laddr, raddr net.Addr) (net.Conn, error) {
|
||||
var err error
|
||||
if sam.stsess == nil {
|
||||
sam.stsess, err = sam.NewUniqueStreamSubSession(network + RandString())
|
||||
_, ok := sam.stsess[network+raddr.String()[0:4]]
|
||||
if !ok {
|
||||
stsess, err := sam.NewUniqueStreamSubSession(network + raddr.String()[0:4])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sam.stsess[network+raddr.String()[0:4]] = stsess
|
||||
}
|
||||
return sam.stsess.Dial(network, raddr.String())
|
||||
return sam.stsess[network+raddr.String()[0:4]].Dial(network, raddr.String())
|
||||
}
|
||||
|
||||
func (sam *PrimarySession) DialTCPI2P(network string, laddr, raddr string) (*SAMConn, error) {
|
||||
var err error
|
||||
if sam.stsess == nil {
|
||||
sam.stsess, err = sam.NewUniqueStreamSubSession(network + RandString())
|
||||
func (sam *PrimarySession) DialTCPI2P(network string, laddr, raddr string) (net.Conn, error) {
|
||||
_, ok := sam.stsess[network+raddr[0:4]]
|
||||
if !ok {
|
||||
stsess, err := sam.NewUniqueStreamSubSession(network + laddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sam.stsess[network+raddr[0:4]] = stsess
|
||||
}
|
||||
c, err := sam.stsess.Dial(network, raddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.(*SAMConn), nil
|
||||
return sam.stsess[network+raddr[0:4]].Dial(network, raddr)
|
||||
}
|
||||
|
||||
// DialUDP implements x/dialer
|
||||
func (sam *PrimarySession) DialUDP(network string, laddr, raddr net.Addr) (net.PacketConn, error) {
|
||||
var err error
|
||||
if sam.dgsess == nil {
|
||||
sam.dgsess, err = sam.NewDatagramSubSession(network+raddr.String()[0:4], 0)
|
||||
_, ok := sam.dgsess[network+raddr.String()[0:4]]
|
||||
if !ok {
|
||||
dgsess, err := sam.NewDatagramSubSession(network+raddr.String()[0:4], 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sam.dgsess[network+raddr.String()[0:4]] = dgsess
|
||||
}
|
||||
return sam.dgsess.Dial(network, raddr.String())
|
||||
return sam.dgsess[network+raddr.String()[0:4]].Dial(network, raddr.String())
|
||||
}
|
||||
|
||||
func (sam *PrimarySession) DialUDPI2P(network, laddr, raddr string) (*DatagramSession, error) {
|
||||
var err error
|
||||
if sam.dgsess == nil {
|
||||
sam.dgsess, err = sam.NewDatagramSubSession(network+raddr[0:4], 0)
|
||||
_, ok := sam.dgsess[network+raddr[0:4]]
|
||||
if !ok {
|
||||
dgsess, err := sam.NewDatagramSubSession(network+laddr, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sam.dgsess[network+raddr[0:4]] = dgsess
|
||||
}
|
||||
return sam.dgsess.Dial(network, raddr)
|
||||
return sam.dgsess[network+raddr[0:4]].Dial(network, raddr)
|
||||
}
|
||||
|
||||
func (s *PrimarySession) Lookup(name string) (a net.Addr, err error) {
|
||||
var sam *SAM
|
||||
if len(strings.Split(name, ":")) <= 1 {
|
||||
name += ":80"
|
||||
name += ":0"
|
||||
}
|
||||
sam, err = NewSAM(s.samAddr)
|
||||
if err == nil {
|
||||
@@ -151,17 +149,14 @@ func (s *PrimarySession) Lookup(name string) (a net.Addr, err error) {
|
||||
}
|
||||
|
||||
func (sam *PrimarySession) Resolve(network, addr string) (net.Addr, error) {
|
||||
fmt.Println("LOGGING RESOLUTION", network, addr)
|
||||
return sam.Lookup(addr)
|
||||
}
|
||||
|
||||
func (sam *PrimarySession) ResolveTCPAddr(network, dest string) (net.Addr, error) {
|
||||
fmt.Println("LOGGING RESOLUTION", network, dest)
|
||||
return sam.Lookup(dest)
|
||||
}
|
||||
|
||||
func (sam *PrimarySession) ResolveUDPAddr(network, dest string) (net.Addr, error) {
|
||||
fmt.Println("LOGGING RESOLUTION", network, dest)
|
||||
return sam.Lookup(dest)
|
||||
}
|
||||
|
||||
@@ -172,7 +167,9 @@ func (sam *SAM) NewPrimarySession(id string, keys i2pkeys.I2PKeys, options []str
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &PrimarySession{sam.Config.I2PConfig.Sam(), id, conn, keys, time.Duration(600 * time.Second), time.Now(), Sig_NONE, sam.Config, nil, nil}, nil
|
||||
ssesss := make(map[string]*StreamSession)
|
||||
dsesss := make(map[string]*DatagramSession)
|
||||
return &PrimarySession{sam.Config.I2PConfig.Sam(), id, conn, keys, time.Duration(600 * time.Second), time.Now(), Sig_NONE, sam.Config, ssesss, dsesss}, nil
|
||||
}
|
||||
|
||||
// Creates a new PrimarySession with the I2CP- and PRIMARYinglib options as
|
||||
@@ -182,7 +179,9 @@ func (sam *SAM) NewPrimarySessionWithSignature(id string, keys i2pkeys.I2PKeys,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &PrimarySession{sam.Config.I2PConfig.Sam(), id, conn, keys, time.Duration(600 * time.Second), time.Now(), sigType, sam.Config, nil, nil}, nil
|
||||
ssesss := make(map[string]*StreamSession)
|
||||
dsesss := make(map[string]*DatagramSession)
|
||||
return &PrimarySession{sam.Config.I2PConfig.Sam(), id, conn, keys, time.Duration(600 * time.Second), time.Now(), sigType, sam.Config, ssesss, dsesss}, nil
|
||||
}
|
||||
|
||||
// Creates a new session with the style of either "STREAM", "DATAGRAM" or "RAW",
|
||||
@@ -261,23 +260,21 @@ func (sam *PrimarySession) newGenericSubSessionWithSignatureAndPorts(style, id,
|
||||
// Creates a new StreamSession with the I2CP- and streaminglib options as
|
||||
// specified. See the I2P documentation for a full list of options.
|
||||
func (sam *PrimarySession) NewStreamSubSession(id string) (*StreamSession, error) {
|
||||
s := RandString()
|
||||
conn, err := sam.newGenericSubSession("STREAM", id+s, []string{})
|
||||
conn, err := sam.newGenericSubSession("STREAM", id, []string{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &StreamSession{sam.Config.I2PConfig.Sam(), id + s, conn, sam.keys, time.Duration(600 * time.Second), time.Now(), Sig_NONE, "0", "0"}, nil
|
||||
return &StreamSession{sam.Config.I2PConfig.Sam(), id, conn, sam.keys, time.Duration(600 * time.Second), time.Now(), Sig_NONE, "0", "0"}, nil
|
||||
}
|
||||
|
||||
// Creates a new StreamSession with the I2CP- and streaminglib options as
|
||||
// specified. See the I2P documentation for a full list of options.
|
||||
func (sam *PrimarySession) NewUniqueStreamSubSession(id string) (*StreamSession, error) {
|
||||
s := RandString()
|
||||
conn, err := sam.newGenericSubSession("STREAM", id+s, []string{})
|
||||
conn, err := sam.newGenericSubSession("STREAM", id, []string{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &StreamSession{sam.Config.I2PConfig.Sam(), id + s, conn, sam.keys, time.Duration(600 * time.Second), time.Now(), Sig_NONE, randport(), "0"}, nil
|
||||
return &StreamSession{sam.Config.I2PConfig.Sam(), id, conn, sam.keys, time.Duration(600 * time.Second), time.Now(), Sig_NONE, randport(), "0"}, nil
|
||||
}
|
||||
|
||||
// Creates a new StreamSession with the I2CP- and streaminglib options as
|
||||
|
@@ -7,6 +7,7 @@ import (
|
||||
"log"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/eyedeekay/sam3/i2pkeys"
|
||||
)
|
||||
@@ -98,11 +99,12 @@ func Test_PrimaryStreamingServerClient(t *testing.T) {
|
||||
}
|
||||
defer sam.Close()
|
||||
fmt.Println("\tServer: Creating tunnel")
|
||||
ss, err := sam.NewStreamSubSession("primaryExampleServerTun")
|
||||
ss, err := sam.NewUniqueStreamSubSession("primaryExampleServerTun")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer ss.Close()
|
||||
time.Sleep(time.Second * 10)
|
||||
c, w := make(chan bool), make(chan bool)
|
||||
go func(c, w chan (bool)) {
|
||||
if !(<-w) {
|
||||
|
121
stream.go
121
stream.go
@@ -6,9 +6,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -28,6 +26,18 @@ type StreamSession struct {
|
||||
to string
|
||||
}
|
||||
|
||||
func (s *StreamSession) SetDeadline(t time.Time) error {
|
||||
return s.conn.SetDeadline(t)
|
||||
}
|
||||
|
||||
func (s *StreamSession) SetReadDeadline(t time.Time) error {
|
||||
return s.conn.SetReadDeadline(t)
|
||||
}
|
||||
|
||||
func (s *StreamSession) SetWriteDeadline(t time.Time) error {
|
||||
return s.conn.SetWriteDeadline(t)
|
||||
}
|
||||
|
||||
func (ss *StreamSession) From() string {
|
||||
return ss.from
|
||||
}
|
||||
@@ -54,6 +64,10 @@ func (ss *StreamSession) Addr() i2pkeys.I2PAddr {
|
||||
return ss.keys.Addr()
|
||||
}
|
||||
|
||||
func (ss *StreamSession) LocalAddr() net.Addr {
|
||||
return ss.keys.Addr()
|
||||
}
|
||||
|
||||
// Returns the keys associated with the stream session
|
||||
func (ss *StreamSession) Keys() i2pkeys.I2PKeys {
|
||||
return ss.keys
|
||||
@@ -239,106 +253,3 @@ func (s *StreamSession) Listen() (*StreamListener, error) {
|
||||
laddr: s.keys.Addr(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
type StreamListener struct {
|
||||
// parent stream session
|
||||
session *StreamSession
|
||||
// our session id
|
||||
id string
|
||||
// our local address for this sam socket
|
||||
laddr i2pkeys.I2PAddr
|
||||
}
|
||||
|
||||
func (l *StreamListener) From() string {
|
||||
return l.session.from
|
||||
}
|
||||
|
||||
func (l *StreamListener) To() string {
|
||||
return l.session.to
|
||||
}
|
||||
|
||||
// get our address
|
||||
// implements net.Listener
|
||||
func (l *StreamListener) Addr() net.Addr {
|
||||
return l.laddr
|
||||
}
|
||||
|
||||
// implements net.Listener
|
||||
func (l *StreamListener) Close() error {
|
||||
return l.session.Close()
|
||||
}
|
||||
|
||||
// implements net.Listener
|
||||
func (l *StreamListener) Accept() (net.Conn, error) {
|
||||
return l.AcceptI2P()
|
||||
}
|
||||
|
||||
func ExtractPairString(input, value string) string {
|
||||
parts := strings.Split(input, " ")
|
||||
for _, part := range parts {
|
||||
if strings.HasPrefix(part, value) {
|
||||
kv := strings.SplitN(input, "=", 2)
|
||||
if len(kv) == 2 {
|
||||
return kv[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func ExtractPairInt(input, value string) int {
|
||||
rv, err := strconv.Atoi(ExtractPairString(input, value))
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return rv
|
||||
}
|
||||
|
||||
func ExtractDest(input string) string {
|
||||
return strings.Split(input, " ")[0]
|
||||
}
|
||||
|
||||
// accept a new inbound connection
|
||||
func (l *StreamListener) AcceptI2P() (*SAMConn, error) {
|
||||
s, err := NewSAM(l.session.samAddr)
|
||||
if err == nil {
|
||||
// we connected to sam
|
||||
// send accept() command
|
||||
_, err = io.WriteString(s.conn, "STREAM ACCEPT ID="+l.id+" SILENT=false\n")
|
||||
// read reply
|
||||
rd := bufio.NewReader(s.conn)
|
||||
// read first line
|
||||
line, err := rd.ReadString(10)
|
||||
log.Println(line)
|
||||
if err == nil {
|
||||
if strings.HasPrefix(line, "STREAM STATUS RESULT=OK") {
|
||||
// we gud read destination line
|
||||
destline, err := rd.ReadString(10)
|
||||
log.Println(destline)
|
||||
if err == nil {
|
||||
dest := ExtractDest(destline)
|
||||
l.session.from = ExtractPairString(destline, "FROM_PORT")
|
||||
l.session.to = ExtractPairString(destline, "TO_PORT")
|
||||
// return wrapped connection
|
||||
dest = strings.Trim(dest, "\n")
|
||||
return &SAMConn{
|
||||
laddr: l.laddr,
|
||||
raddr: i2pkeys.I2PAddr(dest),
|
||||
conn: s.conn,
|
||||
}, nil
|
||||
} else {
|
||||
s.Close()
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
s.Close()
|
||||
return nil, errors.New("invalid sam line: " + line)
|
||||
}
|
||||
} else {
|
||||
s.Close()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
s.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
116
streamListener.go
Normal file
116
streamListener.go
Normal file
@@ -0,0 +1,116 @@
|
||||
package sam3
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/eyedeekay/sam3/i2pkeys"
|
||||
)
|
||||
|
||||
type StreamListener struct {
|
||||
// parent stream session
|
||||
session *StreamSession
|
||||
// our session id
|
||||
id string
|
||||
// our local address for this sam socket
|
||||
laddr i2pkeys.I2PAddr
|
||||
}
|
||||
|
||||
func (l *StreamListener) From() string {
|
||||
return l.session.from
|
||||
}
|
||||
|
||||
func (l *StreamListener) To() string {
|
||||
return l.session.to
|
||||
}
|
||||
|
||||
// get our address
|
||||
// implements net.Listener
|
||||
func (l *StreamListener) Addr() net.Addr {
|
||||
return l.laddr
|
||||
}
|
||||
|
||||
// implements net.Listener
|
||||
func (l *StreamListener) Close() error {
|
||||
return l.session.Close()
|
||||
}
|
||||
|
||||
// implements net.Listener
|
||||
func (l *StreamListener) Accept() (net.Conn, error) {
|
||||
return l.AcceptI2P()
|
||||
}
|
||||
|
||||
func ExtractPairString(input, value string) string {
|
||||
parts := strings.Split(input, " ")
|
||||
for _, part := range parts {
|
||||
if strings.HasPrefix(part, value) {
|
||||
kv := strings.SplitN(input, "=", 2)
|
||||
if len(kv) == 2 {
|
||||
return kv[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func ExtractPairInt(input, value string) int {
|
||||
rv, err := strconv.Atoi(ExtractPairString(input, value))
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return rv
|
||||
}
|
||||
|
||||
func ExtractDest(input string) string {
|
||||
return strings.Split(input, " ")[0]
|
||||
}
|
||||
|
||||
// accept a new inbound connection
|
||||
func (l *StreamListener) AcceptI2P() (*SAMConn, error) {
|
||||
s, err := NewSAM(l.session.samAddr)
|
||||
if err == nil {
|
||||
// we connected to sam
|
||||
// send accept() command
|
||||
_, err = io.WriteString(s.conn, "STREAM ACCEPT ID="+l.id+" SILENT=false\n")
|
||||
// read reply
|
||||
rd := bufio.NewReader(s.conn)
|
||||
// read first line
|
||||
line, err := rd.ReadString(10)
|
||||
log.Println(line)
|
||||
if err == nil {
|
||||
if strings.HasPrefix(line, "STREAM STATUS RESULT=OK") {
|
||||
// we gud read destination line
|
||||
destline, err := rd.ReadString(10)
|
||||
log.Println(destline)
|
||||
if err == nil {
|
||||
dest := ExtractDest(destline)
|
||||
l.session.from = ExtractPairString(destline, "FROM_PORT")
|
||||
l.session.to = ExtractPairString(destline, "TO_PORT")
|
||||
// return wrapped connection
|
||||
dest = strings.Trim(dest, "\n")
|
||||
return &SAMConn{
|
||||
laddr: l.laddr,
|
||||
raddr: i2pkeys.I2PAddr(dest),
|
||||
conn: s.conn,
|
||||
}, nil
|
||||
} else {
|
||||
s.Close()
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
s.Close()
|
||||
return nil, errors.New("invalid sam line: " + line)
|
||||
}
|
||||
} else {
|
||||
s.Close()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
s.Close()
|
||||
return nil, err
|
||||
}
|
Reference in New Issue
Block a user