Esempio n. 1
0
def testRaetPreSharedKeysPromiscous(tdir):
    alphaSigner = SimpleSigner()
    betaSigner = SimpleSigner()

    logger.debug("Alpha's verkey {}".format(alphaSigner.naclSigner.verhex))
    logger.debug("Beta's verkey {}".format(betaSigner.naclSigner.verhex))

    alpha = RoadStack(name='alpha',
                      ha=genHa(),
                      sigkey=alphaSigner.naclSigner.keyhex,
                      auto=AutoMode.always,
                      basedirpath=tdir)

    beta = RoadStack(name='beta',
                     ha=genHa(),
                     sigkey=betaSigner.naclSigner.keyhex,
                     main=True,
                     auto=AutoMode.always,
                     basedirpath=tdir)

    try:

        betaRemote = RemoteEstate(stack=alpha, ha=beta.ha,
                                  verkey=betaSigner.naclSigner.verhex)

        alpha.addRemote(betaRemote)

        alpha.allow(uid=betaRemote.uid, cascade=True)

        handshake(alpha, beta)

        sendMsgs(alpha, beta, betaRemote)

    finally:
        cleanup(alpha, beta)
Esempio n. 2
0
    def __init__(self, *args, **kwargs):

        checkPortAvailable(kwargs['ha'])
        basedirpath = kwargs.get('basedirpath')
        keep = RoadKeep(basedirpath=basedirpath,
                        stackname=kwargs['name'],
                        auto=kwargs.get('auto'),
                        baseroledirpath=basedirpath)  # type: RoadKeep
        kwargs['keep'] = keep
        localRoleData = keep.loadLocalRoleData()

        sighex = kwargs.pop('sighex', None) or localRoleData['sighex']
        if not sighex:
            (sighex, _), (prihex, _) = getEd25519AndCurve25519Keys()
        else:
            prihex = ed25519SkToCurve25519(sighex, toHex=True)
        kwargs['sigkey'] = sighex
        kwargs['prikey'] = prihex

        self.msgHandler = kwargs.pop('msgHandler', None)  # type: Callable
        # if no timeout is set then message will never timeout
        self.messageTimeout = kwargs.pop('messageTimeout', 0)

        self.raetStack = RoadStack(*args, **kwargs)

        if self.ha[1] != kwargs['ha'].port:
            error("the stack port number has changed, likely due to "
                  "information in the keep. {} passed {}, actual {}".format(
                      kwargs['name'], kwargs['ha'].port, self.ha[1]))
        self._created = time.perf_counter()
        self.coro = None

        self._conns = set()  # type: Set[str]
def testPromiscuousConnection(tdir, keysAndNames):
    # Simulating node to client connection
    alphaSighex, alphaPrikey, alphaVerhex, alphaPubkey, alphaName, betaSighex, \
    betaPrikey, betaVerhex, betaPubkey, betaName = keysAndNames
    alpha = RoadStack(name=alphaName,
                      ha=genHa(),
                      sigkey=alphaSighex,
                      prikey=hexlify(alphaPrikey),
                      auto=AutoMode.always,
                      basedirpath=tdir)

    beta = RoadStack(name=betaName,
                     ha=genHa(),
                     main=True,
                     sigkey=betaSighex,
                     prikey=hexlify(betaPrikey),
                     auto=AutoMode.always,
                     basedirpath=tdir)

    try:
        betaRemote = RemoteEstate(stack=alpha, ha=beta.ha)
        alpha.addRemote(betaRemote)

        alpha.join(uid=betaRemote.uid, cascade=True)

        handshake(alpha, beta)

        sendMsgs(alpha, beta, betaRemote)
    finally:
        cleanup(alpha, beta)
Esempio n. 4
0
def testRaetPreSharedKeysNonPromiscous(tdir):

    alphaSigner = SimpleSigner()
    betaSigner = SimpleSigner()

    alphaPrivateer = Privateer()
    betaPrivateer = Privateer()

    logger.debug("Alpha's verkey {}".format(alphaSigner.verkey))
    logger.debug("Beta's verkey {}".format(betaSigner.verkey))

    alpha = RoadStack(name='alpha',
                      ha=genHa(),
                      sigkey=alphaSigner.naclSigner.keyhex,
                      prikey=alphaPrivateer.keyhex,
                      auto=AutoMode.never,
                      basedirpath=tdir)

    beta = RoadStack(name='beta',
                     ha=genHa(),
                     sigkey=betaSigner.naclSigner.keyhex,
                     prikey=betaPrivateer.keyhex,
                     main=True,
                     auto=AutoMode.never,
                      basedirpath=tdir)

    alpha.keep.dumpRemoteRoleData({
        "acceptance": Acceptance.accepted.value,
        "verhex": betaSigner.verkey,
        "pubhex": betaPrivateer.pubhex
    }, "beta")

    beta.keep.dumpRemoteRoleData({
        "acceptance": Acceptance.accepted.value,
        "verhex": alphaSigner.verkey,
        "pubhex": alphaPrivateer.pubhex
    }, "alpha")

    try:

        betaRemote = raet.road.estating.RemoteEstate(stack=alpha,
                                                     ha=beta.ha)

        alpha.addRemote(betaRemote)

        alpha.allow(uid=betaRemote.uid, cascade=True)

        handshake(alpha, beta)

        sendMsgs(alpha, beta, betaRemote)
    finally:
        cleanup(alpha, beta)
Esempio n. 5
0
    def postinitio(self):
        '''
        Setup stack instance
        '''
        sigkey = self.local.data.sigkey
        prikey = self.local.data.prikey
        name = self.local.data.name
        dirpath = os.path.abspath(
            os.path.join(self.opts.value['cachedir'], 'raet'))
        auto = self.local.data.auto
        main = self.local.data.main
        ha = (self.opts.value['interface'], self.opts.value['raet_port'])

        eid = self.local.data.eid
        local = LocalEstate(eid=eid,
                            name=name,
                            ha=ha,
                            sigkey=sigkey,
                            prikey=prikey)
        txMsgs = self.txmsgs.value
        rxMsgs = self.rxmsgs.value
        safe = salting.SaltSafe(opts=self.opts.value)

        self.stack.value = RoadStack(local=local,
                                     store=self.store,
                                     name=name,
                                     auto=auto,
                                     main=main,
                                     dirpath=dirpath,
                                     safe=safe,
                                     txMsgs=txMsgs,
                                     rxMsgs=rxMsgs)
        self.stack.value.Bk = raeting.bodyKinds.msgpack
Esempio n. 6
0
    def action(self):
        '''
        enter action
        should only run once to setup road stack.
        moved from postinitio so can do clean up before stack is initialized

        do salt raet road stack setup at enter
        '''
        kind = self.opts.value['__role']  # application kind
        if kind not in daemons.APPL_KINDS:
            emsg = ("Invalid application kind = '{0}'.".format(kind))
            log.error(emsg + '\n')
            raise ValueError(emsg)
        role = self.opts.value.get('id', '')
        if not role:
            emsg = ("Missing role required to setup RoadStack.")
            log.error(emsg + "\n")
            raise ValueError(emsg)

        name = "{0}_{1}".format(role, kind)
        sigkey = self.local.data.sigkey
        prikey = self.local.data.prikey
        main = self.opts.value.get('raet_main', self.local.data.main)
        mutable = self.opts.value.get('raet_mutable', self.local.data.mutable)
        always = self.opts.value.get('open_mode', False)
        mutable = mutable or always  # open_made when True takes precedence
        uid = self.local.data.uid

        ha = (self.opts.value['interface'], self.opts.value['raet_port'])

        basedirpath = os.path.abspath(
            os.path.join(self.opts.value['cachedir'], 'raet'))

        txMsgs = self.txmsgs.value
        rxMsgs = self.rxmsgs.value

        keep = salting.SaltKeep(opts=self.opts.value,
                                basedirpath=basedirpath,
                                stackname=name)

        self.stack.value = RoadStack(store=self.store,
                                     keep=keep,
                                     name=name,
                                     uid=uid,
                                     ha=ha,
                                     role=role,
                                     sigkey=sigkey,
                                     prikey=prikey,
                                     main=main,
                                     kind=daemons.APPL_KINDS[kind],
                                     mutable=mutable,
                                     txMsgs=txMsgs,
                                     rxMsgs=rxMsgs,
                                     period=3.0,
                                     offset=0.5)

        if self.opts.value.get('raet_clear_remotes'):
            for remote in self.stack.value.remotes.values():
                self.stack.value.removeRemote(remote, clear=True)
            self.stack.puid = self.stack.value.Uid  # reset puid
Esempio n. 7
0
    def action(self):

        self.stats_req.value = deque()

        minionStack = self.road_stack.value

        # Create Master Stack
        self.store.stamp = 0.0
        masterStack = RoadStack(store=self.store,
                                name='master',
                                ha=('', raeting.RAET_PORT),
                                role='master',
                                main=True,
                                cleanremote=True,
                                period=3.0,
                                offset=0.5)
        self.event_stack.value = masterStack

        minionRemoteMaster = RemoteEstate(stack=minionStack,
                                          fuid=0,
                                          sid=0,
                                          ha=masterStack.local.ha)
        minionStack.addRemote(minionRemoteMaster)

        # Make life easier
        masterStack.keep.auto = raeting.AutoMode.always.value
        minionStack.keep.auto = raeting.AutoMode.always.value

        minionStack.join(minionRemoteMaster.uid)
        serviceRoads([minionStack, masterStack])
        minionStack.allow(minionRemoteMaster.uid)
        serviceRoads([minionStack, masterStack])
def testPromiscuousConnection(tdir, keysAndNames):
    # Simulating node to client connection
    alphaSighex, alphaPrikey, alphaVerhex, alphaPubkey, alphaName, betaSighex, \
    betaPrikey, betaVerhex, betaPubkey, betaName = keysAndNames
    alpha = RoadStack(name=alphaName,
                      ha=genHa(),
                      sigkey=alphaSighex,
                      prikey=hexlify(alphaPrikey),
                      auto=AutoMode.always,
                      basedirpath=tdir)

    beta = RoadStack(name=betaName,
                     ha=genHa(),
                     main=True,
                     sigkey=betaSighex,
                     prikey=hexlify(betaPrikey),
                     auto=AutoMode.always,
                     basedirpath=tdir)

    try:
        betaRemote = RemoteEstate(stack=alpha, ha=beta.ha)
        alpha.addRemote(betaRemote)

        alpha.join(uid=betaRemote.uid, cascade=True)

        handshake(alpha, beta)

        sendMsgs(alpha, beta, betaRemote)
    finally:
        cleanup(alpha, beta)
Esempio n. 9
0
def testRaetPreSharedKeysPromiscous(tdir):
    alphaSigner = NaclSigner()
    betaSigner = NaclSigner()

    logger.debug("Alpha's verkey {}".format(alphaSigner.verhex))
    logger.debug("Beta's verkey {}".format(betaSigner.verhex))

    alpha = RoadStack(name='alpha',
                      ha=genHa(),
                      sigkey=alphaSigner.keyhex,
                      auto=AutoMode.always,
                      basedirpath=tdir)

    beta = RoadStack(name='beta',
                     ha=genHa(),
                     sigkey=betaSigner.keyhex,
                     main=True,
                     auto=AutoMode.always,
                     basedirpath=tdir)

    try:

        betaRemote = RemoteEstate(stack=alpha, ha=beta.ha,
                                  verkey=betaSigner.verhex)

        alpha.addRemote(betaRemote)

        alpha.allow(uid=betaRemote.uid, cascade=True)

        handshake(alpha, beta)

        sendMsgs(alpha, beta, betaRemote)

    finally:
        cleanup(alpha, beta)
def testNonPromiscousConnectionWithOneKey(tdir, keysAndNames):
    # Simulating node to node connection
    alphaSighex, alphaPrikey, alphaVerhex, alphaPubkey,  alphaName, betaSighex,\
    betaPrikey, betaVerhex, betaPubkey, betaName = keysAndNames
    alpha = RoadStack(name=alphaName,
                      ha=genHa(),
                      sigkey=alphaSighex,
                      prikey=hexlify(alphaPrikey),
                      auto=AutoMode.never,
                      basedirpath=tdir)

    beta = RoadStack(name=betaName,
                     ha=genHa(),
                     sigkey=betaSighex,
                     prikey=hexlify(betaPrikey),
                     main=True,
                     auto=AutoMode.never,
                     basedirpath=tdir)

    alpha.keep.dumpRemoteRoleData({
        "acceptance": Acceptance.accepted.value,
        "verhex": betaVerhex,
        "pubhex": hexlify(betaPubkey)
    }, betaName)

    beta.keep.dumpRemoteRoleData({
        "acceptance": Acceptance.accepted.value,
        "verhex": alphaVerhex,
        "pubhex": hexlify(alphaPubkey)
    }, alphaName)

    try:

        betaRemote = RemoteEstate(stack=alpha, ha=beta.ha)

        alpha.addRemote(betaRemote)

        alpha.allow(uid=betaRemote.uid, cascade=True)

        handshake(alpha, beta)

        sendMsgs(alpha, beta, betaRemote)
    finally:
        cleanup(alpha, beta)
Esempio n. 11
0
    def setupAlpha(ha):
        nonlocal alpha
        alpha = RoadStack(name='alpha',
                          ha=ha,
                          sigkey=alphaSigner.keyhex,
                          prikey=alphaPrivateer.keyhex,
                          auto=AutoMode.never,
                          basedirpath=tdir)

        alpha.keep.dumpRemoteRoleData({
            "acceptance": Acceptance.accepted.value,
            "verhex": betaSigner.verhex,
            "pubhex": betaPrivateer.pubhex
        }, "beta")
Esempio n. 12
0
def testPromiscuousConnection(tdir):
    alpha = RoadStack(name='alpha',
                      ha=genHa(),
                      auto=AutoMode.always,
                      basedirpath=tdir)

    beta = RoadStack(name='beta',
                     ha=genHa(),
                     main=True,
                     auto=AutoMode.always,
                     basedirpath=tdir)

    try:
        betaRemote = RemoteEstate(stack=alpha, ha=beta.ha)
        alpha.addRemote(betaRemote)

        alpha.join(uid=betaRemote.uid, cascade=True)

        handshake(alpha, beta)

        sendMsgs(alpha, beta, betaRemote)
    finally:
        cleanup(alpha, beta)
Esempio n. 13
0
def testRaetPreSharedKeysNonPromiscous(tdir):
    alphaSigner = SimpleSigner()
    betaSigner = SimpleSigner()

    alphaPrivateer = Privateer()
    betaPrivateer = Privateer()

    logger.debug("Alpha's verkey {}".format(alphaSigner.naclSigner.verhex))
    logger.debug("Beta's verkey {}".format(betaSigner.naclSigner.verhex))

    alpha = RoadStack(name='alpha',
                      ha=genHa(),
                      sigkey=alphaSigner.naclSigner.keyhex,
                      prikey=alphaPrivateer.keyhex,
                      auto=AutoMode.never,
                      basedirpath=tdir)

    beta = RoadStack(name='beta',
                     ha=genHa(),
                     sigkey=betaSigner.naclSigner.keyhex,
                     prikey=betaPrivateer.keyhex,
                     main=True,
                     auto=AutoMode.never,
                     basedirpath=tdir)

    alpha.keep.dumpRemoteRoleData(
        {
            "acceptance": Acceptance.accepted.value,
            "verhex": betaSigner.naclSigner.verhex,
            "pubhex": betaPrivateer.pubhex
        }, "beta")

    beta.keep.dumpRemoteRoleData(
        {
            "acceptance": Acceptance.accepted.value,
            "verhex": alphaSigner.naclSigner.verhex,
            "pubhex": alphaPrivateer.pubhex
        }, "alpha")

    try:

        betaRemote = RemoteEstate(stack=alpha, ha=beta.ha)

        alpha.addRemote(betaRemote)

        alpha.allow(uid=betaRemote.uid, cascade=True)

        handshake(alpha, beta)

        sendMsgs(alpha, beta, betaRemote)
    finally:
        cleanup(alpha, beta)
Esempio n. 14
0
    def action(self):
        '''
        enter action
        should only run once to setup road stack.
        moved from postinitio so can do clean up before stack is initialized

        do salt raet road stack setup at enter
        '''
        role = self.opts.value.get('id', self.local.data.role)
        kind = self.opts.value['__role']  # application kind
        sigkey = self.local.data.sigkey
        prikey = self.local.data.prikey
        #name = self.opts.value.get('id', self.local.data.name)
        #name = LocalEstate.nameGuid(prefix='road') # name is  guid
        #name = 'stack_' +  role
        name = role
        main = self.opts.value.get('raet_main', self.local.data.main)
        mutable = self.opts.value.get('raet_mutable', self.local.data.mutable)
        always = self.opts.value.get('open_mode', False)
        mutable = mutable or always  # open_made when True takes precedence
        uid = self.local.data.uid

        ha = (self.opts.value['interface'], self.opts.value['raet_port'])

        basedirpath = os.path.abspath(
            os.path.join(self.opts.value['cachedir'], 'raet'))

        txMsgs = self.txmsgs.value
        rxMsgs = self.rxmsgs.value

        keep = salting.SaltKeep(opts=self.opts.value,
                                basedirpath=basedirpath,
                                stackname=name)

        self.stack.value = RoadStack(store=self.store,
                                     keep=keep,
                                     name=name,
                                     uid=uid,
                                     ha=ha,
                                     role=role,
                                     sigkey=sigkey,
                                     prikey=prikey,
                                     main=main,
                                     mutable=mutable,
                                     txMsgs=txMsgs,
                                     rxMsgs=rxMsgs,
                                     period=3.0,
                                     offset=0.5)
def testNonPromiscousConnectionWithOneKey(tdir, keysAndNames):
    # Simulating node to node connection
    alphaSighex, alphaPrikey, alphaVerhex, alphaPubkey,  alphaName, betaSighex,\
    betaPrikey, betaVerhex, betaPubkey, betaName = keysAndNames
    alpha = RoadStack(name=alphaName,
                      ha=genHa(),
                      sigkey=alphaSighex,
                      prikey=hexlify(alphaPrikey),
                      auto=AutoMode.never,
                      basedirpath=tdir)

    beta = RoadStack(name=betaName,
                     ha=genHa(),
                     sigkey=betaSighex,
                     prikey=hexlify(betaPrikey),
                     main=True,
                     auto=AutoMode.never,
                     basedirpath=tdir)

    alpha.keep.dumpRemoteRoleData(
        {
            "acceptance": Acceptance.accepted.value,
            "verhex": betaVerhex,
            "pubhex": hexlify(betaPubkey)
        }, betaName)

    beta.keep.dumpRemoteRoleData(
        {
            "acceptance": Acceptance.accepted.value,
            "verhex": alphaVerhex,
            "pubhex": hexlify(alphaPubkey)
        }, alphaName)

    try:

        betaRemote = RemoteEstate(stack=alpha, ha=beta.ha)

        alpha.addRemote(betaRemote)

        alpha.allow(uid=betaRemote.uid, cascade=True)

        handshake(alpha, beta)

        sendMsgs(alpha, beta, betaRemote)
    finally:
        cleanup(alpha, beta)
Esempio n. 16
0
    def action(self):
        '''
        enter action
        should only run once to setup road stack.
        moved from postinitio so can do clean up before stack is initialized

        do salt raet road stack setup at enter
        '''
        name = self.opts.value.get('id', self.local.data.name)
        sigkey = self.local.data.sigkey
        prikey = self.local.data.prikey
        auto = self.local.data.auto
        main = self.local.data.main
        eid = self.local.data.eid

        ha = (self.opts.value['interface'], self.opts.value['raet_port'])

        basedirpath = os.path.abspath(
            os.path.join(self.opts.value['cachedir'], 'raet'))

        local = LocalEstate(eid=eid,
                            name=name,
                            main=main,
                            ha=ha,
                            sigkey=sigkey,
                            prikey=prikey)
        txMsgs = self.txmsgs.value
        rxMsgs = self.rxmsgs.value

        keep = salting.SaltKeep(opts=self.opts.value,
                                basedirpath=basedirpath,
                                stackname=name,
                                auto=auto)

        self.stack.value = RoadStack(local=local,
                                     store=self.store,
                                     name=name,
                                     main=main,
                                     keep=keep,
                                     txMsgs=txMsgs,
                                     rxMsgs=rxMsgs,
                                     period=3.0,
                                     offset=0.5)
Esempio n. 17
0
def testPromiscuousConnection(tdir):
    alpha = RoadStack(name='alpha',
                      ha=genHa(),
                      auto=AutoMode.always,
                      basedirpath=tdir)

    beta = RoadStack(name='beta',
                     ha=genHa(),
                     main=True,
                     auto=AutoMode.always,
                     basedirpath=tdir)

    try:
        betaRemote = RemoteEstate(stack=alpha, ha=beta.ha)
        alpha.addRemote(betaRemote)

        alpha.join(uid=betaRemote.uid, cascade=True)

        handshake(alpha, beta)

        sendMsgs(alpha, beta, betaRemote)
    finally:
        cleanup(alpha, beta)
Esempio n. 18
0
def testConnectionWithHaChanged(tdir):
    console = getConsole()
    console.reinit(verbosity=console.Wordage.verbose)

    alphaSigner = SimpleSigner()
    betaSigner = SimpleSigner()

    alphaPrivateer = Privateer()
    betaPrivateer = Privateer()

    logger.debug("Alpha's verkey {}".format(alphaSigner.naclSigner.verhex))
    logger.debug("Beta's verkey {}".format(betaSigner.naclSigner.verhex))

    alpha = None

    def setupAlpha(ha):
        nonlocal alpha
        alpha = RoadStack(name='alpha',
                          ha=ha,
                          sigkey=alphaSigner.naclSigner.keyhex,
                          prikey=alphaPrivateer.keyhex,
                          auto=AutoMode.never,
                          basedirpath=tdir)

        alpha.keep.dumpRemoteRoleData(
            {
                "acceptance": Acceptance.accepted.value,
                "verhex": betaSigner.naclSigner.verhex,
                "pubhex": betaPrivateer.pubhex
            }, "beta")

    oldHa = genHa()
    setupAlpha(oldHa)

    beta = RoadStack(name='beta',
                     ha=genHa(),
                     sigkey=betaSigner.naclSigner.keyhex,
                     prikey=betaPrivateer.keyhex,
                     main=True,
                     auto=AutoMode.never,
                     basedirpath=tdir,
                     mutable=True)

    beta.keep.dumpRemoteRoleData(
        {
            "acceptance": Acceptance.accepted.value,
            "verhex": alphaSigner.naclSigner.verhex,
            "pubhex": alphaPrivateer.pubhex
        }, "alpha")

    try:
        betaRemote = RemoteEstate(stack=alpha, ha=beta.ha)
        alpha.addRemote(betaRemote)
        alpha.join(uid=betaRemote.uid, cascade=True)
        handshake(alpha, beta)
        sendMsgs(alpha, beta, betaRemote)
        logger.debug("beta knows alpha as {}".format(
            getRemote(beta, "alpha").ha))
        cleanup(alpha)

        newHa = genHa()
        logger.debug("alpha changing ha to {}".format(newHa))

        setupAlpha(newHa)
        betaRemote = RemoteEstate(stack=alpha, ha=beta.ha)
        alpha.addRemote(betaRemote)
        alpha.join(uid=betaRemote.uid, cascade=True)
        handshake(alpha, beta)
        sendMsgs(alpha, beta, betaRemote)
        logger.debug("beta knows alpha as {}".format(
            getRemote(beta, "alpha").ha))
    finally:
        cleanup(alpha, beta)
Esempio n. 19
0
class RStack(NetworkInterface):
    def __init__(self, *args, **kwargs):
        checkPortAvailable(kwargs['ha'])
        basedirpath = kwargs.get('basedirpath')

        authMode = kwargs.pop('auth_mode', None)
        kwargs['auto'] = self._getAuto(authMode)

        keep = RoadKeep(basedirpath=basedirpath,
                        stackname=kwargs['name'],
                        auto=kwargs.get('auto'),
                        baseroledirpath=basedirpath)  # type: RoadKeep
        kwargs['keep'] = keep
        localRoleData = keep.loadLocalRoleData()

        sighex = kwargs.pop('sighex', None) or localRoleData['sighex']
        if not sighex:
            (sighex, _), (prihex, _) = getEd25519AndCurve25519Keys()
        else:
            prihex = ed25519SkToCurve25519(sighex, toHex=True)
        kwargs['sigkey'] = sighex
        kwargs['prikey'] = prihex

        self.msgHandler = kwargs.pop('msgHandler', None)  # type: Callable
        # if no timeout is set then message will never timeout
        self.messageTimeout = kwargs.pop('messageTimeout', 0)

        self.raetStack = RoadStack(*args, **kwargs)

        if self.ha[1] != kwargs['ha'].port:
            error("the stack port number has changed, likely due to "
                  "information in the keep. {} passed {}, actual {}".format(
                      kwargs['name'], kwargs['ha'].port, self.ha[1]))
        self._created = time.perf_counter()
        self.coro = None

        self._conns = set()  # type: Set[str]

    def _getAuto(self, authMode):
        if authMode == AuthMode.ALLOW_ANY.value:
            return AutoMode.always
        if authMode == AuthMode.RESTRICTED.value:
            return AutoMode.never
        return None

    def __repr__(self):
        return self.name

    @property
    def name(self):
        return self.raetStack.name

    @property
    def remotes(self):
        return self.raetStack.remotes

    @property
    def created(self):
        return self._created

    @property
    def rxMsgs(self):
        return self.raetStack.rxMsgs

    @staticmethod
    def isRemoteConnected(r) -> bool:
        """
        A node is considered to be connected if it is joined, allowed and alived.

        :param r: the remote to check
        """
        return r.joined and r.allowed and r.alived

    @staticmethod
    def initLocalKeys(name, baseDir, sigseed, override=False):
        """
        Initialize RAET local keep. Write local role data to file.

        :param name: name of the node
        :param baseDir: base directory
        :param pkseed: seed to generate public and private key pair
        :param sigseed: seed to generate signing and verification key pair
        :param override: overwrite the local role.json file if already exists
        :return: tuple(public key, verification key)
        """
        rolePath = os.path.join(baseDir, name, "role", "local", "role.json")
        if os.path.isfile(rolePath):
            if not override:
                raise FileExistsError(
                    "Keys exists for local role {}".format(name))

        if sigseed and not isinstance(sigseed, bytes):
            sigseed = sigseed.encode()

        signer = Signer(sigseed)
        keep = RoadKeep(stackname=name, baseroledirpath=baseDir)
        sigkey, verkey = signer.keyhex, signer.verhex
        prikey, pubkey = ed25519SkToCurve25519(sigkey, toHex=True), \
                         ed25519PkToCurve25519(verkey, toHex=True)
        data = OrderedDict([("role", name), ("prihex", prikey),
                            ("sighex", sigkey)])
        keep.dumpLocalRoleData(data)
        return pubkey.decode(), verkey.decode()

    @staticmethod
    def initRemoteKeys(name, remoteName, baseDir, verkey, override=False):
        """
        Initialize RAET remote keep

        :param name: name of the node
        :param remoteName: name of the remote to store keys for
        :param baseDir: base directory
        :param pubkey: public key of the remote
        :param verkey: private key of the remote
        :param override: overwrite the role.remoteName.json file if it already
        exists.
        """
        rolePath = os.path.join(baseDir, name, "role", "remote",
                                "role.{}.json".format(remoteName))
        if os.path.isfile(rolePath):
            if not override:
                raise FileExistsError(
                    "Keys exists for remote role {}".format(remoteName))

        keep = RoadKeep(stackname=name, baseroledirpath=baseDir)
        data = OrderedDict([('role', remoteName), ('acceptance', 1),
                            ('pubhex', ed25519PkToCurve25519(verkey,
                                                             toHex=True)),
                            ('verhex', verkey)])
        keep.dumpRemoteRoleData(data, role=remoteName)

    def onHostAddressChanged(self):
        logger.debug(
            "{} clearing local data in keep as host address changed".format(
                self.name))
        self.raetStack.keep.clearLocalData()

    @staticmethod
    def areKeysSetup(name, baseDir):
        """
        Check that the local RAET keep has the values of role, sighex and prihex
        populated for the given node

        :param name: the name of the node to check the keys for
        :param baseDir: base directory of Plenum
        :return: whether the keys are setup
        """
        localRoleData = getLocalKeep(name=name, baseDir=baseDir)

        for key in ['role', 'sighex', 'prihex']:
            if localRoleData.get(key) is None:
                return False
        return True

    @staticmethod
    def learnKeysFromOthers(baseDir, name, others):
        pass

    @staticmethod
    def getHaFromLocal(name, basedirpath):
        localEstate = getLocalEstateData(name, basedirpath)
        if localEstate:
            return localEstate.get("ha")

    def tellKeysToOthers(self, others):
        pass

    def getRemote(self, name: str = None, ha: HA = None):
        """
        Find the remote by name or ha.

        :param name: the name of the remote to find
        :param ha: host address pair the remote to find
        :raises: RemoteNotFound
        """
        return self.findInRemotesByHA(ha) if ha else \
            self.findInRemotesByName(name)

    def connect(self,
                name=None,
                remoteId=None,
                ha=None,
                verKeyRaw=None,
                publicKeyRaw=None):
        """
        Connect to the node specified by name.

        :param name: name of the node to connect to
        :type name: str or (HA, tuple)
        :return: the uid of the remote estate, or None if a connect is not
            attempted
        """
        # if not self.isKeySharing:
        #     logger.debug("{} skipping join with {} because not key sharing".
        #                   format(self, name))
        #     return None
        if not remoteId and not ha:
            raise ValueError(
                'Either Host Address or Remote ID must be provided to connect to a node in Raet stack'
            )

        if remoteId:
            remote = self.remotes[remoteId]
            return self._doConnectRemote(remote, name)
        else:
            return self._doConnectByHA(ha, name)

    def _doConnectByHA(self, ha, name=None):
        remote = RemoteEstate(stack=self.raetStack, ha=ha)
        self.raetStack.addRemote(remote)
        return self._doConnectRemote(remote, name)

    def _doConnectRemote(self, remote, name=None):
        # updates the store time so the join timer is accurate
        self.updateStamp()
        self.raetStack.join(uid=remote.uid, cascade=True, timeout=30)
        logger.info("{} looking for {} at {}:{}".format(
            self, name or remote.name, *remote.ha),
                    extra={
                        "cli": "PLAIN",
                        "tags": ["node-looking"]
                    })
        return remote.uid

    def removeRemote(self, r):
        self.raetStack.removeRemote(r)

    def transmit(self, msg, uid, timeout=None):
        self.raetStack.transmit(msg, uid, timeout=timeout)

    @property
    def ha(self):
        return self.raetStack.ha

    def start(self):
        if not self.opened:
            self.open()
        logger.info("stack {} starting at {} in {} mode".format(
            self, self.ha, self.raetStack.keep.auto),
                    extra={"cli": False})
        # self.coro = self._raetcoro()
        self.coro = self._raetcoro

    def stop(self):
        if self.opened:
            self.close()
        self.coro = None
        logger.info("stack {} stopped".format(self.name), extra={"cli": False})

    async def service(self, limit=None) -> int:
        """
        Service `limit` number of received messages in this stack.

        :param limit: the maximum number of messages to be processed. If None,
        processes all of the messages in rxMsgs.
        :return: the number of messages processed.
        """
        pracLimit = limit if limit else sys.maxsize
        if self.coro:
            # x = next(self.coro)
            x = await self.coro()
            if x > 0:
                for x in range(pracLimit):
                    try:
                        self.msgHandler(self.raetStack.rxMsgs.popleft())
                    except IndexError:
                        break
            return x
        else:
            logger.debug("{} is stopped".format(self))
            return 0

    # def _raetcoro(self):
    #     """
    #     Generator to service all messages.
    #     Yields the length of rxMsgs queue of this stack.
    #     """
    #     while True:
    #         try:
    #             self._serviceStack(self.age)
    #             l = len(self.rxMsgs)
    #         except Exception as ex:
    #             if isinstance(ex, OSError) and \
    #                     len(ex.args) > 0 and \
    #                     ex.args[0] == 22:
    #                 logger.error("Error servicing stack {}: {}. This could be "
    #                              "due to binding to an internal network "
    #                              "and trying to route to an external one.".
    #                              format(self.name, ex), extra={'cli': 'WARNING'})
    #             else:
    #                 logger.error("Error servicing stack {}: {} {}".
    #                              format(self.name, ex, ex.args),
    #                              extra={'cli': 'WARNING'})
    #
    #             l = 0
    #         yield l

    async def _raetcoro(self):
        try:
            await self._serviceStack(self.age)
            l = len(self.raetStack.rxMsgs)
        except Exception as ex:
            if isinstance(ex, OSError) and \
                    len(ex.args) > 0 and \
                    ex.args[0] == 22:
                logger.error("Error servicing stack {}: {}. This could be "
                             "due to binding to an internal network "
                             "and trying to route to an external one.".format(
                                 self.name, ex),
                             extra={'cli': 'WARNING'})
            else:
                logger.error("Error servicing stack {}: {} {}".format(
                    self.name, ex, ex.args),
                             extra={'cli': 'WARNING'})

            l = 0
        return l

    async def _serviceStack(self, age):
        """
        Update stacks clock and service all tx and rx messages.

        :param age: update timestamp of this RoadStack to this value
        """
        self.updateStamp(age)
        self.raetStack.serviceAll()

    def updateStamp(self, age=None):
        """
        Change the timestamp of this stack's test store.

        :param age: the timestamp will be set to this value
        """
        self.raetStack.store.changeStamp(age if age else self.age)

    @property
    def opened(self):
        return self.raetStack.server.opened

    def open(self):
        """
        Open the UDP socket of this stack's server.
        """
        self.raetStack.server.open()  # close the UDP socket

    def close(self):
        """
        Close the UDP socket of this stack's server.
        """
        self.raetStack.server.close()  # close the UDP socket

    @property
    def isKeySharing(self):
        return self.raetStack.keep.auto != AutoMode.never

    @property
    def verhex(self):
        return self.raetStack.local.signer.verhex

    @property
    def keyhex(self):
        return self.raetStack.local.signer.keyhex

    @property
    def pubhex(self):
        return self.raetStack.local.priver.pubhex

    @property
    def prihex(self):
        return self.raetStack.local.priver.keyhex

    def send(self, msg: Any, remoteName: str, ha=None):
        """
        Transmit the specified message to the remote specified by `remoteName`.

        :param msg: a message
        :param remoteName: the name of the remote
        """
        rid = self.getRemote(remoteName, ha).uid
        # Setting timeout to never expire
        self.raetStack.transmit(msg, rid, timeout=self.messageTimeout)