Trying to implement Dial for usage with http.Transport
This commit is contained in:
@ -3,12 +3,11 @@ package goSam
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"net"
|
"net"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
samConn io.ReadWriteCloser
|
samConn net.Conn
|
||||||
|
|
||||||
fromSam *bufio.Reader
|
fromSam *bufio.Reader
|
||||||
toSam *bufio.Writer
|
toSam *bufio.Writer
|
||||||
|
42
dial.go
Normal file
42
dial.go
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package goSam
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// implements the net.Dial function to be used as http.Transport
|
||||||
|
func (c *Client) Dial(network, addr string) (net.Conn, error) {
|
||||||
|
addr = addr[:strings.Index(addr, ":")]
|
||||||
|
addr, err := c.Lookup(addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Dial Lookup:", addr)
|
||||||
|
|
||||||
|
id, _, err := c.createStreamSession("")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
newC, err := NewDefaultClient()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if newC.Hello() != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("newC Hello OK")
|
||||||
|
|
||||||
|
if newC.StreamConnect(id, addr) != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("StreamConnect OK")
|
||||||
|
|
||||||
|
return newC.samConn, nil
|
||||||
|
}
|
34
naming.go
34
naming.go
@ -4,26 +4,25 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Result int
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ResultOk Result = iota //Operation completed successfully
|
ResultOk = "OK" //Operation completed successfully
|
||||||
ResultCantReachPeer //The peer exists, but cannot be reached
|
ResultCantReachPeer = "CANT_REACH_PEER" //The peer exists, but cannot be reached
|
||||||
ResultDuplicatedDest //The specified Destination is already in use
|
ResultDuplicatedId = "DUPLICATED_ID" //If the nickname is already associated with a session :
|
||||||
ResultI2PError //A generic I2P error (e.g. I2CP disconnection, etc.)
|
ResultDuplicatedDest = "DUPLICATED_DEST" //The specified Destination is already in use
|
||||||
ResultInvalidKey //The specified key is not valid (bad format, etc.)
|
ResultI2PError = "I2P_ERROR" //A generic I2P error (e.g. I2CP disconnection, etc.)
|
||||||
ResultKeyNotFound //The naming system can't resolve the given name
|
ResultInvalidKey = "INVALID_KEY" //The specified key is not valid (bad format, etc.)
|
||||||
ResultPeerNotFound //The peer cannot be found on the network
|
ResultKeyNotFound = "KEY_NOT_FOUND" //The naming system can't resolve the given name
|
||||||
ResultTimeout // Timeout while waiting for an event (e.g. peer answer)
|
ResultPeerNotFound = "PEER_NOT_FOUND" //The peer cannot be found on the network
|
||||||
|
ResultTimeout = "TIMEOUT" // Timeout while waiting for an event (e.g. peer answer)
|
||||||
)
|
)
|
||||||
|
|
||||||
type ReplyError struct {
|
type ReplyError struct {
|
||||||
Result Result
|
Result string
|
||||||
Reply *Reply
|
Reply *Reply
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r ReplyError) Error() string {
|
func (r ReplyError) Error() string {
|
||||||
return fmt.Sprintf("ReplyError: Result:%d - Reply:%+v", r.Reply)
|
return fmt.Sprintf("ReplyError: Result:%s - Reply:%+v", r.Result, r.Reply)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) Lookup(name string) (addr string, err error) {
|
func (c *Client) Lookup(name string) (addr string, err error) {
|
||||||
@ -40,7 +39,7 @@ func (c *Client) Lookup(name string) (addr string, err error) {
|
|||||||
line string
|
line string
|
||||||
r *Reply
|
r *Reply
|
||||||
)
|
)
|
||||||
for {
|
|
||||||
line, err = c.fromSam.ReadString('\n')
|
line, err = c.fromSam.ReadString('\n')
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -48,12 +47,12 @@ func (c *Client) Lookup(name string) (addr string, err error) {
|
|||||||
|
|
||||||
r, err = parseReply(line)
|
r, err = parseReply(line)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.Topic != "NAMING" || r.Type != "REPLY" {
|
if r.Topic != "NAMING" || r.Type != "REPLY" {
|
||||||
err = fmt.Errorf("Unknown Reply: %+v\n", r)
|
err = fmt.Errorf("Unknown Reply: %+v\n", r)
|
||||||
break
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
switch r.Pairs["RESULT"] {
|
switch r.Pairs["RESULT"] {
|
||||||
@ -62,14 +61,11 @@ func (c *Client) Lookup(name string) (addr string, err error) {
|
|||||||
return
|
return
|
||||||
case "KEY_NOT_FOUND":
|
case "KEY_NOT_FOUND":
|
||||||
err = ReplyError{ResultKeyNotFound, r}
|
err = ReplyError{ResultKeyNotFound, r}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.Pairs["NAME"] != name {
|
if r.Pairs["NAME"] != name {
|
||||||
err = fmt.Errorf("i2p Replyied with: %+v\n", r)
|
err = fmt.Errorf("i2p Replyied with: %+v\n", r)
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
66
sessions.go
Normal file
66
sessions.go
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package goSam
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"math/rand"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *Client) createStreamSession(dest string) (id int32, newDest string, err error) {
|
||||||
|
if dest == "" {
|
||||||
|
dest = "TRANSIENT"
|
||||||
|
}
|
||||||
|
|
||||||
|
id = rand.Int31n(math.MaxInt32)
|
||||||
|
createCmd := fmt.Sprintf("SESSION CREATE STYLE=STREAM ID=%d DESTINATION=%s\n", id, dest)
|
||||||
|
_, err = c.toSam.WriteString(createCmd)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = c.toSam.Flush(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
line string
|
||||||
|
r *Reply
|
||||||
|
)
|
||||||
|
|
||||||
|
line, err = c.fromSam.ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println("createStreamSession line:", line)
|
||||||
|
|
||||||
|
r, err = parseReply(line)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.Topic != "SESSION" || r.Type != "STATUS" {
|
||||||
|
err = fmt.Errorf("Unknown Reply: %+v\n", r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch r.Pairs["RESULT"] {
|
||||||
|
case ResultOk:
|
||||||
|
fmt.Println("createStreamSession created")
|
||||||
|
newDest = r.Pairs["DESTINATION"]
|
||||||
|
return
|
||||||
|
case ResultDuplicatedId:
|
||||||
|
err = ReplyError{ResultDuplicatedId, r}
|
||||||
|
return
|
||||||
|
case ResultDuplicatedDest:
|
||||||
|
err = ReplyError{ResultDuplicatedDest, r}
|
||||||
|
return
|
||||||
|
case ResultInvalidKey:
|
||||||
|
err = ReplyError{ResultInvalidKey, r}
|
||||||
|
return
|
||||||
|
case ResultI2PError:
|
||||||
|
err = ReplyError{ResultKeyNotFound, r}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
52
stream.go
Normal file
52
stream.go
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
package goSam
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *Client) StreamConnect(id int32, dest string) error {
|
||||||
|
connectCmd := fmt.Sprintf("STREAM CONNECT ID=%d DESTINATION=%s\n", id, dest)
|
||||||
|
_, err := c.toSam.WriteString(connectCmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = c.toSam.Flush(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
line string
|
||||||
|
r *Reply
|
||||||
|
)
|
||||||
|
|
||||||
|
line, err = c.fromSam.ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
r, err = parseReply(line)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.Topic != "STREAM" || r.Type != "STATUS" {
|
||||||
|
return fmt.Errorf("Unknown Reply: %+v\n", r)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch r.Pairs["RESULT"] {
|
||||||
|
case ResultOk:
|
||||||
|
fmt.Println("StreamConnect OK")
|
||||||
|
return nil
|
||||||
|
case ResultDuplicatedId:
|
||||||
|
return ReplyError{ResultDuplicatedId, r}
|
||||||
|
case ResultDuplicatedDest:
|
||||||
|
return ReplyError{ResultDuplicatedDest, r}
|
||||||
|
case ResultInvalidKey:
|
||||||
|
return ReplyError{ResultInvalidKey, r}
|
||||||
|
case ResultI2PError:
|
||||||
|
return ReplyError{ResultKeyNotFound, r}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
Reference in New Issue
Block a user