Compare commits
57 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
27e7865789 | ||
![]() |
5fd5f21be6 | ||
![]() |
d8c0f81c78 | ||
![]() |
291b43dd4b | ||
![]() |
98ddd74e32 | ||
![]() |
9d4fce4593 | ||
![]() |
87a4e609bb | ||
![]() |
4830ef434a | ||
![]() |
00cba613a1 | ||
![]() |
6e0cf375b3 | ||
![]() |
802a59bd65 | ||
![]() |
c9b61b818e | ||
![]() |
f794cd513f | ||
![]() |
6f94d156ec | ||
![]() |
6ebe813d0e | ||
![]() |
4694834222 | ||
![]() |
4a105ff77e | ||
![]() |
e5c90d06eb | ||
![]() |
4b77bc4d02 | ||
![]() |
e42d89a43c | ||
![]() |
376c392d58 | ||
![]() |
88c615b411 | ||
![]() |
4a8fc1acfe | ||
![]() |
6509b803bc | ||
![]() |
49533844d6 | ||
![]() |
09c260e7e1 | ||
![]() |
503c94e7e1 | ||
![]() |
cc91ed6bf0 | ||
![]() |
5ffafcd28d | ||
![]() |
c40b3af503 | ||
![]() |
abd13ace73 | ||
![]() |
4778044200 | ||
![]() |
bf2bef0f4b | ||
![]() |
d7af8dafa9 | ||
![]() |
2e7a301855 | ||
![]() |
56cc5bd017 | ||
![]() |
a537690baa | ||
![]() |
6ea277fc47 | ||
![]() |
d3c0ff150f | ||
![]() |
34baf7bec3 | ||
![]() |
ba1f9719c2 | ||
![]() |
8de30dc68f | ||
![]() |
430fd0b0bb | ||
![]() |
7b4edecf96 | ||
![]() |
2896c839bd | ||
![]() |
c69106a879 | ||
![]() |
ca8fd03818 | ||
![]() |
186b20306e | ||
![]() |
b06ef4ccf8 | ||
![]() |
f569145156 | ||
![]() |
193ce37241 | ||
![]() |
6cd8e18295 | ||
![]() |
69655d5d86 | ||
![]() |
299080f4c2 | ||
![]() |
a57ebd8e7e | ||
![]() |
aab53e9153 | ||
![]() |
90dcde3cac |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -20,3 +20,5 @@ _cgo_export.*
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
itp-golang-github-eyedeekay-gosam.txt
|
||||
.pc
|
||||
|
195
CONTRIBUTING.md
Normal file
195
CONTRIBUTING.md
Normal file
@@ -0,0 +1,195 @@
|
||||
How to make contributions to goSam
|
||||
==================================
|
||||
|
||||
Welcome to goSam, the easy-to-use http client for i2p. We're glad you're here
|
||||
and interested in contributing. Here's some help getting started.
|
||||
|
||||
Table of Contents
|
||||
-----------------
|
||||
|
||||
* (1) Environment
|
||||
* (2) Testing
|
||||
* (3) Filing Issues/Reporting Bugs/Making Suggestions
|
||||
* (4) Contributing Code/Style Guide
|
||||
- (a) Adding i2cp and tunnel Options
|
||||
- (b) Writing Tests
|
||||
- (c) Style
|
||||
- (d) Other kinds of modification?
|
||||
* (5) Conduct
|
||||
|
||||
### (1) Environment
|
||||
|
||||
goSam is a simple go library. You are free to use an IDE if you wish, but all
|
||||
that is required to build and test the library are a go compiler and the gofmt
|
||||
tool. Git is the version control system. All the files in the library are in a
|
||||
single root directory. Invoking go build from this directory not generate any
|
||||
files.
|
||||
|
||||
### (2) Testing
|
||||
|
||||
Tests are implemented using the standard go "testing" library in files named
|
||||
"file\_test.go," so tests of the client go in client\_test.go, name lookups
|
||||
in naming\_test.go, et cetera. Everything that can be tested, should be tested.
|
||||
|
||||
Testing is done by running
|
||||
|
||||
go test
|
||||
|
||||
More information about designing tests is below in the
|
||||
**Contributing Code/Style Guide** section below.
|
||||
|
||||
### (3) Filing issues/Reporting bugs/Making suggestions
|
||||
|
||||
If you discover the library doing something you don't think is right, please let
|
||||
us know! Just filing an issue here is OK.
|
||||
|
||||
If you need to suggest a feature, we're happy to hear from you too. Filing an
|
||||
issue will give us a place to discuss how it's implemented openly and publicly.
|
||||
|
||||
Please file an issue for your new code contributions in order to provide us with
|
||||
a place to discuss them for inclusion.
|
||||
|
||||
### (4) Contributing Code/Style Guide
|
||||
|
||||
Welcome new coders. We have good news for you, this library is really easy to
|
||||
contribute to. The easiest contributions take the form of i2cp and tunnel
|
||||
options.
|
||||
|
||||
#### (a) Adding i2cp and tunnel Options
|
||||
|
||||
First, add a variable to store the state of your new option. For example, the
|
||||
existing variables are in the Client class [here:](https://github.com/cryptix/goSam/blob/701d7fcf03ddb354262fe213163dcf6f202a24f1/client.go#L29)
|
||||
|
||||
i2cp and tunnel options are added in a highly uniform process of basically three
|
||||
steps. First, you create a functional argument in the options.go file, in the
|
||||
form:
|
||||
|
||||
``` Go
|
||||
// SetOPTION sets $OPTION
|
||||
func SetOPTION(arg type) func(*Client) error { // arg type
|
||||
return func(c *Client) error { // pass a client to the inner function and declare error return function
|
||||
if arg == valid { // validate the argument
|
||||
c.option = s // set the variable to the argument value
|
||||
return nil // if option is set successfully return nil error
|
||||
}
|
||||
return fmt.Errorf("Invalid argument:" arg) // return a descriptive error if arg is invalid
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
[example](https://github.com/cryptix/goSam/blob/701d7fcf03ddb354262fe213163dcf6f202a24f1/options.go#L187)
|
||||
|
||||
Next, you create a getter which prepares the option. Regardless of the type of
|
||||
option that is set, these must return strings representing valid i2cp options.
|
||||
|
||||
``` Go
|
||||
//return the OPTION as a string.
|
||||
func (c *Client) option() string {
|
||||
return fmt.Sprintf("i2cp.option=%d", c.option)
|
||||
}
|
||||
```
|
||||
|
||||
[example](https://github.com/cryptix/goSam/blob/701d7fcf03ddb354262fe213163dcf6f202a24f1/options.go#L299)
|
||||
|
||||
Lastly, you'll need to add it to the allOptions function and the
|
||||
Client.NewClient() function. To add it to allOptions, it looks like this:
|
||||
|
||||
``` Go
|
||||
//return all options as string ready for passing to sendcmd
|
||||
func (c *Client) allOptions() string {
|
||||
return c.inlength() + " " +
|
||||
c.outlength() + " " +
|
||||
... //other options removed from example for brevity
|
||||
c.option()
|
||||
}
|
||||
```
|
||||
|
||||
``` Go
|
||||
//return all options as string ready for passing to sendcmd
|
||||
func (c *Client) NewClient() (*Client, error) {
|
||||
return NewClientFromOptions(
|
||||
SetHost(c.host),
|
||||
SetPort(c.port),
|
||||
... //other options removed from example for brevity
|
||||
SetCompression(c.compression),
|
||||
setlastaddr(c.lastaddr),
|
||||
setid(c.id),
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
[example](https://github.com/cryptix/goSam/blob/701d7fcf03ddb354262fe213163dcf6f202a24f1/options.go#L333)
|
||||
|
||||
#### (b) Writing Tests
|
||||
|
||||
Before the feature can be added, you'll need to add a test for it to
|
||||
options_test.go. To do this, just add your new option to the long TestOptions
|
||||
functions in options_test.go.
|
||||
|
||||
``` Go
|
||||
func TestOptionHost(t *testing.T) {
|
||||
client, err := NewClientFromOptions(
|
||||
SetHost("127.0.0.1"),
|
||||
SetPort("7656"),
|
||||
... //other options removed from example for brevity
|
||||
SetCloseIdleTime(300001),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("NewClientFromOptions() Error: %q\n", err)
|
||||
}
|
||||
if result, err := client.validCreate(); err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
} else {
|
||||
t.Log(result)
|
||||
}
|
||||
client.CreateStreamSession("")
|
||||
if err := client.Close(); err != nil {
|
||||
t.Fatalf("client.Close() Error: %q\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOptionPortInt(t *testing.T) {
|
||||
client, err := NewClientFromOptions(
|
||||
SetHost("127.0.0.1"),
|
||||
SetPortInt(7656),
|
||||
... //other options removed from example for brevity
|
||||
SetUnpublished(true),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("NewClientFromOptions() Error: %q\n", err)
|
||||
}
|
||||
if result, err := client.validCreate(); err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
} else {
|
||||
t.Log(result)
|
||||
}
|
||||
client.CreateStreamSession("")
|
||||
if err := client.Close(); err != nil {
|
||||
t.Fatalf("client.Close() Error: %q\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
If any of these tasks fail, then the test should fail.
|
||||
|
||||
#### (c) Style
|
||||
|
||||
It's pretty simple to make sure the code style is right, just run gofmt over it
|
||||
to adjust the indentation, and golint over it to ensure that your comments are
|
||||
of the correct form for the documentation generator.
|
||||
|
||||
#### (d) Other kinds of modification?
|
||||
|
||||
It may be useful to extend goSam in other ways. Since there's not a
|
||||
one-size-fits-all uniform way of dealing with these kinds of changes, open an
|
||||
issue for discussion and
|
||||
|
||||
### (5) Conduct
|
||||
|
||||
This is a small-ish, straightforward library intended to enable a clear
|
||||
technical task. We should be able to be civil with eachother, and give and
|
||||
accept criticism contructively and respectfully.
|
||||
|
||||
This document was drawn from the examples given by Mozilla
|
||||
[here](mozillascience.github.io/working-open-workshop/contributing/)
|
26
README.md
26
README.md
@@ -1,13 +1,16 @@
|
||||
goSam
|
||||
=====
|
||||
|
||||
A go library for using the [I2P](https://geti2p.net/en/) Simple Anonymous Messaging ([SAM version 3.0](https://geti2p.net/en/docs/api/samv3)) bridge
|
||||
A go library for using the [I2P](https://geti2p.net/en/) Simple Anonymous
|
||||
Messaging ([SAM version 3.0](https://geti2p.net/en/docs/api/samv3)) bridge. It
|
||||
has support for SAM version 3.1 signature types.
|
||||
|
||||
This is in an **early development stage**. I would love to hear about any issues or ideas for improvement.
|
||||
This is in an **early development stage**. I would love to hear about any
|
||||
issues or ideas for improvement.
|
||||
|
||||
## Installation
|
||||
```
|
||||
go get github.com/cryptix/goSam
|
||||
go get github.com/eyedeekay/goSam
|
||||
```
|
||||
|
||||
## Using it for HTTP Transport
|
||||
@@ -67,7 +70,22 @@ func checkErr(err error) {
|
||||
}
|
||||
```
|
||||
|
||||
### .deb package
|
||||
|
||||
A package for installing this on Debian is buildable, and a version for Ubuntu
|
||||
is available as a PPA and mirrored via i2p. To build the deb package, from the
|
||||
root of this repository with the build dependencies installed(git, i2p, go,
|
||||
debuild) run the command
|
||||
|
||||
debuild -us -uc
|
||||
|
||||
to produce an unsigned deb for personal use only. For packagers,
|
||||
|
||||
debuild -S
|
||||
|
||||
will produce a viable source package for use with Launchpad PPA's and other
|
||||
similar systems.
|
||||
### TODO
|
||||
|
||||
* Implement `STREAM ACCEPT` and `STREAM FORWARD`
|
||||
* Implement datagrams (Repliable and Anon)
|
||||
* Implement datagrams (Repliable and Anon)
|
||||
|
47
accept.go
47
accept.go
@@ -4,33 +4,62 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/cryptix/go/debug"
|
||||
"github.com/eyedeekay/goSam/debug"
|
||||
)
|
||||
|
||||
// Accept creates a new Client and accepts a connection on it
|
||||
func (c *Client) Accept() (net.Conn, error) {
|
||||
id, newAddr, err := c.CreateStreamSession("")
|
||||
// AcceptI2P creates a new Client and accepts a connection on it
|
||||
func (c *Client) AcceptI2P() (net.Conn, error) {
|
||||
listener, err := c.Listen()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return listener.Accept()
|
||||
}
|
||||
|
||||
// Listen creates a new Client and returns a net.listener which *must* be started
|
||||
// with Accept
|
||||
func (c *Client) Listen() (net.Listener, error) {
|
||||
return c.ListenI2P(c.destination)
|
||||
}
|
||||
|
||||
// ListenI2P creates a new Client and returns a net.listener which *must* be started
|
||||
// with Accept
|
||||
func (c *Client) ListenI2P(dest string) (net.Listener, error) {
|
||||
var err error
|
||||
var id int32
|
||||
c.id = c.NewID()
|
||||
c.destination, err = c.CreateStreamSession(id, dest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fmt.Println("NewAddr:", newAddr)
|
||||
fmt.Println("destination:", c.destination)
|
||||
|
||||
newC, err := NewDefaultClient()
|
||||
c, err = c.NewClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if c.debug {
|
||||
newC.SamConn = debug.WrapConn(newC.SamConn)
|
||||
c.SamConn = debug.WrapConn(c.SamConn)
|
||||
}
|
||||
|
||||
resp, err := newC.StreamAccept(id)
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// Accept accepts a connection on a listening goSam.Client(Implements net.Listener)
|
||||
// or, if the connection isn't listening yet, just calls AcceptI2P for compatibility
|
||||
// with older versions.
|
||||
func (c *Client) Accept() (net.Conn, error) {
|
||||
if c.id == 0 {
|
||||
return c.AcceptI2P()
|
||||
}
|
||||
resp, err := c.StreamAccept(c.id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fmt.Println("Accept Resp:", resp)
|
||||
|
||||
return newC.SamConn, nil
|
||||
return c.SamConn, nil
|
||||
}
|
||||
|
122
client.go
122
client.go
@@ -2,20 +2,32 @@ package goSam
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto/sha256"
|
||||
"encoding/base32"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/rand"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"github.com/cryptix/go/debug"
|
||||
"github.com/eyedeekay/goSam/debug"
|
||||
)
|
||||
|
||||
// A Client represents a single Connection to the SAM bridge
|
||||
type Client struct {
|
||||
host string
|
||||
port string
|
||||
host string
|
||||
port string
|
||||
fromport string
|
||||
toport string
|
||||
|
||||
SamConn net.Conn
|
||||
rd *bufio.Reader
|
||||
|
||||
sigType string
|
||||
destination string
|
||||
|
||||
inLength uint
|
||||
inVariance int
|
||||
inQuantity uint
|
||||
@@ -36,9 +48,27 @@ type Client struct {
|
||||
closeIdle bool
|
||||
closeIdleTime uint
|
||||
|
||||
compression bool
|
||||
|
||||
debug bool
|
||||
//NEVER, EVER modify lastaddr or id yourself. They are used internally only.
|
||||
lastaddr string
|
||||
id int32
|
||||
}
|
||||
|
||||
var SAMsigTypes = []string{
|
||||
"SIGNATURE_TYPE=DSA_SHA1",
|
||||
"SIGNATURE_TYPE=ECDSA_SHA256_P256",
|
||||
"SIGNATURE_TYPE=ECDSA_SHA384_P384",
|
||||
"SIGNATURE_TYPE=ECDSA_SHA512_P521",
|
||||
"SIGNATURE_TYPE=EdDSA_SHA512_Ed25519",
|
||||
}
|
||||
|
||||
var (
|
||||
i2pB64enc *base64.Encoding = base64.NewEncoding("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-~")
|
||||
i2pB32enc *base32.Encoding = base32.NewEncoding("abcdefghijklmnopqrstuvwxyz234567")
|
||||
)
|
||||
|
||||
// NewDefaultClient creates a new client, connecting to the default host:port at localhost:7656
|
||||
func NewDefaultClient() (*Client, error) {
|
||||
return NewClient("localhost:7656")
|
||||
@@ -49,6 +79,41 @@ func NewClient(addr string) (*Client, error) {
|
||||
return NewClientFromOptions(SetAddr(addr))
|
||||
}
|
||||
|
||||
// NewID generates a random number to use as an tunnel name
|
||||
func (c *Client) NewID() int32 {
|
||||
return rand.Int31n(math.MaxInt32)
|
||||
}
|
||||
|
||||
// Destination returns the full destination of the local tunnel
|
||||
func (c *Client) Destination() string {
|
||||
return c.destination
|
||||
}
|
||||
|
||||
// Base32 returns the base32 of the local tunnel
|
||||
func (c *Client) Base32() string {
|
||||
hash := sha256.New()
|
||||
b64, err := i2pB64enc.DecodeString(c.Base64())
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
hash.Write([]byte(b64))
|
||||
return strings.ToLower(strings.Replace(i2pB32enc.EncodeToString(hash.Sum(nil)), "=", "", -1))
|
||||
}
|
||||
|
||||
func (c *Client) base64() []byte {
|
||||
if c.destination != "" {
|
||||
s, _ := i2pB64enc.DecodeString(c.destination)
|
||||
alen := binary.BigEndian.Uint16(s[385:387])
|
||||
return s[:387+alen]
|
||||
}
|
||||
return []byte("")
|
||||
}
|
||||
|
||||
// Base64 returns the base64 of the local tunnel
|
||||
func (c *Client) Base64() string {
|
||||
return i2pB64enc.EncodeToString(c.base64())
|
||||
}
|
||||
|
||||
// NewClientFromOptions creates a new client, connecting to a specified port
|
||||
func NewClientFromOptions(opts ...func(*Client) error) (*Client, error) {
|
||||
var c Client
|
||||
@@ -56,20 +121,24 @@ func NewClientFromOptions(opts ...func(*Client) error) (*Client, error) {
|
||||
c.port = "7656"
|
||||
c.inLength = 3
|
||||
c.inVariance = 0
|
||||
c.inQuantity = 4
|
||||
c.inBackups = 2
|
||||
c.inQuantity = 1
|
||||
c.inBackups = 1
|
||||
c.outLength = 3
|
||||
c.outVariance = 0
|
||||
c.outQuantity = 4
|
||||
c.outBackups = 2
|
||||
c.outQuantity = 1
|
||||
c.outBackups = 1
|
||||
c.dontPublishLease = true
|
||||
c.encryptLease = false
|
||||
c.reduceIdle = false
|
||||
c.reduceIdleTime = 300000
|
||||
c.reduceIdleQuantity = 4
|
||||
c.reduceIdleQuantity = 1
|
||||
c.closeIdle = true
|
||||
c.closeIdleTime = 600000
|
||||
c.debug = false
|
||||
c.sigType = SAMsigTypes[4]
|
||||
c.id = 0
|
||||
c.lastaddr = "invalid"
|
||||
c.destination = ""
|
||||
for _, o := range opts {
|
||||
if err := o(&c); err != nil {
|
||||
return nil, err
|
||||
@@ -87,6 +156,14 @@ func NewClientFromOptions(opts ...func(*Client) error) (*Client, error) {
|
||||
return &c, c.hello()
|
||||
}
|
||||
|
||||
func (p *Client) ID() string {
|
||||
return fmt.Sprintf("%d", p.id)
|
||||
}
|
||||
|
||||
func (p *Client) Addr() net.Addr {
|
||||
return nil
|
||||
}
|
||||
|
||||
//return the combined host:port of the SAM bridge
|
||||
func (c *Client) samaddr() string {
|
||||
return fmt.Sprintf("%s:%s", c.host, c.port)
|
||||
@@ -103,7 +180,7 @@ func (c *Client) hello() error {
|
||||
return fmt.Errorf("Unknown Reply: %+v\n", r)
|
||||
}
|
||||
|
||||
if r.Pairs["RESULT"] != "OK" || r.Pairs["VERSION"] != "3.0" {
|
||||
if r.Pairs["RESULT"] != "OK" {
|
||||
return fmt.Errorf("Handshake did not succeed\nReply:%+v\n", r)
|
||||
}
|
||||
|
||||
@@ -129,3 +206,30 @@ func (c *Client) Close() error {
|
||||
c.rd = nil
|
||||
return c.SamConn.Close()
|
||||
}
|
||||
|
||||
// NewClient generates an exact copy of the client with the same options
|
||||
func (c *Client) NewClient() (*Client, error) {
|
||||
return NewClientFromOptions(
|
||||
SetHost(c.host),
|
||||
SetPort(c.port),
|
||||
SetDebug(c.debug),
|
||||
SetInLength(c.inLength),
|
||||
SetOutLength(c.outLength),
|
||||
SetInVariance(c.inVariance),
|
||||
SetOutVariance(c.outVariance),
|
||||
SetInQuantity(c.inQuantity),
|
||||
SetOutQuantity(c.outQuantity),
|
||||
SetInBackups(c.inBackups),
|
||||
SetOutBackups(c.outBackups),
|
||||
SetUnpublished(c.dontPublishLease),
|
||||
SetEncrypt(c.encryptLease),
|
||||
SetReduceIdle(c.reduceIdle),
|
||||
SetReduceIdleTime(c.reduceIdleTime),
|
||||
SetReduceIdleQuantity(c.reduceIdleQuantity),
|
||||
SetCloseIdle(c.closeIdle),
|
||||
SetCloseIdleTime(c.closeIdleTime),
|
||||
SetCompression(c.compression),
|
||||
setlastaddr(c.lastaddr),
|
||||
setid(c.id),
|
||||
)
|
||||
}
|
||||
|
@@ -1,3 +1,5 @@
|
||||
// +build nettest
|
||||
|
||||
package goSam
|
||||
|
||||
import "testing"
|
||||
@@ -12,7 +14,6 @@ func setup(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("NewDefaultClient() Error: %q\n", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func teardown(t *testing.T) {
|
||||
@@ -23,5 +24,6 @@ func teardown(t *testing.T) {
|
||||
|
||||
func TestClientHello(t *testing.T) {
|
||||
setup(t)
|
||||
t.Log(client.Base32())
|
||||
teardown(t)
|
||||
}
|
||||
|
23
compat/compat.go
Normal file
23
compat/compat.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package samkeys
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/eyedeekay/sam3/i2pkeys"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func DestToKeys(dest string) (i2pkeys.I2PKeys, error) {
|
||||
addr, err := i2pkeys.NewI2PAddrFromString(dest)
|
||||
if err != nil {
|
||||
return i2pkeys.I2PKeys{}, err
|
||||
}
|
||||
return i2pkeys.NewKeys(addr, dest), nil
|
||||
}
|
||||
|
||||
func KeysToDest(keys i2pkeys.I2PKeys) (string, error) {
|
||||
pksk := strings.SplitN(keys.String(), "\n", 2)
|
||||
if len(pksk) != 2 {
|
||||
return "", fmt.Errorf("Error converting from keys to destination")
|
||||
}
|
||||
return pksk[1], nil
|
||||
}
|
56
debian/changelog
vendored
Normal file
56
debian/changelog
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
golang-github-eyedeekay-gosam (0.3.2.0) bionic; urgency=medium
|
||||
|
||||
* Enable persistent destinations
|
||||
* Make Base32 and Base64 addresses retrievable from client
|
||||
* bug fixes
|
||||
|
||||
-- idk <hankhill19580@gmail.com> Fri, 18 May 2019 18:12:21 -0500
|
||||
|
||||
golang-github-eyedeekay-gosam (0.1.1) bionic; urgency=medium
|
||||
|
||||
* Incorporate all the recent bug-fixes and improvements and stabilize.
|
||||
|
||||
-- idk <hankhill19580@gmail.com> Fri, 15 Mar 2019 14:46:21 -0500
|
||||
|
||||
golang-github-eyedeekay-gosam (0.1.0+git20190221.2896c83ubuntu1+nmu2ubuntu1) bionic; urgency=medium
|
||||
|
||||
* only run the offline tests by default
|
||||
|
||||
-- idk <hankhill19580@gmail.com> Thu, 28 Feb 2019 20:35:51 -0500
|
||||
|
||||
golang-github-eyedeekay-gosam (0.1.0+git20190221.2896c83ubuntu1+nmu2) bionic; urgency=medium
|
||||
|
||||
[ idk ]
|
||||
* incorporate cryptix-debug without the counter
|
||||
* incorporate cryptix-debug without the counter
|
||||
* fix module
|
||||
|
||||
-- idk <hankhill19580@gmail.com> Thu, 28 Feb 2019 20:32:58 -0500
|
||||
|
||||
golang-github-eyedeekay-gosam (0.1.0+git20190221.2896c83ubuntu1+nmu1) bionic; urgency=medium
|
||||
|
||||
* add sid
|
||||
*
|
||||
|
||||
-- idk <hankhill19580@gmail.com> Thu, 28 Feb 2019 18:52:01 -0500
|
||||
|
||||
golang-github-eyedeekay-gosam (0.1.0+git20190221.2896c83ubuntu1) bionic; urgency=medium
|
||||
|
||||
[ idk ]
|
||||
* Update changelog for 0.1.0+git20190221.2896c83-1 release
|
||||
* add signature type support
|
||||
* Don't check version if handshake succeeds, just accept that OK is OK
|
||||
* Don't check version if handshake succeeds, just accept that OK is OK
|
||||
* make dialer context aware and avoid redundant session create's
|
||||
* make dialer context aware and avoid redundant session create's
|
||||
* correct CONTRIBUTING.md
|
||||
* correct CONTRIBUTING.md
|
||||
* correct CONTRIBUTING.md
|
||||
* explicitly et invalid initial lastaddr
|
||||
* remove 'commented-out' id
|
||||
* Initial release (Closes: TODO)
|
||||
|
||||
[ idk ]
|
||||
* add bionic
|
||||
|
||||
-- idk <hankhill19580@gmail.com> Thu, 28 Feb 2019 18:51:23 -0500
|
1
debian/compat
vendored
Normal file
1
debian/compat
vendored
Normal file
@@ -0,0 +1 @@
|
||||
11
|
26
debian/control
vendored
Normal file
26
debian/control
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
Source: golang-github-eyedeekay-gosam
|
||||
Section: devel
|
||||
Priority: optional
|
||||
Maintainer: idk <hankhill19580@gmail.com>
|
||||
Uploaders: idk <hankhill19580@gmail.com>
|
||||
Build-Depends: debhelper (>= 11),
|
||||
dh-golang,
|
||||
golang-any,
|
||||
i2pd | i2p
|
||||
Standards-Version: 4.2.1
|
||||
Homepage: https://github.com/eyedeekay/gosam
|
||||
Vcs-Browser: https:/github.com/eyedeekay/gosam
|
||||
Vcs-Git: https://github.com/eyedeekay/gosam.git
|
||||
XS-Go-Import-Path: github.com/eyedeekay/gosam
|
||||
Testsuite: autopkgtest-pkg-go
|
||||
Launchpad-Bugs-Fixed: #1818159
|
||||
|
||||
Package: golang-github-eyedeekay-gosam-dev
|
||||
Architecture: all
|
||||
Depends: ${misc:Depends},
|
||||
i2pd | i2p
|
||||
Description: A go library for using the I2P (https://geti2p.net/en/)
|
||||
Simple Anonymous Messaging (SAM version 3.1
|
||||
(https://geti2p.net/en/docs/api/samv3)) bridge
|
||||
.
|
||||
Launchpad-Bugs-Fixed: #1818159
|
22
debian/copyright
vendored
Normal file
22
debian/copyright
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: gosam
|
||||
Source: https://github.com/eyedeekay/gosam
|
||||
Files-Excluded:
|
||||
Godeps/_workspace
|
||||
|
||||
Files: *
|
||||
Copyright: 2014 cryptix
|
||||
Copyright: 2018 idk
|
||||
License: GPL-2.0
|
||||
|
||||
Files: debug
|
||||
Copyright: 2014 cryptix
|
||||
LICENSE: MIT
|
||||
|
||||
Files: debian/*
|
||||
Copyright: 2019 idk <hankhill19580@gmail.com>
|
||||
License: GPL-2.0
|
||||
Comment: Debian packaging is licensed under the same terms as upstream
|
||||
|
||||
License: GPL-2.0
|
||||
TODO
|
2
debian/gbp.conf
vendored
Normal file
2
debian/gbp.conf
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
[DEFAULT]
|
||||
pristine-tar = False
|
4
debian/rules
vendored
Executable file
4
debian/rules
vendored
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/make -f
|
||||
|
||||
%:
|
||||
dh $@ --buildsystem=golang --with=golang
|
1
debian/source/format
vendored
Normal file
1
debian/source/format
vendored
Normal file
@@ -0,0 +1 @@
|
||||
3.0 (native)
|
4
debian/watch
vendored
Normal file
4
debian/watch
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
version=4
|
||||
opts=filenamemangle=s/.+\/v?(\d\S*)\.tar\.gz/golang-github-eyedeekay-gosam-\$1\.tar\.gz/,\
|
||||
uversionmangle=s/(\d)[_\.\-\+]?(RC|rc|pre|dev|beta|alpha)[.]?(\d*)$/\$1~\$2\$3/ \
|
||||
https://github.com/eyedeekay/gosam/tags .*/v?(\d\S*)\.tar\.gz
|
22
debug/LICENSE
Normal file
22
debug/LICENSE
Normal file
@@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Henry
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
44
debug/conn.go
Normal file
44
debug/conn.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package debug
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Conn struct {
|
||||
RWC
|
||||
conn net.Conn
|
||||
}
|
||||
|
||||
func WrapConn(c net.Conn) *Conn {
|
||||
wrap := Conn{
|
||||
conn: c,
|
||||
}
|
||||
wrap.Reader = NewReadLogger("<", c)
|
||||
wrap.Writer = NewWriteLogger(">", c)
|
||||
wrap.RWC.c = c
|
||||
return &wrap
|
||||
}
|
||||
|
||||
func (c *Conn) LocalAddr() net.Addr {
|
||||
return c.conn.LocalAddr()
|
||||
}
|
||||
|
||||
func (c *Conn) RemoteAddr() net.Addr {
|
||||
return c.conn.RemoteAddr()
|
||||
}
|
||||
|
||||
func (c *Conn) SetDeadline(t time.Time) error {
|
||||
log.Println("WARNING: SetDeadline() not sure this works")
|
||||
return c.conn.SetDeadline(t)
|
||||
}
|
||||
|
||||
func (c *Conn) SetReadDeadline(t time.Time) error {
|
||||
log.Println("WARNING: SetReadDeadline() not sure this works")
|
||||
return c.conn.SetReadDeadline(t)
|
||||
}
|
||||
func (c *Conn) SetWriteDeadline(t time.Time) error {
|
||||
log.Println("WARNING: SetWriteDeadline() not sure this works")
|
||||
return c.conn.SetWriteDeadline(t)
|
||||
}
|
77
debug/rw.go
Normal file
77
debug/rw.go
Normal file
@@ -0,0 +1,77 @@
|
||||
package debug
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"io"
|
||||
"log"
|
||||
)
|
||||
|
||||
/*
|
||||
Copy of testing/iotest Read- and WriteLogger, but using %q instead of %x for printing
|
||||
*/
|
||||
|
||||
type writeLogger struct {
|
||||
prefix string
|
||||
w io.Writer
|
||||
}
|
||||
|
||||
func (l *writeLogger) Write(p []byte) (n int, err error) {
|
||||
n, err = l.w.Write(p)
|
||||
if err != nil {
|
||||
log.Printf("%s %q: %v", l.prefix, string(p[0:n]), err)
|
||||
} else {
|
||||
log.Printf("%s %q", l.prefix, string(p[0:n]))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// NewWriteLogger returns a writer that behaves like w except
|
||||
// that it logs (using log.Printf) each write to standard error,
|
||||
// printing the prefix and the hexadecimal data written.
|
||||
func NewWriteLogger(prefix string, w io.Writer) io.Writer {
|
||||
return &writeLogger{prefix, w}
|
||||
}
|
||||
|
||||
type readLogger struct {
|
||||
prefix string
|
||||
r io.Reader
|
||||
}
|
||||
|
||||
func (l *readLogger) Read(p []byte) (n int, err error) {
|
||||
n, err = l.r.Read(p)
|
||||
if err != nil {
|
||||
log.Printf("%s %q: %v", l.prefix, string(p[0:n]), err)
|
||||
} else {
|
||||
log.Printf("%s %q", l.prefix, string(p[0:n]))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// NewReadLogger returns a reader that behaves like r except
|
||||
// that it logs (using log.Print) each read to standard error,
|
||||
// printing the prefix and the hexadecimal data written.
|
||||
func NewReadLogger(prefix string, r io.Reader) io.Reader {
|
||||
return &readLogger{prefix, r}
|
||||
}
|
||||
|
||||
type readHexLogger struct {
|
||||
prefix string
|
||||
r io.Reader
|
||||
}
|
||||
|
||||
func (l *readHexLogger) Read(p []byte) (n int, err error) {
|
||||
n, err = l.r.Read(p)
|
||||
if err != nil {
|
||||
log.Printf("%s (%d bytes) Error: %v", l.prefix, n, err)
|
||||
} else {
|
||||
log.Printf("%s (%d bytes)", l.prefix, n)
|
||||
}
|
||||
log.Print("\n" + hex.Dump(p[:n]))
|
||||
return
|
||||
}
|
||||
|
||||
// NewReadHexLogger returns a reader that behaves like r except
|
||||
// that it logs to stderr using ecoding/hex.
|
||||
func NewReadHexLogger(prefix string, r io.Reader) io.Reader {
|
||||
return &readHexLogger{prefix, r}
|
||||
}
|
56
debug/rwc.go
Normal file
56
debug/rwc.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package debug
|
||||
|
||||
import (
|
||||
"io"
|
||||
//"github.com/miolini/datacounter"
|
||||
)
|
||||
|
||||
type RWC struct {
|
||||
io.Reader
|
||||
io.Writer
|
||||
c io.Closer
|
||||
}
|
||||
|
||||
func WrapRWC(c io.ReadWriteCloser) io.ReadWriteCloser {
|
||||
rl := NewReadLogger("<", c)
|
||||
wl := NewWriteLogger(">", c)
|
||||
|
||||
return &RWC{
|
||||
Reader: rl,
|
||||
Writer: wl,
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *RWC) Close() error {
|
||||
return c.c.Close()
|
||||
}
|
||||
|
||||
/*
|
||||
type Counter struct {
|
||||
io.Reader
|
||||
io.Writer
|
||||
c io.Closer
|
||||
|
||||
Cr *datacounter.ReaderCounter
|
||||
Cw *datacounter.WriterCounter
|
||||
}
|
||||
|
||||
func WrapCounter(c io.ReadWriteCloser) *Counter {
|
||||
rc := datacounter.NewReaderCounter(c)
|
||||
wc := datacounter.NewWriterCounter(c)
|
||||
|
||||
return &Counter{
|
||||
Reader: rc,
|
||||
Writer: wc,
|
||||
c: c,
|
||||
|
||||
Cr: rc,
|
||||
Cw: wc,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Counter) Close() error {
|
||||
return c.c.Close()
|
||||
}
|
||||
*/
|
53
dial.go
53
dial.go
@@ -1,10 +1,43 @@
|
||||
package goSam
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 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) {
|
||||
errCh := make(chan error, 1)
|
||||
connCh := make(chan net.Conn, 1)
|
||||
go func() {
|
||||
if conn, err := c.Dial(network, addr); err != nil {
|
||||
errCh <- err
|
||||
} else if ctx.Err() != nil {
|
||||
conn.Close()
|
||||
} else {
|
||||
connCh <- conn
|
||||
}
|
||||
}()
|
||||
select {
|
||||
case err := <-errCh:
|
||||
return nil, err
|
||||
case conn := <-connCh:
|
||||
return conn, nil
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
}
|
||||
|
||||
func (c Client) dialCheck(addr string) (int32, bool) {
|
||||
if c.lastaddr == "invalid" {
|
||||
fmt.Println("Preparing to dial new address.")
|
||||
return c.NewID(), true
|
||||
}
|
||||
return c.id, false
|
||||
}
|
||||
|
||||
// Dial implements the net.Dial function and can be used for http.Transport
|
||||
func (c *Client) Dial(network, addr string) (net.Conn, error) {
|
||||
portIdx := strings.Index(addr, ":")
|
||||
@@ -16,20 +49,22 @@ func (c *Client) Dial(network, addr string) (net.Conn, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
id, _, err := c.CreateStreamSession("")
|
||||
var test bool
|
||||
if c.id, test = c.dialCheck(addr); test == true {
|
||||
c.destination, err = c.CreateStreamSession(c.id, c.destination)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.lastaddr = addr
|
||||
}
|
||||
c, err = c.NewClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newC, err := NewClient(c.samaddr())
|
||||
err = c.StreamConnect(c.id, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = newC.StreamConnect(id, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return newC.SamConn, nil
|
||||
return c.SamConn, nil
|
||||
}
|
||||
|
@@ -6,12 +6,12 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/cryptix/goSam"
|
||||
"github.com/eyedeekay/gosam"
|
||||
)
|
||||
|
||||
func main() {
|
||||
//In order to enable debugging, pass the SetDebug(true) option.
|
||||
//sam, err := goSam.NewClientFromOptions(SetDebug(true))
|
||||
//sam, err := goSam.NewClientFromOptions(SetDebug(true))
|
||||
|
||||
// create a default sam client
|
||||
sam, err := goSam.NewDefaultClient()
|
||||
|
7
go.mod
7
go.mod
@@ -1,6 +1,3 @@
|
||||
module github.com/cryptix/goSam
|
||||
module github.com/eyedeekay/goSam
|
||||
|
||||
require (
|
||||
github.com/cryptix/go v1.3.1
|
||||
github.com/miolini/datacounter v0.0.0-20171104152933-fd4e42a1d5e0 // indirect
|
||||
)
|
||||
require github.com/eyedeekay/sam3 v0.0.0-20190613034117-99ad6522ebe3
|
||||
|
8
go.sum
8
go.sum
@@ -1,8 +0,0 @@
|
||||
github.com/cryptix/go v1.3.1 h1:I9opbROgEpldI0PwkMku0UY2DLFYgelZd9u0uaxmMgY=
|
||||
github.com/cryptix/go v1.3.1/go.mod h1:mFQotm9rTzptzvNjJM+1vSIDa/rVOVqMu0889GIXg70=
|
||||
github.com/go-kit/kit v0.6.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-stack/stack v1.7.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/miolini/datacounter v0.0.0-20171104152933-fd4e42a1d5e0 h1:clkDYGefEWUCwyCrwYn900sOaVGDpinPJgD0W6ebEjs=
|
||||
github.com/miolini/datacounter v0.0.0-20171104152933-fd4e42a1d5e0/go.mod h1:P6fDJzlxN+cWYR09KbE9/ta+Y6JofX9tAUhJpWkWPaM=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
@@ -1,3 +1,5 @@
|
||||
// +build nettest
|
||||
|
||||
package goSam
|
||||
|
||||
import (
|
||||
|
244
options.go
244
options.go
@@ -62,6 +62,29 @@ func SetHost(s string) func(*Client) error {
|
||||
}
|
||||
}
|
||||
|
||||
//SetLocalDestination sets the local destination of the tunnel from a private
|
||||
//key
|
||||
func SetLocalDestination(s string) func(*Client) error {
|
||||
return func(c *Client) error {
|
||||
c.destination = s
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func setlastaddr(s string) func(*Client) error {
|
||||
return func(c *Client) error {
|
||||
c.lastaddr = s
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func setid(s int32) func(*Client) error {
|
||||
return func(c *Client) error {
|
||||
c.id = s
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
//SetPort sets the port of the client's SAM bridge using a string
|
||||
func SetPort(s string) func(*Client) error {
|
||||
return func(c *Client) error {
|
||||
@@ -88,6 +111,58 @@ func SetPortInt(i int) func(*Client) error {
|
||||
}
|
||||
}
|
||||
|
||||
//SetFromPort sets the port of the client's SAM bridge using a string
|
||||
func SetFromPort(s string) func(*Client) error {
|
||||
return func(c *Client) error {
|
||||
port, err := strconv.Atoi(s)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Invalid port; non-number")
|
||||
}
|
||||
if port < 65536 && port > -1 {
|
||||
c.fromport = s
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Invalid port")
|
||||
}
|
||||
}
|
||||
|
||||
//SetFromPortInt sets the port of the client's SAM bridge using a string
|
||||
func SetFromPortInt(i int) func(*Client) error {
|
||||
return func(c *Client) error {
|
||||
if i < 65536 && i > -1 {
|
||||
c.fromport = strconv.Itoa(i)
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Invalid port")
|
||||
}
|
||||
}
|
||||
|
||||
//SetToPort sets the port of the client's SAM bridge using a string
|
||||
func SetToPort(s string) func(*Client) error {
|
||||
return func(c *Client) error {
|
||||
port, err := strconv.Atoi(s)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Invalid port; non-number")
|
||||
}
|
||||
if port < 65536 && port > -1 {
|
||||
c.toport = s
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Invalid port")
|
||||
}
|
||||
}
|
||||
|
||||
//SetToPortInt sets the port of the client's SAM bridge using a string
|
||||
func SetToPortInt(i int) func(*Client) error {
|
||||
return func(c *Client) error {
|
||||
if i < 65536 && i > -1 {
|
||||
c.fromport = strconv.Itoa(i)
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Invalid port")
|
||||
}
|
||||
}
|
||||
|
||||
//SetDebug enables debugging messages
|
||||
func SetDebug(b bool) func(*Client) error {
|
||||
return func(c *Client) error {
|
||||
@@ -200,7 +275,7 @@ func SetEncrypt(b bool) func(*Client) error {
|
||||
}
|
||||
}
|
||||
|
||||
//SetReduceIdle tells the router to use an encrypted leaseset
|
||||
//SetReduceIdle sets the created tunnels to be reduced during extended idle time to avoid excessive resource usage
|
||||
func SetReduceIdle(b bool) func(*Client) error {
|
||||
return func(c *Client) error {
|
||||
c.reduceIdle = b
|
||||
@@ -208,10 +283,10 @@ func SetReduceIdle(b bool) func(*Client) error {
|
||||
}
|
||||
}
|
||||
|
||||
//SetReduceIdleTime sets the inbound tunnel backups
|
||||
//SetReduceIdleTime sets time to wait before the tunnel quantity is reduced
|
||||
func SetReduceIdleTime(u uint) func(*Client) error {
|
||||
return func(c *Client) error {
|
||||
if u > 300000 {
|
||||
if u > 299999 {
|
||||
c.reduceIdleTime = u
|
||||
return nil
|
||||
}
|
||||
@@ -219,7 +294,7 @@ func SetReduceIdleTime(u uint) func(*Client) error {
|
||||
}
|
||||
}
|
||||
|
||||
//SetReduceIdleQuantity sets the inbound tunnel backups
|
||||
//SetReduceIdleQuantity sets number of tunnels to keep alive during an extended idle period
|
||||
func SetReduceIdleQuantity(u uint) func(*Client) error {
|
||||
return func(c *Client) error {
|
||||
if u < 5 {
|
||||
@@ -230,7 +305,7 @@ func SetReduceIdleQuantity(u uint) func(*Client) error {
|
||||
}
|
||||
}
|
||||
|
||||
//SetCloseIdle tells the router to use an encrypted leaseset
|
||||
//SetCloseIdle sets the tunnels to close after a specific amount of time
|
||||
func SetCloseIdle(b bool) func(*Client) error {
|
||||
return func(c *Client) error {
|
||||
c.closeIdle = b
|
||||
@@ -238,10 +313,10 @@ func SetCloseIdle(b bool) func(*Client) error {
|
||||
}
|
||||
}
|
||||
|
||||
//SetCloseIdleTime sets the inbound tunnel backups
|
||||
//SetCloseIdleTime sets the time in milliseconds to wait before closing tunnels
|
||||
func SetCloseIdleTime(u uint) func(*Client) error {
|
||||
return func(c *Client) error {
|
||||
if u > 300000 {
|
||||
if u > 299999 {
|
||||
c.closeIdleTime = u
|
||||
return nil
|
||||
}
|
||||
@@ -249,103 +324,184 @@ func SetCloseIdleTime(u uint) func(*Client) error {
|
||||
}
|
||||
}
|
||||
|
||||
//SetCompression sets the tunnels to close after a specific amount of time
|
||||
func SetCompression(b bool) func(*Client) error {
|
||||
return func(c *Client) error {
|
||||
c.compression = b
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
/* SAM v 3.1 Options*/
|
||||
|
||||
//SetSignatureType tells gosam to pass SAM a signature_type parameter with one
|
||||
// of the following values:
|
||||
// "SIGNATURE_TYPE=DSA_SHA1",
|
||||
// "SIGNATURE_TYPE=ECDSA_SHA256_P256",
|
||||
// "SIGNATURE_TYPE=ECDSA_SHA384_P384",
|
||||
// "SIGNATURE_TYPE=ECDSA_SHA512_P521",
|
||||
// "SIGNATURE_TYPE=EdDSA_SHA512_Ed25519",
|
||||
// or an empty string
|
||||
func SetSignatureType(s string) func(*Client) error {
|
||||
return func(c *Client) error {
|
||||
if s == "" {
|
||||
c.sigType = ""
|
||||
return nil
|
||||
}
|
||||
for _, valid := range SAMsigTypes {
|
||||
if s == valid {
|
||||
c.sigType = valid
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("Invalid signature type specified at construction time")
|
||||
}
|
||||
}
|
||||
|
||||
//return the from port as a string.
|
||||
func (c *Client) from() string {
|
||||
if c.fromport == "" {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf(" FROM_PORT=%v ", c.fromport)
|
||||
}
|
||||
|
||||
//return the to port as a string.
|
||||
func (c *Client) to() string {
|
||||
if c.toport == "" {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf(" TO_PORT=%v ", c.toport)
|
||||
}
|
||||
|
||||
//return the signature type as a string.
|
||||
func (c *Client) sigtype() string {
|
||||
return fmt.Sprintf(" %s ", c.sigType)
|
||||
}
|
||||
|
||||
//return the inbound length as a string.
|
||||
func (c *Client) inlength() string {
|
||||
return fmt.Sprintf("inbound.length=%d", c.inLength)
|
||||
return fmt.Sprintf(" inbound.length=%d ", c.inLength)
|
||||
}
|
||||
|
||||
//return the outbound length as a string.
|
||||
func (c *Client) outlength() string {
|
||||
return fmt.Sprintf("outbound.length=%d", c.outLength)
|
||||
return fmt.Sprintf(" outbound.length=%d ", c.outLength)
|
||||
}
|
||||
|
||||
//return the inbound length variance as a string.
|
||||
func (c *Client) invariance() string {
|
||||
return fmt.Sprintf("inbound.lengthVariance=%d", c.inVariance)
|
||||
return fmt.Sprintf(" inbound.lengthVariance=%d ", c.inVariance)
|
||||
}
|
||||
|
||||
//return the outbound length variance as a string.
|
||||
func (c *Client) outvariance() string {
|
||||
return fmt.Sprintf("outbound.lengthVariance=%d", c.outVariance)
|
||||
return fmt.Sprintf(" outbound.lengthVariance=%d ", c.outVariance)
|
||||
}
|
||||
|
||||
//return the inbound tunnel quantity as a string.
|
||||
func (c *Client) inquantity() string {
|
||||
return fmt.Sprintf("inbound.quantity=%d", c.inQuantity)
|
||||
return fmt.Sprintf(" inbound.quantity=%d ", c.inQuantity)
|
||||
}
|
||||
|
||||
//return the outbound tunnel quantity as a string.
|
||||
func (c *Client) outquantity() string {
|
||||
return fmt.Sprintf("outbound.quantity=%d", c.outQuantity)
|
||||
return fmt.Sprintf(" outbound.quantity=%d ", c.outQuantity)
|
||||
}
|
||||
|
||||
//return the inbound tunnel quantity as a string.
|
||||
func (c *Client) inbackups() string {
|
||||
return fmt.Sprintf("inbound.backupQuantity=%d", c.inQuantity)
|
||||
return fmt.Sprintf(" inbound.backupQuantity=%d ", c.inQuantity)
|
||||
}
|
||||
|
||||
//return the outbound tunnel quantity as a string.
|
||||
func (c *Client) outbackups() string {
|
||||
return fmt.Sprintf("outbound.backupQuantity=%d", c.outQuantity)
|
||||
return fmt.Sprintf(" outbound.backupQuantity=%d ", c.outQuantity)
|
||||
}
|
||||
|
||||
func (c *Client) encryptlease() string {
|
||||
if c.encryptLease {
|
||||
return "i2cp.encryptLeaseSet=true"
|
||||
return " i2cp.encryptLeaseSet=true "
|
||||
}
|
||||
return "i2cp.encryptLeaseSet=false"
|
||||
return " i2cp.encryptLeaseSet=false "
|
||||
}
|
||||
|
||||
func (c *Client) dontpublishlease() string {
|
||||
if c.dontPublishLease {
|
||||
return "i2cp.dontPublishLeaseSet=true"
|
||||
return " i2cp.dontPublishLeaseSet=true "
|
||||
}
|
||||
return "i2cp.dontPublishLeaseSet=false"
|
||||
return " i2cp.dontPublishLeaseSet=false "
|
||||
}
|
||||
|
||||
func (c *Client) closeonidle() string {
|
||||
if c.closeIdle {
|
||||
return "i2cp.closeOnIdle=true"
|
||||
return " i2cp.closeOnIdle=true "
|
||||
}
|
||||
return "i2cp.closeOnIdle=false"
|
||||
return " i2cp.closeOnIdle=false "
|
||||
}
|
||||
|
||||
func (c *Client) closeidletime() string {
|
||||
return fmt.Sprintf("i2cp.closeIdleTime=%d", c.closeIdleTime)
|
||||
return fmt.Sprintf(" i2cp.closeIdleTime=%d ", c.closeIdleTime)
|
||||
}
|
||||
|
||||
func (c *Client) reduceonidle() string {
|
||||
if c.reduceIdle {
|
||||
return "i2cp.reduceOnIdle=true"
|
||||
return " i2cp.reduceOnIdle=true "
|
||||
}
|
||||
return "i2cp.reduceOnIdle=false"
|
||||
return " i2cp.reduceOnIdle=false "
|
||||
}
|
||||
|
||||
func (c *Client) reduceidletime() string {
|
||||
return fmt.Sprintf("i2cp.reduceIdleTime=%d", c.reduceIdleTime)
|
||||
return fmt.Sprintf(" i2cp.reduceIdleTime=%d ", c.reduceIdleTime)
|
||||
}
|
||||
|
||||
func (c *Client) reduceidlecount() string {
|
||||
return fmt.Sprintf("i2cp.reduceIdleQuantity=%d", c.reduceIdleQuantity)
|
||||
return fmt.Sprintf(" i2cp.reduceIdleQuantity=%d ", c.reduceIdleQuantity)
|
||||
}
|
||||
|
||||
//return all options as string array ready for passing to sendcmd
|
||||
func (c *Client) allOptions() []string {
|
||||
return []string{
|
||||
c.inlength(),
|
||||
c.outlength(),
|
||||
c.invariance(),
|
||||
c.outvariance(),
|
||||
c.inquantity(),
|
||||
c.outquantity(),
|
||||
c.inbackups(),
|
||||
c.outbackups(),
|
||||
c.dontpublishlease(),
|
||||
c.encryptlease(),
|
||||
c.reduceonidle(),
|
||||
c.reduceidletime(),
|
||||
c.reduceidlecount(),
|
||||
c.closeonidle(),
|
||||
c.closeidletime(),
|
||||
func (c *Client) compresion() string {
|
||||
if c.compression {
|
||||
return " i2cp.gzip=true "
|
||||
}
|
||||
return " i2cp.gzip=false "
|
||||
}
|
||||
|
||||
//return all options as string ready for passing to sendcmd
|
||||
func (c *Client) allOptions() string {
|
||||
return c.inlength() +
|
||||
c.outlength() +
|
||||
c.invariance() +
|
||||
c.outvariance() +
|
||||
c.inquantity() +
|
||||
c.outquantity() +
|
||||
c.inbackups() +
|
||||
c.outbackups() +
|
||||
c.dontpublishlease() +
|
||||
c.encryptlease() +
|
||||
c.reduceonidle() +
|
||||
c.reduceidletime() +
|
||||
c.reduceidlecount() +
|
||||
c.closeonidle() +
|
||||
c.closeidletime() +
|
||||
c.compresion()
|
||||
}
|
||||
|
||||
//Print return all options as string
|
||||
func (c *Client) Print() string {
|
||||
return c.inlength() +
|
||||
c.outlength() +
|
||||
c.invariance() +
|
||||
c.outvariance() +
|
||||
c.inquantity() +
|
||||
c.outquantity() +
|
||||
c.inbackups() +
|
||||
c.outbackups() +
|
||||
c.dontpublishlease() +
|
||||
c.encryptlease() +
|
||||
c.reduceonidle() +
|
||||
c.reduceidletime() +
|
||||
c.reduceidlecount() +
|
||||
c.closeonidle() +
|
||||
c.closeidletime() +
|
||||
c.compresion()
|
||||
}
|
||||
|
321
options_test.go
321
options_test.go
@@ -1,241 +1,188 @@
|
||||
// +build nettest
|
||||
|
||||
package goSam
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/rand"
|
||||
//"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// helper to validate sendCmd inputs
|
||||
func (c *Client) validCmd(str string, args ...interface{}) (string, error) {
|
||||
if s := fmt.Sprintf(str, args...); strings.Contains(s, "\n") {
|
||||
sl := strings.Split(s, "\n")
|
||||
if len(sl) == 2 {
|
||||
if sl[1] != "" {
|
||||
return sl[1], fmt.Errorf("Error, there should be no options after the newline")
|
||||
}
|
||||
for li, in := range sl {
|
||||
fmt.Println(li, in)
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
return "", fmt.Errorf("Error, invalid length: %d", len(sl))
|
||||
}
|
||||
return "", fmt.Errorf("Error, invalid input")
|
||||
}
|
||||
|
||||
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())
|
||||
return result, err
|
||||
}
|
||||
|
||||
func TestOptionAddrString(t *testing.T) {
|
||||
client, err := NewClientFromOptions(SetAddr("127.0.0.1:7656"), SetDebug(true))
|
||||
if err != nil {
|
||||
t.Fatalf("NewDefaultClient() Error: %q\n", err)
|
||||
t.Fatalf("NewClientFromOptions() Error: %q\n", err)
|
||||
}
|
||||
if result, err := client.validCreate(); err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
} else {
|
||||
t.Log(result)
|
||||
}
|
||||
dest, _ := client.CreateStreamSession(client.NewID(), "")
|
||||
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())
|
||||
}
|
||||
|
||||
func TestOptionAddrStringLh(t *testing.T) {
|
||||
client, err := NewClientFromOptions(SetAddr("localhost:7656"), SetDebug(true))
|
||||
if err != nil {
|
||||
t.Fatalf("NewDefaultClient() Error: %q\n", err)
|
||||
t.Fatalf("NewClientFromOptions() Error: %q\n", err)
|
||||
}
|
||||
if result, err := client.validCreate(); err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
} else {
|
||||
t.Log(result)
|
||||
}
|
||||
dest, _ := client.CreateStreamSession(client.NewID(), "")
|
||||
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())
|
||||
}
|
||||
|
||||
func TestOptionAddrSlice(t *testing.T) {
|
||||
client, err := NewClientFromOptions(SetAddr("127.0.0.1", "7656"), SetDebug(true))
|
||||
if err != nil {
|
||||
t.Fatalf("NewDefaultClient() Error: %q\n", err)
|
||||
t.Fatalf("NewClientFromOptions() Error: %q\n", err)
|
||||
}
|
||||
if result, err := client.validCreate(); err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
} else {
|
||||
t.Log(result)
|
||||
}
|
||||
dest, _ := client.CreateStreamSession(client.NewID(), "")
|
||||
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())
|
||||
}
|
||||
|
||||
func TestOptionAddrMixedSlice(t *testing.T) {
|
||||
client, err := NewClientFromOptions(SetAddrMixed("127.0.0.1", 7656), SetDebug(true))
|
||||
if err != nil {
|
||||
t.Fatalf("NewDefaultClient() Error: %q\n", err)
|
||||
t.Fatalf("NewClientFromOptions() Error: %q\n", err)
|
||||
}
|
||||
if result, err := client.validCreate(); err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
} else {
|
||||
t.Log(result)
|
||||
}
|
||||
dest, _ := client.CreateStreamSession(client.NewID(), "")
|
||||
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())
|
||||
}
|
||||
|
||||
func TestOptionHost(t *testing.T) {
|
||||
client, err := NewClientFromOptions(SetHost("127.0.0.1"), SetDebug(true))
|
||||
client, err := NewClientFromOptions(
|
||||
SetHost("127.0.0.1"),
|
||||
SetPort("7656"),
|
||||
SetInLength(3),
|
||||
SetOutLength(3),
|
||||
SetInVariance(1),
|
||||
SetOutVariance(1),
|
||||
SetInQuantity(6),
|
||||
SetOutQuantity(6),
|
||||
SetInBackups(2),
|
||||
SetOutBackups(2),
|
||||
SetEncrypt(true),
|
||||
SetDebug(true),
|
||||
SetUnpublished(true),
|
||||
SetReduceIdle(true),
|
||||
SetReduceIdleTime(300001),
|
||||
SetReduceIdleQuantity(4),
|
||||
SetCloseIdle(true),
|
||||
SetCloseIdleTime(300001),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("NewDefaultClient() Error: %q\n", err)
|
||||
}
|
||||
if err := client.Close(); err != nil {
|
||||
t.Fatalf("client.Close() Error: %q\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOptionPort(t *testing.T) {
|
||||
client, err := NewClientFromOptions(SetPort("7656"), SetDebug(true))
|
||||
if err != nil {
|
||||
t.Fatalf("NewDefaultClient() Error: %q\n", err)
|
||||
t.Fatalf("NewClientFromOptions() Error: %q\n", err)
|
||||
}
|
||||
if result, err := client.validCreate(); err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
} else {
|
||||
t.Log(result)
|
||||
}
|
||||
dest, _ := client.CreateStreamSession(client.NewID(), "")
|
||||
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())
|
||||
}
|
||||
|
||||
func TestOptionPortInt(t *testing.T) {
|
||||
client, err := NewClientFromOptions(SetPortInt(7656), SetDebug(true))
|
||||
client, err := NewClientFromOptions(
|
||||
SetHost("127.0.0.1"),
|
||||
SetPortInt(7656),
|
||||
SetInLength(3),
|
||||
SetOutLength(3),
|
||||
SetInVariance(1),
|
||||
SetOutVariance(1),
|
||||
SetInQuantity(6),
|
||||
SetOutQuantity(6),
|
||||
SetInBackups(2),
|
||||
SetOutBackups(2),
|
||||
SetEncrypt(true),
|
||||
SetDebug(true),
|
||||
SetUnpublished(true),
|
||||
SetReduceIdle(true),
|
||||
SetReduceIdleTime(300001),
|
||||
SetReduceIdleQuantity(4),
|
||||
SetCloseIdle(true),
|
||||
SetCloseIdleTime(300001),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("NewDefaultClient() Error: %q\n", err)
|
||||
}
|
||||
if err := client.Close(); err != nil {
|
||||
t.Fatalf("client.Close() Error: %q\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOptionDebug(t *testing.T) {
|
||||
client, err := NewClientFromOptions(SetDebug(true))
|
||||
if err != nil {
|
||||
t.Fatalf("NewDefaultClient() Error: %q\n", err)
|
||||
}
|
||||
if err := client.Close(); err != nil {
|
||||
t.Fatalf("client.Close() Error: %q\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOptionInLength(t *testing.T) {
|
||||
client, err := NewClientFromOptions(SetInLength(3), SetDebug(true))
|
||||
client.inlength()
|
||||
if err != nil {
|
||||
t.Fatalf("NewDefaultClient() Error: %q\n", err)
|
||||
}
|
||||
if err := client.Close(); err != nil {
|
||||
t.Fatalf("client.Close() Error: %q\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOptionOutLength(t *testing.T) {
|
||||
client, err := NewClientFromOptions(SetInLength(3), SetDebug(true))
|
||||
client.outlength()
|
||||
if err != nil {
|
||||
t.Fatalf("NewDefaultClient() Error: %q\n", err)
|
||||
}
|
||||
if err := client.Close(); err != nil {
|
||||
t.Fatalf("client.Close() Error: %q\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOptionInVariance(t *testing.T) {
|
||||
client, err := NewClientFromOptions(SetInVariance(1), SetDebug(true))
|
||||
client.invariance()
|
||||
if err != nil {
|
||||
t.Fatalf("NewDefaultClient() Error: %q\n", err)
|
||||
}
|
||||
if err := client.Close(); err != nil {
|
||||
t.Fatalf("client.Close() Error: %q\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOptionOutVariance(t *testing.T) {
|
||||
client, err := NewClientFromOptions(SetOutVariance(1), SetDebug(true))
|
||||
client.outvariance()
|
||||
if err != nil {
|
||||
t.Fatalf("NewDefaultClient() Error: %q\n", err)
|
||||
}
|
||||
if err := client.Close(); err != nil {
|
||||
t.Fatalf("client.Close() Error: %q\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOptionInQuantity(t *testing.T) {
|
||||
client, err := NewClientFromOptions(SetInQuantity(6), SetDebug(true))
|
||||
client.inquantity()
|
||||
if err != nil {
|
||||
t.Fatalf("NewDefaultClient() Error: %q\n", err)
|
||||
}
|
||||
if err := client.Close(); err != nil {
|
||||
t.Fatalf("client.Close() Error: %q\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOptionOutQuantity(t *testing.T) {
|
||||
client, err := NewClientFromOptions(SetOutQuantity(6), SetDebug(true))
|
||||
client.outquantity()
|
||||
if err != nil {
|
||||
t.Fatalf("NewDefaultClient() Error: %q\n", err)
|
||||
}
|
||||
if err := client.Close(); err != nil {
|
||||
t.Fatalf("client.Close() Error: %q\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOptionInBackups(t *testing.T) {
|
||||
client, err := NewClientFromOptions(SetInBackups(5), SetDebug(true))
|
||||
client.inbackups()
|
||||
if err != nil {
|
||||
t.Fatalf("NewDefaultClient() Error: %q\n", err)
|
||||
}
|
||||
if err := client.Close(); err != nil {
|
||||
t.Fatalf("client.Close() Error: %q\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOptionOutBackups(t *testing.T) {
|
||||
client, err := NewClientFromOptions(SetOutBackups(5), SetDebug(true))
|
||||
client.outbackups()
|
||||
if err != nil {
|
||||
t.Fatalf("NewDefaultClient() Error: %q\n", err)
|
||||
}
|
||||
if err := client.Close(); err != nil {
|
||||
t.Fatalf("client.Close() Error: %q\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOptionEncryptLease(t *testing.T) {
|
||||
client, err := NewClientFromOptions(SetEncrypt(true), SetDebug(true))
|
||||
if err != nil {
|
||||
t.Fatalf("NewDefaultClient() Error: %q\n", err)
|
||||
}
|
||||
if err := client.Close(); err != nil {
|
||||
t.Fatalf("client.Close() Error: %q\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOptionUnpublishedLease(t *testing.T) {
|
||||
client, err := NewClientFromOptions(SetUnpublished(true), SetDebug(true))
|
||||
if err != nil {
|
||||
t.Fatalf("NewDefaultClient() Error: %q\n", err)
|
||||
}
|
||||
if err := client.Close(); err != nil {
|
||||
t.Fatalf("client.Close() Error: %q\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOptionReduceIdle(t *testing.T) {
|
||||
client, err := NewClientFromOptions(SetReduceIdle(true), SetDebug(true))
|
||||
if err != nil {
|
||||
t.Fatalf("NewDefaultClient() Error: %q\n", err)
|
||||
}
|
||||
if err := client.Close(); err != nil {
|
||||
t.Fatalf("client.Close() Error: %q\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOptionReduceIdleTime(t *testing.T) {
|
||||
client, err := NewClientFromOptions(SetReduceIdleTime(300001), SetDebug(true))
|
||||
if err != nil {
|
||||
t.Fatalf("NewDefaultClient() Error: %q\n", err)
|
||||
}
|
||||
if err := client.Close(); err != nil {
|
||||
t.Fatalf("client.Close() Error: %q\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOptionReduceIdleCount(t *testing.T) {
|
||||
client, err := NewClientFromOptions(SetReduceIdleQuantity(4), SetDebug(true))
|
||||
if err != nil {
|
||||
t.Fatalf("NewDefaultClient() Error: %q\n", err)
|
||||
}
|
||||
if err := client.Close(); err != nil {
|
||||
t.Fatalf("client.Close() Error: %q\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOptionCloseIdle(t *testing.T) {
|
||||
client, err := NewClientFromOptions(SetCloseIdle(true), SetDebug(true))
|
||||
if err != nil {
|
||||
t.Fatalf("NewDefaultClient() Error: %q\n", err)
|
||||
}
|
||||
if err := client.Close(); err != nil {
|
||||
t.Fatalf("client.Close() Error: %q\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOptionCloseIdleTime(t *testing.T) {
|
||||
client, err := NewClientFromOptions(SetCloseIdleTime(300001), SetDebug(true))
|
||||
if err != nil {
|
||||
t.Fatalf("NewDefaultClient() Error: %q\n", err)
|
||||
t.Fatalf("NewClientFromOptions() Error: %q\n", err)
|
||||
}
|
||||
if result, err := client.validCreate(); err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
} else {
|
||||
t.Log(result)
|
||||
}
|
||||
dest, _ := client.CreateStreamSession(client.NewID(), "")
|
||||
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())
|
||||
}
|
||||
|
@@ -57,7 +57,7 @@ func parseReply(line string) (*Reply, error) {
|
||||
}
|
||||
}
|
||||
|
||||
r.Pairs[kvPair[0]] = kvPair[1]
|
||||
r.Pairs[kvPair[0]] = kvPair[len(kvPair)-1]
|
||||
}
|
||||
|
||||
return r, nil
|
||||
|
27
sessions.go
27
sessions.go
@@ -2,7 +2,7 @@ package goSam
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
// "math"
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
@@ -13,26 +13,33 @@ func init() {
|
||||
|
||||
// CreateStreamSession creates a new STREAM Session.
|
||||
// Returns the Id for the new Client.
|
||||
func (c *Client) CreateStreamSession(dest string) (int32, string, error) {
|
||||
func (c *Client) CreateStreamSession(id int32, dest string) (string, error) {
|
||||
if dest == "" {
|
||||
dest = "TRANSIENT"
|
||||
}
|
||||
|
||||
id := rand.Int31n(math.MaxInt32)
|
||||
r, err := c.sendCmd("SESSION CREATE STYLE=STREAM ID=%d DESTINATION=%s %s\n", id, dest, c.allOptions())
|
||||
c.id = id
|
||||
r, err := c.sendCmd(
|
||||
"SESSION CREATE STYLE=STREAM ID=%d %s %s DESTINATION=%s %s %s\n",
|
||||
c.id,
|
||||
c.from(),
|
||||
c.to(),
|
||||
dest,
|
||||
c.sigtype(),
|
||||
c.allOptions(),
|
||||
)
|
||||
if err != nil {
|
||||
return -1, "", err
|
||||
return "", err
|
||||
}
|
||||
|
||||
// TODO: move check into sendCmd()
|
||||
if r.Topic != "SESSION" || r.Type != "STATUS" {
|
||||
return -1, "", fmt.Errorf("Unknown Reply: %+v\n", r)
|
||||
return "", fmt.Errorf("Unknown Reply: %+v\n", r)
|
||||
}
|
||||
|
||||
result := r.Pairs["RESULT"]
|
||||
if result != "OK" {
|
||||
return -1, "", ReplyError{ResultKeyNotFound, r}
|
||||
return "", ReplyError{ResultKeyNotFound, r}
|
||||
}
|
||||
|
||||
return id, r.Pairs["DESTINATION"], nil
|
||||
c.destination = r.Pairs["DESTINATION"]
|
||||
return c.destination, nil
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@ 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 {
|
||||
r, err := c.sendCmd("STREAM CONNECT ID=%d DESTINATION=%s\n", id, dest)
|
||||
r, err := c.sendCmd("STREAM CONNECT ID=%d %s %s DESTINATION=%s\n", id, c.from(), c.to(), dest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
Reference in New Issue
Block a user