def wait(self): """Wait until another coroutine calls send. Returns the value the other coroutine passed to send. >>> from eventlib import coros, api >>> evt = coros.event() >>> def wait_on(): ... retval = evt.wait() ... print "waited for", retval >>> _ = api.spawn(wait_on) >>> evt.send('result') >>> api.sleep(0) waited for result Returns immediately if the event has already occured. >>> evt.wait() 'result' """ if self._result is NOT_USED: self._waiters[api.getcurrent()] = True try: return api.get_hub().switch() finally: self._waiters.pop(api.getcurrent(), None) if self._exc is not None: api.getcurrent().throw(*self._exc) return self._result
def switch(self): assert api.getcurrent() is not self.greenlet, "Cannot switch from MAINLOOP to MAINLOOP" try: api.getcurrent().parent = self.greenlet except ValueError: pass return self.greenlet.switch()
def acquire(self, blocking=True): if not blocking and self.locked(): return False while self.counter <= 0: self._waiters[api.getcurrent()] = None try: api.get_hub().switch() finally: self._waiters.pop(api.getcurrent(), None) self.counter -= 1 return True
def wait(self): """Wait for an item sent by a send() call, in FIFO order. If the corresponding send() specifies exc=SomeExceptionClass, this wait() will raise that exception. Otherwise, this wait() will return the corresponding send() call's result= parameter. """ self.sem.acquire() result, exc = self.items.popleft() if exc is not None: api.getcurrent().throw(*exc) return result
def link_exception(self, listener=None, link=None): if self.value is not _NOT_USED and self._exc is None: return if listener is None: listener = api.getcurrent() if link is None: link = self.getLink(listener) if self.ready() and listener is api.getcurrent(): link(self) else: self._exception_links[listener] = link if self.value is not _NOT_USED: self._start_send_exception() return link
def wait(self): """The difference from queue.wait: if there is an only item in the queue and it is an exception, raise it, but keep it in the queue, so that future calls to wait() will raise it again. """ self.sem.acquire() if self.has_error() and len(self.items)==1: # the last item, which is an exception, raise without emptying the queue self.sem.release() getcurrent().throw(*self.items[0][1]) else: result, exc = self.items.popleft() if exc is not None: getcurrent().throw(*exc) return result
def cb(value): if cur: if getcurrent() is cur[0]: synchronous.append((value, None)) else: cur[0].switch(value) return value
def execute(self, func, *args, **kwargs): """Execute func in one of the coroutines maintained by the pool, when one is free. Immediately returns a Proc object which can be queried for the func's result. >>> pool = Pool() >>> task = pool.execute(lambda a: ('foo', a), 1) >>> task.wait() ('foo', 1) """ # if reentering an empty pool, don't try to wait on a coroutine freeing # itself -- instead, just execute in the current coroutine if self.sem.locked() and api.getcurrent() in self.procs: p = proc.spawn(func, *args, **kwargs) try: p.wait() except: pass else: self.sem.acquire() p = self.procs.spawn(func, *args, **kwargs) # assuming the above line cannot raise p.link(lambda p: self.sem.release()) if self.results is not None: p.link(self.results) return p
def start(self): notification_center = NotificationCenter() self.greenlet = api.getcurrent() settings = SIPSimpleSettings() account = AccountManager().sylkserver_account if account.sip.outbound_proxy is not None: uri = SIPURI(host=account.sip.outbound_proxy.host, port=account.sip.outbound_proxy.port, parameters={'transport': account.sip.outbound_proxy.transport}) else: uri = self.destination_uri lookup = DNSLookup() try: routes = lookup.lookup_sip_proxy(uri, settings.sip.transport_list).wait() except DNSLookupError: notification_center.post_notification('OutgoingFileTransferHandlerDidFail', sender=self) return self.session = Session(account) self.stream = FileTransferStream(self.file_selector, 'sendonly') notification_center.add_observer(self, sender=self.session) notification_center.add_observer(self, sender=self.stream) from_header = FromHeader(self.sender_uri, u'SIPStache File Transfer') to_header = ToHeader(self.destination_uri) transport = routes[0].transport parameters = {} if transport=='udp' else {'transport': transport} contact_header = ContactHeader(SIPURI(user=self.sender_uri.user, host=SIPConfig.local_ip.normalized, port=getattr(Engine(), '%s_port' % transport), parameters=parameters)) extra_headers = [] if ThorNodeConfig.enabled: extra_headers.append(Header('Thor-Scope', 'sipstache-file')) extra_headers.append(Header('X-Originator-From', str(self.destination_uri))) self.session.connect(from_header, to_header, contact_header=contact_header, routes=routes, streams=[self.stream], is_focus=False, extra_headers=extra_headers) notification_center.post_notification('OutgoingFileTransferHandlerDidStart', sender=self)
def switch(self): cur = api.getcurrent() assert cur is not self.greenlet, 'Cannot switch to MAINLOOP from MAINLOOP' switch_out = getattr(cur, 'switch_out', None) if switch_out is not None: try: switch_out() except: traceback.print_exception(*sys.exc_info()) if self.greenlet.dead: self.greenlet = api.Greenlet(self.run) try: api.getcurrent().parent = self.greenlet except ValueError: pass return self.greenlet.switch()
def block_on(deferred): cur = [getcurrent()] synchronous = [] def cb(value): if cur: if getcurrent() is cur[0]: synchronous.append((value, None)) else: cur[0].switch(value) return value def eb(failure): if cur: if getcurrent() is cur[0]: synchronous.append((None, failure)) else: failure.throwExceptionIntoGenerator(cur[0]) deferred.addCallbacks(cb, eb) if synchronous: result, failure = synchronous[0] if failure is not None: failure.raiseException() return result try: return get_hub().switch() finally: del cur[0]
def send_exception(self, *throw_args): """Make greenlet calling wait() wake up (if there is a wait()). Can only be called from get_hub().greenlet. """ assert api.getcurrent() is api.get_hub().greenlet if self.greenlet is not None: self.greenlet.throw(*throw_args)
def send(self, value): """Wake up the greenlet that is calling wait() currently (if there is one). Can only be called from get_hub().greenlet. """ assert api.getcurrent() is api.get_hub().greenlet if self.greenlet is not None: self.greenlet.switch(value)
def wait(self, timeout=None, *throw_args): """Wait until send() or send_exception() is called or `timeout' has expired. Return the argument of send or raise the argument of send_exception. If timeout has expired, None is returned. The arguments, when provided, specify how many seconds to wait and what to do when timeout has expired. They are treated the same way as api.timeout treats them. """ if self.value is not _NOT_USED: if self._exc is None: return self.value else: api.getcurrent().throw(*self._exc) if timeout is not None: timer = api.timeout(timeout, *throw_args) timer.__enter__() if timeout == 0: if timer.__exit__(None, None, None): return else: try: api.getcurrent().throw(*timer.throw_args) except: if not timer.__exit__(*sys.exc_info()): raise return EXC = True try: try: waiter = Waiter() self.link(waiter) try: return waiter.wait() finally: self.unlink(waiter) except: EXC = False if timeout is None or not timer.__exit__(*sys.exc_info()): raise finally: if timeout is not None and EXC: timer.__exit__(None, None, None)
def wait(self, timeout=None, *throw_args): """Wait until send() or send_exception() is called or `timeout' has expired. Return the argument of send or raise the argument of send_exception. If timeout has expired, None is returned. The arguments, when provided, specify how many seconds to wait and what to do when timeout has expired. They are treated the same way as api.timeout treats them. """ if self.value is not _NOT_USED: if self._exc is None: return self.value else: api.getcurrent().throw(*self._exc) if timeout is not None: timer = api.timeout(timeout, *throw_args) timer.__enter__() if timeout==0: if timer.__exit__(None, None, None): return else: try: api.getcurrent().throw(*timer.throw_args) except: if not timer.__exit__(*sys.exc_info()): raise return EXC = True try: try: waiter = Waiter() self.link(waiter) try: return waiter.wait() finally: self.unlink(waiter) except: EXC = False if timeout is None or not timer.__exit__(*sys.exc_info()): raise finally: if timeout is not None and EXC: timer.__exit__(None, None, None)
def killall(procs, *throw_args, **kwargs): if not throw_args: throw_args = (ProcExit, ) wait = kwargs.pop('wait', False) if kwargs: raise TypeError('Invalid keyword argument for proc.killall(): %s' % ', '.join(kwargs.keys())) for g in procs: if not g.dead: api.get_hub().schedule_call_global(0, g.throw, *throw_args) if wait and api.getcurrent() is not api.get_hub().greenlet: api.sleep(0)
def wait(self): """Wait until send or send_exception is called. Return value passed into send() or raise exception passed into send_exception(). """ assert self.greenlet is None current = api.getcurrent() assert current is not api.get_hub().greenlet self.greenlet = current try: return api.get_hub().switch() finally: self.greenlet = None
def killall(procs, *throw_args, **kwargs): if not throw_args: throw_args = (ProcExit, ) wait = kwargs.pop('wait', False) if kwargs: raise TypeError('Invalid keyword argument for proc.killall(): %s' % ', '.join(list(kwargs.keys()))) for g in procs: if not g.dead: api.get_hub().schedule_call_global(0, g.throw, *throw_args) if wait and api.getcurrent() is not api.get_hub().greenlet: api.sleep(0)
def kill(self, *throw_args): """Raise an exception in the greenlet. Unschedule the current greenlet so that this Proc can handle the exception (or die). The exception can be specified with throw_args. By default, ProcExit is raised. """ if not self.dead: if not throw_args: throw_args = (ProcExit, ) api.get_hub().schedule_call_global(0, self.greenlet.throw, *throw_args) if api.getcurrent() is not api.get_hub().greenlet: api.sleep(0)
def run(self): while True: try: event.dispatch() break except api.GreenletExit: break except self.SYSTEM_EXCEPTIONS: raise except: if self.exc_info is not None: self.schedule_call_global(0, api.getcurrent().parent.throw, *self.exc_info) self.exc_info = None else: traceback.print_exc()
def start(self): notification_center = NotificationCenter() self.greenlet = api.getcurrent() settings = SIPSimpleSettings() account = AccountManager().sylkserver_account if account.sip.outbound_proxy is not None: uri = SIPURI( host=account.sip.outbound_proxy.host, port=account.sip.outbound_proxy.port, parameters={'transport': account.sip.outbound_proxy.transport}) else: uri = self.destination_uri lookup = DNSLookup() try: routes = lookup.lookup_sip_proxy( uri, settings.sip.transport_list).wait() except DNSLookupError: notification_center.post_notification( 'OutgoingFileTransferHandlerDidFail', sender=self) return self.session = Session(account) self.stream = FileTransferStream(self.file_selector, 'sendonly') notification_center.add_observer(self, sender=self.session) notification_center.add_observer(self, sender=self.stream) from_header = FromHeader(self.sender_uri, u'SIPStache File Transfer') to_header = ToHeader(self.destination_uri) transport = routes[0].transport parameters = {} if transport == 'udp' else {'transport': transport} contact_header = ContactHeader( SIPURI(user=self.sender_uri.user, host=SIPConfig.local_ip.normalized, port=getattr(Engine(), '%s_port' % transport), parameters=parameters)) extra_headers = [] if ThorNodeConfig.enabled: extra_headers.append(Header('Thor-Scope', 'sipstache-file')) extra_headers.append( Header('X-Originator-From', str(self.destination_uri))) self.session.connect(from_header, to_header, contact_header=contact_header, routes=routes, streams=[self.stream], is_focus=False, extra_headers=extra_headers) notification_center.post_notification( 'OutgoingFileTransferHandlerDidStart', sender=self)
def start(self): notification_center = NotificationCenter() if self.greenlet is not None: return self.greenlet = api.getcurrent() current_address = host.default_ip while True: new_address = host.default_ip # make sure the address stabilized api.sleep(5) if new_address != host.default_ip: continue if new_address != current_address: notification_center.post_notification(name='SystemIPAddressDidChange', sender=self, data=NotificationData(old_ip_address=current_address, new_ip_address=new_address)) current_address = new_address api.sleep(5)
def start(self, local_sdp, remote_sdp, stream_index): self.greenlet = api.getcurrent() notification_center = NotificationCenter() context = 'sdp_negotiation' try: remote_media = remote_sdp.media[stream_index] self.remote_media = remote_media self.remote_accept_types = remote_media.attributes.getfirst( b'accept-types', b'').decode().split() self.remote_accept_wrapped_types = remote_media.attributes.getfirst( b'accept-wrapped-types', b'').decode().split() self.cpim_enabled = contains_mime_type( self.accept_types, 'message/cpim') and contains_mime_type( self.remote_accept_types, 'message/cpim') remote_uri_path = remote_media.attributes.getfirst(b'path') if remote_uri_path is None: raise AttributeError( "remote SDP media does not have 'path' attribute") full_remote_path = [ URI.parse(uri) for uri in remote_uri_path.decode().split() ] remote_transport = 'tls' if full_remote_path[0].use_tls else 'tcp' if self.transport != remote_transport: raise MSRPStreamError( "remote transport ('%s') different from local transport ('%s')" % (remote_transport, self.transport)) if isinstance(self.session.account, Account) and self.local_role == 'actpass': remote_setup = remote_media.attributes.getfirst( 'setup', 'passive') if remote_setup == 'passive': # If actpass is offered connectors are always started as passive # We need to switch to active if the remote answers with passive if self.session.account.msrp.connection_model == 'relay': self.msrp_connector.mode = 'active' else: local_uri = self.msrp_connector.local_uri logger = self.msrp_connector.logger self.msrp_connector = DirectConnector( logger=logger, use_sessmatch=True) self.msrp_connector.prepare(local_uri) context = 'start' self.msrp = self.msrp_connector.complete(full_remote_path) if self.msrp_session_class is not None: self.msrp_session = self.msrp_session_class( self.msrp, accept_types=self.accept_types, on_incoming_cb=self._handle_incoming, automatic_reports=False) self.msrp_connector = None except Exception as e: self._failure_reason = str(e) traceback.print_exc() notification_center.post_notification( 'MediaStreamDidFail', sender=self, data=NotificationData(context=context, reason=self._failure_reason)) else: notification_center.post_notification('MediaStreamDidStart', sender=self) finally: self.greenlet = None
def initialize(self, session, direction): self.greenlet = api.getcurrent() notification_center = NotificationCenter() notification_center.add_observer(self, sender=self) try: self.session = session self.transport = self.session.account.msrp.transport outgoing = direction == 'outgoing' logger = NotificationProxyLogger() if self.session.account is BonjourAccount(): if outgoing: self.msrp_connector = DirectConnector(logger=logger) self.local_role = 'active' else: if self.transport == 'tls' and None in ( self.session.account.tls_credentials.cert, self.session.account.tls_credentials.key): raise MSRPStreamError( "Cannot accept MSRP connection without a TLS certificate" ) self.msrp_connector = DirectAcceptor(logger=logger) self.local_role = 'passive' else: if self.session.account.msrp.connection_model == 'relay': if not outgoing and self.remote_role in ('actpass', 'passive'): # 'passive' not allowed by the RFC but play nice for interoperability. -Saul self.msrp_connector = DirectConnector( logger=logger, use_sessmatch=True) self.local_role = 'active' elif outgoing and not self.session.account.nat_traversal.use_msrp_relay_for_outbound: self.msrp_connector = DirectConnector( logger=logger, use_sessmatch=True) self.local_role = 'active' else: if self.session.account.nat_traversal.msrp_relay is None: relay_host = relay_port = None else: if self.transport != self.session.account.nat_traversal.msrp_relay.transport: raise MSRPStreamError( "MSRP relay transport conflicts with MSRP transport setting" ) relay_host = self.session.account.nat_traversal.msrp_relay.host relay_port = self.session.account.nat_traversal.msrp_relay.port relay = MSRPRelaySettings( domain=self.session.account.uri.host.decode(), username=self.session.account.uri.user.decode(), password=self.session.account.credentials.password. decode(), host=relay_host, port=relay_port, use_tls=self.transport == 'tls') self.msrp_connector = RelayConnection( relay, 'passive', logger=logger, use_sessmatch=True) self.local_role = 'actpass' if outgoing else 'passive' else: if not outgoing and self.remote_role in ('actpass', 'passive'): # 'passive' not allowed by the RFC but play nice for interoperability. -Saul self.msrp_connector = DirectConnector( logger=logger, use_sessmatch=True) self.local_role = 'active' else: if not outgoing and self.transport == 'tls' and None in ( self.session.account.tls_credentials.cert, self.session.account.tls_credentials.key): raise MSRPStreamError( "Cannot accept MSRP connection without a TLS certificate" ) self.msrp_connector = DirectAcceptor( logger=logger, use_sessmatch=True) self.local_role = 'actpass' if outgoing else 'passive' full_local_path = self.msrp_connector.prepare(local_uri=URI( host=host.default_ip, port=0, use_tls=self.transport == 'tls', credentials=self.session.account.tls_credentials)) self.local_media = self._create_local_media(full_local_path) except (CertificateError, CertificateAuthorityError, CertificateExpiredError, CertificateSecurityError, CertificateRevokedError) as e: reason = "%s for %s" % (e.error, e.certificate.subject.CN.lower()) notification_center.post_notification( 'MediaStreamDidNotInitialize', sender=self, data=NotificationData(reason=reason)) except Exception as e: notification_center.post_notification( 'MediaStreamDidNotInitialize', sender=self, data=NotificationData(reason=str(e))) else: notification_center.post_notification('MediaStreamDidInitialize', sender=self) finally: self._initialize_done = True self.greenlet = None
def get_ident(): return id(api.getcurrent())
def unlink(self, listener=None): if listener is None: listener = api.getcurrent() self._value_links.pop(listener, None) self._exception_links.pop(listener, None)
def eb(failure): if cur: if getcurrent() is cur[0]: synchronous.append((None, failure)) else: failure.throwExceptionIntoGenerator(cur[0])
def __init__(self, *args, **kwargs): self.greenlet = api.getcurrent() DelayedCall.__init__(self, *args, **kwargs)
def __init__(self, cb, args, kwargs): self.tpl = cb, args, kwargs self.greenlet = api.getcurrent()
def __init__(self, *args, **kwargs): self.greenlet = getcurrent() Timer.__init__(self, *args, **kwargs)