The problem was in this line
self.session.connect(self.callee, self.routes, [AudioStream(account)])
AudioStream() takes no arguments, so it should be modified to the following
self.session.connect(self.callee, self.routes, [AudioStream()])
Question
I'm using SIPSimpleClient SDK to build a simple script that can create a SIP session with some other SIP user. I started by copying and pasting the Hello World example here to a python script and executing it. I get the following error
Placing call to sip:3333@sip2sip.info, press Enter to quit the program
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/twisted/internet/base.py", line 824, in runUntilCurrent
call.func(*call.args, **call.kw)
File "/usr/lib/python2.7/dist-packages/eventlib/coros.py", line 197, in _do_send
waiter.switch(result)
File "/usr/lib/python2.7/dist-packages/eventlib/api.py", line 235, in _spawn_startup
return cb(*args, **kw)
File "helloworldoriginal.py", line 38, in _NH_SIPApplicationDidStart
self.session.connect(self.callee, routes, [AudioStream(account)])
TypeError: __init__() takes exactly 1 argument (2 given)
After giving up on that script, I built my own script from scratch based on the Hello World example and using the documentation provided here. First, a TestClass object is created (a child class of the SIPApplication class). The init method in the TestClass calls self.start(FileStorage('config')) at which point a SIPApplicationDidStart messgae triggers my _NH_SIPApplicationDidStart method. All good so far, and the lines in this method all work as expected. When the DNSLookup of the callee is successful, it sends a DNSLookupDidSucceed message, which triggers the _NH_DNSLookupDidSucceed method. Whithin this method, I create a new Session object(self.session = Session(account)) which seems to work fine (I can print attributes of this object at this time). The problem seems to be in the self.session.connect(self.callee, self.routes, [AudioStream(account)]) line. This is where I get the same error as in the Hello World example. You can see this connect method and its parameters on page 61 of the documentation.
************ START ************
SIP Application Did Start
SIP URI parse of callee OK
DNS Lookup Did Succeed
Will Call sip:kulzer@sip2sip.info
Session Initiated
Session State: None
Session account: Account('xxxxxx')
Session Direction: None
Session Start Time: None
error: Exception occured in observer <__main__.TestClass object at 0x35329d0> while handling notification 'DNSLookupDidSucceed'
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/application/notification.py", line 216, in post_notification
observer.handle_notification(notification)
File "<string>", line 1, in handle_notification
File "/usr/lib/python2.7/dist-packages/sipsimple/threading/__init__.py", line 100, in wrapper
func(*args, **kwargs)
File "/usr/lib/python2.7/dist-packages/sipsimple/application.py", line 277, in handle_notification
handler(notification)
File "testcall.py", line 84, in _NH_DNSLookupDidSucceed
self.session.connect(self.callee, self.routes, [AudioStream(account)])
TypeError: __init__() takes exactly 1 argument (2 given)
DNS Lookup Did Succeed
Will Call sip:kulzer@sip2sip.info
Session Initiated
Session State: None
Session account: Account('xxxxxx')
Session Direction: None
Session Start Time: None
error: Exception occured in observer <__main__.TestClass object at 0x35329d0> while handling notification 'DNSLookupDidSucceed'
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/application/notification.py", line 216, in post_notification
observer.handle_notification(notification)
File "<string>", line 1, in handle_notification
File "/usr/lib/python2.7/dist-packages/sipsimple/threading/__init__.py", line 100, in wrapper
func(*args, **kwargs)
File "/usr/lib/python2.7/dist-packages/sipsimple/application.py", line 277, in handle_notification
handler(notification)
File "testcall.py", line 84, in _NH_DNSLookupDidSucceed
self.session.connect(self.callee, self.routes, [AudioStream(account)])
TypeError: __init__() takes exactly 1 argument (2 given)
Press "Enter" to exit.
I just put Xs where the program output my account name. I just don't understand what is going on here. Does anybody know why they would post an example program that throws errors? Or is this just a problem on my end? Bonus points if you can tell me what the @run_in_green_thread line is used for or why it sends the DNSLookupDidSucceed message twice. BTW, I'm using Ubuntu Trusty Tahr Server through SSH. I'm doing this for a company so they set up the environment. I assume all of the dependencies are installed correctly, since I can use the sipclients from the command line (such as sip-message and sip-audio-session). I've also looked through the code of those sipclients (not all of them) and they seem to use the same session.connect() method without this problem. There seems to be little help for this SDK outside of the official documentation. Thanks in advance, and here is the code for my script.
#!/usr/bin/env python
import sys
import time
from sipsimple.application import SIPApplication
from sipsimple.storage import FileStorage
from sipsimple.session import Session
from application.notification import NotificationCenter
from sipsimple.account import AccountManager
from sipsimple.lookup import DNSLookup, DNSLookupError
from sipsimple.core import SIPURI, ToHeader, SIPCoreError
from sipsimple.streams import AudioStream
from sipsimple.threading.green import run_in_green_thread
callee = "sip:kulzer@sip2sip.info"
#callee = "sip:3333@sip2sip.info"
class TestClass(SIPApplication):
def __init__(self):
SIPApplication.__init__(self)
self.session = None
self.callee = callee
self.routes = None
self.start(FileStorage('config'))
#make sure our methods are called when a notification is sent
notification_center = NotificationCenter()
notification_center.add_observer(self)
#not sure what this does. I get the same error whether it's here or not
@run_in_green_thread
#After the self.start(FileStorage('storage')) line is executed in __init__,
#a SIPApplicationDidStart message is sent, which invokes this method.
def _NH_SIPApplicationDidStart(self, notification):
print 'SIP Application Did Start'
try:#this line somehow puts the address into a usable format
self.callee = ToHeader(SIPURI.parse(self.callee))
print 'SIP URI parse of callee OK'
except Exception as e:
print 'ERROR1: %s' % e
self.stop()
try:#This line looks up the callee in the proxy
self.routes = DNSLookup().lookup_sip_proxy(self.callee.uri, ['udp']).wait()
except Exception as e:
print 'ERROR2: %s' %e
#Once a session is successfuly created, a SIPSessionDidStart message is
#sent which invokes this method
def _NH_SIPSessionDidStart(self, notification):
print 'SIP Session Did Start'
def _NH_SIPSessionDidFail(self, notification):
print 'SIP Session Did Fail'
def _NH_SIPSessionGotRingIndication(self, notification):
print 'SIP Session Got Ring Indication'
def _NH_SIPSessionWillStart(self, notification):
print 'SIP Session Will Start'
def _NH_DNSLookupDidSucceed(self, notification):
print 'DNS Lookup Did Succeed\nWill Call %s' %self.callee.uri
account = AccountManager().default_account
#These lines begin the creation of a session within the SIPApplication
self.session = Session(account)
print 'Session Initiated'
print 'Session State: %s' %self.session.state
print 'Session account: %s' %self.session.account
print 'Session Direction: %s' %self.session.direction
print 'Session Start Time: %s' %self.session.start_time
#THIS SEEMS TO BE THE PROBLEM LINE
self.session.connect(self.callee, self.routes, [AudioStream(account)])
def main():
print '\n************ START ************'
application = TestClass()
time.sleep(3)
print ('Press "Enter" to exit.')
raw_input()
application.stop()
print '************* END *************\n'
if __name__ == '__main__':
main()
Solution
The problem was in this line
self.session.connect(self.callee, self.routes, [AudioStream(account)])
AudioStream() takes no arguments, so it should be modified to the following
self.session.connect(self.callee, self.routes, [AudioStream()])