func runCore(id directory.Client) { state := core2core.NewNodeState(dirProvider, id) addr := id.GetAddress() srv, err := kiricom.EasyListen(fmt.Sprintf("0.0.0.0:%v", addr.Port), nil, id.GetSecret()) if err != nil { panic(err.Error()) } err = dirProvider.JoinCore(id) if err != nil { panic(err.Error()) } go func() { for { time.Sleep(time.Minute * 5) err = dirProvider.JoinCore(id) if err != nil { kilog.Warning("core: error while joining %v", err.Error()) } } }() fmt.Println(id.GetAddress()) kilog.Info("started core service on %v", addr) for { client, err := srv.Accept() if err != nil { panic(err.Error()) } kilog.Debug("core: accepted a client") go func() { err := state.HandleClient(client) if err != nil { kilog.Warning("core: error %v", err) } }() } }
func handleControl(clnt io.ReadWriteCloser) { defer clnt.Close() greeting := ctlGreeting{0xCACACACA, ctlVersion{0, 0, 0}, socksPort} // 0.0.0 means unnumbered version err := struc.Pack(clnt, &greeting) if err != nil { kilog.Debug("unable to write control greeting: %v", err.Error()) return } var command ctlCommand err = struc.Unpack(clnt, &command) if err != nil { kilog.Debug("unable to read control command: %v", err.Error()) return } var response ctlResponse defer struc.Pack(clnt, &response) // do the actual work switch command.Verb { case ctlCmdNOOP: return case ctlCmdHOST: kilog.Debug("received control request to forward port %v to %v, with %v", command.IntPort, command.ExtPort, command.PrivKey) ctlState.RLock() _, ok := ctlState.prt2prv[command.ExtPort] ctlState.RUnlock() if ok { kilog.Debug("port %v already occupied, refusing request!", command.ExtPort) response.Verb = ctlRespNOPE response.Name = "port already occupied" return } ctlState.Lock() defer ctlState.Unlock() newlistnr, err := kiricom.EasyListen(fmt.Sprintf("0.0.0.0:%v", command.ExtPort), command.PrivKey, command.PrivKey.PublicKey()) kilog.Debug("startControl secret is %x", command.PrivKey.PublicKey()) if err != nil { kilog.Debug("could not create ICOM listener") response.Verb = ctlRespNOPE response.Name = err.Error() return } ctlState.prt2lst[command.ExtPort] = newlistnr ctlState.prt2prv[command.ExtPort] = command.PrivKey response.Verb = ctlRespOKAY pubip, err := getPublicIP() if err != nil { kilog.Critical("computer does not seem to have an Internet connection; dying!") os.Exit(-1) } response.Name = sagiriNames.EdgeID{command.PrivKey.PublicKey(), pubip, uint16(command.ExtPort)}.String() groop, err := newServGroup(command.PrivKey) if err != nil { kilog.Debug("host: could not start servGroup %v", err.Error()) return } // time to spin off threads to forward the connections handle := func(clnt io.ReadWriteCloser) { defer clnt.Close() fwd, err := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%v", command.IntPort)) if err != nil { kilog.Debug("host: could not forward %v", err.Error()) return } kilog.Debug("host: completed forwarding") defer fwd.Close() go func() { defer fwd.Close() defer clnt.Close() io.Copy(fwd, clnt) }() io.Copy(clnt, fwd) } go func() { defer newlistnr.Close() defer groop.Destroy() for { clnt, err := newlistnr.Accept() if err != nil { kilog.Debug("host: direct error %v", err.Error()) return } go handle(clnt) } }() go func() { defer groop.Destroy() defer newlistnr.Close() REDO: for { clnt, err := groop.Accept() if err != nil { kilog.Debug("host: onion error %v", err.Error()) groop.Destroy() groop, err = newServGroup(command.PrivKey) if err != nil { kilog.Debug(err.Error()) time.Sleep(time.Second) } goto REDO } go handle(clnt) } }() case ctlCmdSTOP: ctlState.Lock() defer ctlState.Unlock() _, ok := ctlState.prt2lst[command.ExtPort] if !ok { response.Verb = ctlRespNOPE response.Name = "no service with the given port" return } rlPriv := ctlState.prt2prv[command.ExtPort] if subtle.ConstantTimeCompare(rlPriv, command.PrivKey) != 1 { response.Verb = ctlRespNOPE response.Name = "given private key incorrect, refusing to remove" return } delete(ctlState.prt2prv, command.ExtPort) ctlState.prt2lst[command.ExtPort].Close() response.Verb = ctlRespOKAY } }
func TestDirectoryCoreEdge(t *testing.T) { spinTestDir() defer stopTestDir() for i := 0; i < 10; i++ { //time.Sleep(time.Second) clnt := directory.NewClient(natrium.EdDSAGenerateKey()) prv := directory.DefaultProvider("127.0.0.1:12345") addr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:0") __lol, err := net.ListenTCP("tcp", addr) if err != nil { panic(err.Error()) } clnt.SetAddress(__lol.Addr().(*net.TCPAddr)) addr = __lol.Addr().(*net.TCPAddr) __lol.Close() lol, err := kiricom.EasyListen(addr.String(), nil, clnt.GetSecret()) if err != nil { panic(err.Error()) } defer lol.Close() state := NewNodeState(prv, clnt) go func() { for { clnt, err := lol.Accept() if err != nil { return } go func() { defer clnt.Close() err := state.HandleClient(clnt) if err != nil { kilog.Debug(err.Error()) } }() } }() err = prv.JoinCore(clnt) if err != nil { log.Fatal(err.Error()) } } time.Sleep(time.Second * 2) clnt := directory.NewClient(natrium.EdDSAGenerateKey()) prv := directory.DefaultProvider("127.0.0.1:12345") neiz, err := prv.JoinEdge(clnt) if err != nil { panic(err.Error()) } fmt.Println(neiz) // route in a circle func() { spider, err := NewClient(neiz[0]) if err != nil { panic(err.Error()) } defer spider.Destroy() for i := 0; i < 11; i++ { fmt.Println(spider.curpk) lawl, err := spider.ListNeighs() if err != nil { panic(err.Error()) } err = spider.ConnectNext(lawl[0]) if err != nil { panic(err.Error()) } //time.Sleep(time.Second) } }() fmt.Println("--- ROUTING DONE ---") // time to test ambassadors! func() { alpha, err := NewClient(neiz[0]) if err != nil { panic(err.Error()) } beta, err := NewClient(neiz[0]) if err != nil { panic(err.Error()) } defer alpha.Destroy() defer beta.Destroy() // alpha registers, beta connects id := natrium.EdDSAGenerateKey() srv, err := alpha.RegAmbassador(id.PublicKey()) if err != nil { panic(err.Error()) } clnt, err := beta.ConnAmbassador(id.PublicKey()) if err != nil { panic(err.Error()) } // throwaway echo server go func() { lol, err := srv.Accept() if err != nil { panic(err.Error()) } defer lol.Close() io.Copy(lol, lol) }() // test with random stuff xaxa := make([]byte, 16) rand.Read(xaxa) sok, err := clnt.Dial() if err != nil { panic(err.Error()) } sok.Write(xaxa) resp := make([]byte, 16) io.ReadFull(sok, resp) fmt.Printf("%x\n", xaxa) fmt.Printf("%x\n", resp) if subtle.ConstantTimeCompare(resp, xaxa) != 1 { t.Fatal("ambassador broken") } }() fmt.Println("--- AMBASSADOR DONE ---") }