package main import ( "flag" "fmt" "bytes" iroh "git.coopcloud.tech/decentral1se/iroh-go" "gomod.cblgh.org/iroh-tracker/util" "gomod.cblgh.org/iroh-tracker/proto" ) var ( alpn = util.GetALPN(proto.VERSION) trackerEndpointID string readkey string topic string ) func parseFlags() { flag.StringVar(&readkey, "readkey", "client-hello-there-iroh-tracker", "iroh tracker read key") flag.StringVar(&trackerEndpointID, "endpoint", "", "endpoint id of peer") flag.StringVar(&topic, "topic", "test-topic", "topic to announce & query on") flag.Parse() } func ClientHello() []byte { return []byte(fmt.Sprintf("V%d/CLIENT/HELLO/%x", proto.VERSION, util.TwiceHashedKey(readkey))) } func ClientPut() []byte { // NOTE: twice hashed topic return []byte(fmt.Sprintf("V%d/CLIENT/PUT/%x", proto.VERSION, util.TwiceHashedKey(topic))) } func ClientGet() []byte { // NOTE: twice hashed topic return []byte(fmt.Sprintf("V%d/CLIENT/GET/%x", proto.VERSION, util.TwiceHashedKey(topic))) } func start(e *iroh.Endpoint, id string, done chan struct{}) { remote, err := iroh.EndpointIdFromString(id) util.Check(err) addr := iroh.NewEndpointAddr(remote, nil, nil) conn, err := e.Connect(addr, alpn) util.Check(err) // from docs: // "The peer that calls open_bi must write to its SendStream before the peer Connection is able to accept the stream // using accept_bi()" // https://docs.rs/iroh/latest/iroh/endpoint/struct.Connection.html#method.accept_bi stream, err := conn.OpenBi() util.Check(err) responseCh := make(chan []byte) processClosure := func(incoming []byte) ([]byte, bool) { if bytes.Equal(incoming, []byte("HELLO:welcome")) { fmt.Println("welcome OK!") return ClientPut(), true } if bytes.Equal(incoming, []byte("PUT:OK")) { fmt.Println("PUT OK!") return ClientGet(), true } if endpointList, exists := bytes.CutPrefix(incoming, []byte("GET:")); exists { // endpoints := bytes.Split(endpointList, []byte(",")) fmt.Printf("GET:%s\n", string(endpointList)) // we got what we came for close(done) return nil, false } return nil, false } go util.HandleReading(stream.Recv(), processClosure, responseCh, done) go util.SendResponses(stream.Send(), responseCh, done) // open bidi stream with client hello message responseCh <- ClientHello() util.Check(err) } func main() { parseFlags() preset := iroh.PresetN0() opts := iroh.EndpointOptions{ Preset: &preset, Alpns: &[][]byte{alpn}, } clientEndpoint, err := iroh.EndpointBind(opts) util.Check(err) done := make(chan struct{}) go func() { start(clientEndpoint, trackerEndpointID, done) }() <-done }