Files
nym/sdk/ffi/go/proxy_example.go
mfahampshire 9b6b2117dd Max/general abstraction updates (#5560)
- new instance of echo server with lib / cli split 
- echo server docs update 
- tcpproxy and echosever now listen for kill signal 
- ffi bindings of tcpproxy functions updated
2025-05-14 15:51:18 +00:00

159 lines
4.0 KiB
Go

package main
import (
"bufio"
"fmt"
"net"
"nymffi/go-nym/bindings"
"os"
"time"
)
func runProxyClient() {
run_err := bindings.RunProxyClient()
if run_err != nil {
fmt.Println(run_err)
return
}
}
func runProxyServer() {
run_err := bindings.RunProxyServer()
if run_err != nil {
fmt.Println(run_err)
return
}
}
// connects to the proxy server and listens out for incoming as you would with a normal tcp connection
func startTcpListener() {
ln, err := net.Listen("tcp", ":9000")
if err != nil {
fmt.Println(err)
return
}
for {
conn, err := ln.Accept()
if err != nil {
fmt.Println(err)
continue
}
go handleConnection(conn)
}
}
func handleConnection(conn net.Conn) {
defer conn.Close()
buf := make([]byte, 1024)
_, err := conn.Read(buf)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("Server-side tcp received: %s", buf)
_, err = conn.Write(buf)
if err != nil {
fmt.Println(err)
return
}
}
/*
Flow showing:
- setting up Nym client logging
- creating instances of both the NymProxyClient and NymProxyServer
- running both in goroutines to kick off the process
- starting a vanilla tcp listener/echo in a goroutine connected to the ProxyServer instance
- pinging that via a tcp client and waiting for the reply: this is (under the hood) sent anonymously via SURBs - the ProxyServer and 'server-side' tcp listener never know the Nym address or IP of the ProxyClient/'client-side' tcp client.
*/
func main() {
// our mixnet client config file defining which network to use
var env_path = "../../../envs/canary.env"
// the tcp socket our server communicates with - the remote host your client is trying to hit
var upstreamAddress = "127.0.0.1:9000"
// where the keys and persistent storage for SURBs is located (this path will be prepended with the value of $HOME in the rust lib)
var configDir = "/tmp/go-proxy-server-example"
// tcp socket port our proxy client communicates with
var clientPort = "8080"
// timeout for ephemeral client to shutdown connection after sending Close message enum once it has sent all of the other messages (in seconds): this is used by the ProxyServer for session management
var clientTimeout uint64 = 60
bindings.InitLogging()
// checking loading proper env
file, err := os.Open(env_path)
if err != nil {
fmt.Println("Error opening file:", err)
return
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
// init a proxy server
build_serv_err := bindings.NewProxyServer(upstreamAddress, configDir, &env_path, nil)
if build_serv_err != nil {
fmt.Println(build_serv_err)
return
}
// get proxy addr
proxyAddr, get_addr_err := bindings.ProxyServerAddress()
if get_addr_err != nil {
fmt.Println("(Go) Error:", get_addr_err)
return
}
fmt.Println("(Go) server address:")
fmt.Println(proxyAddr)
// run it in a goroutine
go runProxyServer()
// initialise a proxy client
build_err := bindings.NewProxyClient(proxyAddr, "127.0.0.1", clientPort, clientTimeout, &env_path, 2)
if build_err != nil {
fmt.Println(build_err)
return
}
// run it in a goroutine
go runProxyClient()
// connect 'server-side' tcp socket to ProxyServer
go startTcpListener()
// send a oneshot message, wait for the echo, and close. you will see the session uuid info and the fact that the proxy_client logs it will be closing the session in <clientTimeout>.
conn, err := net.Dial("tcp", "localhost:8080")
if err != nil {
fmt.Println(err)
return
}
_, err = conn.Write([]byte("Hello, server: oneshot ping\n"))
if err != nil {
fmt.Println(err)
return
}
buf := make([]byte, 1024)
_, read_err := conn.Read(buf)
if read_err != nil {
fmt.Println(read_err)
return
}
fmt.Printf("Client-side tcp received: %s", buf)
conn.Close()
// sleep so that the nym client processes can catch up - in reality you'd have another process
// running to keep logging going, so this is only necessary for this reference
time.Sleep(60 * time.Second)
fmt.Println("(Go) end go example")
}