diff --git a/sipsimple/account/__init__.py b/sipsimple/account/__init__.py index 2e9e1b1f..bbf538d6 100644 --- a/sipsimple/account/__init__.py +++ b/sipsimple/account/__init__.py @@ -1,842 +1,845 @@ """ Implements a SIP Account management system that allows the definition of multiple SIP accounts and their properties. """ __all__ = ['Account', 'BonjourAccount', 'AccountManager'] from itertools import chain from threading import Lock from application.notification import IObserver, NotificationCenter, NotificationData from application.python import Null from application.python.descriptor import classproperty from application.python.types import Singleton from application.system import host as Host from eventlib import coros, proc from gnutls.crypto import X509Certificate, X509PrivateKey from gnutls.interfaces.twisted import X509Credentials from zope.interface import implementer from sipsimple.account.bonjour import BonjourServices, _bonjour from sipsimple.account.publication import PresencePublisher, DialogPublisher from sipsimple.account.registration import Registrar from sipsimple.account.subscription import MWISubscriber, PresenceWinfoSubscriber, DialogWinfoSubscriber, PresenceSubscriber, SelfPresenceSubscriber, DialogSubscriber from sipsimple.account.xcap import XCAPManager from sipsimple.core import Credentials, SIPURI, ContactURIFactory from sipsimple.configuration import ConfigurationManager, Setting, SettingsGroup, SettingsObject, SettingsObjectID from sipsimple.configuration.datatypes import AudioCodecList, MSRPConnectionModel, MSRPRelayAddress, MSRPTransport, NonNegativeInteger, Path, SIPAddress, SIPProxyAddress, SRTPKeyNegotiation, STUNServerAddressList, VideoCodecList, XCAPRoot from sipsimple.configuration.settings import SIPSimpleSettings from sipsimple.payloads import ParserError from sipsimple.payloads.messagesummary import MessageSummary from sipsimple.payloads.pidf import PIDFDocument from sipsimple.payloads.rlsnotify import RLSNotify from sipsimple.payloads.watcherinfo import WatcherInfoDocument from sipsimple.threading import call_in_thread from sipsimple.threading.green import call_in_green_thread, run_in_green_thread from sipsimple.util import user_info, execute_once class AuthSettings(SettingsGroup): username = Setting(type=str, default=None, nillable=True) password = Setting(type=str, default='') class SIPSettings(SettingsGroup): always_use_my_proxy = Setting(type=bool, default=False) outbound_proxy = Setting(type=SIPProxyAddress, default=None, nillable=True) register = Setting(type=bool, default=True) register_interval = Setting(type=NonNegativeInteger, default=3600) subscribe_interval = Setting(type=NonNegativeInteger, default=3600) publish_interval = Setting(type=NonNegativeInteger, default=3600) class SRTPEncryptionSettings(SettingsGroup): enabled = Setting(type=bool, default=True) key_negotiation = Setting(type=SRTPKeyNegotiation, default='opportunistic') class RTPSettings(SettingsGroup): audio_codec_list = Setting(type=AudioCodecList, default=None, nillable=True) video_codec_list = Setting(type=VideoCodecList, default=None, nillable=True) encryption = SRTPEncryptionSettings class NATTraversalSettings(SettingsGroup): use_ice = Setting(type=bool, default=False) stun_server_list = Setting(type=STUNServerAddressList, default=None, nillable=True) msrp_relay = Setting(type=MSRPRelayAddress, default=None, nillable=True) use_msrp_relay_for_outbound = Setting(type=bool, default=False) class MessageSummarySettings(SettingsGroup): enabled = Setting(type=bool, default=False) voicemail_uri = Setting(type=SIPAddress, default=None, nillable=True) class XCAPSettings(SettingsGroup): enabled = Setting(type=bool, default=False) discovered = Setting(type=bool, default=False) xcap_root = Setting(type=XCAPRoot, default=None, nillable=True) class PresenceSettings(SettingsGroup): enabled = Setting(type=bool, default=False) class TLSSettings(SettingsGroup): certificate = Setting(type=Path, default=None, nillable=True) verify_server = Setting(type=bool, default=False) class MSRPSettings(SettingsGroup): transport = Setting(type=MSRPTransport, default='tls') connection_model = Setting(type=MSRPConnectionModel, default='relay') @implementer(IObserver) class Account(SettingsObject): """ Object representing a SIP account. Contains configuration settings and attributes for accessing SIP related objects. When the account is active, it will register, publish its presence and subscribe to watcher-info events depending on its settings. If the object is un-pickled and its enabled flag was set, it will automatically activate. When the save method is called, depending on the value of the enabled flag, the account will activate/deactivate. Notifications sent by instances of Account: * CFGSettingsObjectWasCreated * CFGSettingsObjectWasActivated * CFGSettingsObjectWasDeleted * CFGSettingsObjectDidChange * SIPAccountWillActivate * SIPAccountDidActivate * SIPAccountWillDeactivate * SIPAccountDidDeactivate """ __group__ = 'Accounts' __id__ = SettingsObjectID(type=SIPAddress) id = __id__ enabled = Setting(type=bool, default=False) display_name = Setting(type=str, default=None, nillable=True) auth = AuthSettings sip = SIPSettings rtp = RTPSettings nat_traversal = NATTraversalSettings message_summary = MessageSummarySettings msrp = MSRPSettings presence = PresenceSettings xcap = XCAPSettings tls = TLSSettings def __new__(cls, id): #with AccountManager.load.lock: # if not AccountManager.load.called: # raise RuntimeError("cannot instantiate %s before calling AccountManager.load" % cls.__name__) return SettingsObject.__new__(cls, id) def __init__(self, id): self.contact = ContactURIFactory() self.xcap_manager = XCAPManager(self) self._started = False self._deleted = False self._active = False self._activation_lock = coros.Semaphore(1) self._registrar = Registrar(self) self._mwi_subscriber = MWISubscriber(self) self._pwi_subscriber = PresenceWinfoSubscriber(self) self._dwi_subscriber = DialogWinfoSubscriber(self) self._presence_subscriber = PresenceSubscriber(self) self._self_presence_subscriber = SelfPresenceSubscriber(self) self._dialog_subscriber = DialogSubscriber(self) self._presence_publisher = PresencePublisher(self) self._dialog_publisher = DialogPublisher(self) self._mwi_voicemail_uri = None self._pwi_version = None self._dwi_version = None self._presence_version = None self._dialog_version = None def start(self): if self._started or self._deleted: return self._started = True notification_center = NotificationCenter() notification_center.add_observer(self, name='CFGSettingsObjectDidChange', sender=self) notification_center.add_observer(self, name='CFGSettingsObjectDidChange', sender=SIPSimpleSettings()) notification_center.add_observer(self, name='XCAPManagerDidDiscoverServerCapabilities', sender=self.xcap_manager) notification_center.add_observer(self, sender=self._mwi_subscriber) notification_center.add_observer(self, sender=self._pwi_subscriber) notification_center.add_observer(self, sender=self._dwi_subscriber) notification_center.add_observer(self, sender=self._presence_subscriber) notification_center.add_observer(self, sender=self._self_presence_subscriber) notification_center.add_observer(self, sender=self._dialog_subscriber) self.xcap_manager.init() if self.enabled: self._activate() def stop(self): if not self._started: return self._started = False self._deactivate() notification_center = NotificationCenter() notification_center.remove_observer(self, name='CFGSettingsObjectDidChange', sender=self) notification_center.remove_observer(self, name='CFGSettingsObjectDidChange', sender=SIPSimpleSettings()) notification_center.remove_observer(self, name='XCAPManagerDidDiscoverServerCapabilities', sender=self.xcap_manager) notification_center.remove_observer(self, sender=self._mwi_subscriber) notification_center.remove_observer(self, sender=self._pwi_subscriber) notification_center.remove_observer(self, sender=self._dwi_subscriber) notification_center.remove_observer(self, sender=self._presence_subscriber) notification_center.remove_observer(self, sender=self._self_presence_subscriber) notification_center.remove_observer(self, sender=self._dialog_subscriber) def delete(self): if self._deleted: return self._deleted = True self.stop() self._registrar = None self._mwi_subscriber = None self._pwi_subscriber = None self._dwi_subscriber = None self._presence_subscriber = None self._self_presence_subscriber = None self._dialog_subscriber = None self._presence_publisher = None self._dialog_publisher = None self.xcap_manager = None SettingsObject.delete(self) @run_in_green_thread def reregister(self): if self._started: self._registrar.reregister() @run_in_green_thread def resubscribe(self): if self._started: self._mwi_subscriber.resubscribe() self._pwi_subscriber.resubscribe() self._dwi_subscriber.resubscribe() self._presence_subscriber.resubscribe() self._self_presence_subscriber.resubscribe() self._dialog_subscriber.resubscribe() @property def credentials(self): - return Credentials(self.auth.username or self.id.username, self.auth.password) + username = self.auth.username or self.id.username + username = username.encode() if username else None + password = self.auth.password.encode() if self.auth.password else None + return Credentials(username, password) @property def registered(self): try: return self._registrar.registered except AttributeError: return False @property def mwi_active(self): try: return self._mwi_subscriber.subscribed except AttributeError: return False @property def tls_credentials(self): # This property can be optimized to cache the credentials it loads from disk, # however this is not a time consuming operation (~ 3000 req/sec). -Luci settings = SIPSimpleSettings() if self.tls.certificate is not None: certificate_data = open(self.tls.certificate.normalized).read() certificate = X509Certificate(certificate_data) private_key = X509PrivateKey(certificate_data) else: certificate = None private_key = None if settings.tls.ca_list is not None: # we should read all certificates in the file, rather than just the first -Luci trusted = [X509Certificate(open(settings.tls.ca_list.normalized).read())] else: trusted = [] credentials = X509Credentials(certificate, private_key, trusted) credentials.verify_peer = self.tls.verify_server return credentials @property def uri(self): return SIPURI(user=self.id.username, host=self.id.domain) @property def voicemail_uri(self): return self._mwi_voicemail_uri or self.message_summary.voicemail_uri @property def presence_state(self): try: return self._presence_publisher.state except AttributeError: return None @presence_state.setter def presence_state(self, state): try: self._presence_publisher.state = state except AttributeError: pass @property def dialog_state(self): try: return self._dialog_publisher.state except AttributeError: return None @dialog_state.setter def dialog_state(self, state): try: self._dialog_publisher.state = state except AttributeError: pass def handle_notification(self, notification): handler = getattr(self, '_NH_%s' % notification.name, Null) handler(notification) @run_in_green_thread def _NH_CFGSettingsObjectDidChange(self, notification): if self._started and 'enabled' in notification.data.modified: if self.enabled: self._activate() else: self._deactivate() def _NH_XCAPManagerDidDiscoverServerCapabilities(self, notification): if self._started and self.xcap.discovered is False: self.xcap.discovered = True self.save() notification.center.post_notification('SIPAccountDidDiscoverXCAPSupport', sender=self) def _NH_MWISubscriberDidDeactivate(self, notification): self._mwi_voicemail_uri = None def _NH_MWISubscriptionGotNotify(self, notification): if notification.data.body and notification.data.content_type == MessageSummary.content_type: try: message_summary = MessageSummary.parse(notification.data.body) except ParserError: pass else: self._mwi_voicemail_uri = message_summary.message_account and SIPAddress(message_summary.message_account.replace('sip:', '', 1)) or None notification.center.post_notification('SIPAccountGotMessageSummary', sender=self, data=NotificationData(message_summary=message_summary)) def _NH_PresenceWinfoSubscriptionGotNotify(self, notification): if notification.data.body and notification.data.content_type == WatcherInfoDocument.content_type: try: watcher_info = WatcherInfoDocument.parse(notification.data.body) watcher_list = watcher_info['sip:' + self.id] except (ParserError, KeyError): pass else: if watcher_list.package != 'presence': return if self._pwi_version is None: if watcher_info.state == 'partial': self._pwi_subscriber.resubscribe() elif watcher_info.version <= self._pwi_version: return elif watcher_info.state == 'partial' and watcher_info.version > self._pwi_version + 1: self._pwi_subscriber.resubscribe() self._pwi_version = watcher_info.version data = NotificationData(version=watcher_info.version, state=watcher_info.state, watcher_list=watcher_list) notification.center.post_notification('SIPAccountGotPresenceWinfo', sender=self, data=data) def _NH_PresenceWinfoSubscriptionDidEnd(self, notification): self._pwi_version = None def _NH_PresenceWinfoSubscriptionDidFail(self, notification): self._pwi_version = None def _NH_DialogWinfoSubscriptionGotNotify(self, notification): if notification.data.body and notification.data.content_type == WatcherInfoDocument.content_type: try: watcher_info = WatcherInfoDocument.parse(notification.data.body) watcher_list = watcher_info['sip:' + self.id] except (ParserError, KeyError): pass else: if watcher_list.package != 'dialog': return if self._dwi_version is None: if watcher_info.state == 'partial': self._dwi_subscriber.resubscribe() elif watcher_info.version <= self._dwi_version: return elif watcher_info.state == 'partial' and watcher_info.version > self._dwi_version + 1: self._dwi_subscriber.resubscribe() self._dwi_version = watcher_info.version data = NotificationData(version=watcher_info.version, state=watcher_info.state, watcher_list=watcher_list) notification.center.post_notification('SIPAccountGotDialogWinfo', sender=self, data=data) def _NH_DialogWinfoSubscriptionDidEnd(self, notification): self._dwi_version = None def _NH_DialogWinfoSubscriptionDidFail(self, notification): self._dwi_version = None def _NH_PresenceSubscriptionGotNotify(self, notification): if notification.data.body and notification.data.content_type == RLSNotify.content_type: try: rls_notify = RLSNotify.parse('{content_type}\r\n\r\n{body}'.format(content_type=notification.data.headers['Content-Type'], body=notification.data.body)) except ParserError: pass else: if rls_notify.uri != self.xcap_manager.rls_presence_uri: return if self._presence_version is None: if not rls_notify.full_state: self._presence_subscriber.resubscribe() elif rls_notify.version <= self._presence_version: return elif not rls_notify.full_state and rls_notify.version > self._presence_version + 1: self._presence_subscriber.resubscribe() self._presence_version = rls_notify.version data = NotificationData(version=rls_notify.version, full_state=rls_notify.full_state, resource_map=dict((resource.uri, resource) for resource in rls_notify)) notification.center.post_notification('SIPAccountGotPresenceState', sender=self, data=data) def _NH_PresenceSubscriptionDidEnd(self, notification): self._presence_version = None def _NH_PresenceSubscriptionDidFail(self, notification): self._presence_version = None def _NH_SelfPresenceSubscriptionGotNotify(self, notification): if notification.data.body and notification.data.content_type == PIDFDocument.content_type: try: pidf_doc = PIDFDocument.parse(notification.data.body) except ParserError: pass else: if pidf_doc.entity.partition('sip:')[2] != self.id: return notification.center.post_notification('SIPAccountGotSelfPresenceState', sender=self, data=NotificationData(pidf=pidf_doc)) def _NH_DialogSubscriptionGotNotify(self, notification): if notification.data.body and notification.data.content_type == RLSNotify.content_type: try: rls_notify = RLSNotify.parse('{content_type}\r\n\r\n{body}'.format(content_type=notification.data.headers['Content-Type'], body=notification.data.body)) except ParserError: pass else: if rls_notify.uri != self.xcap_manager.rls_dialog_uri: return if self._dialog_version is None: if not rls_notify.full_state: self._dialog_subscriber.resubscribe() elif rls_notify.version <= self._dialog_version: return elif not rls_notify.full_state and rls_notify.version > self._dialog_version + 1: self._dialog_subscriber.resubscribe() self._dialog_version = rls_notify.version data = NotificationData(version=rls_notify.version, full_state=rls_notify.full_state, resource_map=dict((resource.uri, resource) for resource in rls_notify)) notification.center.post_notification('SIPAccountGotDialogState', sender=self, data=data) def _NH_DialogSubscriptionDidEnd(self, notification): self._dialog_version = None def _NH_DialogSubscriptionDidFail(self, notification): self._dialog_version = None def _activate(self): with self._activation_lock: if self._active: return notification_center = NotificationCenter() notification_center.post_notification('SIPAccountWillActivate', sender=self) self._active = True self._registrar.start() self._mwi_subscriber.start() self._pwi_subscriber.start() self._dwi_subscriber.start() self._presence_subscriber.start() self._self_presence_subscriber.start() self._dialog_subscriber.start() self._presence_publisher.start() self._dialog_publisher.start() if self.xcap.enabled: self.xcap_manager.start() notification_center.post_notification('SIPAccountDidActivate', sender=self) def _deactivate(self): with self._activation_lock: if not self._active: return notification_center = NotificationCenter() notification_center.post_notification('SIPAccountWillDeactivate', sender=self) self._active = False handlers = [self._registrar, self._mwi_subscriber, self._pwi_subscriber, self._dwi_subscriber, self._presence_subscriber, self._self_presence_subscriber, self._dialog_subscriber, self._presence_publisher, self._dialog_publisher, self.xcap_manager] proc.waitall([proc.spawn(handler.stop) for handler in handlers]) notification_center.post_notification('SIPAccountDidDeactivate', sender=self) def __repr__(self): return '%s(%r)' % (self.__class__.__name__, self.id) def __setstate__(self, data): # This restores the password from its previous location as a top level setting # after it was moved under the auth group. SettingsObject.__setstate__(self, data) if not data.get('auth', {}).get('password') and data.get('password'): self.auth.password = data.pop('password') self.save() class BonjourMSRPSettings(SettingsGroup): transport = Setting(type=MSRPTransport, default='tcp') class BonjourAccountEnabledSetting(Setting): def __get__(self, obj, objtype): if obj is None: return self return _bonjour.available and self.values.get(obj, self.default) def __set__(self, obj, value): if not _bonjour.available: raise RuntimeError('mdns support is not available') Setting.__set__(self, obj, value) @implementer(IObserver) class BonjourAccount(SettingsObject): """ Object representing a bonjour account. Contains configuration settings and attributes for accessing bonjour related options. When the account is active, it will send broadcast its contact address on the LAN. If the object is un-pickled and its enabled flag was set, it will automatically activate. When the save method is called, depending on the value of the enabled flag, the account will activate/deactivate. Notifications sent by instances of Account: * CFGSettingsObjectWasCreated * CFGSettingsObjectWasActivated * CFGSettingsObjectWasDeleted * CFGSettingsObjectDidChange * SIPAccountWillActivate * SIPAccountDidActivate * SIPAccountWillDeactivate * SIPAccountDidDeactivate """ __group__ = 'Accounts' __id__ = SIPAddress('bonjour@local') id = property(lambda self: self.__id__) enabled = BonjourAccountEnabledSetting(type=bool, default=True) display_name = Setting(type=str, default=user_info.fullname, nillable=False) msrp = BonjourMSRPSettings presence = PresenceSettings rtp = RTPSettings tls = TLSSettings def __new__(cls): # with AccountManager.load.lock: # if not AccountManager.load.called: # raise RuntimeError("cannot instantiate %s before calling AccountManager.load" % cls.__name__) return SettingsObject.__new__(cls) def __init__(self): self.contact = ContactURIFactory() self.credentials = None self._started = False self._active = False self._activation_lock = coros.Semaphore(1) self._bonjour_services = BonjourServices(self) # initialize fake settings (these are here to make the bonjour account quack like a duck) self.nat_traversal = NATTraversalSettings() self.nat_traversal.use_ice = False self.nat_traversal.msrp_relay = None self.nat_traversal.use_msrp_relay_for_outbound = False self.xcap = XCAPSettings() self.xcap.enabled = False self.xcap.discovered = False self.xcap.xcap_root = None def __repr__(self): return '%s()' % self.__class__.__name__ def start(self): if self._started: return self._started = True notification_center = NotificationCenter() notification_center.add_observer(self, name='CFGSettingsObjectDidChange', sender=self) notification_center.add_observer(self, name='CFGSettingsObjectDidChange', sender=SIPSimpleSettings()) self._bonjour_services.start() if self.enabled: self._activate() def stop(self): if not self._started: return self._started = False self._deactivate() self._bonjour_services.stop() notification_center = NotificationCenter() notification_center.remove_observer(self, name='CFGSettingsObjectDidChange', sender=self) notification_center.remove_observer(self, name='CFGSettingsObjectDidChange', sender=SIPSimpleSettings()) @classproperty def mdns_available(cls): return _bonjour.available @property def registered(self): return False @property def tls_credentials(self): # This property can be optimized to cache the credentials it loads from disk, # however this is not a time consuming operation (~ 3000 req/sec). -Luci settings = SIPSimpleSettings() if self.tls.certificate is not None: certificate_data = open(self.tls.certificate.normalized).read() certificate = X509Certificate(certificate_data) private_key = X509PrivateKey(certificate_data) else: certificate = None private_key = None if settings.tls.ca_list is not None: # we should read all certificates in the file, rather than just the first -Luci trusted = [X509Certificate(open(settings.tls.ca_list.normalized).read())] else: trusted = [] credentials = X509Credentials(certificate, private_key, trusted) credentials.verify_peer = self.tls.verify_server return credentials @property def uri(self): return SIPURI(user=self.contact.username, host=Host.default_ip or '127.0.0.1') @property def presence_state(self): return self._bonjour_services.presence_state @presence_state.setter def presence_state(self, state): self._bonjour_services.presence_state = state def handle_notification(self, notification): handler = getattr(self, '_NH_%s' % notification.name, Null) handler(notification) @run_in_green_thread def _NH_CFGSettingsObjectDidChange(self, notification): if self._started: if 'enabled' in notification.data.modified: if self.enabled: self._activate() else: self._deactivate() elif self.enabled: if 'display_name' in notification.data.modified: self._bonjour_services.update_registrations() if {'sip.transport_list', 'tls.certificate'}.intersection(notification.data.modified): self._bonjour_services.update_registrations() self._bonjour_services.restart_discovery() def _activate(self): with self._activation_lock: if self._active: return notification_center = NotificationCenter() notification_center.post_notification('SIPAccountWillActivate', sender=self) self._active = True self._bonjour_services.activate() notification_center.post_notification('SIPAccountDidActivate', sender=self) def _deactivate(self): with self._activation_lock: if not self._active: return notification_center = NotificationCenter() notification_center.post_notification('SIPAccountWillDeactivate', sender=self) self._active = False self._bonjour_services.deactivate() notification_center.post_notification('SIPAccountDidDeactivate', sender=self) @implementer(IObserver) class AccountManager(object, metaclass=Singleton): """ This is a singleton object which manages all the SIP accounts. It is also used to manage the default account (the one used for outbound sessions) using the default_account attribute: manager = AccountManager() manager.default_account = manager.get_account('alice@example.net') The following notifications are sent: * SIPAccountManagerDidRemoveAccount * SIPAccountManagerDidAddAccount * SIPAccountManagerDidChangeDefaultAccount """ def __init__(self): self._lock = Lock() self.accounts = {} notification_center = NotificationCenter() notification_center.add_observer(self, name='CFGSettingsObjectWasActivated') notification_center.add_observer(self, name='CFGSettingsObjectWasCreated') @execute_once def load(self): """ Load all accounts from the configuration. The accounts will not be started until the start method is called. """ configuration = ConfigurationManager() bonjour_account = BonjourAccount() names = configuration.get_names([Account.__group__]) [Account(id) for id in names if id != bonjour_account.id] default_account = self.default_account if default_account is None or not default_account.enabled: try: self.default_account = next((account for account in list(self.accounts.values()) if account.enabled)) except StopIteration: self.default_account = None def start(self): """ Start the accounts, which will determine the ones with the enabled flag set to activate. """ notification_center = NotificationCenter() notification_center.post_notification('SIPAccountManagerWillStart', sender=self) proc.waitall([proc.spawn(account.start) for account in list(self.accounts.values())]) notification_center.post_notification('SIPAccountManagerDidStart', sender=self) def stop(self): """ Stop the accounts, which will determine the ones that were enabled to deactivate. This method returns only once the accounts were stopped successfully or they timed out trying. """ notification_center = NotificationCenter() notification_center.post_notification('SIPAccountManagerWillEnd', sender=self) proc.waitall([proc.spawn(account.stop) for account in list(self.accounts.values())]) notification_center.post_notification('SIPAccountManagerDidEnd', sender=self) def has_account(self, id): return id in self.accounts def get_account(self, id): return self.accounts[id] def get_accounts(self): return list(self.accounts.values()) def iter_accounts(self): return iter(list(self.accounts.values())) def find_account(self, contact_uri): # compare contact_address with account contact exact_matches = (account for account in list(self.accounts.values()) if account.enabled and account.contact.username==contact_uri.user) # compare username in contact URI with account username loose_matches = (account for account in list(self.accounts.values()) if account.enabled and account.id.username==contact_uri.user) return next(chain(exact_matches, loose_matches, [None])) def handle_notification(self, notification): handler = getattr(self, '_NH_%s' % notification.name, Null) handler(notification) def _NH_CFGSettingsObjectWasActivated(self, notification): if isinstance(notification.sender, Account) or (isinstance(notification.sender, BonjourAccount) and _bonjour.available): account = notification.sender self.accounts[account.id] = account notification.center.add_observer(self, sender=account, name='CFGSettingsObjectDidChange') notification.center.add_observer(self, sender=account, name='CFGSettingsObjectWasDeleted') notification.center.post_notification('SIPAccountManagerDidAddAccount', sender=self, data=NotificationData(account=account)) from sipsimple.application import SIPApplication if SIPApplication.running: call_in_green_thread(account.start) def _NH_CFGSettingsObjectWasCreated(self, notification): if isinstance(notification.sender, Account): account = notification.sender if account.enabled and self.default_account is None: self.default_account = account def _NH_CFGSettingsObjectWasDeleted(self, notification): account = notification.sender del self.accounts[account.id] notification.center.remove_observer(self, sender=account, name='CFGSettingsObjectDidChange') notification.center.remove_observer(self, sender=account, name='CFGSettingsObjectWasDeleted') notification.center.post_notification('SIPAccountManagerDidRemoveAccount', sender=self, data=NotificationData(account=account)) def _NH_CFGSettingsObjectDidChange(self, notification): account = notification.sender if '__id__' in notification.data.modified: modified_id = notification.data.modified['__id__'] self.accounts[modified_id.new] = self.accounts.pop(modified_id.old) if 'enabled' in notification.data.modified: if account.enabled and self.default_account is None: self.default_account = account elif not account.enabled and self.default_account is account: try: self.default_account = next((account for account in list(self.accounts.values()) if account.enabled)) except StopIteration: self.default_account = None @property def default_account(self): settings = SIPSimpleSettings() return self.accounts.get(settings.default_account, None) @default_account.setter def default_account(self, account): if account is not None and not account.enabled: raise ValueError("account %s is not enabled" % account.id) notification_center = NotificationCenter() settings = SIPSimpleSettings() with self._lock: old_account = self.accounts.get(settings.default_account, None) if account is old_account: return if account is None: settings.default_account = None else: settings.default_account = account.id settings.save() # we need to post the notification in the file-io thread in order to have it serialized after the # SIPAccountManagerDidAddAccount notification that is triggered when the account is saved the first # time, because save is executed in the file-io thread while this runs in the current thread. -Dan call_in_thread('file-io', notification_center.post_notification, 'SIPAccountManagerDidChangeDefaultAccount', sender=self, data=NotificationData(old_account=old_account, account=account)) diff --git a/sipsimple/core/_core.helper.pxi b/sipsimple/core/_core.helper.pxi index be1f1669..7eb9d9f7 100644 --- a/sipsimple/core/_core.helper.pxi +++ b/sipsimple/core/_core.helper.pxi @@ -1,357 +1,356 @@ import re import urllib # Classes # cdef class BaseCredentials: def __cinit__(self, *args, **kwargs): global _Credentials_scheme_digest, _Credentials_realm_wildcard self._credentials.scheme = _Credentials_scheme_digest.pj_str - def __init__(self, str username not None, str password not None, str realm='*', bint digest=False): + def __init__(self, object username not None, object password not None, object realm=b'*', bint digest=False): if self.__class__ is BaseCredentials: raise TypeError("BaseCredentials cannot be instantiated directly") self.username = username self.realm = realm self.password = password self.digest = digest def __repr__(self): return "%s(username=%r, password=%r, realm=%r, digest=%r)" % (self.__class__.__name__, self.username, self.password, self.realm, self.digest) def __str__(self): return '<%s for "%s@%s">' % (self.__class__.__name__, self.username, self.realm) cdef pjsip_cred_info* get_cred_info(self): return &self._credentials cdef class Credentials(BaseCredentials): property username: def __get__(self): return self._username - def __set__(self, str username not None): - _str_to_pj_str(username.encode(), &self._credentials.username) + def __set__(self, object username not None): + _str_to_pj_str(username, &self._credentials.username) self._username = username property realm: def __get__(self): return self._realm - def __set__(self, str realm not None): - _str_to_pj_str(realm.encode(), &self._credentials.realm) + def __set__(self, object realm not None): + _str_to_pj_str(realm, &self._credentials.realm) self._realm = realm property password: def __get__(self): return self._password - def __set__(self, str password not None): - _str_to_pj_str(password.encode(), &self._credentials.data) + def __set__(self, object password not None): + _str_to_pj_str(password, &self._credentials.data) self._password = password property digest: def __get__(self): return self._digest def __set__(self, bint digest): self._credentials.data_type = PJSIP_CRED_DATA_DIGEST if digest else PJSIP_CRED_DATA_PLAIN_PASSWD self._digest = digest @classmethod def new(cls, BaseCredentials credentials): return cls(credentials.username, credentials.password, credentials.realm, credentials.digest) cdef class FrozenCredentials(BaseCredentials): - def __init__(self, str username not None, str password not None, str realm='*', bint digest=False): + def __init__(self, object username not None, object password not None, object realm=b'*', bint digest=False): if not self.initialized: self.username = username self.realm = realm self.password = password self.digest = digest - _str_to_pj_str(self.username.encode(), &self._credentials.username) - _str_to_pj_str(self.realm.encode(), &self._credentials.realm) - _str_to_pj_str(self.password.encode(), &self._credentials.data) + _str_to_pj_str(self.username, &self._credentials.username) + _str_to_pj_str(self.realm, &self._credentials.realm) + _str_to_pj_str(self.password, &self._credentials.data) self._credentials.data_type = PJSIP_CRED_DATA_DIGEST if digest else PJSIP_CRED_DATA_PLAIN_PASSWD self.initialized = 1 else: raise TypeError("{0.__class__.__name__} is read-only".format(self)) def __hash__(self): return hash((self.username, self.realm, self.password, self.digest)) @classmethod def new(cls, BaseCredentials credentials): if isinstance(credentials, FrozenCredentials): return credentials return cls(credentials.username, credentials.password, credentials.realm, credentials.digest) cdef class BaseSIPURI: def __init__(self, object host not None, object user=None, object password=None, object port=None, bint secure=False, dict parameters=None, dict headers=None): if self.__class__ is BaseSIPURI: raise TypeError("BaseSIPURI cannot be instantiated directly") self.host = host.encode() if isinstance(host, str) else host self.user = user.encode() if user and isinstance(user, str) else user self.password = password.encode() if password else None self.port = port self.secure = secure self.parameters = parameters if parameters is not None else {} self.headers = headers if headers is not None else {} property transport: def __get__(self): return self.parameters.get('transport', b'udp') def __set__(self, object transport not None): print('Set BaseSIPURI transport to %s' % transport) if transport.decode().lower() == 'udp': self.parameters.pop('transport', None) else: self.parameters['transport'] = transport.encode() def __reduce__(self): return self.__class__, (self.host, self.user, self.password, self.port, self.secure, self.parameters, self.headers), None def __repr__(self): return "%s(%r, %r, %r, %r, %r, %r, %r)" % (self.__class__.__name__, self.host, self.user, self.password, self.port, self.secure, self.parameters, self.headers) def __str__(self): cdef object string = self.host.decode() if isinstance(self.host, bytes) else self.host if self.port: string = "%s:%d" % (string, self.port) if self.user is not None: if self.password is not None: string = "%s:%s@%s" % (self.user.decode() if isinstance(self.user, bytes) else self.user, self.password.decode() if isinstance(self.password, bytes) else self.password, string) else: string = "%s@%s" % (self.user.decode() if isinstance(self.user, bytes) else self.user, string) if self.parameters: string += ";" + ";".join(["%s%s" % (name, ("" if val is None else "="+urllib.parse.quote(val, safe="()[]-_.!~*'/:&+$"))) for name, val in list(self.parameters.items())]) if self.headers: string += "?" + "&".join(["%s%s" % (name, ("" if val is None else "="+urllib.parse.quote(val, safe="()[]-_.!~*'/:?+$"))) for name, val in self.headers.items()]) if self.secure: string = "sips:" + string else: string = "sip:" + string return string def __richcmp__(self, other, op): if not isinstance(other, BaseSIPURI): return NotImplemented if op == 2: # 2 is == return all(getattr(self, name) == getattr(other, name) for name in ("user", "password", "host", "port", "secure", "parameters", "headers")) elif op == 3: # 3 is != return any(getattr(self, name) != getattr(other, name) for name in ("user", "password", "host", "port", "secure", "parameters", "headers")) else: operator_map = {0: '<', 1: '<=', 2: '==', 3: '!=', 4: '>', 5: '>='} raise TypeError("unorderable types: {0.__class__.__name__}() {2} {1.__class__.__name__}()".format(self, other, operator_map[op])) def matches(self, address): address = address.decode() if isinstance(address, bytes) else address match = re.match(r'^((?Psip|sips):)?(?P.+?)(@(?P.+?)(:(?P\d+?))?)?(;(?P.+?))?(\?(?P.+?))?$', address) if match is None: return False components = match.groupdict() if components['scheme'] is not None: expected_scheme = 'sips' if self.secure else 'sip' if components['scheme'] != expected_scheme: return False user = self.user.decode() if self.user else None if components['username'] != user: return False if components['domain'] is not None and components['domain'] != self.host.decode(): return False if components['port'] is not None and int(components['port']) != self.port: return False if components['parameters']: parameters = dict([(name, value) for name, sep, value in [param.partition('=') for param in components['parameters'].split(';')]]) expected_parameters = dict([(name, str(value) if value is not None else None) for name, value in list(self.parameters.items()) if name in parameters]) if parameters != expected_parameters: return False if components['headers']: headers = dict([(name, value) for name, sep, value in [header.partition('=') for header in components['headers'].split('&')]]) expected_headers = dict([(name, str(value) if value is not None else None) for name, value in self.headers.items() if name in headers]) if headers != expected_headers: return False return True cdef class SIPURI(BaseSIPURI): property port: def __get__(self): return self._port def __set__(self, object port): if port is not None: port = int(port) if not (0 < port <= 65535): raise ValueError("Invalid port: %d" % port) self._port = port @classmethod def new(cls, BaseSIPURI sipuri): return cls(user=sipuri.user, password=sipuri.password, host=sipuri.host, port=sipuri.port, secure=sipuri.secure, parameters=dict(sipuri.parameters), headers=dict(sipuri.headers)) @classmethod def parse(cls, object uri_str): cdef bytes uri_bytes = uri_str.encode() if isinstance(uri_str, str) else uri_str cdef pjsip_uri *uri = NULL cdef pj_pool_t *pool = NULL cdef pj_str_t tmp cdef char buffer[4096] pool = pj_pool_create_on_buf("SIPURI_parse", buffer, sizeof(buffer)) if pool == NULL: raise SIPCoreError("Could not allocate memory pool") pj_strdup2_with_null(pool, &tmp, uri_bytes) uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0) if uri == NULL: raise SIPCoreError("Not a valid SIP URI: %s" % uri_str) return SIPURI_create(pjsip_uri_get_uri(uri)) cdef class FrozenSIPURI(BaseSIPURI): def __init__(self, object host not None, object user=None, object password=None, object port=None, bint secure=False, frozendict parameters not None=frozendict(), frozendict headers not None=frozendict()): if not self.initialized: if port is not None: port = int(port) if not (0 < port <= 65535): raise ValueError("Invalid port: %d" % port) self.host = host self.user = user self.password = password self.port = port self.secure = secure self.parameters = parameters self.headers = headers self.initialized = 1 else: raise TypeError("{0.__class__.__name__} is read-only".format(self)) property transport: def __get__(self): return self.parameters.get('transport', 'udp') def __hash__(self): return hash((self.user, self.password, self.host, self.port, self.secure, self.parameters, self.headers)) def __richcmp__(self, other, op): # since we define __hash__, __richcmp__ is not inherited (see https://docs.python.org/2/c-api/typeobj.html#c.PyTypeObject.tp_richcompare) if not isinstance(other, BaseSIPURI): return NotImplemented if op == 2: # 2 is == return all(getattr(self, name) == getattr(other, name) for name in ("user", "password", "host", "port", "secure", "parameters", "headers")) elif op == 3: # 3 is != return any(getattr(self, name) != getattr(other, name) for name in ("user", "password", "host", "port", "secure", "parameters", "headers")) else: operator_map = {0: '<', 1: '<=', 2: '==', 3: '!=', 4: '>', 5: '>='} raise TypeError("unorderable types: {0.__class__.__name__}() {2} {1.__class__.__name__}()".format(self, other, operator_map[op])) @classmethod def new(cls, BaseSIPURI sipuri): if isinstance(sipuri, FrozenSIPURI): return sipuri return cls(user=sipuri.user, password=sipuri.password, host=sipuri.host, port=sipuri.port, secure=sipuri.secure, parameters=frozendict(sipuri.parameters), headers=frozendict(sipuri.headers)) @classmethod def parse(cls, object uri_str): cdef bytes uri_bytes = uri_str.encode() if isinstance(uri_str, str) else uri_str cdef pjsip_uri *uri = NULL cdef pj_pool_t *pool = NULL cdef pj_str_t tmp cdef char buffer[4096] pool = pj_pool_create_on_buf("FrozenSIPURI_parse", buffer, sizeof(buffer)) if pool == NULL: raise SIPCoreError("Could not allocate memory pool") pj_strdup2_with_null(pool, &tmp, uri_bytes) uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0) if uri == NULL: raise SIPCoreError("Not a valid SIP URI: %s" % uri_str) return FrozenSIPURI_create(pjsip_uri_get_uri(uri)) # Factory functions # cdef dict _pj_sipuri_to_dict(pjsip_sip_uri *uri): - #print('_pj_sipuri_to_dict ---------------') cdef object scheme cdef pj_str_t *scheme_str cdef pjsip_param *param cdef object parameters = {} cdef object headers = {} cdef object kwargs = dict(parameters=parameters, headers=headers) scheme = _pj_str_to_str(pjsip_uri_get_scheme(uri)[0]) if scheme == "sip": kwargs["secure"] = False elif scheme == "sips": kwargs["secure"] = True else: raise SIPCoreError("Not a valid SIP URI") kwargs["host"] = _pj_str_to_str(uri.host) if uri.user.slen > 0: kwargs["user"] = _pj_str_to_str(uri.user) if uri.passwd.slen > 0: kwargs["password"] = _pj_str_to_str(uri.passwd) if uri.port > 0: kwargs["port"] = uri.port if uri.user_param.slen > 0: parameters["user"] = _pj_str_to_str(uri.user_param) if uri.method_param.slen > 0: parameters["method"] = _pj_str_to_str(uri.method_param) if uri.transport_param.slen > 0: parameters["transport"] = _pj_str_to_str(uri.transport_param) if uri.ttl_param != -1: parameters["ttl"] = uri.ttl_param if uri.lr_param != 0: parameters["lr"] = None if uri.maddr_param.slen > 0: parameters["maddr"] = _pj_str_to_str(uri.maddr_param) param = ( &uri.other_param).next while param != &uri.other_param: if param.value.slen == 0: parameters[_pj_str_to_str(param.name)] = None else: parameters[_pj_str_to_str(param.name)] = _pj_str_to_str(param.value) param = ( param).next param = ( &uri.header_param).next while param != &uri.header_param: if param.value.slen == 0: headers[_pj_str_to_str(param.name)] = None else: headers[_pj_str_to_str(param.name)] = _pj_str_to_str(param.value) param = ( param).next return kwargs cdef SIPURI SIPURI_create(pjsip_sip_uri *uri): cdef dict kwargs = _pj_sipuri_to_dict(uri) return SIPURI(**kwargs) cdef FrozenSIPURI FrozenSIPURI_create(pjsip_sip_uri *uri): cdef dict kwargs = _pj_sipuri_to_dict(uri) kwargs["parameters"] = frozendict(kwargs["parameters"]) kwargs["headers"] = frozendict(kwargs["headers"]) return FrozenSIPURI(**kwargs) # Globals # cdef PJSTR _Credentials_scheme_digest = PJSTR(b"digest") diff --git a/sipsimple/core/_core.pxd b/sipsimple/core/_core.pxd index f6218ceb..04ddbb73 100644 --- a/sipsimple/core/_core.pxd +++ b/sipsimple/core/_core.pxd @@ -1,2645 +1,2645 @@ # cython: language_level=2 cdef extern from *: ctypedef char *char_ptr_const "const char *" enum: PJ_SVN_REV "PJ_SVN_REVISION" # system imports from libc.stdlib cimport malloc, free from libc.string cimport memcpy # Python C imports from cpython.float cimport PyFloat_AsDouble from cpython.ref cimport Py_INCREF, Py_DECREF from cpython.bytes cimport PyBytes_FromString, PyBytes_FromStringAndSize, PyBytes_AsString, PyBytes_Size cdef extern from "Python.h": object PyUnicode_FromString(const char *u) # PJSIP imports cdef extern from "pjlib.h": # constants enum: PJ_ERR_MSG_SIZE enum: PJ_ERRNO_START_SYS PJ_EBUG PJ_ETOOMANY enum: PJ_MAX_OBJ_NAME # init / shutdown int pj_init() nogil void pj_shutdown() nogil # version char *pj_get_version() nogil # string struct pj_str_t: char *ptr int slen ctypedef pj_str_t *pj_str_ptr_const "const pj_str_t *" # errors pj_str_t pj_strerror(int statcode, char *buf, int bufsize) nogil # logging enum: PJ_LOG_MAX_LEVEL enum pj_log_decoration: PJ_LOG_HAS_YEAR PJ_LOG_HAS_MONTH PJ_LOG_HAS_DAY_OF_MON PJ_LOG_HAS_TIME PJ_LOG_HAS_MICRO_SEC PJ_LOG_HAS_SENDER PJ_LOG_HAS_INDENT void pj_log_set_decor(int decor) nogil int pj_log_get_level() nogil void pj_log_set_level(int level) nogil void pj_log_set_log_func(void func(int level, char_ptr_const data, int len)) nogil # memory management struct pj_pool_t struct pj_pool_factory_policy: pass pj_pool_factory_policy pj_pool_factory_default_policy struct pj_pool_factory: pass struct pj_caching_pool: pj_pool_factory factory void pj_caching_pool_init(pj_caching_pool *ch_pool, pj_pool_factory_policy *policy, int max_capacity) nogil void pj_caching_pool_destroy(pj_caching_pool *ch_pool) nogil void *pj_pool_alloc(pj_pool_t *pool, int size) nogil void pj_pool_reset(pj_pool_t *pool) nogil pj_pool_t *pj_pool_create_on_buf(char *name, void *buf, int size) nogil pj_str_t *pj_strdup2_with_null(pj_pool_t *pool, pj_str_t *dst, char *src) nogil void pj_pool_release(pj_pool_t *pool) nogil # threads enum: PJ_THREAD_DESC_SIZE struct pj_mutex_t struct pj_rwmutex_t struct pj_thread_t int pj_mutex_create_simple(pj_pool_t *pool, char *name, pj_mutex_t **mutex) nogil int pj_mutex_create_recursive(pj_pool_t *pool, char *name, pj_mutex_t **mutex) nogil int pj_mutex_lock(pj_mutex_t *mutex) nogil int pj_mutex_unlock(pj_mutex_t *mutex) nogil int pj_mutex_destroy(pj_mutex_t *mutex) nogil int pj_rwmutex_create(pj_pool_t *pool, char *name, pj_rwmutex_t **mutex) nogil int pj_rwmutex_lock_read(pj_rwmutex_t *mutex) nogil int pj_rwmutex_lock_write(pj_rwmutex_t *mutex) nogil int pj_rwmutex_unlock_read(pj_rwmutex_t *mutex) nogil int pj_rwmutex_unlock_write(pj_rwmutex_t *mutex) nogil int pj_rwmutex_destroy(pj_rwmutex_t *mutex) nogil int pj_thread_is_registered() nogil int pj_thread_register(char *thread_name, long *thread_desc, pj_thread_t **thread) nogil # sockets enum: PJ_INET6_ADDRSTRLEN struct pj_ioqueue_t struct pj_addr_hdr: unsigned int sa_family struct pj_sockaddr_in: pass struct pj_sockaddr_in6: pass ctypedef union pj_sockaddr: pj_addr_hdr addr pj_sockaddr_in ipv4 pj_sockaddr_in6 ipv6 ctypedef pj_sockaddr *pj_sockaddr_ptr_const "const pj_sockaddr *" int pj_AF_INET() nogil int pj_AF_INET6() nogil int pj_sockaddr_in_init(pj_sockaddr_in *addr, pj_str_t *cp, int port) nogil int pj_sockaddr_get_port(pj_sockaddr *addr) nogil char *pj_sockaddr_print(pj_sockaddr *addr, char *buf, int size, unsigned int flags) nogil int pj_sockaddr_has_addr(pj_sockaddr *addr) nogil int pj_sockaddr_init(int af, pj_sockaddr *addr, pj_str_t *cp, unsigned int port) nogil int pj_inet_pton(int af, pj_str_t *src, void *dst) nogil # dns struct pj_dns_resolver int pj_dns_resolver_set_ns(pj_dns_resolver *resolver, unsigned count, pj_str_t *servers, int *ports) nogil # time struct pj_time_val: long sec long msec void pj_gettimeofday(pj_time_val *tv) nogil void pj_time_val_normalize(pj_time_val *tv) nogil # timers struct pj_timer_heap_t struct pj_timer_entry: void *user_data int id pj_timer_entry *pj_timer_entry_init(pj_timer_entry *entry, int id, void *user_data, void cb(pj_timer_heap_t *timer_heap, pj_timer_entry *entry) with gil) nogil # lists struct pj_list: void *prev void *next void pj_list_init(pj_list *node) nogil void pj_list_insert_after(pj_list *pos, pj_list *node) nogil # random void pj_srand(unsigned int seed) nogil # maths struct pj_math_stat: int n int max int min int last int mean cdef extern from "pjlib-util.h": # init int pjlib_util_init() nogil cdef extern from "pjnath.h": # init int pjnath_init() nogil # STUN enum: PJ_STUN_PORT struct pj_stun_config: pass struct pj_stun_sock_cfg: pj_sockaddr bound_addr void pj_stun_config_init(pj_stun_config *cfg, pj_pool_factory *factory, unsigned int options, pj_ioqueue_t *ioqueue, pj_timer_heap_t *timer_heap) nogil # NAT detection struct pj_stun_nat_detect_result: int status char *status_text char *nat_type_name ctypedef pj_stun_nat_detect_result *pj_stun_nat_detect_result_ptr_const "const pj_stun_nat_detect_result *" int pj_stun_detect_nat_type(pj_sockaddr_in *server, pj_stun_config *stun_cfg, void *user_data, void pj_stun_nat_detect_cb(void *user_data, pj_stun_nat_detect_result_ptr_const res) with gil) nogil # ICE struct pj_ice_strans struct pj_ice_sess_cand: int type int comp_id int prio pj_sockaddr addr pj_sockaddr rel_addr struct pj_ice_sess_check: pj_ice_sess_cand *lcand pj_ice_sess_cand *rcand int state int nominated ctypedef pj_ice_sess_check *pj_ice_sess_check_ptr_const "const pj_ice_sess_check *" struct pj_ice_sess_comp: pj_ice_sess_check *valid_check struct pj_ice_sess_checklist: int count pj_ice_sess_check *checks struct pj_ice_sess: int comp_cnt pj_ice_sess_comp *comp int lcand_cnt pj_ice_sess_cand *lcand int rcand_cnt pj_ice_sess_cand *rcand pj_ice_sess_checklist valid_list struct pj_ice_strans_cfg_stun: pj_stun_sock_cfg cfg pj_str_t server unsigned int port struct pj_ice_strans_cfg: int af pj_stun_config stun_cfg pj_ice_strans_cfg_stun stun enum pj_ice_strans_op: PJ_ICE_STRANS_OP_INIT PJ_ICE_STRANS_OP_NEGOTIATION enum pj_ice_strans_state: PJ_ICE_STRANS_STATE_NULL PJ_ICE_STRANS_STATE_INIT PJ_ICE_STRANS_STATE_READY PJ_ICE_STRANS_STATE_SESS_READY PJ_ICE_STRANS_STATE_NEGO PJ_ICE_STRANS_STATE_RUNNING PJ_ICE_STRANS_STATE_FAILED enum pj_ice_cand_type: PJ_ICE_CAND_TYPE_HOST PJ_ICE_CAND_TYPE_SRFLX PJ_ICE_CAND_TYPE_PRFLX PJ_ICE_CAND_TYPE_RELAYED enum pj_ice_sess_check_state: PJ_ICE_SESS_CHECK_STATE_FROZEN PJ_ICE_SESS_CHECK_STATE_WAITING PJ_ICE_SESS_CHECK_STATE_IN_PROGRESS PJ_ICE_SESS_CHECK_STATE_SUCCEEDED PJ_ICE_SESS_CHECK_STATE_FAILED struct pjmedia_ice_transport_info: int active pj_ice_strans_state sess_state void pj_ice_strans_cfg_default(pj_ice_strans_cfg *cfg) nogil pj_ice_sess* pj_ice_strans_get_session(pj_ice_strans *ice_st) pj_time_val pj_ice_strans_get_start_time(pj_ice_strans *ice_st) pj_ice_strans_state pj_ice_strans_get_state(pj_ice_strans *ice_st) pj_ice_sess_check_ptr_const pj_ice_strans_get_valid_pair(pj_ice_strans *ice_st, unsigned comp_id) cdef extern from "pjmedia.h": enum: PJMEDIA_ENOSNDREC PJMEDIA_ENOSNDPLAY enum: PJMEDIA_AUD_DEFAULT_CAPTURE_DEV PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV PJMEDIA_AUD_DEV_CAP_EC PJMEDIA_AUD_DEV_CAP_EC_TAIL enum: PJMEDIA_VID_DEFAULT_CAPTURE_DEV PJMEDIA_VID_DEFAULT_RENDER_DEV PJMEDIA_VID_INVALID_DEV enum pjmedia_dir: PJMEDIA_DIR_NONE PJMEDIA_DIR_ENCODING PJMEDIA_DIR_DECODING PJMEDIA_DIR_ENCODING_DECODING PJMEDIA_DIR_PLAYBACK = PJMEDIA_DIR_DECODING PJMEDIA_DIR_RENDER = PJMEDIA_DIR_DECODING PJMEDIA_DIR_CAPTURE = PJMEDIA_DIR_ENCODING PJMEDIA_DIR_CAPTURE_PLAYBACK = PJMEDIA_DIR_ENCODING_DECODING PJMEDIA_DIR_CAPTURE_RENDER = PJMEDIA_DIR_ENCODING_DECODING enum pjmedia_type: PJMEDIA_TYPE_NONE PJMEDIA_TYPE_NONEYPE_AUDIO PJMEDIA_TYPE_VIDEO PJMEDIA_TYPE_APPLICATION PJMEDIA_TYPE_UNKNOWN struct pjmedia_rect_size: unsigned int w unsigned int h struct pjmedia_ratio: int num int denum # frame struct pjmedia_frame: void *buf int size ctypedef pjmedia_frame *pjmedia_frame_ptr_const "const pjmedia_frame *" # codec manager struct pjmedia_codec_mgr enum: PJMEDIA_CODEC_MGR_MAX_CODECS struct pjmedia_codec_info: pj_str_t encoding_name unsigned int clock_rate unsigned int channel_cnt int pjmedia_codec_mgr_enum_codecs(pjmedia_codec_mgr *mgr, unsigned int *count, pjmedia_codec_info *info, unsigned int *prio) nogil int pjmedia_codec_mgr_set_codec_priority(pjmedia_codec_mgr *mgr, pj_str_t *codec_id, unsigned int prio) nogil # transport manager struct pjsip_tpmgr struct pjsip_transport_state_info: int status enum pjsip_transport_state: PJSIP_TP_STATE_CONNECTED PJSIP_TP_STATE_DISCONNECTED ctypedef pjsip_transport_state_info *pjsip_transport_state_info_ptr_const "const pjsip_transport_state_info *" ctypedef void (*pjsip_tp_state_callback)(pjsip_transport *tp, pjsip_transport_state state, pjsip_transport_state_info_ptr_const info) with gil int pjsip_tpmgr_set_state_cb(pjsip_tpmgr *mgr, pjsip_tp_state_callback cb) # formats enum pjmedia_format_detail_type: PJMEDIA_FORMAT_DETAIL_NONE PJMEDIA_FORMAT_DETAIL_AUDIO PJMEDIA_FORMAT_DETAIL_VIDEO PJMEDIA_FORMAT_DETAIL_MAX struct pjmedia_audio_format_detail: unsigned int clock_rate unsigned int channel_count unsigned int frame_time_usec unsigned int baseits_per_sample unsigned int avg_bps unsigned int max_bps struct pjmedia_video_format_detail: pjmedia_rect_size size pjmedia_ratio fps unsigned int avg_bps unsigned int max_bps cdef union pjmedia_format_union: pjmedia_audio_format_detail aud pjmedia_video_format_detail vid char user[1] struct pjmedia_format: unsigned int id pjmedia_type type pjmedia_format_detail_type detail_type pjmedia_format_union det ctypedef pjmedia_format *pjmedia_format_ptr_const "const pjmedia_format *" enum: PJMEDIA_CODEC_MAX_FMTP_CNT struct _param: pj_str_t name pj_str_t val struct pjmedia_codec_fmtp: int cnt _param param[PJMEDIA_CODEC_MAX_FMTP_CNT] # video codec parameters enum pjmedia_vid_packing: PJMEDIA_VID_PACKING_PACKETS struct pjmedia_vid_codec_param: pjmedia_dir dir pjmedia_vid_packing packing pjmedia_format enc_fmt pjmedia_codec_fmtp enc_fmtp pjmedia_format dec_fmt pjmedia_codec_fmtp dec_fmtp ctypedef pjmedia_vid_codec_param *pjmedia_vid_codec_param_ptr_const "const pjmedia_vid_codec_param *" # video codec manager enum: PJMEDIA_VID_CODEC_MGR_MAX_CODECS struct pjmedia_vid_codec_info: pj_str_t encoding_name unsigned int pt unsigned int clock_rate unsigned int packings ctypedef pjmedia_vid_codec_info *pjmedia_vid_codec_info_ptr_const "const pjmedia_vid_codec_info *" struct pjmedia_vid_codec_mgr int pjmedia_vid_codec_mgr_create(pj_pool_t *pool, pjmedia_vid_codec_mgr **mgr) nogil void pjmedia_vid_codec_mgr_destroy(pjmedia_vid_codec_mgr *mgr) nogil pjmedia_vid_codec_mgr* pjmedia_vid_codec_mgr_instance() nogil int pjmedia_vid_codec_mgr_enum_codecs(pjmedia_vid_codec_mgr *mgr, unsigned int *count, pjmedia_vid_codec_info *info, unsigned int *prio) nogil int pjmedia_vid_codec_mgr_set_codec_priority(pjmedia_vid_codec_mgr *mgr, pj_str_t *codec_id, unsigned int prio) nogil int pjmedia_vid_codec_mgr_get_default_param(pjmedia_vid_codec_mgr *mgr, pjmedia_vid_codec_info_ptr_const info, pjmedia_vid_codec_param *param) nogil int pjmedia_vid_codec_mgr_set_default_param(pjmedia_vid_codec_mgr *mgr, pjmedia_vid_codec_info_ptr_const info, pjmedia_vid_codec_param_ptr_const param) nogil # video format manager struct pjmedia_video_format_mgr int pjmedia_video_format_mgr_create(pj_pool_t *pool, unsigned int max_fmt, unsigned int options, pjmedia_video_format_mgr **p_mgr) nogil void pjmedia_video_format_mgr_destroy(pjmedia_video_format_mgr *mgr) nogil pjmedia_video_format_mgr* pjmedia_video_format_mgr_instance() nogil # converter manager struct pjmedia_converter_mgr int pjmedia_converter_mgr_create(pj_pool_t *pool, pjmedia_converter_mgr **mgr) nogil void pjmedia_converter_mgr_destroy(pjmedia_converter_mgr *mgr) nogil pjmedia_converter_mgr* pjmedia_converter_mgr_instance() nogil # event manager struct pjmedia_event_mgr enum pjmedia_event_type: PJMEDIA_EVENT_FMT_CHANGED PJMEDIA_EVENT_KEYFRAME_FOUND PJMEDIA_EVENT_KEYFRAME_MISSING PJMEDIA_EVENT_KEYFRAME_REQUESTED struct pjmedia_event_fmt_changed_data: pjmedia_dir dir pjmedia_format new_fmt cdef union pjmedia_event_data_union: pjmedia_event_fmt_changed_data fmt_changed void* ptr struct pjmedia_event: pjmedia_event_type type pjmedia_event_data_union data int pjmedia_event_mgr_create(pj_pool_t *pool, unsigned int options, pjmedia_event_mgr **mgr) nogil void pjmedia_event_mgr_destroy(pjmedia_event_mgr *mgr) nogil pjmedia_event_mgr* pjmedia_event_mgr_instance() nogil ctypedef int pjmedia_event_cb(pjmedia_event *event, void *user_data) int pjmedia_event_subscribe(pjmedia_event_mgr *mgr, pjmedia_event_cb *cb, void *user_data, void *epub) nogil int pjmedia_event_unsubscribe(pjmedia_event_mgr *mgr, pjmedia_event_cb *cb, void *user_data, void *epub) nogil # endpoint struct pjmedia_endpt int pjmedia_endpt_create(pj_pool_factory *pf, pj_ioqueue_t *ioqueue, int worker_cnt, pjmedia_endpt **p_endpt) nogil pj_pool_t *pjmedia_endpt_create_pool(pjmedia_endpt *endpt, char *pool_name, int initial, int increment) nogil int pjmedia_endpt_destroy(pjmedia_endpt *endpt) nogil pj_ioqueue_t *pjmedia_endpt_get_ioqueue(pjmedia_endpt *endpt) nogil pjmedia_codec_mgr *pjmedia_endpt_get_codec_mgr(pjmedia_endpt *endpt) nogil pjsip_tpmgr* pjsip_endpt_get_tpmgr(pjsip_endpoint *endpt) # sound devices struct pjmedia_aud_dev_info: char *name int input_count int output_count struct pjmedia_aud_param: pjmedia_dir dir int play_id int rec_id int clock_rate int channel_count int samples_per_frame int bits_per_sample int flags int ec_enabled int ec_tail_ms struct pjmedia_aud_stream int pjmedia_aud_dev_count() nogil int pjmedia_aud_dev_get_info(int index, pjmedia_aud_dev_info *info) nogil int pjmedia_aud_stream_get_param(pjmedia_aud_stream *strm, pjmedia_aud_param *param) nogil enum pjmedia_aud_dev_event: PJMEDIA_AUD_DEV_DEFAULT_INPUT_CHANGED PJMEDIA_AUD_DEV_DEFAULT_OUTPUT_CHANGED PJMEDIA_AUD_DEV_LIST_WILL_REFRESH PJMEDIA_AUD_DEV_LIST_DID_REFRESH ctypedef void (*pjmedia_aud_dev_observer_callback)(pjmedia_aud_dev_event event) int pjmedia_aud_dev_set_observer_cb(pjmedia_aud_dev_observer_callback cb) nogil int pjmedia_aud_dev_default_param(int index, pjmedia_aud_param *param) nogil int pjmedia_aud_dev_refresh() nogil # sound port struct pjmedia_port_info: pjmedia_format fmt struct pjmedia_port: pjmedia_port_info info struct pjmedia_snd_port struct pjmedia_snd_port_param: pjmedia_aud_param base ctypedef pjmedia_snd_port_param *pjmedia_snd_port_param_ptr_const "const pjmedia_snd_port_param *" int pjmedia_snd_port_create2(pj_pool_t *pool, pjmedia_snd_port_param_ptr_const prm, pjmedia_snd_port **p_port) nogil void pjmedia_snd_port_param_default(pjmedia_snd_port_param *prm) int pjmedia_snd_port_connect(pjmedia_snd_port *snd_port, pjmedia_port *port) nogil int pjmedia_snd_port_disconnect(pjmedia_snd_port *snd_port) nogil int pjmedia_snd_port_set_ec(pjmedia_snd_port *snd_port, pj_pool_t *pool, unsigned int tail_ms, int options) nogil int pjmedia_snd_port_reset_ec_state(pjmedia_snd_port *snd_port) nogil int pjmedia_snd_port_destroy(pjmedia_snd_port *snd_port) nogil pjmedia_aud_stream *pjmedia_snd_port_get_snd_stream(pjmedia_snd_port *snd_port) nogil int pjmedia_null_port_create(pj_pool_t *pool, unsigned int sampling_rate, unsigned int channel_count, unsigned int samples_per_frame, unsigned int bits_per_sample, pjmedia_port **p_port) nogil int pjmedia_mixer_port_create(pj_pool_t *pool, unsigned int sampling_rate, unsigned int channel_count, unsigned int samples_per_frame, unsigned int bits_per_sample, pjmedia_port **p_port) nogil # master port struct pjmedia_master_port int pjmedia_master_port_create(pj_pool_t *pool, pjmedia_port *u_port, pjmedia_port *d_port, unsigned int options, pjmedia_master_port **p_m) nogil int pjmedia_master_port_start(pjmedia_master_port *m) nogil int pjmedia_master_port_destroy(pjmedia_master_port *m, int destroy_ports) nogil # conference bridge enum pjmedia_conf_option: PJMEDIA_CONF_NO_DEVICE struct pjmedia_conf int pjmedia_conf_create(pj_pool_t *pool, int max_slots, int sampling_rate, int channel_count, int samples_per_frame, int bits_per_sample, int options, pjmedia_conf **p_conf) nogil int pjmedia_conf_destroy(pjmedia_conf *conf) nogil pjmedia_port *pjmedia_conf_get_master_port(pjmedia_conf *conf) nogil int pjmedia_conf_add_port(pjmedia_conf *conf, pj_pool_t *pool, pjmedia_port *strm_port, pj_str_t *name, unsigned int *p_slot) nogil int pjmedia_conf_remove_port(pjmedia_conf *conf, unsigned int slot) nogil int pjmedia_conf_connect_port(pjmedia_conf *conf, unsigned int src_slot, unsigned int sink_slot, int level) nogil int pjmedia_conf_disconnect_port(pjmedia_conf *conf, unsigned int src_slot, unsigned int sink_slot) nogil int pjmedia_conf_adjust_rx_level(pjmedia_conf *conf, unsigned slot, int adj_level) nogil int pjmedia_conf_adjust_tx_level(pjmedia_conf *conf, unsigned slot, int adj_level) nogil # video devices enum pjmedia_vid_dev_cap: PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE PJMEDIA_VID_DEV_CAP_OUTPUT_RESIZE PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW_FLAGS enum pjmedia_vid_dev_wnd_flag: PJMEDIA_VID_DEV_WND_BORDER PJMEDIA_VID_DEV_WND_RESIZABLE struct pjmedia_vid_dev_info: int id char *name char *driver int dir cdef struct pjmedia_hwnd_win: void *hwnd cdef struct pjmedia_hwnd_x11: void *window void *display cdef struct pjmedia_hwnd_cocoa: void *window cdef struct pjmedia_hwnd_ios: void *window cdef union pjmedia_hwnd_union: pjmedia_hwnd_win win pjmedia_hwnd_x11 x11 pjmedia_hwnd_cocoa cocoa pjmedia_hwnd_ios ios void *window struct pjmedia_vid_dev_hwnd: pjmedia_hwnd_union info struct pjmedia_vid_dev_param: pjmedia_dir dir int cap_id int rend_id unsigned int flags pjmedia_format fmt pjmedia_vid_dev_hwnd window pjmedia_rect_size disp_size int window_hide unsigned int window_flags struct pjmedia_vid_dev_stream int pjmedia_vid_dev_count() nogil int pjmedia_vid_dev_get_info(int index, pjmedia_vid_dev_info *info) nogil int pjmedia_vid_dev_subsys_init(pj_pool_factory *pf) nogil int pjmedia_vid_dev_subsys_shutdown() nogil int pjmedia_vid_dev_default_param(pj_pool_t *pool, int id, pjmedia_vid_dev_param *param) nogil int pjmedia_vid_dev_stream_get_cap(pjmedia_vid_dev_stream *strm, pjmedia_vid_dev_cap cap, void *value) nogil int pjmedia_vid_dev_stream_set_cap(pjmedia_vid_dev_stream *strm, pjmedia_vid_dev_cap cap, void *value) nogil int pjmedia_vid_dev_stream_get_param(pjmedia_vid_dev_stream *strm, pjmedia_vid_dev_param *param) nogil int pjmedia_vid_dev_refresh() nogil int pjmedia_vid_dev_lookup(char_ptr_const drv_name, char_ptr_const dev_name, int *id) # video stream struct pjmedia_vid_stream_info: pjmedia_vid_codec_param *codec_param pjmedia_vid_codec_info codec_info int use_ka struct pjmedia_vid_stream ctypedef pjmedia_vid_stream *pjmedia_vid_stream_ptr_const "const pjmedia_vid_stream *" int pjmedia_vid_stream_get_stat(pjmedia_vid_stream_ptr_const stream, pjmedia_rtcp_stat *stat) nogil int pjmedia_vid_stream_get_info(pjmedia_vid_stream_ptr_const stream, pjmedia_vid_stream_info *info) nogil int pjmedia_vid_stream_info_from_sdp(pjmedia_vid_stream_info *si, pj_pool_t *pool, pjmedia_endpt *endpt, pjmedia_sdp_session *local, pjmedia_sdp_session *remote, unsigned int stream_idx) nogil int pjmedia_vid_stream_create(pjmedia_endpt *endpt, pj_pool_t *pool, pjmedia_vid_stream_info *info, pjmedia_transport *tp, void *user_data, pjmedia_vid_stream **p_stream) nogil int pjmedia_vid_stream_start(pjmedia_vid_stream *stream) nogil int pjmedia_vid_stream_destroy(pjmedia_vid_stream *stream) nogil int pjmedia_vid_stream_get_port(pjmedia_vid_stream *stream, pjmedia_dir dir, pjmedia_port **p_port) nogil int pjmedia_vid_stream_pause(pjmedia_vid_stream *stream, pjmedia_dir dir) nogil int pjmedia_vid_stream_resume(pjmedia_vid_stream *stream, pjmedia_dir dir) nogil int pjmedia_vid_stream_send_keyframe(pjmedia_vid_stream *stream) nogil int pjmedia_vid_stream_send_rtcp_sdes(pjmedia_vid_stream *stream) nogil int pjmedia_vid_stream_send_rtcp_bye(pjmedia_vid_stream *stream) nogil int pjmedia_vid_stream_send_rtcp_pli(pjmedia_vid_stream *stream) nogil # video port struct pjmedia_vid_port struct pjmedia_vid_port_param: pjmedia_vid_dev_param vidparam int active void pjmedia_vid_port_param_default(pjmedia_vid_port_param *prm) nogil ctypedef pjmedia_vid_port_param *pjmedia_vid_port_param_ptr_const "const pjmedia_vid_port_param *" int pjmedia_vid_port_create(pj_pool_t *pool, pjmedia_vid_port_param_ptr_const prm, pjmedia_vid_port **p_vp) nogil int pjmedia_vid_port_start(pjmedia_vid_port *vid_port) nogil int pjmedia_vid_port_is_running(pjmedia_vid_port *vid_port) nogil int pjmedia_vid_port_stop(pjmedia_vid_port *vid_port) nogil int pjmedia_vid_port_connect(pjmedia_vid_port *vid_port, pjmedia_port *port, int destroy) nogil pjmedia_port *pjmedia_vid_port_get_passive_port(pjmedia_vid_port *vid_port) nogil int pjmedia_vid_port_disconnect(pjmedia_vid_port *vid_port) nogil void pjmedia_vid_port_destroy(pjmedia_vid_port *vid_port) nogil pjmedia_vid_dev_stream *pjmedia_vid_port_get_stream(pjmedia_vid_port *vid_port) nogil # video tee int pjmedia_vid_tee_create(pj_pool_t *pool, pjmedia_format_ptr_const fmt, unsigned int max_dst_cnt, pjmedia_port **p_vid_tee) nogil int pjmedia_vid_tee_add_dst_port2(pjmedia_port *vid_tee, unsigned int option, pjmedia_port *port) nogil int pjmedia_vid_tee_remove_dst_port(pjmedia_port *vid_tee, pjmedia_port *port) nogil # sdp enum: PJMEDIA_MAX_SDP_FMT enum: PJMEDIA_MAX_SDP_ATTR enum: PJMEDIA_MAX_SDP_MEDIA enum: PJMEDIA_MAX_SDP_BANDW struct pjmedia_sdp_attr: pj_str_t name pj_str_t value struct pjmedia_sdp_bandw: pj_str_t modifier unsigned int value struct pjmedia_sdp_conn: pj_str_t net_type pj_str_t addr_type pj_str_t addr struct pjmedia_sdp_media_desc: pj_str_t media unsigned int port unsigned int port_count pj_str_t transport unsigned int fmt_count pj_str_t fmt[PJMEDIA_MAX_SDP_FMT] struct pjmedia_sdp_media: pjmedia_sdp_media_desc desc pjmedia_sdp_conn *conn unsigned int attr_count pjmedia_sdp_attr *attr[PJMEDIA_MAX_SDP_ATTR] unsigned int bandw_count pjmedia_sdp_bandw *bandw[PJMEDIA_MAX_SDP_BANDW] struct pjmedia_sdp_session_origin: pj_str_t user unsigned int id unsigned int version pj_str_t net_type pj_str_t addr_type pj_str_t addr struct pjmedia_sdp_session_time: unsigned int start unsigned int stop struct pjmedia_sdp_session: pjmedia_sdp_session_origin origin pj_str_t name pjmedia_sdp_conn *conn pjmedia_sdp_session_time time unsigned int attr_count pjmedia_sdp_attr *attr[PJMEDIA_MAX_SDP_ATTR] unsigned int bandw_count pjmedia_sdp_bandw *bandw[PJMEDIA_MAX_SDP_BANDW] unsigned int media_count pjmedia_sdp_media *media[PJMEDIA_MAX_SDP_MEDIA] ctypedef pjmedia_sdp_session *pjmedia_sdp_session_ptr_const "const pjmedia_sdp_session *" pjmedia_sdp_media *pjmedia_sdp_media_clone(pj_pool_t *pool, pjmedia_sdp_media *rhs) nogil pjmedia_sdp_session *pjmedia_sdp_session_clone(pj_pool_t *pool, pjmedia_sdp_session_ptr_const sdp) nogil int pjmedia_sdp_print(pjmedia_sdp_session_ptr_const sdp, char *buf, int length) int pjmedia_sdp_parse(pj_pool_t *pool, char *buf, int length, pjmedia_sdp_session **p_sdp) nogil # sdp negotiation enum pjmedia_sdp_neg_state: PJMEDIA_SDP_NEG_STATE_NULL PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER PJMEDIA_SDP_NEG_STATE_REMOTE_OFFER PJMEDIA_SDP_NEG_STATE_WAIT_NEGO PJMEDIA_SDP_NEG_STATE_DONE struct pjmedia_sdp_neg int pjmedia_sdp_neg_create_w_local_offer(pj_pool_t *pool, pjmedia_sdp_session_ptr_const local, pjmedia_sdp_neg **neg) nogil int pjmedia_sdp_neg_create_w_remote_offer(pj_pool_t *pool, pjmedia_sdp_session_ptr_const initial, pjmedia_sdp_session_ptr_const remote, pjmedia_sdp_neg **neg) nogil int pjmedia_sdp_neg_set_local_answer(pj_pool_t *pool, pjmedia_sdp_neg *neg, pjmedia_sdp_session_ptr_const local) nogil int pjmedia_sdp_neg_set_remote_answer(pj_pool_t *pool, pjmedia_sdp_neg *neg, pjmedia_sdp_session_ptr_const remote) nogil int pjmedia_sdp_neg_set_remote_offer(pj_pool_t *pool, pjmedia_sdp_neg *neg, pjmedia_sdp_session_ptr_const remote) nogil int pjmedia_sdp_neg_get_neg_remote(pjmedia_sdp_neg *neg, pjmedia_sdp_session_ptr_const *remote) nogil int pjmedia_sdp_neg_get_neg_local(pjmedia_sdp_neg *neg, pjmedia_sdp_session_ptr_const *local) nogil int pjmedia_sdp_neg_get_active_remote(pjmedia_sdp_neg *neg, pjmedia_sdp_session_ptr_const *remote) nogil int pjmedia_sdp_neg_get_active_local(pjmedia_sdp_neg *neg, pjmedia_sdp_session_ptr_const *local) nogil int pjmedia_sdp_neg_modify_local_offer (pj_pool_t *pool, pjmedia_sdp_neg *neg, pjmedia_sdp_session_ptr_const local) nogil int pjmedia_sdp_neg_cancel_offer(pjmedia_sdp_neg *neg) nogil int pjmedia_sdp_neg_negotiate(pj_pool_t *poll, pjmedia_sdp_neg *neg, int allow_asym) nogil pjmedia_sdp_neg_state pjmedia_sdp_neg_get_state(pjmedia_sdp_neg *neg) nogil char *pjmedia_sdp_neg_state_str(pjmedia_sdp_neg_state state) nogil # transport enum pjmedia_transport_type: PJMEDIA_TRANSPORT_TYPE_ICE PJMEDIA_TRANSPORT_TYPE_SRTP PJMEDIA_TRANSPORT_TYPE_ZRTP struct pjmedia_sock_info: pj_sockaddr rtp_addr_name ctypedef pjmedia_sock_info *pjmedia_sock_info_ptr_const "const pjmedia_sock_info *" struct pjmedia_transport: char *name pjmedia_transport_type type void *user_data struct pjmedia_transport_specific_info: pjmedia_transport_type type char *buffer struct pjmedia_transport_info: pjmedia_sock_info sock_info pj_sockaddr src_rtp_name int specific_info_cnt pjmedia_transport_specific_info *spc_info void pjmedia_transport_info_init(pjmedia_transport_info *info) nogil int pjmedia_transport_udp_create3(pjmedia_endpt *endpt, int af, char *name, pj_str_t *addr, int port, unsigned int options, pjmedia_transport **p_tp) nogil int pjmedia_transport_get_info(pjmedia_transport *tp, pjmedia_transport_info *info) nogil void *pjmedia_transport_info_get_spc_info(pjmedia_transport_info *info, pjmedia_transport_type type) int pjmedia_transport_close(pjmedia_transport *tp) nogil int pjmedia_transport_media_create(pjmedia_transport *tp, pj_pool_t *sdp_pool, unsigned int options, pjmedia_sdp_session *rem_sdp, unsigned int media_index) nogil int pjmedia_transport_encode_sdp(pjmedia_transport *tp, pj_pool_t *sdp_pool, pjmedia_sdp_session *sdp, pjmedia_sdp_session *rem_sdp, unsigned int media_index) nogil int pjmedia_transport_media_start(pjmedia_transport *tp, pj_pool_t *tmp_pool, pjmedia_sdp_session *sdp_local, pjmedia_sdp_session *sdp_remote, unsigned int media_index) nogil int pjmedia_transport_media_stop(pjmedia_transport *tp) nogil int pjmedia_endpt_create_sdp(pjmedia_endpt *endpt, pj_pool_t *pool, unsigned int stream_cnt, pjmedia_sock_info *sock_info, pjmedia_sdp_session **p_sdp) nogil int pjmedia_endpt_create_base_sdp(pjmedia_endpt *endpt, pj_pool_t *pool, pj_str_ptr_const sess_name, pj_sockaddr_ptr_const origin, pjmedia_sdp_session **p_sdp) nogil int pjmedia_endpt_create_audio_sdp(pjmedia_endpt *endpt, pj_pool_t *pool, pjmedia_sock_info_ptr_const si, unsigned int options, pjmedia_sdp_media **p_media) nogil int pjmedia_endpt_create_video_sdp(pjmedia_endpt *endpt, pj_pool_t *pool, pjmedia_sock_info_ptr_const si, unsigned int options, pjmedia_sdp_media **p_media) nogil # SRTP struct pjmedia_srtp_crypto: pj_str_t key pj_str_t name unsigned int flags struct pjmedia_srtp_info: int active pjmedia_srtp_crypto tx_policy enum pjmedia_srtp_use: PJMEDIA_SRTP_MANDATORY struct pjmedia_srtp_setting: pjmedia_srtp_use use void pjmedia_srtp_setting_default(pjmedia_srtp_setting *opt) nogil int pjmedia_transport_srtp_create(pjmedia_endpt *endpt, pjmedia_transport *tp, pjmedia_srtp_setting *opt, pjmedia_transport **p_tp) nogil # ZRTP struct pjmedia_zrtp_info: int active char cipher[128] struct pjmedia_zrtp_cb: void secure_on(pjmedia_transport *tp, char* cipher) with gil void secure_off(pjmedia_transport *tp) with gil void show_sas(pjmedia_transport *tp, char* sas, int verified) with gil void confirm_go_clear(pjmedia_transport *tp) with gil void show_message(pjmedia_transport *tp, int severity, int subCode) with gil void negotiation_failed(pjmedia_transport *tp, int severity, int subCode) with gil void not_supported_by_other(pjmedia_transport *tp) with gil void ask_enrollment(pjmedia_transport *tp, int info) with gil void inform_enrollment(pjmedia_transport *tp, int info) with gil void sign_sas(pjmedia_transport *tp, unsigned char* sas) with gil int check_sas_signature(pjmedia_transport *tp, unsigned char* sas) with gil int pjmedia_transport_zrtp_create(pjmedia_endpt *endpt, pj_timer_heap_t *timer_heap, pjmedia_transport *tp, pjmedia_transport **p_tp, int close_slave) nogil int pjmedia_transport_zrtp_initialize(pjmedia_transport *tp, char_ptr_const zidFilename, int autoEnable, pjmedia_zrtp_cb *zrtp_cb) nogil void pjmedia_transport_zrtp_setSASVerified(pjmedia_transport *tp, int verified) nogil char* pjmedia_transport_zrtp_getPeerName(pjmedia_transport *tp) nogil void pjmedia_transport_zrtp_putPeerName(pjmedia_transport *tp, const char *name) nogil int pjmedia_transport_zrtp_getPeerZid(pjmedia_transport *tp, unsigned char* data) nogil void pjmedia_transport_zrtp_setEnableZrtp(pjmedia_transport *tp, int onOff) nogil char* pjmedia_transport_zrtp_getMultiStreamParameters(pjmedia_transport *tp, int *length) nogil void pjmedia_transport_zrtp_setMultiStreamParameters(pjmedia_transport *tp, const char *parameters, int length, pjmedia_transport *master_tp) nogil # ICE struct pjmedia_ice_cb: void on_ice_complete(pjmedia_transport *tp, pj_ice_strans_op op, int status) with gil void on_ice_state(pjmedia_transport *tp, pj_ice_strans_state prev, pj_ice_strans_state curr) with gil void on_ice_stop(pjmedia_transport *tp, char *reason, int err) with gil int pjmedia_ice_create2(pjmedia_endpt *endpt, char *name, unsigned int comp_cnt, pj_ice_strans_cfg *cfg, pjmedia_ice_cb *cb, unsigned int options, pjmedia_transport **p_tp) nogil pj_ice_strans *pjmedia_ice_get_strans(pjmedia_transport *tp) with gil # stream struct pjmedia_codec_param_setting: unsigned int vad struct pjmedia_codec_param: pjmedia_codec_param_setting setting struct pjmedia_stream_info: pjmedia_codec_info fmt pjmedia_codec_param *param unsigned int tx_event_pt int use_ka struct pjmedia_rtcp_stream_stat_loss_type: unsigned int burst unsigned int random struct pjmedia_rtcp_stream_stat: unsigned int pkt unsigned int bytes unsigned int discard unsigned int loss unsigned int reorder unsigned int dup pj_math_stat loss_period pjmedia_rtcp_stream_stat_loss_type loss_type pj_math_stat jitter struct pjmedia_rtcp_stat: pjmedia_rtcp_stream_stat tx pjmedia_rtcp_stream_stat rx pj_math_stat rtt struct pjmedia_stream int pjmedia_stream_info_from_sdp(pjmedia_stream_info *si, pj_pool_t *pool, pjmedia_endpt *endpt, pjmedia_sdp_session *local, pjmedia_sdp_session *remote, unsigned int stream_idx) nogil int pjmedia_stream_create(pjmedia_endpt *endpt, pj_pool_t *pool, pjmedia_stream_info *info, pjmedia_transport *tp, void *user_data, pjmedia_stream **p_stream) nogil int pjmedia_stream_destroy(pjmedia_stream *stream) nogil int pjmedia_stream_get_port(pjmedia_stream *stream, pjmedia_port **p_port) nogil int pjmedia_stream_start(pjmedia_stream *stream) nogil int pjmedia_stream_dial_dtmf(pjmedia_stream *stream, pj_str_t *ascii_digit) nogil int pjmedia_stream_set_dtmf_callback(pjmedia_stream *stream, void cb(pjmedia_stream *stream, void *user_data, int digit) with gil, void *user_data) nogil int pjmedia_stream_pause(pjmedia_stream *stream, pjmedia_dir dir) nogil int pjmedia_stream_resume(pjmedia_stream *stream, pjmedia_dir dir) nogil int pjmedia_stream_get_stat(pjmedia_stream *stream, pjmedia_rtcp_stat *stat) nogil # wav player enum: PJMEDIA_FILE_NO_LOOP int pjmedia_port_destroy(pjmedia_port *port) nogil int pjmedia_wav_player_port_create(pj_pool_t *pool, char *filename, unsigned int ptime, unsigned int flags, unsigned int buff_size, pjmedia_port **p_port) nogil int pjmedia_wav_player_set_eof_cb(pjmedia_port *port, void *user_data, int cb(pjmedia_port *port, void *usr_data) with gil) nogil int pjmedia_wav_player_port_set_pos(pjmedia_port *port, unsigned int offset) nogil # wav recorder enum pjmedia_file_writer_option: PJMEDIA_FILE_WRITE_PCM int pjmedia_wav_writer_port_create(pj_pool_t *pool, char *filename, unsigned int clock_rate, unsigned int channel_count, unsigned int samples_per_frame, unsigned int bits_per_sample, unsigned int flags, int buff_size, pjmedia_port **p_port) nogil # tone generator enum: PJMEDIA_TONEGEN_MAX_DIGITS struct pjmedia_tone_desc: short freq1 short freq2 short on_msec short off_msec short volume short flags struct pjmedia_tone_digit: char digit short on_msec short off_msec short volume int pjmedia_tonegen_create(pj_pool_t *pool, unsigned int clock_rate, unsigned int channel_count, unsigned int samples_per_frame, unsigned int bits_per_sample, unsigned int options, pjmedia_port **p_port) nogil int pjmedia_tonegen_play(pjmedia_port *tonegen, unsigned int count, pjmedia_tone_desc *tones, unsigned int options) nogil int pjmedia_tonegen_play_digits(pjmedia_port *tonegen, unsigned int count, pjmedia_tone_digit *digits, unsigned int options) nogil int pjmedia_tonegen_stop(pjmedia_port *tonegen) nogil int pjmedia_tonegen_is_busy(pjmedia_port *tonegen) nogil cdef extern from "pjmedia_videodev.h": ctypedef void (*pjmedia_vid_dev_fb_frame_cb)(pjmedia_frame_ptr_const frame, pjmedia_rect_size size, void *user_data) int pjmedia_vid_dev_fb_set_callback(pjmedia_vid_dev_stream *strm, pjmedia_vid_dev_fb_frame_cb cb, void *user_data) cdef extern from "pjmedia-codec.h": # codecs enum: PJMEDIA_SPEEX_NO_NB struct speex_options: unsigned int option int quality int complexity struct ilbc_options: unsigned mode struct pjmedia_audio_codec_config: speex_options speex ilbc_options ilbc void pjmedia_audio_codec_config_default(pjmedia_audio_codec_config *cfg) int pjmedia_codec_register_audio_codecs(pjmedia_endpt *endpt, const pjmedia_audio_codec_config *c) nogil int pjmedia_codec_ffmpeg_vid_init(pjmedia_vid_codec_mgr *mgr, pj_pool_factory *pf) nogil int pjmedia_codec_ffmpeg_vid_deinit() nogil int pjmedia_codec_vpx_init(pjmedia_vid_codec_mgr *mgr, pj_pool_factory *pf) nogil int pjmedia_codec_vpx_deinit() nogil cdef extern from "pjsip.h": # messages enum pjsip_status_code: PJSIP_SC_TSX_TIMEOUT PJSIP_SC_TSX_TRANSPORT_ERROR PJSIP_TLS_EUNKNOWN PJSIP_TLS_EINVMETHOD PJSIP_TLS_ECACERT PJSIP_TLS_ECERTFILE PJSIP_TLS_EKEYFILE PJSIP_TLS_ECIPHER PJSIP_TLS_ECTX enum pjsip_uri_context_e: PJSIP_URI_IN_CONTACT_HDR struct pjsip_param: pj_str_t name pj_str_t value struct pjsip_uri struct pjsip_sip_uri: pj_str_t user pj_str_t passwd pj_str_t host int port pj_str_t user_param pj_str_t method_param pj_str_t transport_param int ttl_param int lr_param pj_str_t maddr_param pjsip_param other_param pjsip_param header_param struct pjsip_name_addr: pj_str_t display pjsip_uri *uri struct pjsip_media_type: pj_str_t type pj_str_t subtype pjsip_param param enum pjsip_method_e: PJSIP_OPTIONS_METHOD PJSIP_CANCEL_METHOD PJSIP_OTHER_METHOD struct pjsip_method: pjsip_method_e id pj_str_t name struct pjsip_host_port: pj_str_t host int port enum pjsip_hdr_e: PJSIP_H_VIA PJSIP_H_CALL_ID PJSIP_H_CONTACT PJSIP_H_CSEQ PJSIP_H_EXPIRES PJSIP_H_FROM struct pjsip_hdr: pjsip_hdr_e type pj_str_t name ctypedef pjsip_hdr *pjsip_hdr_ptr_const "const pjsip_hdr*" struct pjsip_generic_array_hdr: unsigned int count pj_str_t *values struct pjsip_generic_string_hdr: pj_str_t name pj_str_t hvalue struct pjsip_cid_hdr: pj_str_t id struct pjsip_contact_hdr: int star pjsip_uri *uri int q1000 int expires pjsip_param other_param struct pjsip_clen_hdr: int len struct pjsip_ctype_hdr: pjsip_media_type media struct pjsip_cseq_hdr: int cseq pjsip_method method struct pjsip_generic_int_hdr: int ivalue ctypedef pjsip_generic_int_hdr pjsip_expires_hdr struct pjsip_fromto_hdr: pjsip_uri *uri pj_str_t tag pjsip_param other_param struct pjsip_routing_hdr: pjsip_name_addr name_addr pjsip_param other_param ctypedef pjsip_routing_hdr pjsip_route_hdr struct pjsip_retry_after_hdr: int ivalue pjsip_param param pj_str_t comment struct pjsip_via_hdr: pj_str_t transport pjsip_host_port sent_by int ttl_param int rport_param pj_str_t maddr_param pj_str_t recvd_param pj_str_t branch_param pjsip_param other_param pj_str_t comment enum: PJSIP_MAX_ACCEPT_COUNT struct pjsip_msg_body: pjsip_media_type content_type void *data unsigned int len struct pjsip_request_line: pjsip_method method pjsip_uri *uri struct pjsip_status_line: int code pj_str_t reason union pjsip_msg_line: pjsip_request_line req pjsip_status_line status enum pjsip_msg_type_e: PJSIP_REQUEST_MSG PJSIP_RESPONSE_MSG struct pjsip_msg: pjsip_msg_type_e type pjsip_msg_line line pjsip_hdr hdr pjsip_msg_body *body struct pjsip_buffer: char *start char *cur struct pjsip_tx_data_tp_info: char *dst_name int dst_port pjsip_transport *transport struct pjsip_tx_data: pjsip_msg *msg pj_pool_t *pool pjsip_buffer buf pjsip_tx_data_tp_info tp_info struct pjsip_rx_data_tp_info: pj_pool_t *pool pjsip_transport *transport struct pjsip_rx_data_pkt_info: pj_time_val timestamp char *packet int len char *src_name int src_port struct pjsip_rx_data_msg_info: pjsip_msg *msg pjsip_fromto_hdr *from_hdr "from" pjsip_fromto_hdr *to_hdr "to" pjsip_via_hdr *via struct pjsip_rx_data: pjsip_rx_data_pkt_info pkt_info pjsip_rx_data_tp_info tp_info pjsip_rx_data_msg_info msg_info void *pjsip_hdr_clone(pj_pool_t *pool, void *hdr) nogil void pjsip_msg_add_hdr(pjsip_msg *msg, pjsip_hdr *hdr) nogil void *pjsip_msg_find_hdr(pjsip_msg *msg, pjsip_hdr_e type, void *start) nogil void *pjsip_msg_find_hdr_by_name(pjsip_msg *msg, pj_str_t *name, void *start) nogil void *pjsip_msg_find_remove_hdr_by_name(pjsip_msg *msg, pj_str_t *name, void *start) nogil pjsip_generic_string_hdr *pjsip_generic_string_hdr_create(pj_pool_t *pool, pj_str_t *hname, pj_str_t *hvalue) nogil pjsip_contact_hdr *pjsip_contact_hdr_create(pj_pool_t *pool) nogil pjsip_expires_hdr *pjsip_expires_hdr_create(pj_pool_t *pool, int value) nogil pjsip_msg_body *pjsip_msg_body_create(pj_pool_t *pool, pj_str_t *type, pj_str_t *subtype, pj_str_t *text) nogil pjsip_msg_body *pjsip_msg_body_clone(pj_pool_t *pool, const pjsip_msg_body *body) nogil pjsip_route_hdr *pjsip_route_hdr_init(pj_pool_t *pool, void *mem) nogil void pjsip_sip_uri_init(pjsip_sip_uri *url, int secure) nogil int pjsip_tx_data_dec_ref(pjsip_tx_data *tdata) nogil void pjsip_tx_data_add_ref(pjsip_tx_data *tdata) nogil pj_str_t *pjsip_uri_get_scheme(pjsip_uri *uri) nogil void *pjsip_uri_get_uri(pjsip_uri *uri) nogil int pjsip_uri_print(pjsip_uri_context_e context, void *uri, char *buf, unsigned int size) nogil int PJSIP_URI_SCHEME_IS_SIP(pjsip_sip_uri *uri) nogil enum: PJSIP_PARSE_URI_AS_NAMEADDR pjsip_uri *pjsip_parse_uri(pj_pool_t *pool, char *buf, unsigned int size, unsigned int options) nogil void pjsip_method_init_np(pjsip_method *m, pj_str_t *str) nogil pj_str_t *pjsip_get_status_text(int status_code) nogil int pjsip_print_body(pjsip_msg_body *msg_body, char **buf, int *len) # module enum pjsip_module_priority: PJSIP_MOD_PRIORITY_APPLICATION PJSIP_MOD_PRIORITY_DIALOG_USAGE PJSIP_MOD_PRIORITY_TRANSPORT_LAYER struct pjsip_event struct pjsip_transaction struct pjsip_module: pj_str_t name int id int priority int on_rx_request(pjsip_rx_data *rdata) with gil int on_rx_response(pjsip_rx_data *rdata) with gil int on_tx_request(pjsip_tx_data *tdata) with gil int on_tx_response(pjsip_tx_data *tdata) with gil void on_tsx_state(pjsip_transaction *tsx, pjsip_event *event) with gil # endpoint struct pjsip_endpoint int pjsip_endpt_create(pj_pool_factory *pf, char *name, pjsip_endpoint **endpt) nogil void pjsip_endpt_destroy(pjsip_endpoint *endpt) nogil pj_pool_t *pjsip_endpt_create_pool(pjsip_endpoint *endpt, char *pool_name, int initial, int increment) nogil void pjsip_endpt_release_pool(pjsip_endpoint *endpt, pj_pool_t *pool) nogil int pjsip_endpt_handle_events(pjsip_endpoint *endpt, pj_time_val *max_timeout) nogil int pjsip_endpt_register_module(pjsip_endpoint *endpt, pjsip_module *module) nogil int pjsip_endpt_schedule_timer(pjsip_endpoint *endpt, pj_timer_entry *entry, pj_time_val *delay) nogil void pjsip_endpt_cancel_timer(pjsip_endpoint *endpt, pj_timer_entry *entry) nogil enum: PJSIP_H_ACCEPT PJSIP_H_ALLOW PJSIP_H_SUPPORTED pjsip_hdr_ptr_const pjsip_endpt_get_capability(pjsip_endpoint *endpt, int htype, pj_str_t *hname) nogil int pjsip_endpt_add_capability(pjsip_endpoint *endpt, pjsip_module *mod, int htype, pj_str_t *hname, unsigned count, pj_str_t *tags) nogil int pjsip_endpt_create_response(pjsip_endpoint *endpt, pjsip_rx_data *rdata, int st_code, pj_str_t *st_text, pjsip_tx_data **p_tdata) nogil int pjsip_endpt_send_response2(pjsip_endpoint *endpt, pjsip_rx_data *rdata, pjsip_tx_data *tdata, void *token, void *cb) nogil int pjsip_endpt_respond_stateless(pjsip_endpoint *endpt, pjsip_rx_data *rdata, int st_code, pj_str_t *st_text, pjsip_hdr *hdr_list, pjsip_msg_body *body) nogil int pjsip_endpt_create_request(pjsip_endpoint *endpt, pjsip_method *method, pj_str_t *target, pj_str_t *frm, pj_str_t *to, pj_str_t *contact, pj_str_t *call_id, int cseq,pj_str_t *text, pjsip_tx_data **p_tdata) nogil pj_timer_heap_t *pjsip_endpt_get_timer_heap(pjsip_endpoint *endpt) nogil int pjsip_endpt_create_resolver(pjsip_endpoint *endpt, pj_dns_resolver **p_resv) nogil int pjsip_endpt_set_resolver(pjsip_endpoint *endpt, pj_dns_resolver *resv) nogil pj_dns_resolver* pjsip_endpt_get_resolver(pjsip_endpoint *endpt) nogil # transports enum pjsip_ssl_method: PJSIP_TLSV1_METHOD PJSIP_SSLV23_METHOD struct pjsip_transport: char *type_name pj_sockaddr local_addr pjsip_host_port local_name pjsip_host_port remote_name struct pjsip_tpfactory: pjsip_host_port addr_name int destroy(pjsip_tpfactory *factory) nogil struct pjsip_tls_setting: pj_str_t ca_list_file pj_str_t cert_file pj_str_t privkey_file int method int verify_server pj_time_val timeout enum pjsip_tpselector_type: PJSIP_TPSELECTOR_TRANSPORT union pjsip_tpselector_u: pjsip_transport *transport struct pjsip_tpselector: pjsip_tpselector_type type pjsip_tpselector_u u int pjsip_transport_shutdown(pjsip_transport *tp) nogil int pjsip_udp_transport_start(pjsip_endpoint *endpt, pj_sockaddr_in *local, pjsip_host_port *a_name, unsigned int async_cnt, pjsip_transport **p_transport) nogil int pjsip_tcp_transport_start2(pjsip_endpoint *endpt, pj_sockaddr_in *local, pjsip_host_port *a_name, unsigned int async_cnt, pjsip_tpfactory **p_tpfactory) nogil int pjsip_tls_transport_start(pjsip_endpoint *endpt, pjsip_tls_setting *opt, pj_sockaddr_in *local, pjsip_host_port *a_name, unsigned async_cnt, pjsip_tpfactory **p_factory) nogil void pjsip_tls_setting_default(pjsip_tls_setting *tls_opt) nogil int pjsip_transport_shutdown(pjsip_transport *tp) nogil # transaction layer enum pjsip_role_e: PJSIP_ROLE_UAC PJSIP_ROLE_UAS enum pjsip_tsx_state_e: PJSIP_TSX_STATE_TRYING PJSIP_TSX_STATE_PROCEEDING PJSIP_TSX_STATE_COMPLETED PJSIP_TSX_STATE_TERMINATED struct pjsip_transaction: int status_code pj_str_t status_text pjsip_role_e role pjsip_tx_data *last_tx pjsip_tsx_state_e state void **mod_data pjsip_method method int pjsip_tsx_layer_init_module(pjsip_endpoint *endpt) nogil int pjsip_tsx_create_key(pj_pool_t *pool, pj_str_t *key, pjsip_role_e role, pjsip_method *method, pjsip_rx_data *rdata) nogil pjsip_transaction *pjsip_tsx_layer_find_tsx(pj_str_t *key, int lock) nogil int pjsip_tsx_create_uac(pjsip_module *tsx_user, pjsip_tx_data *tdata, pjsip_transaction **p_tsx) nogil int pjsip_tsx_terminate(pjsip_transaction *tsx, int code) nogil int pjsip_tsx_send_msg(pjsip_transaction *tsx, pjsip_tx_data *tdata) nogil pjsip_transaction *pjsip_rdata_get_tsx(pjsip_rx_data *rdata) nogil int pjsip_tsx_create_uas(pjsip_module *tsx_user, pjsip_rx_data *rdata, pjsip_transaction **p_tsx) nogil void pjsip_tsx_recv_msg(pjsip_transaction *tsx, pjsip_rx_data *rdata) nogil # event enum pjsip_event_id_e: PJSIP_EVENT_TSX_STATE PJSIP_EVENT_RX_MSG PJSIP_EVENT_TX_MSG PJSIP_EVENT_TRANSPORT_ERROR PJSIP_EVENT_TIMER union pjsip_event_body_tsx_state_src: pjsip_rx_data *rdata pjsip_tx_data *tdata struct pjsip_event_body_tsx_state: pjsip_event_body_tsx_state_src src pjsip_transaction *tsx pjsip_event_id_e type struct pjsip_event_body_rx_msg: pjsip_rx_data *rdata union pjsip_event_body: pjsip_event_body_tsx_state tsx_state pjsip_event_body_rx_msg rx_msg struct pjsip_event: pjsip_event_id_e type pjsip_event_body body int pjsip_endpt_send_request(pjsip_endpoint *endpt, pjsip_tx_data *tdata, int timeout, void *token, void cb(void *token, pjsip_event *e) with gil) nogil # auth enum: PJSIP_EFAILEDCREDENTIAL enum pjsip_cred_data_type: PJSIP_CRED_DATA_PLAIN_PASSWD PJSIP_CRED_DATA_DIGEST struct pjsip_cred_info: pj_str_t realm pj_str_t scheme pj_str_t username pjsip_cred_data_type data_type pj_str_t data struct pjsip_auth_clt_sess: pass int pjsip_auth_clt_init(pjsip_auth_clt_sess *sess, pjsip_endpoint *endpt, pj_pool_t *pool, unsigned int options) nogil int pjsip_auth_clt_set_credentials(pjsip_auth_clt_sess *sess, int cred_cnt, pjsip_cred_info *c) nogil int pjsip_auth_clt_reinit_req(pjsip_auth_clt_sess *sess, pjsip_rx_data *rdata, pjsip_tx_data *old_request, pjsip_tx_data **new_request) nogil # dialog layer ctypedef pjsip_module pjsip_user_agent struct pjsip_dlg_party: pjsip_contact_hdr *contact pjsip_fromto_hdr *info struct pjsip_dialog: pjsip_auth_clt_sess auth_sess pjsip_cid_hdr *call_id pj_pool_t *pool pjsip_dlg_party local pjsip_dlg_party remote struct pjsip_ua_init_param: pjsip_dialog *on_dlg_forked(pjsip_dialog *first_set, pjsip_rx_data *res) nogil int pjsip_ua_init_module(pjsip_endpoint *endpt, pjsip_ua_init_param *prm) nogil pjsip_user_agent *pjsip_ua_instance() nogil int pjsip_dlg_create_uac(pjsip_user_agent *ua, pj_str_t *local_uri, pj_str_t *local_contact, pj_str_t *remote_uri, pj_str_t *target, pjsip_dialog **p_dlg) nogil int pjsip_dlg_set_route_set(pjsip_dialog *dlg, pjsip_route_hdr *route_set) nogil int pjsip_dlg_create_uas_and_inc_lock(pjsip_user_agent *ua, pjsip_rx_data *rdata, pj_str_t *contact, pjsip_dialog **p_dlg) nogil int pjsip_dlg_terminate(pjsip_dialog *dlg) nogil int pjsip_dlg_set_transport(pjsip_dialog *dlg, pjsip_tpselector *sel) nogil int pjsip_dlg_respond(pjsip_dialog *dlg, pjsip_rx_data *rdata, int st_code, pj_str_t *st_text, pjsip_hdr *hdr_list, pjsip_msg_body *body) nogil int pjsip_dlg_create_response(pjsip_dialog *dlg, pjsip_rx_data *rdata, int st_code, pj_str_t *st_text, pjsip_tx_data **tdata) nogil int pjsip_dlg_modify_response(pjsip_dialog *dlg, pjsip_tx_data *tdata, int st_code, pj_str_t *st_text) nogil int pjsip_dlg_send_response(pjsip_dialog *dlg, pjsip_transaction *tsx, pjsip_tx_data *tdata) nogil void pjsip_dlg_inc_lock(pjsip_dialog *dlg) nogil void pjsip_dlg_dec_lock(pjsip_dialog *dlg) nogil int pjsip_dlg_inc_session(pjsip_dialog *dlg, pjsip_module *mod) nogil int pjsip_dlg_dec_session(pjsip_dialog *dlg, pjsip_module *mod) nogil cdef extern from "pjsip-simple/evsub_msg.h": struct pjsip_event_hdr: pj_str_t event_type pj_str_t id_param pjsip_param other_param struct pjsip_sub_state_hdr: pj_str_t sub_state pj_str_t reason_param int expires_param int retry_after pjsip_param other_param pjsip_event_hdr *pjsip_event_hdr_create(pj_pool_t *pool) nogil cdef extern from "pjsip_simple.h": # subscribe / notify enum: PJSIP_EVSUB_NO_EVENT_ID enum pjsip_evsub_state: PJSIP_EVSUB_STATE_PENDING PJSIP_EVSUB_STATE_ACTIVE PJSIP_EVSUB_STATE_TERMINATED struct pjsip_evsub struct pjsip_evsub_user: void on_evsub_state(pjsip_evsub *sub, pjsip_event *event) with gil void on_tsx_state(pjsip_evsub *sub, pjsip_transaction *tsx, pjsip_event *event) with gil void on_rx_refresh(pjsip_evsub *sub, pjsip_rx_data *rdata, int *p_st_code, pj_str_t **p_st_text, pjsip_hdr *res_hdr, pjsip_msg_body **p_body) with gil void on_rx_notify(pjsip_evsub *sub, pjsip_rx_data *rdata, int *p_st_code, pj_str_t **p_st_text,pjsip_hdr *res_hdr, pjsip_msg_body **p_body) with gil void on_client_refresh(pjsip_evsub *sub) with gil void on_server_timeout(pjsip_evsub *sub) with gil int pjsip_evsub_init_module(pjsip_endpoint *endpt) nogil int pjsip_evsub_register_pkg(pjsip_module *pkg_mod, pj_str_t *event_name, unsigned int expires, unsigned int accept_cnt, pj_str_t *accept) nogil int pjsip_evsub_create_uac(pjsip_dialog *dlg, pjsip_evsub_user *user_cb, pj_str_t *event, int option, pjsip_evsub **p_evsub) nogil int pjsip_evsub_create_uas(pjsip_dialog *dlg, pjsip_evsub_user *user_cb, pjsip_rx_data *rdata, unsigned int option, pjsip_evsub **p_evsub) nogil int pjsip_evsub_initiate(pjsip_evsub *sub, void *method, unsigned int expires, pjsip_tx_data **p_tdata) nogil int pjsip_evsub_send_request(pjsip_evsub *sub, pjsip_tx_data *tdata) nogil int pjsip_evsub_terminate(pjsip_evsub *sub, int notify) nogil char *pjsip_evsub_get_state_name(pjsip_evsub *sub) nogil void pjsip_evsub_set_mod_data(pjsip_evsub *sub, int mod_id, void *data) nogil void *pjsip_evsub_get_mod_data(pjsip_evsub *sub, int mod_id) nogil void pjsip_evsub_update_expires(pjsip_evsub *sub, int interval) nogil void pjsip_evsub_set_timer(pjsip_evsub *sub, int timer_id, int seconds) nogil pjsip_hdr *pjsip_evsub_get_allow_events_hdr(pjsip_module *m) nogil int pjsip_evsub_notify(pjsip_evsub *sub, pjsip_evsub_state state, pj_str_t *state_str, pj_str_t *reason, pjsip_tx_data **p_tdata) nogil cdef extern from "pjsip_ua.h": # 100rel / PRACK int pjsip_100rel_init_module(pjsip_endpoint *endpt) nogil # invite sessions enum pjsip_inv_option: PJSIP_INV_SUPPORT_100REL enum pjsip_inv_state: PJSIP_INV_STATE_INCOMING PJSIP_INV_STATE_CONFIRMED enum pjmedia_mod_offer_flag: PJMEDIA_SDP_NEG_ALLOW_MEDIA_CHANGE struct pjsip_inv_session: pjsip_inv_state state void **mod_data pjmedia_sdp_neg *neg unsigned sdp_neg_flags int cause pj_str_t cause_text int cancelling pjsip_transaction *invite_tsx struct pjsip_inv_callback: void on_state_changed(pjsip_inv_session *inv, pjsip_event *e) with gil void on_new_session(pjsip_inv_session *inv, pjsip_event *e) with gil void on_tsx_state_changed(pjsip_inv_session *inv, pjsip_transaction *tsx, pjsip_event *e) with gil void on_media_update(pjsip_inv_session *inv, int status) with gil int on_rx_reinvite(pjsip_inv_session *inv, pjmedia_sdp_session_ptr_const offer, pjsip_rx_data *rdata) with gil int pjsip_inv_usage_init(pjsip_endpoint *endpt, pjsip_inv_callback *cb) nogil int pjsip_inv_terminate(pjsip_inv_session *inv, int st_code, int notify) nogil int pjsip_inv_end_session(pjsip_inv_session *inv, int st_code, pj_str_t *st_text, pjsip_tx_data **p_tdata) nogil int pjsip_inv_cancel_reinvite(pjsip_inv_session *inv, pjsip_tx_data **p_tdata) nogil int pjsip_inv_send_msg(pjsip_inv_session *inv, pjsip_tx_data *tdata) nogil int pjsip_inv_verify_request(pjsip_rx_data *rdata, unsigned int *options, pjmedia_sdp_session *sdp, pjsip_dialog *dlg, pjsip_endpoint *endpt, pjsip_tx_data **tdata) nogil int pjsip_inv_create_uas(pjsip_dialog *dlg, pjsip_rx_data *rdata, pjmedia_sdp_session *local_sdp, unsigned int options, pjsip_inv_session **p_inv) nogil int pjsip_inv_initial_answer(pjsip_inv_session *inv, pjsip_rx_data *rdata, int st_code, pj_str_t *st_text, pjmedia_sdp_session *sdp, pjsip_tx_data **p_tdata) nogil int pjsip_inv_answer(pjsip_inv_session *inv, int st_code, pj_str_t *st_text, pjmedia_sdp_session *local_sdp, pjsip_tx_data **p_tdata) nogil int pjsip_inv_create_uac(pjsip_dialog *dlg, pjmedia_sdp_session *local_sdp, unsigned int options, pjsip_inv_session **p_inv) nogil int pjsip_inv_invite(pjsip_inv_session *inv, pjsip_tx_data **p_tdata) nogil char *pjsip_inv_state_name(pjsip_inv_state state) nogil int pjsip_inv_reinvite(pjsip_inv_session *inv, pj_str_t *new_contact, pjmedia_sdp_session *new_offer, pjsip_tx_data **p_tdata) nogil int pjsip_create_sdp_body(pj_pool_t *pool, pjmedia_sdp_session *sdp, pjsip_msg_body **p_body) nogil # Replaces struct pjsip_replaces_hdr: pj_str_t call_id pj_str_t to_tag pj_str_t from_tag int early_only pjsip_param other_param pjsip_replaces_hdr *pjsip_replaces_hdr_create(pj_pool_t *pool) nogil int pjsip_replaces_verify_request(pjsip_rx_data *rdata, pjsip_dialog **p_dlg, int lock_dlg, pjsip_tx_data **p_tdata) nogil int pjsip_replaces_init_module(pjsip_endpoint *endpt) nogil # declarations # core.util cdef class frozenlist(object): # attributes cdef int initialized cdef list list cdef long hash cdef class frozendict(object): # attributes cdef int initialized cdef dict dict cdef long hash cdef class PJSTR(object): # attributes cdef pj_str_t pj_str cdef object str # core.lib cdef class PJLIB(object): # attributes cdef int _init_done cdef class PJCachingPool(object): # attributes cdef pj_caching_pool _obj cdef int _init_done cdef class PJSIPEndpoint(object): # attributes cdef pjsip_endpoint *_obj cdef pj_pool_t *_pool cdef pjsip_transport *_udp_transport cdef pjsip_tpfactory *_tcp_transport cdef pjsip_tpfactory *_tls_transport cdef int _tls_verify_server cdef PJSTR _tls_ca_file cdef PJSTR _tls_cert_file cdef PJSTR _tls_privkey_file cdef object _local_ip_used cdef int _tls_timeout # private methods cdef int _make_local_addr(self, pj_sockaddr_in *local_addr, object ip_address, int port) except -1 cdef int _start_udp_transport(self, int port) except -1 cdef int _stop_udp_transport(self) except -1 cdef int _start_tcp_transport(self, int port) except -1 cdef int _stop_tcp_transport(self) except -1 cdef int _start_tls_transport(self, port) except -1 cdef int _stop_tls_transport(self) except -1 cdef int _set_dns_nameservers(self, list servers) except -1 cdef class PJMEDIAEndpoint(object): # attributes cdef pjmedia_endpt *_obj cdef pj_pool_t *_pool cdef int _has_audio_codecs cdef int _has_video cdef int _has_ffmpeg_video cdef int _has_vpx # private methods cdef list _get_codecs(self) cdef list _get_all_codecs(self) cdef list _get_current_codecs(self) cdef int _set_codecs(self, list req_codecs) except -1 cdef list _get_video_codecs(self) cdef list _get_all_video_codecs(self) cdef list _get_current_video_codecs(self) cdef int _set_video_codecs(self, list req_codecs) except -1 cdef void _audio_subsystem_init(self, PJCachingPool caching_pool) cdef void _audio_subsystem_shutdown(self) cdef void _video_subsystem_init(self, PJCachingPool caching_pool) cdef void _video_subsystem_shutdown(self) cdef void _set_h264_options(self, str profile, int level) cdef void _set_video_options(self, tuple max_resolution, int max_framerate, float max_bitrate) # core.helper cdef class BaseCredentials(object): # attributes cdef pjsip_cred_info _credentials # private methods cdef pjsip_cred_info* get_cred_info(self) cdef class Credentials(BaseCredentials): # attributes - cdef str _username - cdef str _realm - cdef str _password + cdef object _username + cdef object _realm + cdef object _password cdef bint _digest cdef class FrozenCredentials(BaseCredentials): # attributes cdef int initialized - cdef readonly str username - cdef readonly str realm - cdef readonly str password + cdef readonly object username + cdef readonly object realm + cdef readonly object password cdef readonly bint digest cdef class BaseSIPURI(object): pass cdef class SIPURI(BaseSIPURI): # attributes cdef public object user cdef public object password cdef public object host cdef public bint secure cdef public dict parameters cdef public dict headers cdef object _port cdef class FrozenSIPURI(BaseSIPURI): # attributes cdef int initialized cdef readonly object user cdef readonly object password cdef readonly object host cdef readonly object port cdef readonly bint secure cdef readonly frozendict parameters cdef readonly frozendict headers cdef SIPURI SIPURI_create(pjsip_sip_uri *base_uri) cdef FrozenSIPURI FrozenSIPURI_create(pjsip_sip_uri *base_uri) # core.headers cdef class BaseHeader(object): pass cdef class Header(BaseHeader): # attributes cdef str _name cdef str _body cdef class FrozenHeader(BaseHeader): # attributes cdef readonly str name cdef readonly str body cdef class BaseContactHeader(object): pass cdef class ContactHeader(BaseContactHeader): # attributes cdef SIPURI _uri cdef unicode _display_name cdef dict _parameters cdef class FrozenContactHeader(BaseContactHeader): # attributes cdef int initialized cdef readonly FrozenSIPURI uri cdef readonly unicode display_name cdef readonly frozendict parameters cdef class BaseContentTypeHeader(object): pass cdef class ContentTypeHeader(BaseContentTypeHeader): # attributes cdef str _content_type cdef dict _parameters cdef class FrozenContentTypeHeader(BaseContentTypeHeader): # attributes cdef int initialized cdef readonly str _content_type cdef readonly frozendict parameters cdef class BaseIdentityHeader(object): pass cdef class IdentityHeader(BaseIdentityHeader): # attributes cdef SIPURI _uri cdef public unicode display_name cdef dict _parameters cdef class FrozenIdentityHeader(BaseIdentityHeader): # attributes cdef int initialized cdef readonly FrozenSIPURI uri cdef readonly unicode display_name cdef readonly frozendict parameters cdef class FromHeader(IdentityHeader): pass cdef class FrozenFromHeader(FrozenIdentityHeader): pass cdef class ToHeader(IdentityHeader): pass cdef class FrozenToHeader(FrozenIdentityHeader): pass cdef class RouteHeader(IdentityHeader): pass cdef class FrozenRouteHeader(FrozenIdentityHeader): pass cdef class RecordRouteHeader(IdentityHeader): pass cdef class FrozenRecordRouteHeader(FrozenIdentityHeader): pass cdef class BaseRetryAfterHeader(object): pass cdef class RetryAfterHeader(BaseRetryAfterHeader): # attributes cdef public int seconds cdef public str comment cdef dict _parameters cdef class FrozenRetryAfterHeader(BaseRetryAfterHeader): # attributes cdef int initialized cdef readonly int seconds cdef readonly str comment cdef readonly frozendict parameters cdef class BaseViaHeader(object): pass cdef class ViaHeader(BaseViaHeader): # attributes cdef str _transport cdef str _host cdef int _port cdef dict _parameters cdef class FrozenViaHeader(BaseViaHeader): # attributes cdef int initialized cdef readonly str transport cdef readonly str host cdef readonly int port cdef readonly frozendict parameters cdef class BaseWarningHeader(object): pass cdef class WarningHeader(BaseWarningHeader): # attributes cdef int _code cdef str _agent cdef str _text cdef class FrozenWarningHeader(BaseWarningHeader): # attributes cdef int initialized cdef readonly int code cdef readonly str agent cdef readonly str text cdef class BaseEventHeader(object): pass cdef class EventHeader(BaseEventHeader): # attributes cdef public event cdef dict _parameters cdef class FrozenEventHeader(BaseEventHeader): # attributes cdef int initialized cdef readonly str event cdef readonly frozendict parameters cdef class BaseSubscriptionStateHeader(object): pass cdef class SubscriptionStateHeader(BaseSubscriptionStateHeader): # attributes cdef public state cdef dict _parameters cdef class FrozenSubscriptionStateHeader(BaseSubscriptionStateHeader): # attributes cdef int initialized cdef readonly str state cdef readonly frozendict parameters cdef class BaseReasonHeader(object): pass cdef class ReasonHeader(BaseReasonHeader): # attributes cdef public str protocol cdef public dict parameters cdef class FrozenReasonHeader(BaseReasonHeader): # attributes cdef int initialized cdef readonly str protocol cdef readonly frozendict parameters cdef class BaseReferToHeader(object): pass cdef class ReferToHeader(BaseReferToHeader): # attributes cdef public str uri cdef dict _parameters cdef class FrozenReferToHeader(BaseReferToHeader): # attributes cdef int initialized cdef readonly str uri cdef readonly frozendict parameters cdef class BaseSubjectHeader(object): pass cdef class SubjectHeader(BaseSubjectHeader): # attributes cdef public unicode subject cdef class FrozenSubjectHeader(BaseSubjectHeader): # attributes cdef int initialized cdef readonly unicode subject cdef class BaseReplacesHeader(object): pass cdef class ReplacesHeader(BaseReplacesHeader): # attributes cdef public str call_id cdef public str from_tag cdef public str to_tag cdef public int early_only cdef dict _parameters cdef class FrozenReplacesHeader(BaseReplacesHeader): # attributes cdef int initialized cdef readonly str call_id cdef readonly str from_tag cdef readonly str to_tag cdef readonly int early_only cdef readonly frozendict parameters cdef Header Header_create(pjsip_generic_string_hdr *header) cdef FrozenHeader FrozenHeader_create(pjsip_generic_string_hdr *header) cdef ContactHeader ContactHeader_create(pjsip_contact_hdr *header) cdef FrozenContactHeader FrozenContactHeader_create(pjsip_contact_hdr *header) cdef ContentTypeHeader ContentTypeHeader_create(pjsip_ctype_hdr *header) cdef FrozenContentTypeHeader FrozenContentTypeHeader_create(pjsip_ctype_hdr *header) cdef FromHeader FromHeader_create(pjsip_fromto_hdr *header) cdef FrozenFromHeader FrozenFromHeader_create(pjsip_fromto_hdr *header) cdef ToHeader ToHeader_create(pjsip_fromto_hdr *header) cdef FrozenToHeader FrozenToHeader_create(pjsip_fromto_hdr *header) cdef RouteHeader RouteHeader_create(pjsip_routing_hdr *header) cdef FrozenRouteHeader FrozenRouteHeader_create(pjsip_routing_hdr *header) cdef RecordRouteHeader RecordRouteHeader_create(pjsip_routing_hdr *header) cdef FrozenRecordRouteHeader FrozenRecordRouteHeader_create(pjsip_routing_hdr *header) cdef RetryAfterHeader RetryAfterHeader_create(pjsip_retry_after_hdr *header) cdef FrozenRetryAfterHeader FrozenRetryAfterHeader_create(pjsip_retry_after_hdr *header) cdef ViaHeader ViaHeader_create(pjsip_via_hdr *header) cdef FrozenViaHeader FrozenViaHeader_create(pjsip_via_hdr *header) cdef EventHeader EventHeader_create(pjsip_event_hdr *header) cdef FrozenEventHeader FrozenEventHeader_create(pjsip_event_hdr *header) cdef SubscriptionStateHeader SubscriptionStateHeader_create(pjsip_sub_state_hdr *header) cdef FrozenSubscriptionStateHeader FrozenSubscriptionStateHeader_create(pjsip_sub_state_hdr *header) cdef ReferToHeader ReferToHeader_create(pjsip_generic_string_hdr *header) cdef FrozenReferToHeader FrozenReferToHeader_create(pjsip_generic_string_hdr *header) cdef SubjectHeader SubjectHeader_create(pjsip_generic_string_hdr *header) cdef FrozenSubjectHeader FrozenSubjectHeader_create(pjsip_generic_string_hdr *header) cdef ReplacesHeader ReplacesHeader_create(pjsip_replaces_hdr *header) cdef FrozenReplacesHeader FrozenReplacesHeader_create(pjsip_replaces_hdr *header) # core.util cdef int _str_to_pj_str(object string, pj_str_t *pj_str) except -1 cdef object _pj_str_to_bytes(pj_str_t pj_bytes) cdef object _pj_str_to_str(pj_str_t pj_str) cdef object _pj_status_to_str(int status) cdef object _pj_status_to_def(int status) cdef object _buf_to_str(object buf) cdef object _str_as_str(object string) cdef object _str_as_size(object string) cdef dict _pjsip_param_to_dict(pjsip_param *param_list) cdef int _dict_to_pjsip_param(object params, pjsip_param *param_list, pj_pool_t *pool) cdef int _pjsip_msg_to_dict(pjsip_msg *msg, dict info_dict) except -1 cdef int _is_valid_ip(int af, object ip) except -1 cdef int _get_ip_version(object ip) except -1 cdef int _add_headers_to_tdata(pjsip_tx_data *tdata, object headers) except -1 cdef int _remove_headers_from_tdata(pjsip_tx_data *tdata, object headers) except -1 cdef int _BaseSIPURI_to_pjsip_sip_uri(BaseSIPURI uri, pjsip_sip_uri *pj_uri, pj_pool_t *pool) except -1 cdef int _BaseRouteHeader_to_pjsip_route_hdr(BaseIdentityHeader header, pjsip_route_hdr *pj_header, pj_pool_t *pool) except -1 # core.ua ctypedef int (*timer_callback)(object, object) except -1 cdef class Timer(object): # attributes cdef int _scheduled cdef double schedule_time cdef timer_callback callback cdef object obj # private methods cdef int schedule(self, float delay, timer_callback callback, object obj) except -1 cdef int cancel(self) except -1 cdef int call(self) except -1 cdef class PJSIPThread(object): # attributes cdef pj_thread_t *_obj cdef long _thread_desc[PJ_THREAD_DESC_SIZE] cdef class PJSIPUA(object): # attributes cdef object _threads cdef object _event_handler cdef list _timers cdef PJLIB _pjlib cdef PJCachingPool _caching_pool cdef PJSIPEndpoint _pjsip_endpoint cdef PJMEDIAEndpoint _pjmedia_endpoint cdef pjsip_module _module cdef PJSTR _module_name cdef pjsip_module _opus_fix_module cdef PJSTR _opus_fix_module_name cdef pjsip_module _trace_module cdef PJSTR _trace_module_name cdef pjsip_module _ua_tag_module cdef PJSTR _ua_tag_module_name cdef pjsip_module _event_module cdef PJSTR _event_module_name cdef int _trace_sip cdef int _detect_sip_loops cdef int _enable_colorbar_device cdef PJSTR _user_agent cdef object _events cdef object _sent_messages cdef object _ip_address cdef int _rtp_port_start cdef int _rtp_port_count cdef int _rtp_port_usable_count cdef int _rtp_port_index cdef pj_stun_config _stun_cfg cdef int _fatal_error cdef set _incoming_events cdef set _incoming_requests cdef pj_rwmutex_t *audio_change_rwlock cdef pj_mutex_t *video_lock cdef list old_devices cdef list old_video_devices cdef object _zrtp_cache # private methods cdef object _get_sound_devices(self, int is_output) cdef object _get_default_sound_device(self, int is_output) cdef object _get_video_devices(self) cdef object _get_default_video_device(self) cdef int _poll_log(self) except -1 cdef int _handle_exception(self, int is_fatal) except -1 cdef int _check_self(self) except -1 cdef int _check_thread(self) except -1 cdef int _add_timer(self, Timer timer) except -1 cdef int _remove_timer(self, Timer timer) except -1 cdef int _cb_rx_request(self, pjsip_rx_data *rdata) except 0 cdef pj_pool_t* create_memory_pool(self, bytes name, int initial_size, int resize_size) cdef void release_memory_pool(self, pj_pool_t* pool) cdef void reset_memory_pool(self, pj_pool_t* pool) cdef int _PJSIPUA_cb_rx_request(pjsip_rx_data *rdata) with gil cdef void _cb_detect_nat_type(void *user_data, pj_stun_nat_detect_result_ptr_const res) with gil cdef int _cb_opus_fix_tx(pjsip_tx_data *tdata) with gil cdef int _cb_trace_rx(pjsip_rx_data *rdata) with gil cdef int _cb_trace_tx(pjsip_tx_data *tdata) with gil cdef int _cb_add_user_agent_hdr(pjsip_tx_data *tdata) with gil cdef int _cb_add_server_hdr(pjsip_tx_data *tdata) with gil cdef PJSIPUA _get_ua() cdef int deallocate_weakref(object weak_ref, object timer) except -1 with gil # core.sound cdef class AudioMixer(object): # attributes cdef int _input_volume cdef int _output_volume cdef bint _muted cdef pj_mutex_t *_lock cdef pj_pool_t *_conf_pool cdef pj_pool_t *_snd_pool cdef pjmedia_conf *_obj cdef pjmedia_master_port *_master_port cdef pjmedia_port *_null_port cdef pjmedia_snd_port *_snd cdef list _connected_slots cdef readonly int ec_tail_length cdef readonly int sample_rate cdef readonly int slot_count cdef readonly int used_slot_count cdef readonly unicode input_device cdef readonly unicode output_device cdef readonly unicode real_input_device cdef readonly unicode real_output_device # private methods cdef void _start_sound_device(self, PJSIPUA ua, unicode input_device, unicode output_device, int ec_tail_length) cdef void _stop_sound_device(self, PJSIPUA ua) cdef int _add_port(self, PJSIPUA ua, pj_pool_t *pool, pjmedia_port *port) except -1 with gil cdef int _remove_port(self, PJSIPUA ua, unsigned int slot) except -1 with gil cdef int _cb_postpoll_stop_sound(self, timer) except -1 cdef class ToneGenerator(object): # attributes cdef int _slot cdef int _volume cdef pj_mutex_t *_lock cdef pj_pool_t *_pool cdef pjmedia_port *_obj cdef Timer _timer cdef readonly AudioMixer mixer # private methods cdef PJSIPUA _get_ua(self, int raise_exception) cdef int _stop(self, PJSIPUA ua) except -1 cdef int _cb_check_done(self, timer) except -1 cdef class RecordingWaveFile(object): # attributes cdef int _slot cdef int _was_started cdef pj_mutex_t *_lock cdef pj_pool_t *_pool cdef pjmedia_port *_port cdef readonly str filename cdef readonly AudioMixer mixer # private methods cdef PJSIPUA _check_ua(self) cdef int _stop(self, PJSIPUA ua) except -1 cdef class WaveFile(object): # attributes cdef object __weakref__ cdef object weakref cdef int _slot cdef int _volume cdef pj_mutex_t *_lock cdef pj_pool_t *_pool cdef pjmedia_port *_port cdef readonly str filename cdef readonly AudioMixer mixer # private methods cdef PJSIPUA _check_ua(self) cdef int _stop(self, PJSIPUA ua, int notify) except -1 cdef int _cb_eof(self, timer) except -1 cdef class MixerPort(object): cdef int _slot cdef int _was_started cdef pj_mutex_t *_lock cdef pj_pool_t *_pool cdef pjmedia_port *_port cdef readonly AudioMixer mixer # private methods cdef PJSIPUA _check_ua(self) cdef int _stop(self, PJSIPUA ua) except -1 cdef int _AudioMixer_dealloc_handler(object obj) except -1 cdef int cb_play_wav_eof(pjmedia_port *port, void *user_data) with gil # core.video cdef class VideoFrame(object): cdef readonly str data cdef readonly int width cdef readonly int height cdef class VideoConsumer(object): cdef pjmedia_port *consumer_port cdef pjmedia_vid_port *_video_port cdef pj_pool_t *_pool cdef pj_mutex_t *_lock cdef int _running cdef int _closed cdef VideoProducer _producer cdef object __weakref__ cdef object weakref cdef void _set_producer(self, VideoProducer producer) cdef class VideoProducer(object): cdef pjmedia_port *producer_port cdef pjmedia_vid_port *_video_port cdef pj_pool_t *_pool cdef pj_mutex_t *_lock cdef int _running cdef int _started cdef int _closed cdef object _consumers cdef void _add_consumer(self, VideoConsumer consumer) cdef void _remove_consumer(self, VideoConsumer consumer) cdef class VideoCamera(VideoProducer): cdef pjmedia_port *_video_tee cdef readonly unicode name cdef readonly unicode real_name cdef void _start(self) cdef void _stop(self) cdef class FrameBufferVideoRenderer(VideoConsumer): cdef pjmedia_vid_dev_stream *_video_stream cdef object _frame_handler cdef _initialize(self, VideoProducer producer) cdef void _destroy_video_port(self) cdef void _start(self) cdef void _stop(self) cdef class LocalVideoStream(VideoConsumer): cdef void _initialize(self, pjmedia_port *media_port) cdef class RemoteVideoStream(VideoProducer): cdef pjmedia_vid_stream *_video_stream cdef object _event_handler cdef void _initialize(self, pjmedia_vid_stream *stream) cdef LocalVideoStream_create(pjmedia_vid_stream *stream) cdef RemoteVideoStream_create(pjmedia_vid_stream *stream, format_change_handler=*) cdef int RemoteVideoStream_on_event(pjmedia_event *event, void *user_data) with gil cdef void _start_video_port(pjmedia_vid_port *port) cdef void _stop_video_port(pjmedia_vid_port *port) # core.event cdef struct _core_event cdef struct _handler_queue cdef int _event_queue_append(_core_event *event) cdef void _cb_log(int level, char_ptr_const data, int len) cdef int _add_event(object event_name, dict params) except -1 cdef list _get_clear_event_queue() cdef int _add_handler(int func(object obj) except -1, object obj, _handler_queue *queue) except -1 cdef int _remove_handler(object obj, _handler_queue *queue) except -1 cdef int _process_handler_queue(PJSIPUA ua, _handler_queue *queue) except -1 # core.request cdef class EndpointAddress(object): # attributes cdef readonly bytes ip cdef readonly int port cdef class Request(object): # attributes cdef readonly object state cdef PJSTR _method cdef readonly EndpointAddress peer_address cdef readonly FrozenCredentials credentials cdef readonly FrozenFromHeader from_header cdef readonly FrozenToHeader to_header cdef readonly FrozenSIPURI request_uri cdef readonly FrozenContactHeader contact_header cdef readonly FrozenRouteHeader route_header cdef PJSTR _call_id cdef readonly int cseq cdef readonly frozenlist extra_headers cdef PJSTR _content_type cdef PJSTR _content_subtype cdef PJSTR _body cdef pjsip_tx_data *_tdata cdef pjsip_transaction *_tsx cdef pjsip_auth_clt_sess _auth cdef pjsip_route_hdr _route_header cdef int _need_auth cdef pj_timer_entry _timer cdef int _timer_active cdef int _expire_rest cdef object _expire_time cdef object _timeout # private methods cdef PJSIPUA _get_ua(self) cdef int _cb_tsx_state(self, PJSIPUA ua, pjsip_rx_data *rdata) except -1 cdef int _cb_timer(self, PJSIPUA ua) except -1 cdef class IncomingRequest(object): # attributes cdef readonly str state cdef pjsip_transaction *_tsx cdef pjsip_tx_data *_tdata cdef readonly EndpointAddress peer_address # methods cdef int init(self, PJSIPUA ua, pjsip_rx_data *rdata) except -1 cdef void _Request_cb_tsx_state(pjsip_transaction *tsx, pjsip_event *event) with gil cdef void _Request_cb_timer(pj_timer_heap_t *timer_heap, pj_timer_entry *entry) with gil # core.referral cdef class Referral(object): # attributes cdef pjsip_evsub *_obj cdef pjsip_dialog *_dlg cdef pjsip_route_hdr _route_header cdef pj_list _route_set cdef int _create_subscription cdef readonly object state cdef pj_timer_entry _timeout_timer cdef int _timeout_timer_active cdef pj_timer_entry _refresh_timer cdef int _refresh_timer_active cdef readonly EndpointAddress peer_address cdef readonly FrozenFromHeader from_header cdef readonly FrozenToHeader to_header cdef readonly FrozenReferToHeader refer_to_header cdef readonly FrozenRouteHeader route_header cdef readonly FrozenCredentials credentials cdef readonly FrozenContactHeader local_contact_header cdef readonly FrozenContactHeader remote_contact_header cdef readonly int refresh cdef readonly frozenlist extra_headers cdef pj_time_val _request_timeout cdef int _want_end cdef int _term_code cdef object _term_reason # private methods cdef PJSIPUA _get_ua(self) cdef int _update_contact_header(self, BaseContactHeader contact_header) except -1 cdef int _cancel_timers(self, PJSIPUA ua, int cancel_timeout, int cancel_refresh) except -1 cdef int _send_refer(self, PJSIPUA ua, pj_time_val *timeout, FrozenReferToHeader refer_to_header, frozenlist extra_headers) except -1 cdef int _send_subscribe(self, PJSIPUA ua, int expires, pj_time_val *timeout, frozenlist extra_headers) except -1 cdef int _cb_state(self, PJSIPUA ua, object state, int code, str reason) except -1 cdef int _cb_got_response(self, PJSIPUA ua, pjsip_rx_data *rdata, str method) except -1 cdef int _cb_notify(self, PJSIPUA ua, pjsip_rx_data *rdata) except -1 cdef int _cb_timeout_timer(self, PJSIPUA ua) cdef int _cb_refresh_timer(self, PJSIPUA ua) cdef class IncomingReferral(object): cdef pjsip_evsub *_obj cdef pjsip_dialog *_dlg cdef pjsip_tx_data *_initial_response cdef pjsip_transaction *_initial_tsx cdef pj_time_val _expires_time cdef int _create_subscription cdef readonly str state cdef readonly EndpointAddress peer_address cdef readonly FrozenContactHeader local_contact_header cdef readonly FrozenContactHeader remote_contact_header cdef PJSTR _content cdef int init(self, PJSIPUA ua, pjsip_rx_data *rdata) except -1 cdef PJSIPUA _get_ua(self, int raise_exception) cdef int _set_content(self, int code, str reason) except -1 cdef int _set_state(self, str state) except -1 cdef int _send_initial_response(self, int code) except -1 cdef int _send_notify(self) except -1 cdef int _terminate(self, PJSIPUA ua, int do_cleanup) except -1 cdef int _cb_rx_refresh(self, PJSIPUA ua, pjsip_rx_data *rdata) except -1 cdef int _cb_server_timeout(self, PJSIPUA ua) except -1 cdef int _cb_tsx(self, PJSIPUA ua, pjsip_event *event) except -1 cdef void _Referral_cb_state(pjsip_evsub *sub, pjsip_event *event) with gil cdef void _Referral_cb_notify(pjsip_evsub *sub, pjsip_rx_data *rdata, int *p_st_code, pj_str_t **p_st_text, pjsip_hdr *res_hdr, pjsip_msg_body **p_body) with gil cdef void _Referral_cb_refresh(pjsip_evsub *sub) with gil cdef void _IncomingReferral_cb_rx_refresh(pjsip_evsub *sub, pjsip_rx_data *rdata, int *p_st_code, pj_str_t **p_st_text, pjsip_hdr *res_hdr, pjsip_msg_body **p_body) with gil cdef void _IncomingReferral_cb_server_timeout(pjsip_evsub *sub) with gil cdef void _IncomingReferral_cb_tsx(pjsip_evsub *sub, pjsip_transaction *tsx, pjsip_event *event) with gil # core.subscription cdef class Subscription(object): # attributes cdef pjsip_evsub *_obj cdef pjsip_dialog *_dlg cdef pjsip_route_hdr _route_header cdef pj_list _route_set cdef pj_timer_entry _timeout_timer cdef int _timeout_timer_active cdef pj_timer_entry _refresh_timer cdef int _refresh_timer_active cdef readonly object state cdef readonly EndpointAddress peer_address cdef readonly FrozenFromHeader from_header cdef readonly FrozenToHeader to_header cdef readonly FrozenContactHeader contact_header cdef readonly object event cdef readonly FrozenRouteHeader route_header cdef readonly FrozenCredentials credentials cdef readonly int refresh cdef readonly frozenlist extra_headers cdef readonly object body cdef readonly object content_type cdef readonly str call_id cdef pj_time_val _subscribe_timeout cdef int _want_end cdef int _term_code cdef object _term_reason cdef int _expires # private methods cdef PJSIPUA _get_ua(self) cdef int _cancel_timers(self, PJSIPUA ua, int cancel_timeout, int cancel_refresh) except -1 cdef int _send_subscribe(self, PJSIPUA ua, int expires, pj_time_val *timeout, object extra_headers, object content_type, object body) except -1 cdef int _cb_state(self, PJSIPUA ua, object state, int code, object reason, dict headers) except -1 cdef int _cb_got_response(self, PJSIPUA ua, pjsip_rx_data *rdata) except -1 cdef int _cb_notify(self, PJSIPUA ua, pjsip_rx_data *rdata) except -1 cdef int _cb_timeout_timer(self, PJSIPUA ua) cdef int _cb_refresh_timer(self, PJSIPUA ua) cdef class IncomingSubscription(object): # attributes cdef pjsip_evsub *_obj cdef pjsip_dialog *_dlg cdef PJSTR _content_type cdef PJSTR _content_subtype cdef PJSTR _content cdef pjsip_tx_data *_initial_response cdef pjsip_transaction *_initial_tsx cdef int _expires cdef readonly str state cdef readonly str event cdef readonly str call_id cdef readonly EndpointAddress peer_address # methods cdef int _set_state(self, str state) except -1 cdef PJSIPUA _get_ua(self, int raise_exception) cdef int init(self, PJSIPUA ua, pjsip_rx_data *rdata, str event) except -1 cdef int _send_initial_response(self, int code) except -1 cdef int _send_notify(self, str reason=*) except -1 cdef int _terminate(self, PJSIPUA ua, str reason, int do_cleanup) except -1 cdef int _cb_rx_refresh(self, PJSIPUA ua, pjsip_rx_data *rdata) except -1 cdef int _cb_server_timeout(self, PJSIPUA ua) except -1 cdef int _cb_tsx(self, PJSIPUA ua, pjsip_event *event) except -1 cdef void _Subscription_cb_state(pjsip_evsub *sub, pjsip_event *event) with gil cdef void _Subscription_cb_notify(pjsip_evsub *sub, pjsip_rx_data *rdata, int *p_st_code, pj_str_t **p_st_text, pjsip_hdr *res_hdr, pjsip_msg_body **p_body) with gil cdef void _Subscription_cb_refresh(pjsip_evsub *sub) with gil cdef void _IncomingSubscription_cb_rx_refresh(pjsip_evsub *sub, pjsip_rx_data *rdata, int *p_st_code, pj_str_t **p_st_text, pjsip_hdr *res_hdr, pjsip_msg_body **p_body) with gil cdef void _IncomingSubscription_cb_server_timeout(pjsip_evsub *sub) with gil cdef void _IncomingSubscription_cb_tsx(pjsip_evsub *sub, pjsip_transaction *tsx, pjsip_event *event) with gil # core.sdp cdef class BaseSDPConnection(object): # attributes cdef pjmedia_sdp_conn _sdp_connection # private methods cdef pjmedia_sdp_conn* get_sdp_connection(self) cdef class SDPConnection(BaseSDPConnection): # attributes cdef object _address cdef object _net_type cdef object _address_type cdef class FrozenSDPConnection(BaseSDPConnection): # attributes cdef int initialized cdef readonly object address cdef readonly object net_type cdef readonly object address_type cdef class SDPAttributeList(list): pass cdef class FrozenSDPAttributeList(frozenlist): pass cdef class SDPBandwidthInfoList(list): pass cdef class FrozenSDPBandwidthInfoList(frozenlist): pass cdef class BaseSDPSession(object): # attributes cdef pjmedia_sdp_session _sdp_session # private methods cdef pjmedia_sdp_session* get_sdp_session(self) cdef class SDPSession(BaseSDPSession): # attributes cdef object _address cdef object _user cdef object _net_type cdef object _address_type cdef object _name cdef object _info cdef SDPConnection _connection cdef list _attributes cdef list _bandwidth_info cdef list _media # private methods cdef int _update(self) except -1 cdef class FrozenSDPSession(BaseSDPSession): # attributes cdef int initialized cdef readonly object address cdef readonly unsigned int id cdef readonly unsigned int version cdef readonly object user cdef readonly object net_type cdef readonly object address_type cdef readonly object name cdef readonly object info cdef readonly FrozenSDPConnection connection cdef readonly int start_time cdef readonly int stop_time cdef readonly FrozenSDPAttributeList attributes cdef readonly FrozenSDPBandwidthInfoList bandwidth_info cdef readonly frozenlist media cdef class BaseSDPMediaStream(object): # attributes cdef pjmedia_sdp_media _sdp_media # private methods cdef pjmedia_sdp_media* get_sdp_media(self) cdef class SDPMediaStream(BaseSDPMediaStream): # attributes cdef object _media cdef object _transport cdef list _formats cdef list _codec_list cdef object _info cdef SDPConnection _connection cdef SDPAttributeList _attributes cdef SDPBandwidthInfoList _bandwidth_info # private methods cdef int _update(self, SDPMediaStream media) except -1 cdef class FrozenSDPMediaStream(BaseSDPMediaStream): # attributes cdef int initialized cdef readonly object media cdef readonly int port cdef readonly object transport cdef readonly int port_count cdef readonly frozenlist formats cdef readonly frozenlist codec_list cdef readonly object info cdef readonly FrozenSDPConnection connection cdef readonly FrozenSDPAttributeList attributes cdef readonly FrozenSDPBandwidthInfoList bandwidth_info cdef class BaseSDPAttribute(object): # attributes cdef pjmedia_sdp_attr _sdp_attribute # private methods cdef pjmedia_sdp_attr* get_sdp_attribute(self) cdef class SDPAttribute(BaseSDPAttribute): # attributes cdef object _name cdef object _value cdef class FrozenSDPAttribute(BaseSDPAttribute): # attributes cdef int initialized cdef readonly object name cdef readonly object value cdef class BaseSDPBandwidthInfo(object): # attributes cdef pjmedia_sdp_bandw _sdp_bandwidth_info # private methods cdef pjmedia_sdp_bandw* get_sdp_bandwidth_info(self) cdef class SDPBandwidthInfo(BaseSDPBandwidthInfo): # attributes cdef object _modifier cdef object _value cdef class FrozenSDPBandwidthInfo(BaseSDPBandwidthInfo): # attributes cdef int initialized cdef readonly object modifier cdef readonly int value cdef SDPSession SDPSession_create(pjmedia_sdp_session_ptr_const pj_session) cdef FrozenSDPSession FrozenSDPSession_create(pjmedia_sdp_session_ptr_const pj_session) cdef SDPMediaStream SDPMediaStream_create(pjmedia_sdp_media *pj_media) cdef FrozenSDPMediaStream FrozenSDPMediaStream_create(pjmedia_sdp_media *pj_media) cdef SDPConnection SDPConnection_create(pjmedia_sdp_conn *pj_conn) cdef FrozenSDPConnection FrozenSDPConnection_create(pjmedia_sdp_conn *pj_conn) cdef SDPAttribute SDPAttribute_create(pjmedia_sdp_attr *pj_attr) cdef FrozenSDPAttribute FrozenSDPAttribute_create(pjmedia_sdp_attr *pj_attr) cdef SDPBandwidthInfo SDPBandwidthInfo_create(pjmedia_sdp_bandw *pj_bandw) cdef FrozenSDPBandwidthInfo FrozenSDPBandwidthInfo_create(pjmedia_sdp_bandw *pj_bandw) cdef class SDPNegotiator(object): # attributes cdef pjmedia_sdp_neg* _neg cdef pj_pool_t *_pool # core.invitation cdef class SDPPayloads: cdef readonly FrozenSDPSession proposed_local cdef readonly FrozenSDPSession proposed_remote cdef readonly FrozenSDPSession active_local cdef readonly FrozenSDPSession active_remote cdef class StateCallbackTimer(Timer): cdef object state cdef object sub_state cdef object rdata cdef object tdata cdef object originator cdef class SDPCallbackTimer(Timer): cdef int status cdef object active_local cdef object active_remote cdef class TransferStateCallbackTimer(Timer): cdef object state cdef object code cdef object reason cdef class TransferResponseCallbackTimer(Timer): cdef object method cdef object rdata cdef class TransferRequestCallbackTimer(Timer): cdef object rdata cdef class Invitation(object): # attributes cdef object __weakref__ cdef object weakref cdef int _sdp_neg_status cdef int _failed_response cdef pj_list _route_set cdef pj_mutex_t *_lock cdef pjsip_inv_session *_invite_session cdef pjsip_evsub *_transfer_usage cdef pjsip_role_e _transfer_usage_role cdef pjsip_dialog *_dialog cdef pjsip_route_hdr _route_header cdef pjsip_transaction *_reinvite_transaction cdef PJSTR _sipfrag_payload cdef Timer _timer cdef Timer _transfer_timeout_timer cdef Timer _transfer_refresh_timer cdef readonly str call_id cdef readonly str direction cdef readonly str remote_user_agent cdef readonly str state cdef readonly str sub_state cdef readonly str transport cdef readonly str transfer_state cdef readonly EndpointAddress peer_address cdef readonly FrozenCredentials credentials cdef readonly FrozenContactHeader local_contact_header cdef readonly FrozenContactHeader remote_contact_header cdef readonly FrozenFromHeader from_header cdef readonly FrozenToHeader to_header cdef readonly FrozenSIPURI request_uri cdef readonly FrozenRouteHeader route_header cdef readonly SDPPayloads sdp # private methods cdef int init_incoming(self, PJSIPUA ua, pjsip_rx_data *rdata, unsigned int inv_options) except -1 cdef int process_incoming_transfer(self, PJSIPUA ua, pjsip_rx_data *rdata) except -1 cdef int process_incoming_options(self, PJSIPUA ua, pjsip_rx_data *rdata) except -1 cdef PJSIPUA _check_ua(self) cdef int _do_dealloc(self) except -1 cdef int _update_contact_header(self, BaseContactHeader contact_header) except -1 cdef int _fail(self, PJSIPUA ua) except -1 cdef int _cb_state(self, StateCallbackTimer timer) except -1 cdef int _cb_sdp_done(self, SDPCallbackTimer timer) except -1 cdef int _cb_timer_disconnect(self, timer) except -1 cdef int _cb_postpoll_fail(self, timer) except -1 cdef int _start_incoming_transfer(self, timer) except -1 cdef int _terminate_transfer(self) except -1 cdef int _terminate_transfer_uac(self) except -1 cdef int _terminate_transfer_uas(self) except -1 cdef int _set_transfer_state(self, str state) except -1 cdef int _set_sipfrag_payload(self, int code, str reason) except -1 cdef int _send_notify(self) except -1 cdef int _transfer_cb_timeout_timer(self, timer) except -1 cdef int _transfer_cb_refresh_timer(self, timer) except -1 cdef int _transfer_cb_state(self, TransferStateCallbackTimer timer) except -1 cdef int _transfer_cb_response(self, TransferResponseCallbackTimer timer) except -1 cdef int _transfer_cb_notify(self, TransferRequestCallbackTimer timer) except -1 cdef int _transfer_cb_server_timeout(self, timer) except -1 cdef void _Invitation_cb_state(pjsip_inv_session *inv, pjsip_event *e) with gil cdef void _Invitation_cb_sdp_done(pjsip_inv_session *inv, int status) with gil cdef int _Invitation_cb_rx_reinvite(pjsip_inv_session *inv, pjmedia_sdp_session_ptr_const offer, pjsip_rx_data *rdata) with gil cdef void _Invitation_cb_tsx_state_changed(pjsip_inv_session *inv, pjsip_transaction *tsx, pjsip_event *e) with gil cdef void _Invitation_cb_new(pjsip_inv_session *inv, pjsip_event *e) with gil cdef void _Invitation_transfer_cb_state(pjsip_evsub *sub, pjsip_event *event) with gil cdef void _Invitation_transfer_cb_tsx(pjsip_evsub *sub, pjsip_transaction *tsx, pjsip_event *event) with gil cdef void _Invitation_transfer_cb_notify(pjsip_evsub *sub, pjsip_rx_data *rdata, int *p_st_code, pj_str_t **p_st_text, pjsip_hdr *res_hdr, pjsip_msg_body **p_body) with gil cdef void _Invitation_transfer_cb_refresh(pjsip_evsub *sub) with gil cdef void _Invitation_transfer_in_cb_rx_refresh(pjsip_evsub *sub, pjsip_rx_data *rdata, int *p_st_code, pj_str_t **p_st_text, pjsip_hdr *res_hdr, pjsip_msg_body **p_body) with gil cdef void _Invitation_transfer_in_cb_server_timeout(pjsip_evsub *sub) with gil # core.mediatransport cdef class ICECandidate(object): # attributes cdef readonly str component cdef readonly str type cdef readonly str address cdef readonly int port cdef readonly int priority cdef readonly str rel_address cdef class ICECheck(object): cdef readonly ICECandidate local_candidate cdef readonly ICECandidate remote_candidate cdef readonly str state cdef readonly int nominated cdef class RTPTransport(object): # attributes cdef object __weakref__ cdef object weakref cdef int _af cdef pj_mutex_t *_lock cdef pj_pool_t *_pool cdef pjmedia_transport *_obj cdef pjmedia_transport *_wrapped_transport cdef ICECheck _rtp_valid_pair cdef object _encryption cdef readonly object ice_stun_address cdef readonly object ice_stun_port cdef readonly object state cdef readonly object use_ice # private methods cdef PJSIPUA _check_ua(self) cdef void _get_info(self, pjmedia_transport_info *info) cdef int _init_local_sdp(self, BaseSDPSession local_sdp, BaseSDPSession remote_sdp, int sdp_index) cdef int _ice_active(self) cdef class MediaCheckTimer(Timer): # attributes cdef int media_check_interval cdef class SDPInfo(object): # attributes cdef BaseSDPMediaStream _local_media cdef BaseSDPSession _local_sdp cdef BaseSDPSession _remote_sdp cdef public int index cdef class AudioTransport(object): # attributes cdef object __weakref__ cdef object weakref cdef int _is_offer cdef int _is_started cdef int _slot cdef int _volume cdef unsigned int _packets_received cdef unsigned int _vad cdef pj_mutex_t *_lock cdef pj_pool_t *_pool cdef pjmedia_stream *_obj cdef pjmedia_stream_info _stream_info cdef Timer _timer cdef readonly object direction cdef readonly AudioMixer mixer cdef readonly RTPTransport transport cdef SDPInfo _sdp_info # private methods cdef PJSIPUA _check_ua(self) cdef int _cb_check_rtp(self, MediaCheckTimer timer) except -1 cdef class VideoTransport(object): # attributes cdef object __weakref__ cdef object weakref cdef int _is_offer cdef int _is_started cdef unsigned int _packets_received cdef pj_mutex_t *_lock cdef pj_pool_t *_pool cdef pjmedia_vid_stream *_obj cdef pjmedia_vid_stream_info _stream_info cdef Timer _timer cdef readonly object direction cdef readonly RTPTransport transport cdef SDPInfo _sdp_info cdef readonly LocalVideoStream local_video cdef readonly RemoteVideoStream remote_video # private methods cdef PJSIPUA _check_ua(self) cdef int _cb_check_rtp(self, MediaCheckTimer timer) except -1 cdef void _RTPTransport_cb_ice_complete(pjmedia_transport *tp, pj_ice_strans_op op, int status) with gil cdef void _RTPTransport_cb_ice_state(pjmedia_transport *tp, pj_ice_strans_state prev, pj_ice_strans_state curr) with gil cdef void _RTPTransport_cb_ice_stop(pjmedia_transport *tp, char *reason, int err) with gil cdef void _RTPTransport_cb_zrtp_secure_on(pjmedia_transport *tp, char* cipher) with gil cdef void _RTPTransport_cb_zrtp_secure_off(pjmedia_transport *tp) with gil cdef void _RTPTransport_cb_zrtp_show_sas(pjmedia_transport *tp, char* sas, int verified) with gil cdef void _RTPTransport_cb_zrtp_confirm_goclear(pjmedia_transport *tp) with gil cdef void _RTPTransport_cb_zrtp_show_message(pjmedia_transport *tp, int severity, int subCode) with gil cdef void _RTPTransport_cb_zrtp_negotiation_failed(pjmedia_transport *tp, int severity, int subCode) with gil cdef void _RTPTransport_cb_zrtp_not_supported_by_other(pjmedia_transport *tp) with gil cdef void _RTPTransport_cb_zrtp_ask_enrollment(pjmedia_transport *tp, int info) with gil cdef void _RTPTransport_cb_zrtp_inform_enrollment(pjmedia_transport *tp, int info) with gil cdef void _AudioTransport_cb_dtmf(pjmedia_stream *stream, void *user_data, int digit) with gil cdef ICECandidate ICECandidate_create(pj_ice_sess_cand *cand) cdef ICECheck ICECheck_create(pj_ice_sess_check *check) cdef str _ice_state_to_str(int state) cdef dict _extract_ice_session_data(pj_ice_sess *ice_sess) cdef object _extract_rtp_transport(pjmedia_transport *tp) cdef dict _pj_math_stat_to_dict(pj_math_stat *stat) cdef dict _pjmedia_rtcp_stream_stat_to_dict(pjmedia_rtcp_stream_stat *stream_stat) diff --git a/sipsimple/core/_core.request.pxi b/sipsimple/core/_core.request.pxi index 4820d02b..cc08beec 100644 --- a/sipsimple/core/_core.request.pxi +++ b/sipsimple/core/_core.request.pxi @@ -1,505 +1,505 @@ from datetime import datetime, timedelta cdef class EndpointAddress: def __init__(self, ip, port): self.ip = ip self.port = port def __repr__(self): return "%s(%r, %r)" % (self.__class__.__name__, self.ip, self.port) def __str__(self): return "%s:%d" % (self.ip, self.port) cdef class Request: expire_warning_time = 30 # properties property method: def __get__(self): return self._method.str property call_id: def __get__(self): return self._call_id.str property content_type: def __get__(self): if self._content_type is None: return None else: return "/".join([self._content_type.str, self._content_subtype.str]) property body: def __get__(self): if self._body is None: return None else: return self._body.str property expires_in: def __get__(self): cdef object dt self._get_ua() if self.state != "EXPIRING" or self._expire_time is None: return 0 else: dt = self._expire_time - datetime.now() return max(0, dt.seconds) # public methods def __cinit__(self, *args, **kwargs): self.state = "INIT" self.peer_address = None pj_timer_entry_init(&self._timer, 0, self, _Request_cb_timer) self._timer_active = 0 def __init__(self, method, SIPURI request_uri not None, FromHeader from_header not None, ToHeader to_header not None, RouteHeader route_header not None, Credentials credentials=None, ContactHeader contact_header=None, call_id=None, cseq=None, object extra_headers=None, content_type=None, body=None): cdef pjsip_method method_pj cdef PJSTR from_header_str cdef PJSTR to_header_str cdef PJSTR request_uri_str cdef PJSTR contact_header_str cdef pj_str_t *contact_header_pj = NULL cdef pj_str_t *call_id_pj = NULL cdef object content_type_spl cdef pjsip_hdr *hdr cdef pjsip_contact_hdr *contact_hdr cdef pjsip_cid_hdr *cid_hdr cdef pjsip_cseq_hdr *cseq_hdr cdef int status cdef dict event_dict cdef PJSIPUA ua = _get_ua() if self._tsx != NULL or self.state != "INIT": raise SIPCoreError("Request.__init__() was already called") if cseq is not None and cseq < 0: raise ValueError("cseq argument cannot be negative") if extra_headers is not None: header_names = set([header.name for header in extra_headers]) if "Route" in header_names: raise ValueError("Route should be specified with route_header argument, not extra_headers") if "Content-Type" in header_names: raise ValueError("Content-Type should be specified with content_type argument, not extra_headers") else: header_names = () if content_type is not None and body is None: raise ValueError("Cannot specify a content_type without a body") if content_type is None and body is not None: raise ValueError("Cannot specify a body without a content_type") self._method = PJSTR(method.encode()) pjsip_method_init_np(&method_pj, &self._method.pj_str) if credentials is not None: self.credentials = FrozenCredentials.new(credentials) from_header_str = PJSTR(from_header.body.encode()) self.to_header = FrozenToHeader.new(to_header) to_header_str = PJSTR(to_header.body.encode()) struri = str(request_uri) self.request_uri = FrozenSIPURI.new(request_uri) request_uri_str = PJSTR(struri.encode()) self.route_header = FrozenRouteHeader.new(route_header) self.route_header.uri.parameters.dict["lr"] = None # always send lr parameter in Route header #self.route_header.uri.parameters.dict["hide"] = None # always hide Route header if contact_header is not None: self.contact_header = FrozenContactHeader.new(contact_header) contact_parameters = contact_header.parameters.copy() contact_parameters.pop("q", None) contact_parameters.pop("expires", None) contact_header.parameters = {} contact_header_str = PJSTR(contact_header.body.encode()) contact_header_pj = &contact_header_str.pj_str if call_id is not None: - self._call_id = PJSTR(call_id.encode()) + self._call_id = PJSTR(call_id) call_id_pj = &self._call_id.pj_str if cseq is None: self.cseq = -1 else: self.cseq = cseq if extra_headers is None: self.extra_headers = frozenlist() else: self.extra_headers = frozenlist([header.frozen_type.new(header) for header in extra_headers]) if body is not None: content_type_spl = content_type.split("/", 1) self._content_type = PJSTR(content_type_spl[0].encode()) self._content_subtype = PJSTR(content_type_spl[1].encode()) self._body = PJSTR(body) status = pjsip_endpt_create_request(ua._pjsip_endpoint._obj, &method_pj, &request_uri_str.pj_str, &from_header_str.pj_str, &to_header_str.pj_str, contact_header_pj, call_id_pj, self.cseq, NULL, &self._tdata) if status != 0: raise PJSIPError("Could not create request", status) if body is not None: self._tdata.msg.body = pjsip_msg_body_create(self._tdata.pool, &self._content_type.pj_str, &self._content_subtype.pj_str, &self._body.pj_str) status = _BaseRouteHeader_to_pjsip_route_hdr(self.route_header, &self._route_header, self._tdata.pool) pjsip_msg_add_hdr(self._tdata.msg, &self._route_header) hdr = ( &self._tdata.msg.hdr).next while hdr != &self._tdata.msg.hdr: hdr_name = _pj_str_to_str(hdr.name) if hdr_name in header_names: raise ValueError("Cannot override %s header value in extra_headers" % _pj_str_to_bytes(hdr.name)) if hdr.type == PJSIP_H_CONTACT: contact_hdr = hdr _dict_to_pjsip_param(contact_parameters, &contact_hdr.other_param, self._tdata.pool) elif hdr.type == PJSIP_H_CALL_ID: cid_hdr = hdr self._call_id = PJSTR(_pj_str_to_bytes(cid_hdr.id)) elif hdr.type == PJSIP_H_CSEQ: cseq_hdr = hdr self.cseq = cseq_hdr.cseq elif hdr.type == PJSIP_H_FROM: self.from_header = FrozenFromHeader_create( hdr) else: pass hdr = ( hdr).next _add_headers_to_tdata(self._tdata, self.extra_headers) - event_dict = dict(obj=self) - _pjsip_msg_to_dict(self._tdata.msg, event_dict) - print('Request dict %s' % event_dict) + #event_dict = dict(obj=self) + #_pjsip_msg_to_dict(self._tdata.msg, event_dict) + #print('Request dict %s' % event_dict) if self.credentials is not None: status = pjsip_auth_clt_init(&self._auth, ua._pjsip_endpoint._obj, self._tdata.pool, 0) if status != 0: raise PJSIPError("Could not init authentication credentials", status) status = pjsip_auth_clt_set_credentials(&self._auth, 1, self.credentials.get_cred_info()) if status != 0: raise PJSIPError("Could not set authentication credentials", status) self._need_auth = 1 else: self._need_auth = 0 status = pjsip_tsx_create_uac(&ua._module, self._tdata, &self._tsx) if status != 0: raise PJSIPError("Could not create transaction for request", status) self._tsx.mod_data[ua._module.id] = self def __dealloc__(self): cdef PJSIPUA ua = self._get_ua() if self._tsx != NULL: self._tsx.mod_data[ua._module.id] = NULL if self._tsx.state < PJSIP_TSX_STATE_COMPLETED: pjsip_tsx_terminate(self._tsx, 500) self._tsx = NULL if self._tdata != NULL: pjsip_tx_data_dec_ref(self._tdata) self._tdata = NULL if self._timer_active: pjsip_endpt_cancel_timer(ua._pjsip_endpoint._obj, &self._timer) self._timer_active = 0 def send(self, timeout=None): cdef pj_time_val timeout_pj cdef int status cdef PJSIPUA ua = self._get_ua() if self.state != "INIT": raise SIPCoreError('This method may only be called in the "INIT" state, current state is "%s"' % self.state) if timeout is not None: if timeout <= 0: raise ValueError("Timeout value cannot be negative") timeout_pj.sec = int(timeout) timeout_pj.msec = (timeout * 1000) % 1000 self._timeout = timeout status = pjsip_tsx_send_msg(self._tsx, self._tdata) if status != 0: raise PJSIPError("Could not send request", status) pjsip_tx_data_add_ref(self._tdata) if timeout: status = pjsip_endpt_schedule_timer(ua._pjsip_endpoint._obj, &self._timer, &timeout_pj) if status == 0: self._timer_active = 1 self.state = "IN_PROGRESS" def end(self): cdef PJSIPUA ua = self._get_ua() if self.state == "IN_PROGRESS": pjsip_tsx_terminate(self._tsx, 408) elif self.state == "EXPIRING": pjsip_endpt_cancel_timer(ua._pjsip_endpoint._obj, &self._timer) self._timer_active = 0 self.state = "TERMINATED" _add_event("SIPRequestDidEnd", dict(obj=self)) # private methods cdef PJSIPUA _get_ua(self): cdef PJSIPUA ua try: ua = _get_ua() except SIPCoreError: self._tsx = NULL self._tdata = NULL self._timer_active = 0 self.state = "TERMINATED" return None else: return ua cdef int _cb_tsx_state(self, PJSIPUA ua, pjsip_rx_data *rdata) except -1: cdef pjsip_tx_data *tdata_auth cdef pjsip_transaction *tsx_auth cdef pjsip_cseq_hdr *cseq cdef dict event_dict cdef int expires = -1 cdef SIPURI contact_uri cdef dict contact_params cdef pj_time_val timeout_pj cdef int status if rdata != NULL: self.to_header = FrozenToHeader_create(rdata.msg_info.to_hdr) if self.peer_address is None: self.peer_address = EndpointAddress(rdata.pkt_info.src_name, rdata.pkt_info.src_port) else: self.peer_address.ip = rdata.pkt_info.src_name self.peer_address.port = rdata.pkt_info.src_port if self._tsx.state == PJSIP_TSX_STATE_PROCEEDING: if rdata == NULL: return 0 event_dict = dict(obj=self) _pjsip_msg_to_dict(rdata.msg_info.msg, event_dict) _add_event("SIPRequestGotProvisionalResponse", event_dict) elif self._tsx.state == PJSIP_TSX_STATE_COMPLETED: if self._timer_active: pjsip_endpt_cancel_timer(ua._pjsip_endpoint._obj, &self._timer) self._timer_active = 0 if self._need_auth and self._tsx.status_code in [401, 407]: self._need_auth = 0 status = pjsip_auth_clt_reinit_req(&self._auth, rdata, self._tdata, &tdata_auth) if status != 0: _add_event("SIPRequestDidFail", dict(obj=self, code=0, reason="Could not add auth data to request %s" % _pj_status_to_str(status))) self.state = "TERMINATED" _add_event("SIPRequestDidEnd", dict(obj=self)) return 0 cseq = pjsip_msg_find_hdr(tdata_auth.msg, PJSIP_H_CSEQ, NULL) if cseq != NULL: cseq.cseq += 1 self.cseq = cseq.cseq status = pjsip_tsx_create_uac(&ua._module, tdata_auth, &tsx_auth) if status != 0: pjsip_tx_data_dec_ref(tdata_auth) _add_event("SIPRequestDidFail", dict(obj=self, code=0, reason="Could not create transaction for request with auth %s" % _pj_status_to_str(status))) self.state = "TERMINATED" _add_event("SIPRequestDidEnd", dict(obj=self)) return 0 self._tsx.mod_data[ua._module.id] = NULL self._tsx = tsx_auth self._tsx.mod_data[ua._module.id] = self status = pjsip_tsx_send_msg(self._tsx, tdata_auth) if status != 0: pjsip_tx_data_dec_ref(tdata_auth) _add_event("SIPRequestDidFail", dict(obj=self, code=0, reason="Could not send request with auth %s" % _pj_status_to_str(status))) self.state = "TERMINATED" _add_event("SIPRequestDidEnd", dict(obj=self)) return 0 elif self._timeout is not None: timeout_pj.sec = int(self._timeout) timeout_pj.msec = (self._timeout * 1000) % 1000 status = pjsip_endpt_schedule_timer(ua._pjsip_endpoint._obj, &self._timer, &timeout_pj) if status == 0: self._timer_active = 1 else: event_dict = dict(obj=self) if rdata != NULL: # This shouldn't happen, but safety fist! _pjsip_msg_to_dict(rdata.msg_info.msg, event_dict) if self._tsx.status_code / 100 == 2: if rdata != NULL: if "Expires" in event_dict["headers"]: expires = event_dict["headers"]["Expires"] elif self.contact_header is not None: for contact_header in event_dict["headers"].get("Contact", []): if contact_header.uri == self.contact_header.uri and contact_header.expires is not None: expires = contact_header.expires if expires == -1: expires = 0 for header in self.extra_headers: if header.name == "Expires": try: expires = int(header.body) except ValueError: pass break event_dict["expires"] = expires self._expire_time = datetime.now() + timedelta(seconds=expires) _add_event("SIPRequestDidSucceed", event_dict) else: expires = 0 _add_event("SIPRequestDidFail", event_dict) if expires == 0: self.state = "TERMINATED" _add_event("SIPRequestDidEnd", dict(obj=self)) else: timeout_pj.sec = max(1, expires - self.expire_warning_time, expires/2) timeout_pj.msec = 0 status = pjsip_endpt_schedule_timer(ua._pjsip_endpoint._obj, &self._timer, &timeout_pj) if status == 0: self._timer_active = 1 self.state = "EXPIRING" self._expire_rest = max(1, expires - timeout_pj.sec) else: self.state = "TERMINATED" _add_event("SIPRequestDidEnd", dict(obj=self)) elif self._tsx.state == PJSIP_TSX_STATE_TERMINATED: if self.state == "IN_PROGRESS": if self._timer_active: pjsip_endpt_cancel_timer(ua._pjsip_endpoint._obj, &self._timer) self._timer_active = 0 _add_event("SIPRequestDidFail", dict(obj=self, code=self._tsx.status_code, reason=_pj_str_to_bytes(self._tsx.status_text))) self.state = "TERMINATED" _add_event("SIPRequestDidEnd", dict(obj=self)) self._tsx.mod_data[ua._module.id] = NULL self._tsx = NULL else: pass cdef int _cb_timer(self, PJSIPUA ua) except -1: cdef pj_time_val expires cdef int status if self.state == "IN_PROGRESS": pjsip_tsx_terminate(self._tsx, 408) elif self.state == "EXPIRING": if self._expire_rest > 0: _add_event("SIPRequestWillExpire", dict(obj=self, expires=self._expire_rest)) expires.sec = self._expire_rest expires.msec = 0 self._expire_rest = 0 status = pjsip_endpt_schedule_timer(ua._pjsip_endpoint._obj, &self._timer, &expires) if status == 0: self._timer_active = 1 else: self.state = "TERMINATED" _add_event("SIPRequestDidEnd", dict(obj=self)) else: self.state = "TERMINATED" _add_event("SIPRequestDidEnd", dict(obj=self)) return 0 cdef class IncomingRequest: def __cinit__(self, *args, **kwargs): self.peer_address = None def __dealloc__(self): cdef PJSIPUA ua try: ua = _get_ua() except SIPCoreError: return if self._tsx != NULL: pjsip_tsx_terminate(self._tsx, 500) self._tsx = NULL if self._tdata != NULL: pjsip_tx_data_dec_ref(self._tdata) self._tdata = NULL def answer(self, int code, str reason=None, object extra_headers=None): cdef bytes reason_bytes cdef dict event_dict cdef int status cdef PJSIPUA ua = _get_ua() if self.state != "incoming": raise SIPCoreInvalidStateError('Can only answer an incoming request in the "incoming" state, ' 'object is currently in the "%s" state' % self.state) if code < 200 or code >= 700: raise ValueError("Invalid SIP final response code: %d" % code) self._tdata.msg.line.status.code = code if reason is None: self._tdata.msg.line.status.reason = pjsip_get_status_text(code)[0] else: pj_strdup2_with_null(self._tdata.pool, &self._tdata.msg.line.status.reason, reason.encode()) if extra_headers is not None: _add_headers_to_tdata(self._tdata, extra_headers) event_dict = dict(obj=self) _pjsip_msg_to_dict(self._tdata.msg, event_dict) status = pjsip_tsx_send_msg(self._tsx, self._tdata) if status != 0: raise PJSIPError("Could not send response", status) self.state = "answered" self._tdata = NULL self._tsx = NULL _add_event("SIPIncomingRequestSentResponse", event_dict) cdef int init(self, PJSIPUA ua, pjsip_rx_data *rdata) except -1: cdef dict event_dict cdef int status status = pjsip_endpt_create_response(ua._pjsip_endpoint._obj, rdata, 500, NULL, &self._tdata) if status != 0: raise PJSIPError("Could not create response", status) status = pjsip_tsx_create_uas(&ua._module, rdata, &self._tsx) if status != 0: pjsip_tx_data_dec_ref(self._tdata) self._tdata = NULL raise PJSIPError("Could not create transaction for incoming request", status) pjsip_tsx_recv_msg(self._tsx, rdata) self.state = "incoming" self.peer_address = EndpointAddress(rdata.pkt_info.src_name, rdata.pkt_info.src_port) event_dict = dict(obj=self) _pjsip_msg_to_dict(rdata.msg_info.msg, event_dict) _add_event("SIPIncomingRequestGotRequest", event_dict) # callback functions cdef void _Request_cb_tsx_state(pjsip_transaction *tsx, pjsip_event *event) with gil: cdef PJSIPUA ua cdef void *req_ptr cdef Request req cdef pjsip_rx_data *rdata = NULL try: ua = _get_ua() except: return try: req_ptr = tsx.mod_data[ua._module.id] if req_ptr != NULL: req = req_ptr if event.type == PJSIP_EVENT_RX_MSG: rdata = event.body.rx_msg.rdata elif event.type == PJSIP_EVENT_TSX_STATE and event.body.tsx_state.type == PJSIP_EVENT_RX_MSG: rdata = event.body.tsx_state.src.rdata req._cb_tsx_state(ua, rdata) except: ua._handle_exception(1) cdef void _Request_cb_timer(pj_timer_heap_t *timer_heap, pj_timer_entry *entry) with gil: cdef PJSIPUA ua cdef Request req try: ua = _get_ua() except: return try: if entry.user_data != NULL: req = entry.user_data req._timer_active = 0 req._cb_timer(ua) except: ua._handle_exception(1) diff --git a/sipsimple/core/_core.util.pxi b/sipsimple/core/_core.util.pxi index 91f55df7..fe396d01 100644 --- a/sipsimple/core/_core.util.pxi +++ b/sipsimple/core/_core.util.pxi @@ -1,425 +1,424 @@ import platform import re import sys from application.version import Version cdef class PJSTR: def __cinit__(self, str): self.str = str _str_to_pj_str(str, &self.pj_str) def __str__(self): return self.str cdef class SIPStatusMessages: cdef object _default_status def __cinit__(self, *args, **kwargs): self._default_status = _pj_str_to_str(pjsip_get_status_text(0)[0]) def __getitem__(self, int val): cdef object _status _status = _pj_str_to_str(pjsip_get_status_text(val)[0]) if _status == self._default_status: raise IndexError("Unknown SIP response code: %d" % val) return _status cdef class frozenlist: def __cinit__(self, *args, **kw): self.list = list() self.initialized = 0 self.hash = 0 def __init__(self, *args, **kw): if not self.initialized: self.list = list(*args, **kw) self.initialized = 1 self.hash = hash(tuple(self.list)) def __reduce__(self): return (self.__class__, (self.list,), None) def __repr__(self): return "frozenlist(%r)" % self.list def __len__(self): return self.list.__len__() def __hash__(self): return self.hash def __iter__(self): return self.list.__iter__() def __cmp__(self, frozenlist other): return self.list.__cmp__(other.list) def __richcmp__(frozenlist self, other, op): if isinstance(other, frozenlist): other = (other).list if op == 0: return self.list.__cmp__(other) < 0 elif op == 1: return self.list.__cmp__(other) <= 0 elif op == 2: return self.list.__eq__(other) elif op == 3: return self.list.__ne__(other) elif op == 4: return self.list.__cmp__(other) > 0 elif op == 5: return self.list.__cmp__(other) >= 0 else: return NotImplemented def __contains__(self, item): return self.list.__contains__(item) def __getitem__(self, key): return self.list.__getitem__(key) def __add__(first, second): if isinstance(first, frozenlist): first = (first).list if isinstance(second, frozenlist): second = (second).list return frozenlist(first+second) def __mul__(first, second): if isinstance(first, frozenlist): first = (first).list if isinstance(second, frozenlist): second = (second).list return frozenlist(first*second) def __reversed__(self): return self.list.__reversed__() def count(self, elem): return self.list.count(elem) def index(self, elem): return self.list.index(elem) cdef class frozendict: def __cinit__(self, *args, **kw): self.dict = dict() self.initialized = 0 def __init__(self, *args, **kw): if not self.initialized: self.dict = dict(*args, **kw) self.initialized = 1 self.hash = hash(tuple(self.dict.iteritems())) def __reduce__(self): return (self.__class__, (self.dict,), None) def __repr__(self): return "frozendict(%r)" % self.dict def __len__(self): return self.dict.__len__() def __hash__(self): return self.hash def __iter__(self): return self.dict.__iter__() def __cmp__(self, frozendict other): return self.dict.__cmp__(other.dict) def __richcmp__(frozendict self, other, op): if isinstance(other, frozendict): other = (other).dict if op == 0: return self.dict.__cmp__(other) < 0 elif op == 1: return self.dict.__cmp__(other) <= 0 elif op == 2: return self.dict.__eq__(other) elif op == 3: return self.dict.__ne__(other) elif op == 4: return self.dict.__cmp__(other) > 0 elif op == 5: return self.dict.__cmp__(other) >= 0 else: return NotImplemented def __contains__(self, item): return self.dict.__contains__(item) def __getitem__(self, key): return self.dict.__getitem__(key) def copy(self): return self def get(self, *args): return self.dict.get(*args) def has_key(self, key): return self.dict.has_key(key) def items(self): return list(self.dict.items()) def iteritems(self): return list(self.dict.items()) def iterkeys(self): return list(self.dict.keys()) def itervalues(self): return list(self.dict.values()) def keys(self): return list(self.dict.keys()) def values(self): return list(self.dict.values()) # functions cdef int _str_to_pj_str(object string, pj_str_t *pj_str) except -1: - print('Convert %s (%s)' % (string, type(string))) pj_str.ptr = PyBytes_AsString(string) pj_str.slen = len(string) cdef object _pj_str_to_bytes(pj_str_t pj_str): return PyBytes_FromStringAndSize(pj_str.ptr, pj_str.slen) cdef object _pj_str_to_str(pj_str_t pj_str): return PyBytes_FromStringAndSize(pj_str.ptr, pj_str.slen).decode() cdef object _pj_buf_len_to_str(object buf, int buf_len): return PyBytes_FromStringAndSize(buf, buf_len) cdef object _buf_to_str(object buf): return PyBytes_FromString(buf).decode() cdef object _str_as_str(object string): return PyBytes_AsString(string) cdef object _str_as_size(object string): return PyBytes_Size(string) cdef object _pj_status_to_str(int status): cdef char buf[PJ_ERR_MSG_SIZE] return _pj_str_to_str(pj_strerror(status, buf, PJ_ERR_MSG_SIZE)) cdef object _pj_status_to_def(int status): return _re_pj_status_str_def.match(_pj_status_to_str(status)).group(1) cdef dict _pjsip_param_to_dict(pjsip_param *param_list): cdef pjsip_param *param cdef dict retval = dict() param = ( param_list).next while param != param_list: if param.value.slen == 0: retval[_pj_str_to_str(param.name)] = None else: retval[_pj_str_to_str(param.name)] = _pj_str_to_str(param.value) param = ( param).next return retval cdef int _dict_to_pjsip_param(object params, pjsip_param *param_list, pj_pool_t *pool): cdef pjsip_param *param = NULL for name, value in params.iteritems(): param = pj_pool_alloc(pool, sizeof(pjsip_param)) if param == NULL: return -1 _str_to_pj_str(name, ¶m.name) if value is None: param.value.slen = 0 else: _str_to_pj_str(value, ¶m.value) pj_list_insert_after( param_list, param) return 0 cdef int _pjsip_msg_to_dict(pjsip_msg *msg, dict info_dict) except -1: cdef pjsip_msg_body *body cdef pjsip_hdr *header cdef pjsip_generic_array_hdr *array_header cdef pjsip_ctype_hdr *ctype_header cdef pjsip_cseq_hdr *cseq_header cdef char *buf cdef int buf_len, i, status headers = {} header = ( &msg.hdr).next while header != &msg.hdr: header_name = _pj_str_to_str(header.name) header_data = None multi_header = False if header_name in ("Accept", "Allow", "Require", "Supported", "Unsupported", "Allow-Events"): array_header = header header_data = [] for i from 0 <= i < array_header.count: pass # TODO crash here #header_data.append(_pj_str_to_str(array_header.values[i])) elif header_name == "Contact": multi_header = True header_data = FrozenContactHeader_create( header) elif header_name == "Content-Length": header_data = ( header).len elif header_name == "Content-Type": header_data = FrozenContentTypeHeader_create( header) elif header_name == "CSeq": cseq_header = header hvalue = _pj_str_to_str(cseq_header.method.name) header_data = (cseq_header.cseq, hvalue) elif header_name in ("Expires", "Max-Forwards", "Min-Expires"): header_data = ( header).ivalue elif header_name == "From": header_data = FrozenFromHeader_create( header) elif header_name == "To": header_data = FrozenToHeader_create( header) elif header_name == "Route": multi_header = True header_data = FrozenRouteHeader_create( header) elif header_name == "Reason": value = _pj_str_to_str((header).hvalue) protocol, sep, params_str = value.partition(';') params = frozendict([(name, value or None) for name, sep, value in [param.partition('=') for param in params_str.split(';')]]) header_data = FrozenReasonHeader(protocol, params) elif header_name == "Record-Route": multi_header = True header_data = FrozenRecordRouteHeader_create( header) elif header_name == "Retry-After": header_data = FrozenRetryAfterHeader_create( header) elif header_name == "Via": multi_header = True header_data = FrozenViaHeader_create( header) elif header_name == "Warning": match = _re_warning_hdr.match(_pj_str_to_str((header).hvalue)) if match is not None: warning_params = match.groupdict() warning_params['code'] = int(warning_params['code']) header_data = FrozenWarningHeader(**warning_params) elif header_name == "Event": header_data = FrozenEventHeader_create( header) elif header_name == "Subscription-State": header_data = FrozenSubscriptionStateHeader_create( header) elif header_name == "Refer-To": header_data = FrozenReferToHeader_create( header) elif header_name == "Subject": header_data = FrozenSubjectHeader_create( header) elif header_name == "Replaces": header_data = FrozenReplacesHeader_create( header) # skip the following headers: elif header_name not in ("Authorization", "Proxy-Authenticate", "Proxy-Authorization", "WWW-Authenticate"): hvalue = ( header).hvalue header_value = _pj_str_to_str(hvalue) header_data = FrozenHeader(header_name, header_value) if header_data is not None: if multi_header: headers.setdefault(header_name, []).append(header_data) else: if header_name not in headers: headers[header_name] = header_data header = ( header).next info_dict["headers"] = headers body = msg.body if body == NULL: info_dict["body"] = None else: status = pjsip_print_body(body, &buf, &buf_len) if status != 0: info_dict["body"] = None else: info_dict["body"] = _pj_buf_len_to_str(buf, buf_len).decode() if msg.type == PJSIP_REQUEST_MSG: info_dict["method"] = _pj_str_to_str(msg.line.req.method.name) # You need to call pjsip_uri_get_uri on the request URI if the message is for transmitting, # but it isn't required if message is one received. Otherwise, a seg fault occurs. Don't ask. info_dict["request_uri"] = FrozenSIPURI_create(pjsip_uri_get_uri(msg.line.req.uri)) else: info_dict["code"] = msg.line.status.code info_dict["reason"] = _pj_str_to_str(msg.line.status.reason) return 0 cdef int _is_valid_ip(int af, object ip) except -1: cdef char buf[16] cdef pj_str_t src cdef int status _str_to_pj_str(ip, &src) status = pj_inet_pton(af, &src, buf) if status == 0: return 1 else: return 0 cdef int _get_ip_version(object ip) except -1: if _is_valid_ip(pj_AF_INET(), ip): return pj_AF_INET() elif _is_valid_ip(pj_AF_INET6(), ip): return pj_AF_INET() else: return 0 cdef int _add_headers_to_tdata(pjsip_tx_data *tdata, object headers) except -1: cdef pj_str_t name_pj, value_pj cdef pjsip_hdr *hdr for header in headers: hb = header.name.encode() bb = header.body.encode() _str_to_pj_str(hb, &name_pj) _str_to_pj_str(bb, &value_pj) hdr = pjsip_generic_string_hdr_create(tdata.pool, &name_pj, &value_pj) pjsip_msg_add_hdr(tdata.msg, hdr) cdef int _remove_headers_from_tdata(pjsip_tx_data *tdata, object headers) except -1: cdef pj_str_t header_name_pj cdef pjsip_hdr *hdr for header in headers: _str_to_pj_str(header, &header_name_pj) hdr = pjsip_msg_find_remove_hdr_by_name(tdata.msg, &header_name_pj, NULL) cdef int _BaseRouteHeader_to_pjsip_route_hdr(BaseIdentityHeader header, pjsip_route_hdr *pj_header, pj_pool_t *pool) except -1: cdef pjsip_param *param cdef pjsip_sip_uri *sip_uri pjsip_route_hdr_init(NULL, pj_header) sip_uri = pj_pool_alloc(pool, sizeof(pjsip_sip_uri)) _BaseSIPURI_to_pjsip_sip_uri(header.uri, sip_uri, pool) pj_header.name_addr.uri = sip_uri if header.display_name: _str_to_pj_str(header.display_name, &pj_header.name_addr.display) _dict_to_pjsip_param(header.parameters, &pj_header.other_param, pool) return 0 cdef int _BaseSIPURI_to_pjsip_sip_uri(BaseSIPURI uri, pjsip_sip_uri *pj_uri, pj_pool_t *pool) except -1: cdef pjsip_param *param pjsip_sip_uri_init(pj_uri, uri.secure) if uri.user: _str_to_pj_str(uri.user, &pj_uri.user) if uri.password: _str_to_pj_str(uri.password, &pj_uri.passwd) if uri.host: _str_to_pj_str(uri.host, &pj_uri.host) if uri.port: pj_uri.port = uri.port for name, value in uri.parameters.iteritems(): print('Adding parameter for host %s: %s=%s' % (uri.host, name, value)) if name == "lr": pj_uri.lr_param = 1 elif name == "maddr": _str_to_pj_str(value, &pj_uri.maddr_param) elif name == "method": _str_to_pj_str(value, &pj_uri.method_param) elif name == "transport": _str_to_pj_str(value, &pj_uri.transport_param) elif name == "ttl": pj_uri.ttl_param = int(value) elif name == "user": _str_to_pj_str(value, &pj_uri.user_param) else: param = pj_pool_alloc(pool, sizeof(pjsip_param)) _str_to_pj_str(name, ¶m.name) if value is None: param.value.slen = 0 else: _str_to_pj_str(value, ¶m.value) pj_list_insert_after( &pj_uri.other_param, param) _dict_to_pjsip_param(uri.headers, &pj_uri.header_param, pool) return 0 def _get_device_name_encoding(): if sys.platform == 'win32': encoding = 'mbcs' elif sys.platform.startswith('linux2') and Version.parse(platform.release()) < Version(2,6,31): encoding = 'latin1' else: encoding = 'utf-8' return encoding _device_name_encoding = _get_device_name_encoding() def decode_device_name(device_name): # ignore decoding errors, some systems (I'm looking at you, OSX), seem to misbehave return device_name.decode(_device_name_encoding, 'ignore') # globals cdef object _re_pj_status_str_def = re.compile("^.*\((.*)\)$") cdef object _re_warning_hdr = re.compile('(?P[0-9]{3}) (?P.*?) "(?P.*?)"') sip_status_messages = SIPStatusMessages()