= SIP Accounts = [[TracNav(Python_SIP/TOC)]] [http://www.pjsip.org/python/pjsua.htm#Account Accounts] provide identity (or identities) of the user who is currently using the application. An account has one SIP Uniform Resource Identifier (URI) associated with it. In SIP terms, the identity is used as the From header in outgoing requests. Account may or may not have client registration associated with it. An account is also associated with route set and some authentication credentials, which are used when sending SIP request messages using the account. An account also has presence online status, which will be reported to remote peer when they subscribe to the account's presence, or which is published to a presence server if presence publication is enabled for the account. At least one account MUST be created in the application, since any outgoing requests require an account context. If no user association is required, application can create a user-less account by calling {{{lib.create_account_for_transport()}}}. A userless account identifies local endpoint instead of a particular user, and it corresponds to a particular transport instance. Also one account must be set as the default account, which will be used as the account identity when pjsua fails to match the request with any accounts using the stricter matching rules. == Creating Userless Accounts == A ''user-less'' account is an account without user ID (duh!). It identifies a particular SIP endpoint rather than a particular user. Some other SIP softphones may call this peer-to-peer mode, which means that we are calling another computer via its address rather than calling a particular user ID. So for example, we might identify ourself as ''"sip:192.168.0.15"'' (a user-less account) rather than ''"sip:user@pjsip.org"'' (an account). In pjsua, a user-less account may be created for each particular transport instance. Creating user-less account is very simple, all we need is the transport instance which is returned by {{{lib.create_transport()}}} method as explained in previous chapter. Here's a snippet: {{{ #!python acc_cb = MyAccountCallback() acc = lib.create_account_for_transport(udp, cb=acc_cb) }}} The account callback will be explained later. Basically it is used to capture events emitted by the account, such as incoming call events. Once the account is created, you can use the instance as a normal account. More will be explained later. Accounts created this way will have its URI derived from the transport address. For example, if the transport address is "192.168.0.15:5080", then the account's URI for UDP transport will be "sip:192.168.0.15:5080", or "sip:192.168.0.15:5080;transport=tcp" for TCP transport. == Creating Account == For the "normal" account, we need to configure [http://www.pjsip.org/python/pjsua.htm#AccountConfig AccountConfig] and call {{{lib.create_account()}}} to create the account. At the very minimum, pjsua only requires the account's ID, which is an URI to identify the account (or in SIP terms, it's called Address of Record/AOR). Here's a snippet: {{{ #!python try: acc_cfg = pjsua.AccountConfig() acc_cfg.id = "sip:user@pjsip.org" acc_cb = MyAccountCallback() acc = lib.create_account(acc_cfg, cb=acc_cb) except pjsua.Error, err: print 'Error creating account:', err }}} Again the account callback will be explained later. The account created above doesn't do anything except to provide identity in the {{{From:}}} header for outgoing requests. The account will not register to SIP server or anything. Typically you will want the account to authenticate and register to your SIP server so that you can receive incoming calls. To do that you will need to configure some more settings in your [http://www.pjsip.org/python/pjsua.htm#AccountConfig AccountConfig], something like this: {{{ #!python try: acc_cfg = pjsua.AccountConfig() acc_cfg.id = "sip:someuser@pjsip.org" acc_cfg.reg_uri = "sip:pjsip.org" acc_cfg.proxy = [ "sip:pjsip.org;lr" ] acc_cfg.auth_cred = [ AuthCred("*", "someuser", "secretpass") ] acc_cb = MyAccountCallback() acc = lib.create_account(acc_cfg, cb=acc_cb) except pjsua.Error, err: print 'Error creating account:', err }}} Or alternatively, for typical account settings like above, you can build the account config like this: {{{ #!python acc_cfg = pjsua.AccountConfig("pjsip.org", "someuser", "secretpass") }}} == More on Account Settings == There are many more settings that can be specified in [http://www.pjsip.org/python/pjsua.htm#AccountConfig AccountConfig], like: * whether reliable provisional response (SIP 100rel) is required * whether presence publication (PUBLISH) is enabled * Secure RTP (SRTP) related settings * etc. Please see [http://www.pjsip.org/python/pjsua.htm#AccountConfig AccountConfig] reference documentation for more info. == Account Operations == Some of the operations to the [http://www.pjsip.org/python/pjsua.htm#Account Account] object: * make outgoing calls * add buddy objects * set account's presence status * stop/start SIP registration Please see the reference documentation for Account (link above) for more info. Calls, presence, and buddy list will be explained in later chapters. == Account Callbacks == Account object emits events, such as: * the status of SIP registration * incoming calls * incoming presence subscription requests * incoming instant message not from buddy These events will be reported to [http://www.pjsip.org/python/pjsua.htm#AccountCallback AccountCallback] instance that is registered to the account object. Application MUST install a class derived from [http://www.pjsip.org/python/pjsua.htm#AccountCallback AccountCallback] class if it wants to handle these events. If these events are not handled, default actions will be invoked: * incoming calls will be rejected * incoming presence subscription requests will be accepted * incoming instant messages from non-buddy will be ignored === Creating Custom Callback Class === To create a custom callback class to handle the events, derive a class from [http://www.pjsip.org/python/pjsua.htm#AccountCallback AccountCallback] and override the relevant class method to handle the particular events. For example: {{{ #!python class MyAccountCallback(pjsua.AccountCallback): def __init__(self, account=None): pjsua.AccountCallback.__init__(self, account) def on_incoming_call(self, call): call.hangup(501, "Sorry, not ready to accept calls yet") def on_reg_state(self): print "Registration complete, status=", self.account.info().reg_status, \ "(" + self.account.info().reg_reason + ")" }}} In the account callback, you can refer the [http://www.pjsip.org/python/pjsua.htm#Account Account] instance of this callback with '''self.account'''. === Installing Your Callback to Account Object === Once you've created the custom callback class, you can install the callback by specifying your callback instance when creating the account, like the previous examples. Here they are again: {{{ #!python my_cb = MyAccountCallback() acc = lib.create_account_for_transport(udp, cb=my_cb) }}} or {{{ #!python acc_cfg = pjsua.AccountConfig("pjsip.org", "someuser", "secretpass") my_cb = MyAccountCallback() acc = lib.create_account(acc_cfg, cb=my_cb) }}} ''(Note: we omit error handling for brevity)'' That is the preferred way to install the callback, i.e. to specify the callback instance when creating the account. However, if for some reason you cannot do this, you may install the callback later using Account's [[http://www.pjsip.org/python/pjsua.htm#Account-set_callback set_callback()] method. You SHOULD, however, protect the code fragment with library lock to avoid loosing events. A sample code to do this: {{{ #!python # Create account without callback. Protect the fragment with the # library lock below. lck = lib.auto_lock() acc_cfg = pjsua.AccountConfig("pjsip.org", "someuser", "secretpass") acc = lib.create_account(acc_cfg) # Do something else ... # Create and install the callback my_cb = MyAccountCallback() acc.set_callback(my_cb) # Release library lock del lck }}} Without the library lock like above, it is possible that some events may be delivered to the account while the callback has not been installed yet, thus we're loosing the events. The lock will prevent that from happening (in this case), '''however''', please bear in mind that while you're holding the library lock, the worker thread can't run, so incoming SIP messages will be queued in socket buffer. So please use the library lock wisely. [[TracNav(Python_SIP/TOC)]]