diff --git a/client.go b/client.go index 73e3aad..c05c9de 100644 --- a/client.go +++ b/client.go @@ -8,6 +8,7 @@ import ( "github.com/cryptix/go/debug" ) +// ConnDebug if set to true, Sam connections are wrapped with logging var ConnDebug = false // A Client represents a single Connection to the SAM bridge @@ -38,10 +39,8 @@ func NewClient(addr string) (*Client, error) { } // send the initial handshake command and check that the reply is ok -func (c *Client) hello() (err error) { - var r *Reply - - r, err = c.sendCmd("HELLO VERSION MIN=3.0 MAX=3.0") +func (c *Client) hello() error { + r, err := c.sendCmd("HELLO VERSION MIN=3.0 MAX=3.0\n") if err != nil { return err } @@ -58,14 +57,14 @@ func (c *Client) hello() (err error) { } // helper to send one command and parse the reply by sam -func (c *Client) sendCmd(cmd string) (r *Reply, err error) { - if _, err = fmt.Fprintln(c.SamConn, cmd); err != nil { - return +func (c *Client) sendCmd(str string, args ...interface{}) (*Reply, error) { + if _, err := fmt.Fprintf(c.SamConn, str, args...); err != nil { + return nil, err } line, err := c.rd.ReadString('\n') if err != nil { - return + return nil, err } return parseReply(line) @@ -73,5 +72,6 @@ func (c *Client) sendCmd(cmd string) (r *Reply, err error) { // Close the underlying socket to SAM func (c *Client) Close() error { + c.rd = nil return c.SamConn.Close() } diff --git a/client_test.go b/client_test.go index ace1033..1d9e3f3 100644 --- a/client_test.go +++ b/client_test.go @@ -2,9 +2,7 @@ package goSam import "testing" -var ( - client *Client -) +var client *Client func setup(t *testing.T) { var err error diff --git a/naming.go b/naming.go index 75b8934..b47f790 100644 --- a/naming.go +++ b/naming.go @@ -6,34 +6,29 @@ import ( ) // Lookup askes SAM for the internal i2p address from name -func (c *Client) Lookup(name string) (addr string, err error) { - var r *Reply - - r, err = c.sendCmd(fmt.Sprintf("NAMING LOOKUP NAME=%s", name)) +func (c *Client) Lookup(name string) (string, error) { + r, err := c.sendCmd("NAMING LOOKUP NAME=%s\n", name) if err != nil { - return + return "", nil } + // TODO: move check into sendCmd() if r.Topic != "NAMING" || r.Type != "REPLY" { - err = fmt.Errorf("Unknown Reply: %+v\n", r) - return + return "", fmt.Errorf("Unknown Reply: %+v\n", r) } result := r.Pairs["RESULT"] if result != "OK" { - err = ReplyError{result, r} - return + return "", ReplyError{result, r} } if r.Pairs["NAME"] != name { // somehow different on i2pd if r.Pairs["NAME"] != "ME" { - err = fmt.Errorf("Lookup() Replyed to another name.\nWanted:%s\nGot: %+v\n", name, r) - return + return "", fmt.Errorf("Lookup() Replyed to another name.\nWanted:%s\nGot: %+v\n", name, r) } fmt.Fprintln(os.Stderr, "WARNING: Lookup() Replyed to another name. assuming i2pd c++ fluke") } - addr = r.Pairs["VALUE"] - return + return r.Pairs["VALUE"], nil } diff --git a/replyParser.go b/replyParser.go index 2b8c497..89152fa 100644 --- a/replyParser.go +++ b/replyParser.go @@ -36,14 +36,14 @@ type Reply struct { Pairs map[string]string } -func parseReply(line string) (r *Reply, err error) { +func parseReply(line string) (*Reply, error) { line = strings.TrimSpace(line) parts := strings.Split(line, " ") if len(parts) < 3 { return nil, fmt.Errorf("Malformed Reply.\n%s\n", line) } - r = &Reply{ + r := &Reply{ Topic: parts[0], Type: parts[1], Pairs: make(map[string]string, len(parts)-2), @@ -57,5 +57,5 @@ func parseReply(line string) (r *Reply, err error) { r.Pairs[kvPair[0]] = kvPair[1] } - return + return r, nil } diff --git a/sessions.go b/sessions.go index 94e19a4..b6725be 100644 --- a/sessions.go +++ b/sessions.go @@ -13,32 +13,26 @@ func init() { // CreateStreamSession creates a new STREAM Session. // Returns the Id for the new Client. -func (c *Client) CreateStreamSession(dest string) (id int32, newDest string, err error) { +func (c *Client) CreateStreamSession(dest string) (int32, string, error) { if dest == "" { dest = "TRANSIENT" } - var r *Reply - - id = rand.Int31n(math.MaxInt32) - createCmd := fmt.Sprintf("SESSION CREATE STYLE=STREAM ID=%d DESTINATION=%s", id, dest) - r, err = c.sendCmd(createCmd) + id := rand.Int31n(math.MaxInt32) + r, err := c.sendCmd("SESSION CREATE STYLE=STREAM ID=%d DESTINATION=%s\n", id, dest) if err != nil { - return + return -1, "", err } + // TODO: move check into sendCmd() if r.Topic != "SESSION" || r.Type != "STATUS" { - err = fmt.Errorf("Unknown Reply: %+v\n", r) - return + return -1, "", fmt.Errorf("Unknown Reply: %+v\n", r) } result := r.Pairs["RESULT"] if result != "OK" { - err = ReplyError{ResultKeyNotFound, r} - return + return -1, "", ReplyError{ResultKeyNotFound, r} } - newDest = r.Pairs["DESTINATION"] - - return + return id, r.Pairs["DESTINATION"], nil } diff --git a/stream.go b/stream.go index 92f63c6..1b79370 100644 --- a/stream.go +++ b/stream.go @@ -5,14 +5,13 @@ 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) (err error) { - var r *Reply - - r, err = c.sendCmd(fmt.Sprintf("STREAM CONNECT ID=%d DESTINATION=%s", id, dest)) +func (c *Client) StreamConnect(id int32, dest string) error { + r, err := c.sendCmd("STREAM CONNECT ID=%d DESTINATION=%s\n", id, dest) if err != nil { return err } + // TODO: move check into sendCmd() if r.Topic != "STREAM" || r.Type != "STATUS" { return fmt.Errorf("Unknown Reply: %+v\n", r) } @@ -26,13 +25,13 @@ func (c *Client) StreamConnect(id int32, dest string) (err error) { } // StreamAccept asks SAM to accept a TCP-Like connection -func (c *Client) StreamAccept(id int32) (r *Reply, err error) { - - r, err = c.sendCmd(fmt.Sprintf("STREAM ACCEPT ID=%d SILENT=false", id)) +func (c *Client) StreamAccept(id int32) (*Reply, error) { + r, err := c.sendCmd("STREAM ACCEPT ID=%d SILENT=false\n", id) if err != nil { return nil, err } + // TODO: move check into sendCmd() if r.Topic != "STREAM" || r.Type != "STATUS" { return nil, fmt.Errorf("Unknown Reply: %+v\n", r) }