Merge pull request #7 from eyedeekay/no-keys

Don't rely on sam3 for key generation. Cleanup API issues. Improve Stability. Begin to add DG, RAW support.
This commit is contained in:
idk
2021-04-15 14:24:56 -07:00
committed by GitHub
12 changed files with 154 additions and 112 deletions

View File

@ -24,8 +24,7 @@ func (c *Client) Listen() (net.Listener, error) {
// with Accept
func (c *Client) ListenI2P(dest string) (net.Listener, error) {
var err error
c.id = c.NewID()
c.destination, err = c.CreateStreamSession(c.id, dest)
c.destination, err = c.CreateStreamSession(dest)
d := c.destination
if err != nil {
return nil, err
@ -52,7 +51,7 @@ func (c *Client) Accept() (net.Conn, error) {
if c.id == 0 {
return c.AcceptI2P()
}
resp, err := c.StreamAccept(c.id)
resp, err := c.StreamAccept()
if err != nil {
return nil, err
}

View File

@ -22,8 +22,9 @@ type Client struct {
fromport string
toport string
SamConn net.Conn
rd *bufio.Reader
SamConn net.Conn
SamDGConn DatagramConn
rd *bufio.Reader
sigType string
destination string
@ -91,6 +92,7 @@ func NewClient(addr string) (*Client, error) {
func (c *Client) NewID() int32 {
if c.id == 0 {
c.id = rand.Int31n(math.MaxInt32)
fmt.Printf("Initializing new ID: %d\n", c.id)
}
return c.id
}
@ -177,7 +179,7 @@ func NewClientFromOptions(opts ...func(*Client) error) (*Client, error) {
}
func (p *Client) ID() string {
return fmt.Sprintf("%d", p.id)
return fmt.Sprintf("%d", p.NewID())
}
func (p *Client) Addr() net.Addr {

View File

@ -6,6 +6,8 @@ import "testing"
import (
"fmt"
"math"
"math/rand"
"time"
//"log"
"net/http"
@ -18,48 +20,40 @@ func HelloServer(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:])
}
var client *Client
func setup(t *testing.T) {
var err error
// these tests expect a running SAM brige on this address
client, err = NewClientFromOptions(SetDebug(true))
if err != nil {
t.Fatalf("NewDefaultClient() Error: %q\n", err)
}
}
func TestCompositeClient(t *testing.T) {
listener, err := sam.I2PListener("testservice", "127.0.0.1:7656", "testkeys")
listener, err := sam.I2PListener("testservice"+fmt.Sprintf("%d", rand.Int31n(math.MaxInt32)), "127.0.0.1:7656", "testkeys")
if err != nil {
t.Fatalf("Listener() Error: %q\n", err)
}
defer listener.Close()
http.HandleFunc("/", HelloServer)
go http.Serve(listener, nil)
listener2, err := sam.I2PListener("testservice2", "127.0.0.1:7656", "testkeys2")
listener2, err := sam.I2PListener("testservice"+fmt.Sprintf("%d", rand.Int31n(math.MaxInt32)), "127.0.0.1:7656", "testkeys2")
if err != nil {
t.Fatalf("Listener() Error: %q\n", err)
}
defer listener2.Close()
// http.HandleFunc("/", HelloServer)
go http.Serve(listener2, nil)
listener3, err := sam.I2PListener("testservice3", "127.0.0.1:7656", "testkeys3")
listener3, err := sam.I2PListener("testservice"+fmt.Sprintf("%d", rand.Int31n(math.MaxInt32)), "127.0.0.1:7656", "testkeys3")
if err != nil {
t.Fatalf("Listener() Error: %q\n", err)
}
defer listener3.Close()
// http.HandleFunc("/", HelloServer)
go http.Serve(listener3, nil)
client, err = NewClientFromOptions(SetDebug(true))
sam, err := NewClientFromOptions(SetDebug(false))
if err != nil {
t.Fatalf("NewDefaultClient() Error: %q\n", err)
}
tr := &http.Transport{
Dial: client.Dial,
Dial: sam.Dial,
}
client := &http.Client{Transport: tr}
defer sam.Close()
time.Sleep(time.Second * 30)
go func() {
resp, err := client.Get("http://" + listener.Addr().(i2pkeys.I2PAddr).Base32())
@ -67,45 +61,50 @@ func TestCompositeClient(t *testing.T) {
t.Fatalf("Get Error: %q\n", err)
}
defer resp.Body.Close()
t.Log("Get returned ", resp)
}()
time.Sleep(time.Second * 15)
go func() {
resp, err := client.Get("http://" + listener2.Addr().(i2pkeys.I2PAddr).Base32())
if err != nil {
t.Fatalf("Get Error: %q\n", err)
}
defer resp.Body.Close()
t.Log("Get returned ", resp)
}()
time.Sleep(time.Second * 15)
go func() {
resp, err := client.Get("http://" + listener3.Addr().(i2pkeys.I2PAddr).Base32())
if err != nil {
t.Fatalf("Get Error: %q\n", err)
}
defer resp.Body.Close()
t.Log("Get returned ", resp)
}()
time.Sleep(time.Second * 15)
time.Sleep(time.Second * 45)
}
func teardown(t *testing.T) {
func TestClientHello(t *testing.T) {
client, err := NewClientFromOptions(SetDebug(false))
if err != nil {
t.Fatalf("NewDefaultClient() Error: %q\n", err)
}
t.Log(client.Base32())
if err := client.Close(); err != nil {
t.Fatalf("client.Close() Error: %q\n", err)
}
}
func TestClientHello(t *testing.T) {
setup(t)
t.Log(client.Base32())
teardown(t)
}
func TestNewDestination(t *testing.T) {
setup(t)
t.Log(client.Base32())
if _, err := client.NewDestination(SAMsigTypes[3]); err != nil {
t.Error(err)
client, err := NewClientFromOptions(SetDebug(false))
if err != nil {
t.Fatalf("NewDefaultClient() Error: %q\n", err)
}
t.Log(client.Base32())
if s, p, err := client.NewDestination(SAMsigTypes[3]); err != nil {
t.Error(err)
} else {
t.Log(s, p)
}
if err := client.Close(); err != nil {
t.Fatalf("client.Close() Error: %q\n", err)
}
teardown(t)
}

19
datagram.go Normal file
View File

@ -0,0 +1,19 @@
package goSam
import (
"net"
"time"
)
type DatagramConn interface {
ReadFrom(p []byte) (n int, addr net.Addr, err error)
Read(b []byte) (n int, err error)
WriteTo(p []byte, addr net.Addr) (n int, err error)
Write(b []byte) (n int, err error)
Close() error
LocalAddr() net.Addr
RemoteAddr() net.Addr
SetDeadline(t time.Time) error
SetReadDeadline(t time.Time) error
SetWriteDeadline(t time.Time) error
}

45
dial.go
View File

@ -37,6 +37,23 @@ func (c *Client) Dial(network, addr string) (net.Conn, error) {
// Dial implements the net.Dial function and can be used for http.Transport
func (c *Client) DialContextFree(network, addr string) (net.Conn, error) {
if network == "tcp" || network == "tcp6" || network == "tcp4" {
return c.DialStreamingContextFree(addr)
}
if network == "udp" || network == "udp6" || network == "udp4" {
return c.DialDatagramContextFree(addr)
}
if network == "raw" || network == "ip" {
return c.DialDatagramContextFree(addr)
}
return c.DialStreamingContextFree(addr)
}
func (c *Client) DialDatagramContextFree(addr string) (DatagramConn, error) {
return c.SamDGConn, nil
}
func (c *Client) DialStreamingContextFree(addr string) (net.Conn, error) {
portIdx := strings.Index(addr, ":")
if portIdx >= 0 {
addr = addr[:portIdx]
@ -47,36 +64,20 @@ func (c *Client) DialContextFree(network, addr string) (net.Conn, error) {
return nil, err
}
c.destination, err = c.CreateStreamSession(c.id, c.destination)
if err != nil {
c.Close()
d, err := c.NewClient(c.id + 1) /**/
if c.destination == "" {
c.destination, err = c.CreateStreamSession(c.destination)
if err != nil {
return nil, err
}
d.destination, err = d.CreateStreamSession(d.id, c.destination)
if err != nil {
return nil, err
}
d, err = d.NewClient(d.id)
if err != nil {
return nil, err
}
// d.lastaddr = addr
err = d.StreamConnect(d.id, addr)
if err != nil {
return nil, err
}
c = d
return d.SamConn, nil
}
c, err = c.NewClient(c.id)
d, err := c.NewClient(c.NewID())
if err != nil {
return nil, err
}
err = c.StreamConnect(c.id, addr)
err = d.StreamConnect(addr)
if err != nil {
return nil, err
}
return c.SamConn, nil
return d.SamConn, nil
}

View File

@ -2,17 +2,14 @@ package goSam
import (
"errors"
"github.com/eyedeekay/sam3/i2pkeys"
)
// NewDestination generates a new I2P destination, creating the underlying
// public/private keys in the process. The public key can be used to send messages
// to the destination, while the private key can be used to reply to messages
func (c *Client) NewDestination(sigType ...string) (i2pkeys.I2PKeys, error) {
func (c *Client) NewDestination(sigType ...string) (string, string, error) {
var (
sigtmp string
keys i2pkeys.I2PKeys
)
if len(sigType) > 0 {
sigtmp = sigType[0]
@ -22,14 +19,14 @@ func (c *Client) NewDestination(sigType ...string) (i2pkeys.I2PKeys, error) {
sigtmp,
)
if err != nil {
return keys, err
return "", "", err
}
var pub, priv string
if priv = r.Pairs["PRIV"]; priv == "" {
return keys, errors.New("failed to generate private destination key")
return "", "", errors.New("failed to generate private destination key")
}
if pub = r.Pairs["PUB"]; pub == "" {
return keys, errors.New("failed to generate public destination key")
return priv, "", errors.New("failed to generate public destination key")
}
return i2pkeys.NewKeys(i2pkeys.I2PAddr(pub), priv), nil
return priv, pub, nil
}

View File

@ -17,7 +17,7 @@ func (c *Client) Lookup(name string) (string, error) {
// TODO: move check into sendCmd()
if r.Topic != "NAMING" || r.Type != "REPLY" {
return "", fmt.Errorf("Naming Unknown Reply: %+v\n", r)
return "", fmt.Errorf("Naming Unknown Reply: %s, %s\n", r.Topic, r.Type)
}
result := r.Pairs["RESULT"]

View File

@ -10,8 +10,10 @@ import (
func TestClientLookupInvalid(t *testing.T) {
var err error
setup(t)
defer teardown(t)
client, err := NewClientFromOptions(SetDebug(false))
if err != nil {
t.Fatalf("NewDefaultClient() Error: %q\n", err)
}
addr, err := client.Lookup(`!(@#)`)
if addr != "" || err == nil {
@ -25,6 +27,9 @@ func TestClientLookupInvalid(t *testing.T) {
if repErr.Result != ResultKeyNotFound {
t.Errorf("client.Lookup() should throw an ResultKeyNotFound error.\nGot:%+v%s%s\n", repErr, "!=", ResultKeyNotFound)
}
if err := client.Close(); err != nil {
t.Fatalf("client.Close() Error: %q\n", err)
}
}
func TestClientLookupValid(t *testing.T) {

View File

@ -31,12 +31,12 @@ func (c *Client) validCmd(str string, args ...interface{}) (string, error) {
func (c *Client) validCreate() (string, error) {
id := rand.Int31n(math.MaxInt32)
result, err := c.validCmd("SESSION CREATE STYLE=STREAM ID=%d DESTINATION=%s %s\n", id, "abc.i2p", client.allOptions())
result, err := c.validCmd("SESSION CREATE STYLE=STREAM ID=%d DESTINATION=%s %s\n", id, "abc.i2p", c.allOptions())
return result, err
}
func TestOptionAddrString(t *testing.T) {
client, err := NewClientFromOptions(SetAddr("127.0.0.1:7656"), SetDebug(true))
client, err := NewClientFromOptions(SetAddr("127.0.0.1:7656"), SetDebug(false))
if err != nil {
t.Fatalf("NewClientFromOptions() Error: %q\n", err)
}
@ -45,17 +45,17 @@ func TestOptionAddrString(t *testing.T) {
} else {
t.Log(result)
}
dest, _ := client.CreateStreamSession(client.NewID(), "")
_, err = client.CreateStreamSession("")
if err := client.Close(); err != nil {
t.Fatalf("client.Close() Error: %q\n", err)
}
fmt.Printf("\t destination- %s \n", dest)
fmt.Printf("\t address64- %s \t", client.Base64())
fmt.Printf("\t address- %s \t", client.Base32())
/* fmt.Printf("\t destination- %s \n", dest)
fmt.Printf("\t address64- %s \t", client.Base64())
fmt.Printf("\t address- %s \t", client.Base32())*/
}
func TestOptionAddrStringLh(t *testing.T) {
client, err := NewClientFromOptions(SetAddr("localhost:7656"), SetDebug(true))
client, err := NewClientFromOptions(SetAddr("localhost:7656"), SetDebug(false))
if err != nil {
t.Fatalf("NewClientFromOptions() Error: %q\n", err)
}
@ -64,17 +64,17 @@ func TestOptionAddrStringLh(t *testing.T) {
} else {
t.Log(result)
}
dest, _ := client.CreateStreamSession(client.NewID(), "")
_, err = client.CreateStreamSession("")
if err := client.Close(); err != nil {
t.Fatalf("client.Close() Error: %q\n", err)
}
fmt.Printf("\t destination- %s \n", dest)
fmt.Printf("\t address64- %s \t", client.Base64())
fmt.Printf("\t address- %s \t", client.Base32())
/* fmt.Printf("\t destination- %s \n", dest)
fmt.Printf("\t address64- %s \t", client.Base64())
fmt.Printf("\t address- %s \t", client.Base32())*/
}
func TestOptionAddrSlice(t *testing.T) {
client, err := NewClientFromOptions(SetAddr("127.0.0.1", "7656"), SetDebug(true))
client, err := NewClientFromOptions(SetAddr("127.0.0.1", "7656"), SetDebug(false))
if err != nil {
t.Fatalf("NewClientFromOptions() Error: %q\n", err)
}
@ -83,17 +83,17 @@ func TestOptionAddrSlice(t *testing.T) {
} else {
t.Log(result)
}
dest, _ := client.CreateStreamSession(client.NewID(), "")
_, err = client.CreateStreamSession("")
if err := client.Close(); err != nil {
t.Fatalf("client.Close() Error: %q\n", err)
}
fmt.Printf("\t destination- %s \n", dest)
fmt.Printf("\t address64- %s \t", client.Base64())
fmt.Printf("\t address- %s \t", client.Base32())
/* fmt.Printf("\t destination- %s \n", dest)
fmt.Printf("\t address64- %s \t", client.Base64())
fmt.Printf("\t address- %s \t", client.Base32())*/
}
func TestOptionAddrMixedSlice(t *testing.T) {
client, err := NewClientFromOptions(SetAddrMixed("127.0.0.1", 7656), SetDebug(true))
client, err := NewClientFromOptions(SetAddrMixed("127.0.0.1", 7656), SetDebug(false))
if err != nil {
t.Fatalf("NewClientFromOptions() Error: %q\n", err)
}
@ -102,13 +102,13 @@ func TestOptionAddrMixedSlice(t *testing.T) {
} else {
t.Log(result)
}
dest, _ := client.CreateStreamSession(client.NewID(), "")
_, err = client.CreateStreamSession("")
if err := client.Close(); err != nil {
t.Fatalf("client.Close() Error: %q\n", err)
}
fmt.Printf("\t destination- %s \n", dest)
fmt.Printf("\t address64- %s \t", client.Base64())
fmt.Printf("\t address- %s \t", client.Base32())
/* fmt.Printf("\t destination- %s \n", dest)
fmt.Printf("\t address64- %s \t", client.Base64())
fmt.Printf("\t address- %s \t", client.Base32())*/
}
func TestOptionHost(t *testing.T) {
@ -124,7 +124,7 @@ func TestOptionHost(t *testing.T) {
SetInBackups(2),
SetOutBackups(2),
SetEncrypt(true),
SetDebug(true),
SetDebug(false),
SetUnpublished(true),
SetReduceIdle(true),
SetReduceIdleTime(300001),
@ -140,13 +140,13 @@ func TestOptionHost(t *testing.T) {
} else {
t.Log(result)
}
dest, _ := client.CreateStreamSession(client.NewID(), "")
_, err = client.CreateStreamSession("")
if err := client.Close(); err != nil {
t.Fatalf("client.Close() Error: %q\n", err)
}
fmt.Printf("\t destination- %s \n", dest)
fmt.Printf("\t address64- %s \t", client.Base64())
fmt.Printf("\t address- %s \t", client.Base32())
/* fmt.Printf("\t destination- %s \n", dest)
fmt.Printf("\t address64- %s \t", client.Base64())
fmt.Printf("\t address- %s \t", client.Base32())*/
}
func TestOptionPortInt(t *testing.T) {
@ -162,7 +162,7 @@ func TestOptionPortInt(t *testing.T) {
SetInBackups(2),
SetOutBackups(2),
SetEncrypt(true),
SetDebug(true),
SetDebug(false),
SetUnpublished(true),
SetReduceIdle(true),
SetReduceIdleTime(300001),
@ -178,11 +178,11 @@ func TestOptionPortInt(t *testing.T) {
} else {
t.Log(result)
}
dest, _ := client.CreateStreamSession(client.NewID(), "")
_, err = client.CreateStreamSession("")
if err := client.Close(); err != nil {
t.Fatalf("client.Close() Error: %q\n", err)
}
fmt.Printf("\t destination- %s \n", dest)
fmt.Printf("\t address64- %s \t", client.Base64())
fmt.Printf("\t address- %s \t", client.Base32())
/* fmt.Printf("\t destination- %s \n", dest)
fmt.Printf("\t address64- %s \t", client.Base64())
fmt.Printf("\t address- %s \t", client.Base32())*/
}

1
raw.go Normal file
View File

@ -0,0 +1 @@
package goSam

View File

@ -11,16 +11,17 @@ func init() {
rand.Seed(time.Now().UnixNano())
}
// CreateStreamSession creates a new STREAM Session.
// CreateSession creates a new STREAM Session.
// Returns the Id for the new Client.
func (c *Client) CreateStreamSession(id int32, dest string) (string, error) {
func (c *Client) CreateSession(style, dest string) (string, error) {
if dest == "" {
dest = "TRANSIENT"
}
c.id = id
// c.id = id
r, err := c.sendCmd(
"SESSION CREATE STYLE=STREAM ID=%d DESTINATION=%s %s %s %s %s \n",
c.id,
"SESSION CREATE STYLE=%s ID=%s DESTINATION=%s %s %s %s %s \n",
style,
c.ID(),
dest,
c.from(),
c.to(),
@ -43,3 +44,21 @@ func (c *Client) CreateStreamSession(id int32, dest string) (string, error) {
c.destination = r.Pairs["DESTINATION"]
return c.destination, nil
}
// CreateStreamSession creates a new STREAM Session.
// Returns the Id for the new Client.
func (c *Client) CreateStreamSession(dest string) (string, error) {
return c.CreateSession("STREAM", dest)
}
// CreateDatagramSession creates a new DATAGRAM Session.
// Returns the Id for the new Client.
func (c *Client) CreateDatagramSession(dest string) (string, error) {
return c.CreateSession("DATAGRAM", dest)
}
// CreateRawSession creates a new RAW Session.
// Returns the Id for the new Client.
func (c *Client) CreateRawSession(dest string) (string, error) {
return c.CreateSession("RAW", dest)
}

View File

@ -5,11 +5,11 @@ import (
)
// StreamConnect asks SAM for a TCP-Like connection to dest, has to be called on a new Client
func (c *Client) StreamConnect(id int32, dest string) error {
func (c *Client) StreamConnect(dest string) error {
if dest == "" {
return nil
}
r, err := c.sendCmd("STREAM CONNECT ID=%d DESTINATION=%s %s %s\n", id, dest, c.from(), c.to())
r, err := c.sendCmd("STREAM CONNECT ID=%s DESTINATION=%s %s %s\n", c.ID(), dest, c.from(), c.to())
if err != nil {
return err
}
@ -28,8 +28,8 @@ func (c *Client) StreamConnect(id int32, dest string) error {
}
// StreamAccept asks SAM to accept a TCP-Like connection
func (c *Client) StreamAccept(id int32) (*Reply, error) {
r, err := c.sendCmd("STREAM ACCEPT ID=%d SILENT=false\n", id)
func (c *Client) StreamAccept() (*Reply, error) {
r, err := c.sendCmd("STREAM ACCEPT ID=%s SILENT=false\n", c.ID())
if err != nil {
return nil, err
}