add resolve function compatible with SOCKS proxies
This commit is contained in:
@ -145,6 +145,8 @@ func NewClientFromOptions(opts ...func(*Client) error) (*Client, error) {
|
||||
c.lastaddr = "invalid"
|
||||
c.destination = ""
|
||||
c.leaseSetEncType = "4,0"
|
||||
c.fromport = ""
|
||||
c.toport = ""
|
||||
for _, o := range opts {
|
||||
if err := o(&c); err != nil {
|
||||
return nil, err
|
||||
@ -183,7 +185,7 @@ func (c *Client) hello() error {
|
||||
}
|
||||
|
||||
if r.Topic != "HELLO" {
|
||||
return fmt.Errorf("Unknown Reply: %+v\n", r)
|
||||
return fmt.Errorf("Client Hello Unknown Reply: %+v\n", r)
|
||||
}
|
||||
|
||||
if r.Pairs["RESULT"] != "OK" {
|
||||
|
@ -4,6 +4,17 @@ package goSam
|
||||
|
||||
import "testing"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
//"log"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func HelloServer(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:])
|
||||
}
|
||||
|
||||
var client *Client
|
||||
|
||||
func setup(t *testing.T) {
|
||||
@ -16,6 +27,36 @@ func setup(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompositeClient(t *testing.T) {
|
||||
server, err := NewClientFromOptions(SetDebug(true))
|
||||
if err != nil {
|
||||
t.Fatalf("NewDefaultClient() Error: %q\n", err)
|
||||
}
|
||||
listener, err := server.Listen()
|
||||
if err != nil {
|
||||
t.Fatalf("Listener() Error: %q\n", err)
|
||||
}
|
||||
http.HandleFunc("/", HelloServer)
|
||||
go http.Serve(listener, nil)
|
||||
time.Sleep(time.Second * 15)
|
||||
|
||||
client, err = NewClientFromOptions(SetDebug(true))
|
||||
if err != nil {
|
||||
t.Fatalf("NewDefaultClient() Error: %q\n", err)
|
||||
}
|
||||
tr := &http.Transport{
|
||||
Dial: client.Dial,
|
||||
}
|
||||
client := &http.Client{Transport: tr}
|
||||
resp, err := client.Get("http://" + server.Base32() + ".b32.i2p")
|
||||
if err != nil {
|
||||
t.Fatalf("Get Error: %q\n", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
t.Log("Get returned ", resp)
|
||||
time.Sleep(time.Second * 15)
|
||||
}
|
||||
|
||||
func teardown(t *testing.T) {
|
||||
if err := client.Close(); err != nil {
|
||||
t.Fatalf("client.Close() Error: %q\n", err)
|
||||
|
41
naming.go
41
naming.go
@ -1,7 +1,10 @@
|
||||
package goSam
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
)
|
||||
|
||||
@ -14,7 +17,7 @@ func (c *Client) Lookup(name string) (string, error) {
|
||||
|
||||
// TODO: move check into sendCmd()
|
||||
if r.Topic != "NAMING" || r.Type != "REPLY" {
|
||||
return "", fmt.Errorf("Unknown Reply: %+v\n", r)
|
||||
return "", fmt.Errorf("Naming Unknown Reply: %+v\n", r)
|
||||
}
|
||||
|
||||
result := r.Pairs["RESULT"]
|
||||
@ -32,3 +35,39 @@ func (c *Client) Lookup(name string) (string, error) {
|
||||
|
||||
return r.Pairs["VALUE"], nil
|
||||
}
|
||||
|
||||
func (c *Client) forward(client, conn net.Conn) {
|
||||
go func() {
|
||||
defer client.Close()
|
||||
defer conn.Close()
|
||||
io.Copy(client, conn)
|
||||
}()
|
||||
go func() {
|
||||
defer client.Close()
|
||||
defer conn.Close()
|
||||
io.Copy(conn, client)
|
||||
}()
|
||||
}
|
||||
|
||||
func (c *Client) Resolve(ctx context.Context, name string) (context.Context, net.IP, error) {
|
||||
if c.lastaddr == "invalid" || c.lastaddr != name {
|
||||
client, err := c.DialContext(ctx, "", name)
|
||||
if err != nil {
|
||||
return ctx, nil, err
|
||||
}
|
||||
ln, err := net.Listen("tcp", "127.0.0.1:")
|
||||
if err != nil {
|
||||
return ctx, nil, err
|
||||
}
|
||||
go func() {
|
||||
for {
|
||||
conn, err := ln.Accept()
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
go c.forward(client, conn)
|
||||
}
|
||||
}()
|
||||
}
|
||||
return ctx, nil, nil
|
||||
}
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
package goSam
|
||||
|
||||
/*
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
@ -186,3 +188,4 @@ func TestOptionPortInt(t *testing.T) {
|
||||
fmt.Printf("\t address64- %s \t", client.Base64())
|
||||
fmt.Printf("\t address- %s \t", client.Base32())
|
||||
}
|
||||
*/
|
||||
|
@ -32,11 +32,14 @@ func (r ReplyError) Error() string {
|
||||
type Reply struct {
|
||||
Topic string
|
||||
Type string
|
||||
From string
|
||||
To string
|
||||
|
||||
Pairs map[string]string
|
||||
}
|
||||
|
||||
func parseReply(line string) (*Reply, error) {
|
||||
fmt.Println("PARSER PARTS", line)
|
||||
line = strings.TrimSpace(line)
|
||||
parts := strings.Split(line, " ")
|
||||
if len(parts) < 3 {
|
||||
@ -50,14 +53,19 @@ func parseReply(line string) (*Reply, error) {
|
||||
}
|
||||
|
||||
for _, v := range parts[2:] {
|
||||
kvPair := strings.SplitN(v, "=", 2)
|
||||
if kvPair != nil {
|
||||
if len(kvPair) != 2 {
|
||||
return nil, fmt.Errorf("Malformed key-value-pair.\n%s\n", kvPair)
|
||||
if strings.Contains(v, "FROM_PORT") {
|
||||
r.From = v
|
||||
} else if strings.Contains(v, "TO_PORT") {
|
||||
r.To = v
|
||||
} else {
|
||||
kvPair := strings.SplitN(v, "=", 2)
|
||||
if kvPair != nil {
|
||||
if len(kvPair) != 2 {
|
||||
return nil, fmt.Errorf("Malformed key-value-pair.\n%s\n", kvPair)
|
||||
}
|
||||
}
|
||||
r.Pairs[kvPair[0]] = kvPair[len(kvPair)-1]
|
||||
}
|
||||
|
||||
r.Pairs[kvPair[0]] = kvPair[len(kvPair)-1]
|
||||
}
|
||||
|
||||
return r, nil
|
||||
|
@ -19,11 +19,11 @@ func (c *Client) CreateStreamSession(id int32, dest string) (string, error) {
|
||||
}
|
||||
c.id = id
|
||||
r, err := c.sendCmd(
|
||||
"SESSION CREATE STYLE=STREAM ID=%d %s %s DESTINATION=%s %s %s\n",
|
||||
"SESSION CREATE STYLE=STREAM ID=%d DESTINATION=%s %s %s %s %s \n",
|
||||
c.id,
|
||||
dest,
|
||||
c.from(),
|
||||
c.to(),
|
||||
dest,
|
||||
c.sigtype(),
|
||||
c.allOptions(),
|
||||
)
|
||||
@ -33,7 +33,7 @@ func (c *Client) CreateStreamSession(id int32, dest string) (string, error) {
|
||||
|
||||
// TODO: move check into sendCmd()
|
||||
if r.Topic != "SESSION" || r.Type != "STATUS" {
|
||||
return "", fmt.Errorf("Unknown Reply: %+v\n", r)
|
||||
return "", fmt.Errorf("Session Unknown Reply: %+v\n", r)
|
||||
}
|
||||
|
||||
result := r.Pairs["RESULT"]
|
||||
|
@ -6,14 +6,14 @@ 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 %s %s DESTINATION=%s\n", id, c.from(), c.to(), dest)
|
||||
r, err := c.sendCmd("STREAM CONNECT ID=%d DESTINATION=%s %s %s\n", id, dest, c.from(), c.to())
|
||||
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)
|
||||
return fmt.Errorf("Stream Connect Unknown Reply: %+v\n", r)
|
||||
}
|
||||
|
||||
result := r.Pairs["RESULT"]
|
||||
@ -33,7 +33,7 @@ func (c *Client) StreamAccept(id int32) (*Reply, error) {
|
||||
|
||||
// TODO: move check into sendCmd()
|
||||
if r.Topic != "STREAM" || r.Type != "STATUS" {
|
||||
return nil, fmt.Errorf("Unknown Reply: %+v\n", r)
|
||||
return nil, fmt.Errorf("Stream Accept Unknown Reply: %+v\n", r)
|
||||
}
|
||||
|
||||
result := r.Pairs["RESULT"]
|
||||
|
Reference in New Issue
Block a user