14 Commits

Author SHA1 Message Date
idk
1fc3dc5a20 Force SetDebug true 2022-02-02 00:44:08 -05:00
idk
a2fcfb8bc1 Fix issue where the control socket should not be used as a streamsession 2022-02-02 00:40:01 -05:00
idk
0623ed8a79 Fix issue where the control socket should not be used as a streamsession 2022-02-01 23:27:28 -05:00
idk
964219c25f Disable datagram support in the dialer function until it's ready, so I can cut a release tonight. 2022-02-01 21:50:35 -05:00
idk
23c45022b3 tests should run in debug mode. Don't attempt to hot-restore SAM sessions by replacing the net.Conn parts inside if they go down, just let it die and tell the user to restart. 2022-02-01 20:03:13 -05:00
idk
c6d9c0e340 protect the dialer with a mutex 2021-04-15 19:16:11 -04:00
idk
460926afe8 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.
2021-04-15 14:24:56 -07:00
idk
e278de3a66 Fix a bunch of errors that could potentially happen because of changes I made to the Dialer 2021-04-15 17:21:41 -04:00
idk
d1d2663c42 Add session creation commands for datagrams and raw sessions, stub out a repliable datagram dialer, add a DatagramConn interface that implements both net.Conn and net.PacketConn so that Dial can return a whole DatagramConn 2021-02-24 23:08:19 -05:00
idk
5af3086205 Add session creation commands for datagrams and raw sessions, stub out a repliable datagram dialer, add a DatagramConn interface that implements both net.Conn and net.PacketConn so that Dial can return a whole DatagramConn 2021-02-24 23:04:55 -05:00
idk
f97683379f make a version which stringifies i2pkeys 2021-01-22 16:18:17 -05:00
idk
42d542dd8b make a version which stringifies i2pkeys 2021-01-22 16:18:13 -05:00
idk
d94d9c4da0 make a version which stringifies i2pkeys 2021-01-22 16:17:35 -05:00
idk
dddd8ea916 make a version which stringifies i2pkeys 2021-01-22 16:10:24 -05:00
15 changed files with 215 additions and 122 deletions

View File

@@ -1,6 +1,6 @@
USER_GH=eyedeekay USER_GH=eyedeekay
VERSION=0.32.30 VERSION=0.32.52
packagename=gosam packagename=gosam
echo: fmt echo: fmt

View File

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

View File

@@ -11,8 +11,10 @@ import (
"math/rand" "math/rand"
"net" "net"
"strings" "strings"
// "sync" "sync"
"time" "time"
samkeys "github.com/eyedeekay/goSam/compat"
) )
// A Client represents a single Connection to the SAM bridge // A Client represents a single Connection to the SAM bridge
@@ -22,8 +24,10 @@ type Client struct {
fromport string fromport string
toport string toport string
SamConn net.Conn SamConn net.Conn // Control socket
rd *bufio.Reader SamDGConn DatagramConn // Datagram socket
rd *bufio.Reader
// d *Client
sigType string sigType string
destination string destination string
@@ -52,12 +56,14 @@ type Client struct {
compression bool compression bool
debug bool debug bool
mutex sync.Mutex
//NEVER, EVER modify lastaddr or id yourself. They are used internally only. //NEVER, EVER modify lastaddr or id yourself. They are used internally only.
id int32 id int32
sammin int sammin int
sammax int sammax int
} }
// SAMsigTypes is a slice of the available signature types
var SAMsigTypes = []string{ var SAMsigTypes = []string{
"SIGNATURE_TYPE=DSA_SHA1", "SIGNATURE_TYPE=DSA_SHA1",
"SIGNATURE_TYPE=ECDSA_SHA256_P256", "SIGNATURE_TYPE=ECDSA_SHA256_P256",
@@ -87,10 +93,16 @@ func NewClient(addr string) (*Client, error) {
return NewClientFromOptions(SetAddr(addr)) return NewClientFromOptions(SetAddr(addr))
} }
func NewID() int32 {
id := rand.Int31n(math.MaxInt32)
fmt.Printf("Initializing new ID: %d\n", id)
return id
}
// NewID generates a random number to use as an tunnel name // NewID generates a random number to use as an tunnel name
func (c *Client) NewID() int32 { func (c *Client) NewID() int32 {
if c.id == 0 { if c.id == 0 {
c.id = rand.Int31n(math.MaxInt32) c.id = NewID()
} }
return c.id return c.id
} }
@@ -176,12 +188,22 @@ func NewClientFromOptions(opts ...func(*Client) error) (*Client, error) {
return &c, c.hello() return &c, c.hello()
} }
// ID returns a the current ID of the client as a string
func (p *Client) ID() string { func (p *Client) ID() string {
return fmt.Sprintf("%d", p.id) return fmt.Sprintf("%d", p.NewID())
} }
// Addr returns the address of the client as a net.Addr
func (p *Client) Addr() net.Addr { func (p *Client) Addr() net.Addr {
return nil keys, err := samkeys.DestToKeys(p.Destination())
if err != nil {
return nil
}
return keys.Addr()
}
func (p *Client) LocalAddr() net.Addr {
return p.Addr()
} }
//return the combined host:port of the SAM bridge //return the combined host:port of the SAM bridge

View File

@@ -1,3 +1,4 @@
//go:build nettest
// +build nettest // +build nettest
package goSam package goSam
@@ -6,6 +7,8 @@ import "testing"
import ( import (
"fmt" "fmt"
"math"
"math/rand"
"time" "time"
//"log" //"log"
"net/http" "net/http"
@@ -18,94 +21,96 @@ func HelloServer(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:]) 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) { 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 { if err != nil {
t.Fatalf("Listener() Error: %q\n", err) t.Fatalf("Listener() Error: %q\n", err)
} }
defer listener.Close()
http.HandleFunc("/", HelloServer) http.HandleFunc("/", HelloServer)
go http.Serve(listener, nil) 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 { if err != nil {
t.Fatalf("Listener() Error: %q\n", err) t.Fatalf("Listener() Error: %q\n", err)
} }
defer listener2.Close()
// http.HandleFunc("/", HelloServer) // http.HandleFunc("/", HelloServer)
go http.Serve(listener2, nil) 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 { if err != nil {
t.Fatalf("Listener() Error: %q\n", err) t.Fatalf("Listener() Error: %q\n", err)
} }
defer listener3.Close()
// http.HandleFunc("/", HelloServer) // http.HandleFunc("/", HelloServer)
go http.Serve(listener3, nil) go http.Serve(listener3, nil)
client, err = NewClientFromOptions(SetDebug(true)) sam, err := NewClientFromOptions(SetDebug(false))
if err != nil { if err != nil {
t.Fatalf("NewDefaultClient() Error: %q\n", err) t.Fatalf("NewDefaultClient() Error: %q\n", err)
} }
tr := &http.Transport{ tr := &http.Transport{
Dial: client.Dial, Dial: sam.Dial,
} }
client := &http.Client{Transport: tr} client := &http.Client{Transport: tr}
time.Sleep(time.Second * 30) defer sam.Close()
x := 0
for x < 15 {
time.Sleep(time.Second * 2)
t.Log("waiting a little while for services to register", (30 - (x * 2)))
x++
}
go func() { go func() {
resp, err := client.Get("http://" + listener.Addr().(i2pkeys.I2PAddr).Base32()) resp, err := client.Get("http://" + listener.Addr().(i2pkeys.I2PAddr).Base32())
if err != nil { if err != nil {
t.Fatalf("Get Error: %q\n", err) t.Fatalf("Get Error test 1: %q\n", err)
} }
defer resp.Body.Close() defer resp.Body.Close()
t.Log("Get returned ", resp)
}() }()
//time.Sleep(time.Second * 15)
go func() { go func() {
resp, err := client.Get("http://" + listener2.Addr().(i2pkeys.I2PAddr).Base32()) resp, err := client.Get("http://" + listener2.Addr().(i2pkeys.I2PAddr).Base32())
if err != nil { if err != nil {
t.Fatalf("Get Error: %q\n", err) t.Fatalf("Get Error test 2: %q\n", err)
} }
defer resp.Body.Close() defer resp.Body.Close()
t.Log("Get returned ", resp)
}() }()
//time.Sleep(time.Second * 15)
go func() { go func() {
resp, err := client.Get("http://" + listener3.Addr().(i2pkeys.I2PAddr).Base32()) resp, err := client.Get("http://" + listener3.Addr().(i2pkeys.I2PAddr).Base32())
if err != nil { if err != nil {
t.Fatalf("Get Error: %q\n", err) t.Fatalf("Get Error test 3: %q\n", err)
} }
defer resp.Body.Close() 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 { if err := client.Close(); err != nil {
t.Fatalf("client.Close() Error: %q\n", err) 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) { func TestNewDestination(t *testing.T) {
setup(t) client, err := NewClientFromOptions(SetDebug(false))
t.Log(client.Base32()) if err != nil {
if _, err := client.NewDestination(SAMsigTypes[3]); err != nil { t.Fatalf("NewDefaultClient() Error: %q\n", err)
t.Error(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)
} }

View File

@@ -30,11 +30,14 @@ import (
"time" "time"
) )
// Conn Read data from the connection, writes data to te connection
// and logs the data in-between.
type Conn struct { type Conn struct {
RWC RWC
conn net.Conn conn net.Conn
} }
// WrapConn wraps a net.Conn in a Conn.
func WrapConn(c net.Conn) *Conn { func WrapConn(c net.Conn) *Conn {
wrap := Conn{ wrap := Conn{
conn: c, conn: c,
@@ -45,23 +48,29 @@ func WrapConn(c net.Conn) *Conn {
return &wrap return &wrap
} }
// LocalAddr returns the local address of the connection.
func (c *Conn) LocalAddr() net.Addr { func (c *Conn) LocalAddr() net.Addr {
return c.conn.LocalAddr() return c.conn.LocalAddr()
} }
// RemoteAddr returns the remote address of the connection.
func (c *Conn) RemoteAddr() net.Addr { func (c *Conn) RemoteAddr() net.Addr {
return c.conn.RemoteAddr() return c.conn.RemoteAddr()
} }
// SetDeadline sets the read and write deadlines associated with the connection
func (c *Conn) SetDeadline(t time.Time) error { func (c *Conn) SetDeadline(t time.Time) error {
log.Println("WARNING: SetDeadline() not sure this works") log.Println("WARNING: SetDeadline() not sure this works")
return c.conn.SetDeadline(t) return c.conn.SetDeadline(t)
} }
// SetReadDeadline sets the read deadline associated with the connection
func (c *Conn) SetReadDeadline(t time.Time) error { func (c *Conn) SetReadDeadline(t time.Time) error {
log.Println("WARNING: SetReadDeadline() not sure this works") log.Println("WARNING: SetReadDeadline() not sure this works")
return c.conn.SetReadDeadline(t) return c.conn.SetReadDeadline(t)
} }
// SetWriteDeadline sets the write deadline associated with the connection
func (c *Conn) SetWriteDeadline(t time.Time) error { func (c *Conn) SetWriteDeadline(t time.Time) error {
log.Println("WARNING: SetWriteDeadline() not sure this works") log.Println("WARNING: SetWriteDeadline() not sure this works")
return c.conn.SetWriteDeadline(t) return c.conn.SetWriteDeadline(t)

25
datagram.go Normal file
View File

@@ -0,0 +1,25 @@
package goSam
import (
"net"
"time"
)
// DatagramConn
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
}
/**
* When datagram support is finished, this will compile.
* var conn DatagramConn = &Client{}
**/

51
dial.go
View File

@@ -2,6 +2,7 @@ package goSam
import ( import (
"context" "context"
"fmt"
"log" "log"
"net" "net"
"strings" "strings"
@@ -9,6 +10,8 @@ import (
// DialContext implements the net.DialContext function and can be used for http.Transport // DialContext implements the net.DialContext function and can be used for http.Transport
func (c *Client) DialContext(ctx context.Context, network, addr string) (net.Conn, error) { func (c *Client) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
c.mutex.Lock()
defer c.mutex.Unlock()
errCh := make(chan error, 1) errCh := make(chan error, 1)
connCh := make(chan net.Conn, 1) connCh := make(chan net.Conn, 1)
go func() { go func() {
@@ -29,6 +32,7 @@ func (c *Client) DialContext(ctx context.Context, network, addr string) (net.Con
case <-ctx.Done(): case <-ctx.Done():
return nil, ctx.Err() return nil, ctx.Err()
} }
} }
func (c *Client) Dial(network, addr string) (net.Conn, error) { func (c *Client) Dial(network, addr string) (net.Conn, error) {
@@ -37,6 +41,25 @@ func (c *Client) Dial(network, addr string) (net.Conn, error) {
// Dial implements the net.Dial function and can be used for http.Transport // Dial implements the net.Dial function and can be used for http.Transport
func (c *Client) DialContextFree(network, addr string) (net.Conn, error) { 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)
}
// DialDatagramContextFree is a "Dialer" for "Client-Like" Datagram connections.
// It is also not finished. If you need datagram support right now, use sam3.
func (c *Client) DialDatagramContextFree(addr string) (DatagramConn, error) {
return nil, fmt.Errorf("Datagram support is not finished yet, come back later`")
}
func (c *Client) DialStreamingContextFree(addr string) (net.Conn, error) {
portIdx := strings.Index(addr, ":") portIdx := strings.Index(addr, ":")
if portIdx >= 0 { if portIdx >= 0 {
addr = addr[:portIdx] addr = addr[:portIdx]
@@ -47,36 +70,20 @@ func (c *Client) DialContextFree(network, addr string) (net.Conn, error) {
return nil, err return nil, err
} }
c.destination, err = c.CreateStreamSession(c.id, c.destination) if c.destination == "" {
if err != nil { c.destination, err = c.CreateStreamSession(c.destination)
c.Close()
d, err := c.NewClient(c.id + 1) /**/
if err != nil { if err != nil {
return nil, err 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 { if err != nil {
return nil, err return nil, err
} }
err = c.StreamConnect(c.id, addr) err = d.StreamConnect(addr)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return c.SamConn, nil return d.SamConn, nil
} }

View File

@@ -2,17 +2,14 @@ package goSam
import ( import (
"errors" "errors"
"github.com/eyedeekay/sam3/i2pkeys"
) )
// NewDestination generates a new I2P destination, creating the underlying // NewDestination generates a new I2P destination, creating the underlying
// public/private keys in the process. The public key can be used to send messages // 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 // 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 ( var (
sigtmp string sigtmp string
keys i2pkeys.I2PKeys
) )
if len(sigType) > 0 { if len(sigType) > 0 {
sigtmp = sigType[0] sigtmp = sigType[0]
@@ -22,14 +19,14 @@ func (c *Client) NewDestination(sigType ...string) (i2pkeys.I2PKeys, error) {
sigtmp, sigtmp,
) )
if err != nil { if err != nil {
return keys, err return "", "", err
} }
var pub, priv string var pub, priv string
if priv = r.Pairs["PRIV"]; priv == "" { 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 == "" { 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() // TODO: move check into sendCmd()
if r.Topic != "NAMING" || r.Type != "REPLY" { 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"] result := r.Pairs["RESULT"]

View File

@@ -1,3 +1,4 @@
//go:build nettest
// +build nettest // +build nettest
package goSam package goSam
@@ -10,8 +11,10 @@ import (
func TestClientLookupInvalid(t *testing.T) { func TestClientLookupInvalid(t *testing.T) {
var err error var err error
setup(t) client, err := NewClientFromOptions(SetDebug(false))
defer teardown(t) if err != nil {
t.Fatalf("NewDefaultClient() Error: %q\n", err)
}
addr, err := client.Lookup(`!(@#)`) addr, err := client.Lookup(`!(@#)`)
if addr != "" || err == nil { if addr != "" || err == nil {
@@ -25,6 +28,9 @@ func TestClientLookupInvalid(t *testing.T) {
if repErr.Result != ResultKeyNotFound { if repErr.Result != ResultKeyNotFound {
t.Errorf("client.Lookup() should throw an ResultKeyNotFound error.\nGot:%+v%s%s\n", repErr, "!=", 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) { func TestClientLookupValid(t *testing.T) {

View File

@@ -185,7 +185,8 @@ func SetToPortInt(i int) func(*Client) error {
//SetDebug enables debugging messages //SetDebug enables debugging messages
func SetDebug(b bool) func(*Client) error { func SetDebug(b bool) func(*Client) error {
return func(c *Client) error { return func(c *Client) error {
c.debug = b //c.debug = b
d.debug = true
return nil return nil
} }
} }

View File

@@ -1,3 +1,4 @@
//go:build nettest
// +build nettest // +build nettest
package goSam package goSam
@@ -31,12 +32,12 @@ func (c *Client) validCmd(str string, args ...interface{}) (string, error) {
func (c *Client) validCreate() (string, error) { func (c *Client) validCreate() (string, error) {
id := rand.Int31n(math.MaxInt32) 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 return result, err
} }
func TestOptionAddrString(t *testing.T) { 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 { if err != nil {
t.Fatalf("NewClientFromOptions() Error: %q\n", err) t.Fatalf("NewClientFromOptions() Error: %q\n", err)
} }
@@ -45,17 +46,17 @@ func TestOptionAddrString(t *testing.T) {
} else { } else {
t.Log(result) t.Log(result)
} }
dest, _ := client.CreateStreamSession(client.NewID(), "") _, err = client.CreateStreamSession("")
if err := client.Close(); err != nil { if err := client.Close(); err != nil {
t.Fatalf("client.Close() Error: %q\n", err) t.Fatalf("client.Close() Error: %q\n", err)
} }
fmt.Printf("\t destination- %s \n", dest) /* fmt.Printf("\t destination- %s \n", dest)
fmt.Printf("\t address64- %s \t", client.Base64()) fmt.Printf("\t address64- %s \t", client.Base64())
fmt.Printf("\t address- %s \t", client.Base32()) fmt.Printf("\t address- %s \t", client.Base32())*/
} }
func TestOptionAddrStringLh(t *testing.T) { func TestOptionAddrStringLh(t *testing.T) {
client, err := NewClientFromOptions(SetAddr("localhost:7656"), SetDebug(true)) client, err := NewClientFromOptions(SetAddr("localhost:7656"), SetDebug(false))
if err != nil { if err != nil {
t.Fatalf("NewClientFromOptions() Error: %q\n", err) t.Fatalf("NewClientFromOptions() Error: %q\n", err)
} }
@@ -64,17 +65,17 @@ func TestOptionAddrStringLh(t *testing.T) {
} else { } else {
t.Log(result) t.Log(result)
} }
dest, _ := client.CreateStreamSession(client.NewID(), "") _, err = client.CreateStreamSession("")
if err := client.Close(); err != nil { if err := client.Close(); err != nil {
t.Fatalf("client.Close() Error: %q\n", err) t.Fatalf("client.Close() Error: %q\n", err)
} }
fmt.Printf("\t destination- %s \n", dest) /* fmt.Printf("\t destination- %s \n", dest)
fmt.Printf("\t address64- %s \t", client.Base64()) fmt.Printf("\t address64- %s \t", client.Base64())
fmt.Printf("\t address- %s \t", client.Base32()) fmt.Printf("\t address- %s \t", client.Base32())*/
} }
func TestOptionAddrSlice(t *testing.T) { 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 { if err != nil {
t.Fatalf("NewClientFromOptions() Error: %q\n", err) t.Fatalf("NewClientFromOptions() Error: %q\n", err)
} }
@@ -83,17 +84,17 @@ func TestOptionAddrSlice(t *testing.T) {
} else { } else {
t.Log(result) t.Log(result)
} }
dest, _ := client.CreateStreamSession(client.NewID(), "") _, err = client.CreateStreamSession("")
if err := client.Close(); err != nil { if err := client.Close(); err != nil {
t.Fatalf("client.Close() Error: %q\n", err) t.Fatalf("client.Close() Error: %q\n", err)
} }
fmt.Printf("\t destination- %s \n", dest) /* fmt.Printf("\t destination- %s \n", dest)
fmt.Printf("\t address64- %s \t", client.Base64()) fmt.Printf("\t address64- %s \t", client.Base64())
fmt.Printf("\t address- %s \t", client.Base32()) fmt.Printf("\t address- %s \t", client.Base32())*/
} }
func TestOptionAddrMixedSlice(t *testing.T) { 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 { if err != nil {
t.Fatalf("NewClientFromOptions() Error: %q\n", err) t.Fatalf("NewClientFromOptions() Error: %q\n", err)
} }
@@ -102,13 +103,13 @@ func TestOptionAddrMixedSlice(t *testing.T) {
} else { } else {
t.Log(result) t.Log(result)
} }
dest, _ := client.CreateStreamSession(client.NewID(), "") _, err = client.CreateStreamSession("")
if err := client.Close(); err != nil { if err := client.Close(); err != nil {
t.Fatalf("client.Close() Error: %q\n", err) t.Fatalf("client.Close() Error: %q\n", err)
} }
fmt.Printf("\t destination- %s \n", dest) /* fmt.Printf("\t destination- %s \n", dest)
fmt.Printf("\t address64- %s \t", client.Base64()) fmt.Printf("\t address64- %s \t", client.Base64())
fmt.Printf("\t address- %s \t", client.Base32()) fmt.Printf("\t address- %s \t", client.Base32())*/
} }
func TestOptionHost(t *testing.T) { func TestOptionHost(t *testing.T) {
@@ -124,7 +125,7 @@ func TestOptionHost(t *testing.T) {
SetInBackups(2), SetInBackups(2),
SetOutBackups(2), SetOutBackups(2),
SetEncrypt(true), SetEncrypt(true),
SetDebug(true), SetDebug(false),
SetUnpublished(true), SetUnpublished(true),
SetReduceIdle(true), SetReduceIdle(true),
SetReduceIdleTime(300001), SetReduceIdleTime(300001),
@@ -140,13 +141,13 @@ func TestOptionHost(t *testing.T) {
} else { } else {
t.Log(result) t.Log(result)
} }
dest, _ := client.CreateStreamSession(client.NewID(), "") _, err = client.CreateStreamSession("")
if err := client.Close(); err != nil { if err := client.Close(); err != nil {
t.Fatalf("client.Close() Error: %q\n", err) t.Fatalf("client.Close() Error: %q\n", err)
} }
fmt.Printf("\t destination- %s \n", dest) /* fmt.Printf("\t destination- %s \n", dest)
fmt.Printf("\t address64- %s \t", client.Base64()) fmt.Printf("\t address64- %s \t", client.Base64())
fmt.Printf("\t address- %s \t", client.Base32()) fmt.Printf("\t address- %s \t", client.Base32())*/
} }
func TestOptionPortInt(t *testing.T) { func TestOptionPortInt(t *testing.T) {
@@ -162,7 +163,7 @@ func TestOptionPortInt(t *testing.T) {
SetInBackups(2), SetInBackups(2),
SetOutBackups(2), SetOutBackups(2),
SetEncrypt(true), SetEncrypt(true),
SetDebug(true), SetDebug(false),
SetUnpublished(true), SetUnpublished(true),
SetReduceIdle(true), SetReduceIdle(true),
SetReduceIdleTime(300001), SetReduceIdleTime(300001),
@@ -178,11 +179,11 @@ func TestOptionPortInt(t *testing.T) {
} else { } else {
t.Log(result) t.Log(result)
} }
dest, _ := client.CreateStreamSession(client.NewID(), "") _, err = client.CreateStreamSession("")
if err := client.Close(); err != nil { if err := client.Close(); err != nil {
t.Fatalf("client.Close() Error: %q\n", err) t.Fatalf("client.Close() Error: %q\n", err)
} }
fmt.Printf("\t destination- %s \n", dest) /* fmt.Printf("\t destination- %s \n", dest)
fmt.Printf("\t address64- %s \t", client.Base64()) fmt.Printf("\t address64- %s \t", client.Base64())
fmt.Printf("\t address- %s \t", client.Base32()) 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,18 @@ func init() {
rand.Seed(time.Now().UnixNano()) rand.Seed(time.Now().UnixNano())
} }
// CreateStreamSession creates a new STREAM Session. // CreateSession creates a new Session of type style, with an optional destination.
// Returns the Id for the new Client. // an empty destination is interpreted as "TRANSIENT"
func (c *Client) CreateStreamSession(id int32, dest string) (string, error) { // Returns the destination for the new Client or an error.
func (c *Client) CreateSession(style, dest string) (string, error) {
if dest == "" { if dest == "" {
dest = "TRANSIENT" dest = "TRANSIENT"
} }
c.id = id // c.id = id
r, err := c.sendCmd( r, err := c.sendCmd(
"SESSION CREATE STYLE=STREAM ID=%d DESTINATION=%s %s %s %s %s \n", "SESSION CREATE STYLE=%s ID=%s DESTINATION=%s %s %s %s %s \n",
c.id, style,
c.ID(),
dest, dest,
c.from(), c.from(),
c.to(), c.to(),
@@ -43,3 +45,21 @@ func (c *Client) CreateStreamSession(id int32, dest string) (string, error) {
c.destination = r.Pairs["DESTINATION"] c.destination = r.Pairs["DESTINATION"]
return c.destination, nil 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 // 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 == "" { if dest == "" {
return nil 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 { if err != nil {
return err return err
} }
@@ -28,8 +28,8 @@ func (c *Client) StreamConnect(id int32, dest string) error {
} }
// StreamAccept asks SAM to accept a TCP-Like connection // StreamAccept asks SAM to accept a TCP-Like connection
func (c *Client) StreamAccept(id int32) (*Reply, error) { func (c *Client) StreamAccept() (*Reply, error) {
r, err := c.sendCmd("STREAM ACCEPT ID=%d SILENT=false\n", id) r, err := c.sendCmd("STREAM ACCEPT ID=%s SILENT=false\n", c.ID())
if err != nil { if err != nil {
return nil, err return nil, err
} }