func (sg *servGroup) connAmb(i int) (*kiricom.ServerCtx, error) { nonce := make([]byte, 8) binary.BigEndian.PutUint64(nonce, uint64(i)) hash := natrium.SecureHash(sg.aidee.PublicKey(), nonce) kilog.Debug("serv: building circuit %v -> %x for %v", i, hash, sg.aidee.PublicKey()) var tgt directory.ChordKey tgt.FromBytes(hash) // build circuit to each and every one of them thingy, err := buildCirc(tgt) if err != nil { //thingy.Destroy() return nil, err } haha, err := thingy.RegAmbassador(sg.aidee.PublicKey()) if err != nil { thingy.Destroy() if err == core2core.ErrRejectedReq { kilog.Warning("serv: circuit number %v for %v rejected", i, sg.aidee.PublicKey()) return nil, err } else { return nil, err } } return haha, nil }
func buildCirc(tgt directory.ChordKey) (*core2core.Client, error) { // find the closest neighbor to the destination circPool.Lock() nxt := circPool.neighs[0] for _, v := range circPool.neighs[1:] { var vkee directory.ChordKey var xkee directory.ChordKey vkee.FromBytes(v.PubKey) xkee.FromBytes(nxt.PubKey) if vkee.Distance(tgt).Cmp(xkee.Distance(tgt)) == -1 { nxt = v } } circPool.Unlock() kilog.Debug("circ: closest neighbor to %x is %v", tgt.ToBytes(), nxt.PubKey) // begin to route spider, err := core2core.NewClient(nxt) if err != nil { return nil, err } //defer spider.Destroy() // loop closest := false for !closest { neighs, err := spider.ListNeighs() if err != nil { spider.Destroy() return nil, err } if len(neighs) == 0 { kilog.Warning("circ: topology anomaly! node with no neighbors!") spider.Destroy() return nil, err } better := spider.CurrentPublic() closest = true // can we find a closer one? for _, cand := range neighs { var candkee directory.ChordKey var currkee directory.ChordKey candkee.FromBytes(cand) currkee.FromBytes(better) if candkee.Distance(tgt).Cmp(currkee.Distance(tgt)) == -1 { better = cand closest = false } } // connect to the next hop if !closest { kilog.Debug("circ: circuit to %x extending to %v", tgt.ToBytes(), better) err = spider.ConnectNext(better) if err != nil { spider.Destroy() return nil, err } } } return spider, nil }
// connect to the service identified by the public key func dialPubKey(pub natrium.EdDSAPublic) (io.ReadWriteCloser, error) { kilog.Debug("circ: beginning to dial %v", pub) var key directory.ChordKey key.FromBytes(pub) circPool.Lock() if len(circPool.neighs) == 0 { circPool.Unlock() return nil, ErrNoRoute } once, ok := circPool.onceTab[key] if !ok { kilog.Debug("circ: %v is a new destination, will have to build a fresh one", pub) once = new(sync.Once) circPool.onceTab[key] = once } circPool.Unlock() once.Do(func() { kilog.Debug("circ: entered atomic action for %v", pub) defer kilog.Debug("circ: leaving atomic action for %v", pub) thing, err := newCircGroup(pub) if err != nil { kilog.Debug("circ: rolling back %v due to %v", pub, err.Error()) circPool.Lock() delete(circPool.onceTab, key) circPool.Unlock() return } circPool.Lock() circPool.dialTab[key] = thing circPool.Unlock() }) circPool.Lock() thing, ok := circPool.dialTab[key] circPool.Unlock() if !ok { return nil, ErrNoRoute } raah, err := thing.Dial() if err != nil { thing.Destroy() circPool.Lock() if circPool.onceTab[key] != nil { delete(circPool.onceTab, key) } if circPool.dialTab[key] != nil { delete(circPool.dialTab, key) } circPool.Unlock() return nil, err } toret, err := kiss.KiSSAnonHandshake(kiss.NewDirectVerifier(pub), raah) if err != nil { thing.Destroy() circPool.Lock() if circPool.onceTab[key] != nil { delete(circPool.onceTab, key) } if circPool.dialTab[key] != nil { delete(circPool.dialTab, key) } circPool.Unlock() return nil, err } return toret, nil }