예제 #1
0
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
}
예제 #2
0
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
}
예제 #3
0
// 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
}