Improve the parser, automatically set empty destinations to TRANSIENT when using a dialer, better error handling, when a socket gets closed, increment the ID and re-create it
This commit is contained in:
14
client.go
14
client.go
@ -12,6 +12,7 @@ import (
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// A Client represents a single Connection to the SAM bridge
|
||||
@ -83,7 +84,10 @@ func NewClient(addr string) (*Client, error) {
|
||||
|
||||
// NewID generates a random number to use as an tunnel name
|
||||
func (c *Client) NewID() int32 {
|
||||
return rand.Int31n(math.MaxInt32)
|
||||
if c.id == 0 {
|
||||
c.id = rand.Int31n(math.MaxInt32)
|
||||
}
|
||||
return c.id
|
||||
}
|
||||
|
||||
// Destination returns the full destination of the local tunnel
|
||||
@ -127,11 +131,11 @@ func NewClientFromOptions(opts ...func(*Client) error) (*Client, error) {
|
||||
c.port = "7656"
|
||||
c.inLength = 3
|
||||
c.inVariance = 0
|
||||
c.inQuantity = 1
|
||||
c.inQuantity = 3
|
||||
c.inBackups = 1
|
||||
c.outLength = 3
|
||||
c.outVariance = 0
|
||||
c.outQuantity = 1
|
||||
c.outQuantity = 3
|
||||
c.outBackups = 1
|
||||
c.dontPublishLease = true
|
||||
c.encryptLease = false
|
||||
@ -139,7 +143,7 @@ func NewClientFromOptions(opts ...func(*Client) error) (*Client, error) {
|
||||
c.reduceIdleTime = 300000
|
||||
c.reduceIdleQuantity = 1
|
||||
c.closeIdle = true
|
||||
c.closeIdleTime = 600000
|
||||
c.closeIdleTime = 60000000
|
||||
c.debug = true
|
||||
c.sigType = SAMsigTypes[4]
|
||||
c.id = 0
|
||||
@ -153,7 +157,7 @@ func NewClientFromOptions(opts ...func(*Client) error) (*Client, error) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
conn, err := net.Dial("tcp", c.samaddr())
|
||||
conn, err := net.DialTimeout("tcp", c.samaddr(), 3*time.Minute)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
23
dial.go
23
dial.go
@ -3,6 +3,7 @@ package goSam
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
@ -17,19 +18,14 @@ func (c *Client) DialContext(ctx context.Context, network, addr string) (net.Con
|
||||
if conn, err := c.Dial(network, addr); err != nil {
|
||||
errCh <- err
|
||||
} else if ctx.Err() != nil {
|
||||
var err error
|
||||
c, err = c.NewClient()
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
}
|
||||
log.Println(ctx)
|
||||
errCh <- ctx.Err()
|
||||
} else {
|
||||
connCh <- conn
|
||||
}
|
||||
}()
|
||||
select {
|
||||
case err := <-errCh:
|
||||
// var err error
|
||||
c, err = c.NewClient()
|
||||
return c.SamConn, err
|
||||
case conn := <-connCh:
|
||||
return conn, nil
|
||||
@ -44,6 +40,7 @@ func (c *Client) dialCheck(addr string) (int32, bool) {
|
||||
return c.NewID(), true
|
||||
} else if c.lastaddr != addr {
|
||||
fmt.Println("Preparing to dial next new address.")
|
||||
return c.NewID(), true
|
||||
}
|
||||
return c.id, false
|
||||
}
|
||||
@ -61,18 +58,24 @@ func (c *Client) Dial(network, addr string) (net.Conn, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var test bool
|
||||
if c.id, test = c.dialCheck(addr); test == true {
|
||||
c.id, _ = c.dialCheck(addr)
|
||||
c.destination, err = c.CreateStreamSession(c.id, c.destination)
|
||||
if err != nil {
|
||||
c.id += 1
|
||||
c, err = c.NewClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
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
|
||||
}
|
||||
c.lastaddr = addr
|
||||
|
||||
err = c.StreamConnect(c.id, addr)
|
||||
if err != nil {
|
||||
|
@ -44,6 +44,25 @@ func parseReply(line string) (*Reply, error) {
|
||||
if len(parts) < 3 {
|
||||
return nil, fmt.Errorf("Malformed Reply.\n%s\n", line)
|
||||
}
|
||||
preParseReply := func() []string {
|
||||
val := ""
|
||||
quote := false
|
||||
for _, v := range parts {
|
||||
if strings.Contains(v, "=\"") {
|
||||
quote = true
|
||||
}
|
||||
if strings.Contains(v, "\"\n") || strings.Contains(v, "\" ") {
|
||||
quote = false
|
||||
}
|
||||
if quote {
|
||||
val += v + "_"
|
||||
} else {
|
||||
val += v + " "
|
||||
}
|
||||
}
|
||||
return strings.Split(strings.TrimSuffix(strings.TrimSpace(val), "_"), " ")
|
||||
}
|
||||
parts = preParseReply()
|
||||
|
||||
r := &Reply{
|
||||
Topic: parts[0],
|
||||
@ -64,8 +83,9 @@ func parseReply(line string) (*Reply, error) {
|
||||
kvPair := strings.SplitN(v, "=", 2)
|
||||
if kvPair != nil {
|
||||
if len(kvPair) == 1 {
|
||||
return nil, fmt.Errorf("Malformed key-value-pair len 1.\n%s\n", kvPair)
|
||||
} else if len(kvPair) != 2 {
|
||||
return nil, fmt.Errorf("Malformed key-value-pair.\n%s\n", kvPair)
|
||||
return nil, fmt.Errorf("Malformed key-value-pair len != 2.\n%s\n", kvPair)
|
||||
}
|
||||
}
|
||||
r.Pairs[kvPair[0]] = kvPair[len(kvPair)-1]
|
||||
|
@ -6,6 +6,9 @@ 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 {
|
||||
if dest == "" {
|
||||
dest = "TRANSIENT"
|
||||
}
|
||||
r, err := c.sendCmd("STREAM CONNECT ID=%d DESTINATION=%s %s %s\n", id, dest, c.from(), c.to())
|
||||
if err != nil {
|
||||
return err
|
||||
|
Reference in New Issue
Block a user