예제 #1
0
// applyDeltaOnce pushes one piece of info into the network
func (srv *Server) applyDeltaOnce(key ChordKey, meta Neighbor) {
	kilog.Debug("directory: beginning push to %x", key.ToBytes())
	rawsok, err := kiricom.EasyDial(fmt.Sprintf("%v:%v", meta.Address, meta.Port),
		nil,
		meta.Secret)
	if err != nil {
		kilog.Debug("directory: push to %x failed due to %v", key.ToBytes(), err.Error())
		return
	}
	defer rawsok.Close()

	sok, err := kiss.KiSSAnonHandshake(kiss.NewDirectVerifier(meta.PubKey), rawsok)
	if err != nil {
		kilog.Debug("directory: push to %x failed in KiSS due to %v", key.ToBytes(), err.Error())
		return
	}
	defer sok.Close()

	srv.Lock()
	neighs, err := srv.crd.Neighs(key)
	if err != nil {
		panic("WTF is going on here")
	}
	srv.Unlock()
	var msg textprot.NeighInfo
	// expires 1hr from now
	msg.Json.Expires = int(time.Now().Add(time.Hour).Unix())
	msg.Json.IssuedTo = meta.PubKey
	for _, nay := range neighs {
		msg.Json.NeighList = append(msg.Json.NeighList, nay.ToBytes())
	}
	msg.Signat = srv.prv.Sign(msg.Json.HashValue())
	// send the message
	req := textprot.TextReq{
		Verb: "NEIGH_PUSH",
		Blob: msg.ToString(),
	}
	err = req.WriteTo(sok)
	if err != nil {
		kilog.Debug("directory: push to %x failed while pushing due to %v", key.ToBytes(), err.Error())
		return
	}
	//fmt.Println(msg.ToString())
	// get msg back
	err = req.ReadFrom(sok)
	if err != nil {
		kilog.Debug("directory: push to %x failed at the final stage", key.ToBytes())
		return
	}
	kilog.Debug("directory: push to %x succeeded", key.ToBytes())
}
예제 #2
0
// NewClient creates a client from the given first-node information.
func NewClient(first directory.Neighbor) (toret *Client, err error) {
	// kissless kiricom
	sok, err := kiricom.EasyDial(
		fmt.Sprintf("%v:%v", first.Address, first.Port),
		nil,
		first.Secret)
	if err != nil {
		return
	}
	// negotiate KiSS
	secsok, err := kiss.KiSSAnonHandshake(kiss.NewDirectVerifier(first.PubKey), sok)
	if err != nil {
		return
	}
	// return the client
	toret = &Client{
		sok:   secsok,
		pklst: []natrium.EdDSAPublic{first.PubKey},
	}
	return
}
예제 #3
0
// ConnectNext connects to the next hop, identified by public key
func (clnt *Client) ConnectNext(nxpub natrium.EdDSAPublic) error {
	req := textprot.TextReq{
		Verb: "NEIGH_CONNECT",
		Args: []string{hex.EncodeToString(nxpub)},
	}
	_, err := clnt.execCmd(req)
	if err != nil {
		return err
	}
	// now negotiate KiSS
	newsok, err := kiss.KiSSAnonHandshake(kiss.NewDirectVerifier(nxpub), clnt.sok)
	if err != nil {
		clnt.sok.Close()
		return ErrBadSocket
	}
	clnt.sok = newsok
	clnt.pklst = append(clnt.pklst, nxpub)

	clnt.circlen++

	return nil
}
예제 #4
0
// EasyDial dials to a target address (in `host:port` form) using Kiricom over hlObfs.
// `secret` may be specified, or it may be nil, in which case the default secret is implied.
//
// When `verify` is nil, KiSS is not used at all.
func EasyDial(targetAddr string, verify kiss.Verifier, secret []byte) (io.ReadWriteCloser, error) {
	dialState.Lock()
	res, ok := dialState.table[targetAddr]
	if !ok {
		raw, err := net.Dial("tcp", targetAddr)
		if err != nil {
			dialState.Unlock()
			return nil, err
		}
		raw.(*net.TCPConn).SetNoDelay(true)
		sec, err := kiss.LLObfsClientHandshake(secret, raw)
		if err != nil {
			dialState.Unlock()
			return nil, err
		}
		if verify != nil {
			sec, err = kiss.KiSSAnonHandshake(verify, sec)
			if err != nil {
				dialState.Unlock()
				return nil, err
			}
		}
		state := NewClientCtx(32768, sec)
		dialState.table[targetAddr] = state
		dialState.Unlock()
		return state.Dial()
	}
	dialState.Unlock()
	toret, err := res.Dial()
	if err != nil {
		kilog.Debug("kiricom: EasyDial error: %v", err.Error())
		dialState.Lock()
		delete(dialState.table, targetAddr)
		dialState.Unlock()
		return nil, err
	}
	return toret, nil
}
예제 #5
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
}