Exemplo n.º 1
0
    async def _runShareLoop(self):

        try:

            async for item in self.item:

                if self.isfini:
                    break

                retn = (True, item)
                mesg = ('share:data', {'share': self.iden, 'data': retn})

                await self.link.tx(mesg)

                # purposely yield for fair scheduling
                await asyncio.sleep(0)

        except Exception as e:
            retn = s_common.retnexc(e)
            mesg = ('share:data', {'share': self.iden, 'data': retn})
            await self.link.tx(mesg)

        finally:

            mesg = ('share:data', {'share': self.iden, 'data': None})
            await self.link.tx(mesg)
            await self.fini()
Exemplo n.º 2
0
    async def inetHttpConnect(self, url, headers=None, ssl_verify=True, timeout=300):

        sock = await WebSocket.anit()

        proxyurl = await self.runt.snap.core.getConfOpt('http:proxy')
        connector = None
        if proxyurl is not None:
            connector = aiohttp_socks.ProxyConnector.from_url(proxyurl)

        timeout = aiohttp.ClientTimeout(total=timeout)

        try:
            sess = await sock.enter_context(aiohttp.ClientSession(connector=connector, timeout=timeout))
            sock.resp = await sock.enter_context(sess.ws_connect(url, headers=headers, ssl=ssl_verify, timeout=timeout))

            sock._syn_refs = 0
            self.runt.onfini(sock)

            return (True, sock)

        except asyncio.CancelledError: # pragma: no cover
            raise

        except Exception as e: # pragma: no cover
            await sock.fini()
            return s_common.retnexc(e)
Exemplo n.º 3
0
    async def _onTaskInit(self, link, mesg):

        task = mesg[1].get('task')
        name = mesg[1].get('name')

        sess = link.get('sess')
        if sess is None:
            raise s_exc.NoSuchObj(name=name)

        item = sess.getSessItem(name)
        if item is None:
            raise s_exc.NoSuchObj(name=name)

        try:

            methname, args, kwargs = mesg[1].get('todo')

            if methname[0] == '_':
                raise s_exc.NoSuchMeth(name=methname)

            meth = getattr(item, methname, None)
            if meth is None:
                logger.warning(f'{item!r} has no method: {methname}')
                raise s_exc.NoSuchMeth(name=methname)

            valu = await self._runTodoMeth(link, meth, args, kwargs)

            mesg = self._getTaskFiniMesg(task, valu)

            await link.tx(mesg)

            # if it's a Share(), spin off the share loop
            if isinstance(valu, s_share.Share):

                if isinstance(item, s_base.Base):
                    item.onfini(valu)

                async def spinshareloop():
                    try:
                        await valu._runShareLoop()
                    except asyncio.CancelledError:
                        pass
                    except Exception:
                        logger.exception('Error running %r', valu)
                    finally:
                        await valu.fini()

                self.schedCoro(spinshareloop())

        except Exception as e:

            logger.exception('on task:init: %r' % (mesg,))

            retn = s_common.retnexc(e)

            await link.tx(
                ('task:fini', {'task': task, 'retn': retn})
            )
Exemplo n.º 4
0
    async def _onTaskInit(self, link, mesg):

        task = mesg[1].get('task')
        name = mesg[1].get('name')

        sess = link.get('sess')
        if sess is None:
            raise s_exc.NoSuchObj(name=name)

        item = sess.getSessItem(name)
        if item is None:
            raise s_exc.NoSuchObj(name=name)

        try:

            methname, args, kwargs = mesg[1].get('todo')

            if methname[0] == '_':
                raise s_exc.NoSuchMeth(name=methname)

            meth = getattr(item, methname, None)
            if meth is None:
                logger.warning('%r has no method: %s', item, methname)
                raise s_exc.NoSuchMeth(name=methname)

            valu = await self._runTodoMeth(link, meth, args, kwargs)

            mesg = self._getTaskFiniMesg(task, valu)

            await link.tx(mesg)

            # if it's a Share(), spin off the share loop
            if isinstance(valu, s_share.Share):

                if isinstance(item, s_base.Base):
                    item.onfini(valu)

                async def spinshareloop():
                    try:
                        await valu._runShareLoop()
                    except asyncio.CancelledError:
                        pass
                    except Exception:
                        logger.exception('Error running %r', valu)
                    finally:
                        await valu.fini()

                self.schedCoro(spinshareloop())

        except (asyncio.CancelledError, Exception) as e:

            logger.exception('on task:init: %r', mesg)

            retn = s_common.retnexc(e)

            await link.tx(
                ('task:fini', {'task': task, 'retn': retn})
            )
Exemplo n.º 5
0
    async def _onTeleSyn(self, link, mesg):

        reply = ('tele:syn', {
            'vers': self.televers,
            'retn': (True, None),
        })

        try:

            vers = mesg[1].get('vers')

            if vers[0] != s_telepath.televers[0]:
                raise s_exc.BadMesgVers(vers=vers, myvers=s_telepath.televers)

            path = ()

            name = mesg[1].get('name')
            if not name:
                name = '*'

            if '/' in name:
                name, rest = name.split('/', 1)
                if rest:
                    path = rest.split('/')

            item = self.shared.get(name)

            if item is None:
                raise s_exc.NoSuchName(name=name)

            sess = await Sess.anit()

            async def sessfini():
                self.sessions.pop(sess.iden, None)

            sess.onfini(sessfini)
            link.onfini(sess.fini)

            self.sessions[sess.iden] = sess
            sess.conninfo = link.getAddrInfo()

            link.set('sess', sess)

            if isinstance(item, s_telepath.Aware):
                item = await s_coro.ornot(item.getTeleApi, link, mesg, path)
                if isinstance(item, s_base.Base):
                    link.onfini(item)

            reply[1]['sharinfo'] = s_reflect.getShareInfo(item)

            sess.setSessItem(None, item)
            reply[1]['sess'] = sess.iden

        except Exception as e:
            logger.exception('tele:syn error')
            reply[1]['retn'] = s_common.retnexc(e)

        await link.tx(reply)
Exemplo n.º 6
0
    async def _onTeleSyn(self, link, mesg):

        reply = ('tele:syn', {
            'vers': self.televers,
            'retn': (True, None),
        })

        try:

            vers = mesg[1].get('vers')

            if vers[0] != s_telepath.televers[0]:
                raise s_exc.BadMesgVers(vers=vers, myvers=s_telepath.televers)

            path = ()

            name = mesg[1].get('name')
            if not name:
                name = '*'

            if '/' in name:
                name, rest = name.split('/', 1)
                if rest:
                    path = rest.split('/')

            item = self.shared.get(name)

            if item is None:
                raise s_exc.NoSuchName(name=name)

            sess = await Sess.anit()
            async def sessfini():
                self.sessions.pop(sess.iden, None)

            sess.onfini(sessfini)
            link.onfini(sess.fini)

            self.sessions[sess.iden] = sess

            link.set('sess', sess)

            if isinstance(item, s_telepath.Aware):
                item = await s_coro.ornot(item.getTeleApi, link, mesg, path)
                if isinstance(item, s_base.Base):
                    link.onfini(item.fini)

            reply[1]['sharinfo'] = s_reflect.getShareInfo(item)

            sess.setSessItem(None, item)
            reply[1]['sess'] = sess.iden

        except Exception as e:
            logger.exception('tele:syn error')
            reply[1]['retn'] = s_common.retnexc(e)

        await link.tx(reply)
Exemplo n.º 7
0
    async def _onTeleSyn(self, link, mesg):

        reply = ('tele:syn', {
            'vers': self.televers,
            'retn': (True, None),
        })

        try:

            vers = mesg[1].get('vers')

            if vers[0] != s_telepath.televers[0]:
                raise s_exc.BadMesgVers(vers=vers, myvers=s_telepath.televers)

            name = mesg[1].get('name')

            item = self.shared.get(name)

            # allow a telepath aware object a shot at dynamic share names
            if item is None and name.find('/') != -1:

                path = name.split('/')

                base = self.shared.get(path[0])
                if base is not None and isinstance(base, s_telepath.Aware):
                    item = await s_coro.ornot(base.onTeleOpen, link, path)

            if item is None:
                raise s_exc.NoSuchName(name=name)

            sess = await Sess.anit()

            async def sessfini():
                self.sessions.pop(sess.iden, None)

            sess.onfini(sessfini)
            link.onfini(sess.fini)

            self.sessions[sess.iden] = sess

            link.set('sess', sess)

            if isinstance(item, s_telepath.Aware):
                item = await s_coro.ornot(item.getTeleApi, link, mesg)
                if isinstance(item, s_base.Base):
                    link.onfini(item.fini)

            sess.setSessItem(None, item)
            reply[1]['sess'] = sess.iden

        except Exception as e:
            logger.exception('tele:syn error')
            reply[1]['retn'] = s_common.retnexc(e)

        await link.tx(reply)
Exemplo n.º 8
0
    async def tx(self, mesg):
        try:

            mesg = await s_stormtypes.toprim(mesg)
            await self.resp.send_bytes(json.dumps(mesg).encode())
            return (True, None)

        except asyncio.CancelledError:  # pragma: no cover
            raise

        except Exception as e:  # pragma: no cover
            return s_common.retnexc(e)
Exemplo n.º 9
0
    async def rx(self, timeout=None):

        try:
            _type, data, extra = await asyncio.wait_for(self.resp.receive(), timeout=timeout)
            if _type == aiohttp.WSMsgType.BINARY:
                return (True, json.loads(data))
            if _type == aiohttp.WSMsgType.TEXT:
                return (True, json.loads(data.encode()))
            if _type == aiohttp.WSMsgType.CLOSED: # pragma: no cover
                return (True, None)
            return (False, ('BadMesgFormat', {'mesg': f'WebSocket RX unhandled type: {_type.name}'})) # pragma: no cover

        except asyncio.CancelledError: # pragma: no cover
            raise

        except Exception as e: # pragma: no cover
            return s_common.retnexc(e)
Exemplo n.º 10
0
    async def _onTaskV2Init(self, link, mesg):

        # t2:init is used by the pool sockets on the client

        name = mesg[1].get('name')
        sidn = mesg[1].get('sess')
        todo = mesg[1].get('todo')

        try:

            if sidn is None or todo is None:
                raise s_exc.NoSuchObj(name=name)

            sess = self.sessions.get(sidn)
            if sess is None:
                raise s_exc.NoSuchObj(name=name)

            item = sess.getSessItem(name)
            if item is None:
                raise s_exc.NoSuchObj(name=name)

            s_scope.set('sess', sess)
            s_scope.set('link', link)

            methname, args, kwargs = todo

            if methname[0] == '_':
                raise s_exc.NoSuchMeth(name=methname)

            meth = getattr(item, methname, None)
            if meth is None:
                logger.warning('%r has no method: %r', item, methname)
                raise s_exc.NoSuchMeth(name=methname)

            sessitem = await t2call(link, meth, args, kwargs)
            if sessitem is not None:
                sess.onfini(sessitem)

        except Exception as e:
            logger.exception('on t2:init: %r' % (mesg, ))
            if not link.isfini:
                retn = s_common.retnexc(e)
                await link.tx(('t2:fini', {'retn': retn}))
Exemplo n.º 11
0
    async def _runShareLoop(self):

        try:

            async for item in self.item:

                if self.isfini:
                    break

                retn = (True, item)
                mesg = ('share:data', {'share': self.iden, 'data': retn})
                await self.link.tx(mesg)

        except Exception as e:
            retn = s_common.retnexc(e)
            mesg = ('share:data', {'share': self.iden, 'data': retn})
            await self.link.tx(mesg)

        finally:

            mesg = ('share:data', {'share': self.iden, 'data': None})
            await self.link.tx(mesg)
            await self.fini()
Exemplo n.º 12
0
    async def _runShareLoop(self):

        try:

            async for item in self.item:

                if self.isfini:
                    break

                retn = (True, item)
                mesg = ('share:data', {'share': self.iden, 'data': retn})
                await self.link.tx(mesg)

        except Exception as e:
            retn = s_common.retnexc(e)
            mesg = ('share:data', {'share': self.iden, 'data': retn})
            await self.link.tx(mesg)

        finally:

            mesg = ('share:data', {'share': self.iden, 'data': None})
            await self.link.tx(mesg)
            await self.fini()
Exemplo n.º 13
0
    async def tx(self, mesg):
        '''
        Async transmit routine which will wait for writer drain().
        '''
        if self.isfini:
            raise s_exc.IsFini()

        byts = s_msgpack.en(mesg)
        try:

            self.writer.write(byts)

            # Avoid Python bug.  See https://bugs.python.org/issue29930
            async with self._drain_lock:
                await self.writer.drain()

        except Exception as e:

            await self.fini()

            einfo = s_common.retnexc(e)
            logger.debug('link.tx connection trouble %s', einfo)

            raise
Exemplo n.º 14
0
    async def tx(self, mesg):
        '''
        Async transmit routine which will wait for writer drain().
        '''
        if self.isfini:
            raise s_exc.IsFini()

        byts = s_msgpack.en(mesg)
        try:

            self.writer.write(byts)

            # Avoid Python bug.  See https://bugs.python.org/issue29930
            async with self._drain_lock:
                await self.writer.drain()

        except Exception as e:

            await self.fini()

            einfo = s_common.retnexc(e)
            logger.debug('link.tx connection trouble %s', einfo)

            raise
Exemplo n.º 15
0
    async def _onTaskV2Init(self, link, mesg):

        # t2:init is used by the pool sockets on the client

        name = mesg[1].get('name')
        sidn = mesg[1].get('sess')
        todo = mesg[1].get('todo')

        try:

            if sidn is None or todo is None:
                raise s_exc.NoSuchObj(name=name)

            sess = self.sessions.get(sidn)
            if sess is None:
                raise s_exc.NoSuchObj(name=name)

            item = sess.getSessItem(name)
            if item is None:
                raise s_exc.NoSuchObj(name=name)

            s_scope.set('sess', sess)
            # TODO set user....

            methname, args, kwargs = todo

            if methname[0] == '_':
                raise s_exc.NoSuchMeth(name=methname)

            meth = getattr(item, methname, None)
            if meth is None:
                logger.warning(f'{item!r} has no method: {methname}')
                raise s_exc.NoSuchMeth(name=methname)

            valu = meth(*args, **kwargs)

            if s_coro.iscoro(valu):
                valu = await valu

            try:
                if isinstance(valu, types.AsyncGeneratorType):
                    desc = 'async generator'

                    await link.tx(('t2:genr', {}))

                    async for item in valu:
                        await link.tx(('t2:yield', {'retn': (True, item)}))

                    await link.tx(('t2:yield', {'retn': None}))
                    return

                elif isinstance(valu, types.GeneratorType):
                    desc = 'generator'

                    await link.tx(('t2:genr', {}))

                    for item in valu:
                        await link.tx(('t2:yield', {'retn': (True, item)}))

                    await link.tx(('t2:yield', {'retn': None}))
                    return

            except Exception as e:
                logger.exception(f'error during {desc} task: {methname}')
                if not link.isfini:
                    retn = s_common.retnexc(e)
                    await link.tx(('t2:yield', {'retn': retn}))

                return

            if isinstance(valu, s_share.Share):
                sess.onfini(valu)
                iden = s_common.guid()
                sess.setSessItem(iden, valu)
                info = s_reflect.getShareInfo(valu)
                await link.tx(('t2:share', {'iden': iden, 'sharinfo': info}))
                return

            await link.tx(('t2:fini', {'retn': (True, valu)}))

        except Exception as e:

            logger.exception('on t2:init: %r' % (mesg,))

            if not link.isfini:
                retn = s_common.retnexc(e)
                await link.tx(('t2:fini', {'retn': retn}))
Exemplo n.º 16
0
async def t2call(link, meth, args, kwargs):
    '''
    Call the given ``meth(*args, **kwargs)`` and handle the response to provide
    telepath task v2 events to the given link.
    '''
    try:

        valu = meth(*args, **kwargs)

        if s_coro.iscoro(valu):
            valu = await valu

        try:

            first = True
            if isinstance(valu, types.AsyncGeneratorType):

                async for item in valu:

                    if first:
                        await link.tx(('t2:genr', {}))
                        first = False

                    await link.tx(('t2:yield', {'retn': (True, item)}))

                if first:
                    await link.tx(('t2:genr', {}))

                await link.tx(('t2:yield', {'retn': None}))
                return

            elif isinstance(valu, types.GeneratorType):

                for item in valu:

                    if first:
                        await link.tx(('t2:genr', {}))
                        first = False

                    await link.tx(('t2:yield', {'retn': (True, item)}))

                if first:
                    await link.tx(('t2:genr', {}))

                await link.tx(('t2:yield', {'retn': None}))
                return

        except s_exc.DmonSpawn as e:
            context = e.__context__
            if context:
                if not isinstance(context, asyncio.CancelledError):
                    logger.error('Error during DmonSpawn call: %r', context)
                await link.fini()
            return

        except (asyncio.CancelledError, Exception) as e:

            if isinstance(e, asyncio.CancelledError):
                logger.info('t2call task %s cancelled', meth.__name__)
            else:
                logger.exception('error during task %s', meth.__name__)

            if isinstance(valu, types.AsyncGeneratorType):
                await valu.aclose()
            elif isinstance(valu, types.GeneratorType):
                valu.close()

            if not link.isfini:

                if first:
                    await link.tx(('t2:genr', {}))

                retn = s_common.retnexc(e)
                await link.tx(('t2:yield', {'retn': retn}))

            return

        if isinstance(valu, s_share.Share):

            info = s_reflect.getShareInfo(valu)
            await link.tx(('t2:share', {'iden': valu.iden, 'sharinfo': info}))
            return valu

        await link.tx(('t2:fini', {'retn': (True, valu)}))

    except s_exc.DmonSpawn as e:
        context = e.__context__
        if context:
            logger.error('Error during DmonSpawn call: %r', context)
            await link.fini()
        return

    except (asyncio.CancelledError, Exception) as e:
        logger.exception('error during task: %s', meth.__name__)
        if not link.isfini:
            retn = s_common.retnexc(e)
            await link.tx(('t2:fini', {'retn': retn}))
Exemplo n.º 17
0
    async def _onTaskV2Init(self, link, mesg):

        # t2:init is used by the pool sockets on the client

        name = mesg[1].get('name')
        sidn = mesg[1].get('sess')
        todo = mesg[1].get('todo')

        try:

            if sidn is None or todo is None:
                raise s_exc.NoSuchObj(name=name)

            sess = self.sessions.get(sidn)
            if sess is None:
                raise s_exc.NoSuchObj(name=name)

            item = sess.getSessItem(name)
            if item is None:
                raise s_exc.NoSuchObj(name=name)

            s_scope.set('sess', sess)
            # TODO set user....

            methname, args, kwargs = todo

            if methname[0] == '_':
                raise s_exc.NoSuchMeth(name=methname)

            meth = getattr(item, methname, None)
            if meth is None:
                logger.warning(f'{item!r} has no method: {methname}')
                raise s_exc.NoSuchMeth(name=methname)

            valu = meth(*args, **kwargs)

            if s_coro.iscoro(valu):
                valu = await valu

            if isinstance(valu, types.AsyncGeneratorType):

                try:

                    await link.tx(('t2:genr', {}))

                    async for item in valu:
                        await link.tx(('t2:yield', {'retn': (True, item)}))

                    await link.tx(('t2:yield', {'retn': None}))

                except Exception as e:
                    if not link.isfini:
                        retn = s_common.retnexc(e)
                        await link.tx(('t2:yield', {'retn': retn}))

                return

            if isinstance(valu, types.GeneratorType):

                try:

                    await link.tx(('t2:genr', {}))

                    for item in valu:
                        await link.tx(('t2:yield', {'retn': (True, item)}))

                    await link.tx(('t2:yield', {'retn': None}))

                except Exception as e:
                    if not link.isfini:
                        retn = s_common.retnexc(e)
                        await link.tx(('t2:yield', {'retn': (False, retn)}))

                return

            if isinstance(valu, s_share.Share):
                iden = s_common.guid()
                sess.setSessItem(iden, valu)
                await link.tx(('t2:share', {'iden': iden}))
                return

            await link.tx(('t2:fini', {'retn': (True, valu)}))

        except Exception as e:

            logger.exception('on task:init: %r' % (mesg, ))

            if not link.isfini:
                retn = s_common.retnexc(e)
                await link.tx(('t2:fini', {'retn': retn}))