From anthony at interlink.com.au Sun Jan 9 13:08:23 2005 From: anthony at interlink.com.au (Anthony Baxter) Date: Sun, 9 Jan 2005 23:08:23 +1100 Subject: [Shtoom] UPnP, improved STUN support are checked in Message-ID: <200501092308.25070.anthony@interlink.com.au> I've just checked in support for UPnP and new STUN code, from the improved-stun branch. This should make things much, much better than they were before. Note that as part of this, the minimum required version of Twisted is now 1.3. This also requires the 'zope.interface' package, available from http://zope.org/Products/ZopeInterface Anthony -- Anthony Baxter It's never too late to have a happy childhood. From anthony at interlink.com.au Sun Jan 9 13:11:04 2005 From: anthony at interlink.com.au (Anthony Baxter) Date: Sun, 9 Jan 2005 23:11:04 +1100 Subject: [Shtoom] Re: UPnP, improved STUN support are checked in In-Reply-To: <200501092308.25070.anthony@interlink.com.au> References: <200501092308.25070.anthony@interlink.com.au> Message-ID: <200501092311.05139.anthony@interlink.com.au> On Sunday 09 January 2005 23:08, Anthony Baxter wrote: > I've just checked in support for UPnP and new STUN code, > from the improved-stun branch. This should make things much, > much better than they were before. I forgot to add - there's a new 'shtoominfo.py' script in the scripts directory. This should output a bunch of useful information. Please include it's output in any bug reports. Anthony -- Anthony Baxter It's never too late to have a happy childhood. From anthony at interlink.com.au Wed Jan 12 12:50:55 2005 From: anthony at interlink.com.au (Anthony Baxter) Date: Wed, 12 Jan 2005 22:50:55 +1100 Subject: [Shtoom] Re: [Divmod-dev] integrating Shtoom In-Reply-To: References: Message-ID: <200501122250.57734.anthony@interlink.com.au> [followups should probably go to the shtoom at python.org list] On Monday 10 January 2005 21:04, Eric Ries wrote: > Hey there, > > I'm the author of a program called IMVU, which is an IM add-on for > existing IM services. It's pretty fun, you can read about it here: > www.imvu.com > > IMVU is written in Python/C++ and I thought it might be interesting to > try embedding Shtoom as part of it. Sure - one of the goals of shtoom is that is should be possible to embed it in other applications. What sort of things did you have in mind? Anthony -- Anthony Baxter It's never too late to have a happy childhood. From anthony at interlink.com.au Wed Jan 12 17:31:42 2005 From: anthony at interlink.com.au (Anthony Baxter) Date: Thu, 13 Jan 2005 03:31:42 +1100 Subject: [Shtoom] CocoaShtoom snapshots now available Message-ID: <200501130331.42768.anthony@interlink.com.au> Thanks to the heroic efforts of a cast of thousands [1] there's now a CocoaShtoom application available. It's very much a snapshot/work-in-progress thing, but it seems to work for me. If you want to try it out and let me know if it works/doesn't work for you, that'd be great! They're available from http://www.interlink.com.au/anthony/tech/shtoom/ This really is a first cut - it's quite possible that while it works for me, it will utterly fail for you in very bad ways. Nonetheless, if you want to try it out, that'd be great! It's built with GSM and ulaw audio - I'll look at getting the Speex stuff built at some point. If you have a Mac (OSX 10.3 required) and want to try it out, please do so and let us know how it works for you (either on this list, or to #shtoom on irc.freenode.net). You can try calling sip:613 at fwd.pulver.com for a simple echo-test. And yes, windows executables are the next cab off the rank. Anthony [1] well, ok - Bob and Donovan did the heavy lifting, and a magnificent job of it they did, too. -- Anthony Baxter It's never too late to have a happy childhood. From eric.ries at aya.yale.edu Wed Jan 12 20:48:52 2005 From: eric.ries at aya.yale.edu (Eric Ries) Date: Wed, 12 Jan 2005 11:48:52 -0800 Subject: [Shtoom] Re: [Divmod-dev] integrating Shtoom In-Reply-To: <200501122250.57734.anthony@interlink.com.au> References: <200501122250.57734.anthony@interlink.com.au> Message-ID: IMVU is an IM add-on that provides an immersive 3D environment for chat. Several of our users have suggested adding voice-chat capabilities, which I think is a cool idea. So I've been looking around for something that'd be interesting to embed. I thought it might be an opportunity to bring Shtoom to a pretty big audience. We often hire contributors who work on open source projects as contractors to help us. Naturally, we ask that any improvements they make to the project be contributed back under a free software license. If you're interested, please let me know. Eric On Jan 12, 2005, at 3:50 AM, Anthony Baxter wrote: > [followups should probably go to the shtoom at python.org list] > > On Monday 10 January 2005 21:04, Eric Ries wrote: >> Hey there, >> >> I'm the author of a program called IMVU, which is an IM add-on for >> existing IM services. It's pretty fun, you can read about it here: >> www.imvu.com >> >> IMVU is written in Python/C++ and I thought it might be interesting to >> try embedding Shtoom as part of it. > > Sure - one of the goals of shtoom is that is should be possible to > embed > it in other applications. What sort of things did you have in mind? > > Anthony > -- > Anthony Baxter > It's never too late to have a happy childhood. > From zooko at zooko.com Wed Jan 19 21:49:44 2005 From: zooko at zooko.com (Zooko O'Whielacronx) Date: 19 Jan 2005 16:49:44 -0400 Subject: [Shtoom] bug report: Shtoom doesn't register on startup Message-ID: Current SVN head doesn't register with a SIP server on startup. Here is a complete log of Shtoom starting and not registering. Regards, Zooko 2005/01/19 16:45 AST [-] Log opened. 2005-01-19 16:45:32.001 Shtoom[7619] ShtoomAudioMonitor setDelegate 2005-01-19 16:45:32.057 Shtoom[7619] ShtoomAudioMonitor awakeFromNib 2005-01-19 16:45:32.058 Shtoom[7619] ShtoomAudioMonitor setSampleRate 2005-01-19 16:45:32.435 Shtoom[7619] MTAudioDeviceBrowser:selectedDeviceDidChange: 2005-01-19 16:45:32.436 Shtoom[7619] setDeviceOpen: 2005-01-19 16:45:32.436 Shtoom[7619] Stopping devices. 2005-01-19 16:45:32.442 Shtoom[7619] MTAudioDeviceBrowser:selectedDeviceDidChange: 2005-01-19 16:45:32.443 Shtoom[7619] setDeviceOpen: 2005-01-19 16:45:32.443 Shtoom[7619] Stopping devices. 2005-01-19 16:45:32.444 Shtoom[7619] setDeviceOpen: 2005-01-19 16:45:32.444 Shtoom[7619] Stopping devices. 2005-01-19 16:45:32.598 Shtoom[7619] Application did finish launching. 2005-01-19 16:45:32.600 Shtoom[7619] Audio Monitor = 2005/01/19 16:45 AST [-] starting on 5066 2005/01/19 16:45 AST [-] Starting protocol 2005/01/19 16:45 AST [-] /Users/zooko/playground/shtoom/svnworld/trunk/CocoaShtoom/dist/ Shtoom.app/Contents/Resources/Python/site-packages/shtoom/app/base.py: 54: exceptions.DeprecationWarning: IPv4Address.__getitem__ is deprecated. Use attributes instead. 2005/01/19 16:45 AST [app] sip listener installed on 5066 2005/01/19 16:45 AST [-] starting on 1900 2005/01/19 16:45 AST [-] Starting protocol 2005/01/19 16:45 AST [-] starting on 0 2005/01/19 16:45 AST [-] Starting protocol 2005/01/19 16:45 AST [-] /Users/zooko/playground/shtoom/svnworld/trunk/CocoaShtoom/dist/ Shtoom.app/Contents/Resources/Python/site-packages/nevow/static.py:25: exceptions.DeprecationWarning: twisted.protocols.http is DEPRECATED. See http://twistedmatrix.com/projects/web. 2005/01/19 16:45 AST [-] NamedAnyError: Name twisted.web.woven.guard.GuardSession not found. 2005/01/19 16:45 AST [-] NamedAnyError: Name twisted.web.woven.guard.GuardSession not found. 2005/01/19 16:45 AST [-] nevow.appserver.NevowSite starting on 0 2005/01/19 16:45 AST [-] Starting factory 2005-01-19 16:45:34.058 Shtoom[7619] Preferences server listening on port 53237. 2005/01/19 16:45 AST [sip] no outstanding registrations, registering 2005/01/19 16:45 AST [-] /Users/zooko/playground/shtoom/svnworld/trunk/CocoaShtoom/dist/ Shtoom.app/Contents/Resources/Python/site-packages/shtoom/sip.py:294: exceptions.DeprecationWarning: use listenUDP and then transport.connect(). 2005/01/19 16:45 AST [-] twisted.internet.protocol.ConnectedDatagramProtocol starting on 0 2005/01/19 16:45 AST [-] Starting protocol 2005/01/19 16:45 AST [-] /Users/zooko/playground/shtoom/svnworld/trunk/CocoaShtoom/dist/ Shtoom.app/Contents/Resources/Python/site-packages/shtoom/sip.py:299: exceptions.DeprecationWarning: IPv4Address.__getitem__ is deprecated. Use attributes instead. 2005/01/19 16:45 AST [-] /Users/zooko/playground/shtoom/svnworld/trunk/CocoaShtoom/dist/ Shtoom.app/Contents/Resources/Python/site-packages/shtoom/sip.py:300: exceptions.DeprecationWarning: IPv4Address.__getitem__ is deprecated. Use attributes instead. 2005/01/19 16:45 AST [sip] discovered local address ('192.168.1.110', 5066), remote ('divmod.com', 5060) 2005/01/19 16:45 AST [sip] NAT policy says yes, we're transitting a NAT 2005/01/19 16:45 AST [-] twisted.internet.protocol.ConnectedDatagramProtocol starting on 0 2005/01/19 16:45 AST [-] Starting protocol 2005/01/19 16:45 AST [-] (Port 0 Closed) 2005/01/19 16:45 AST [-] Stopping protocol 2005/01/19 16:45 AST [stun] got STUN response from ('64.69.76.23', 3478) 2005/01/19 16:45 AST [-] (Port 0 Closed) 2005/01/19 16:45 AST [-] Stopping protocol 2005/01/19 16:45 AST [UPnP] got a response from ('192.168.1.1', 1900), status 200 2005/01/19 16:45 AST [UPnP] got a response from ('192.168.1.1', 1900), status 200 2005/01/19 16:45 AST [UPnP] got a response from ('192.168.1.1', 1900), status 200 2005/01/19 16:45 AST [UPnP] you're behind a Linksys Inc. 2005/01/19 16:45 AST [UPnP] 'upnp response has no urlbase?!?' 2005/01/19 16:45 AST [UPnP] you're behind a Linksys Inc. 2005/01/19 16:45 AST [UPnP] 'upnp response has no urlbase?!?' 2005/01/19 16:45 AST [UPnP] you're behind a Linksys Inc. 2005/01/19 16:45 AST [UPnP] 'upnp response has no urlbase?!?' 2005/01/19 16:45 AST [stun] got STUN response from ('64.69.76.24', 3478) 2005/01/19 16:45 AST [-] (Port 0 Closed) 2005/01/19 16:45 AST [-] Stopping protocol From zooko at zooko.com Wed Jan 19 21:58:57 2005 From: zooko at zooko.com (Zooko O'Whielacronx) Date: 19 Jan 2005 16:58:57 -0400 Subject: [Shtoom] bug report followup: it works when not behind NAT Message-ID: I plugged into the Real Internet and tried again, and it registered. Here is the current shtoominfo when plugged into the Real Internet. HACK draco:~/playground/shtoom/svnworld/trunk$ ./shtoom/scripts/shtoominfo.py Shtoom, version 0.3alpha0 Using python version 2.3.0 Using twisted version SVN-trunk Running on Darwin Power Macintosh 7.7.0 Available audio interfaces: fileaudio Available codecs: mulaw Local IP address: 24.215.68.128 No UPnP-capable device discovered STUN says NAT type: FullCone And the mapper we'd use is: Here is the log: 2005/01/19 16:55 AST [-] Log opened. 2005-01-19 16:55:35.890 Shtoom[7752] ShtoomAudioMonitor setDelegate 2005-01-19 16:55:35.989 Shtoom[7752] ShtoomAudioMonitor awakeFromNib 2005-01-19 16:55:35.990 Shtoom[7752] ShtoomAudioMonitor setSampleRate 2005-01-19 16:55:36.136 Shtoom[7752] MTAudioDeviceBrowser:selectedDeviceDidChange: 2005-01-19 16:55:36.136 Shtoom[7752] setDeviceOpen: 2005-01-19 16:55:36.137 Shtoom[7752] Stopping devices. 2005-01-19 16:55:36.143 Shtoom[7752] MTAudioDeviceBrowser:selectedDeviceDidChange: 2005-01-19 16:55:36.143 Shtoom[7752] setDeviceOpen: 2005-01-19 16:55:36.143 Shtoom[7752] Stopping devices. 2005-01-19 16:55:36.144 Shtoom[7752] setDeviceOpen: 2005-01-19 16:55:36.144 Shtoom[7752] Stopping devices. 2005-01-19 16:55:36.371 Shtoom[7752] Application did finish launching. 2005-01-19 16:55:36.373 Shtoom[7752] Audio Monitor = 2005/01/19 16:55 AST [-] Zfone devel revision zfone v365, platform: Darwin-7.7.0-Power_Macintosh-powerpc-32bit 2005/01/19 16:55 AST [-] starting on 5066 2005/01/19 16:55 AST [-] Starting protocol 2005/01/19 16:55 AST [app] sip listener installed on 5066 2005/01/19 16:55 AST [-] starting on 1900 2005/01/19 16:55 AST [-] Starting protocol 2005/01/19 16:55 AST [-] starting on 0 2005/01/19 16:55 AST [-] Starting protocol 2005/01/19 16:55 AST [-] NamedAnyError: Name twisted.web.woven.guard.GuardSession not found. 2005/01/19 16:55 AST [-] NamedAnyError: Name twisted.web.woven.guard.GuardSession not found. 2005/01/19 16:55 AST [-] nevow.appserver.NevowSite starting on 0 2005/01/19 16:55 AST [-] Starting factory 2005-01-19 16:55:38.798 Shtoom[7752] Preferences server listening on port 53419. 2005/01/19 16:55 AST [sip] no outstanding registrations, registering 2005/01/19 16:55 AST [-] twisted.internet.protocol.ConnectedDatagramProtocol starting on 0 2005/01/19 16:55 AST [-] Starting protocol 2005/01/19 16:55 AST [sip] discovered local address ('24.215.68.128', 5066), remote ('divmod.com', 5060) 2005/01/19 16:55 AST [-] Debug: register sent REGISTER sip:divmod.com:5060 SIP/2.0 Via: SIP/2.0/UDP 24.215.68.128:5066;rport CSeq: 2697 REGISTER To: sip:zooko at divmod.com:5060 From: sip:zooko at divmod.com:5060 Expires: 900 Call-ID: 400993727 at 24.215.68.128 User-Agent: Shtoom/0.3alpha0 Contact: Content-Length: 0 2005/01/19 16:55 AST [-] twisted.internet.protocol.ConnectedDatagramProtocol starting on 0 2005/01/19 16:55 AST [-] Starting protocol 2005/01/19 16:55 AST [-] (Port 0 Closed) 2005/01/19 16:55 AST [-] Stopping protocol 2005/01/19 16:55 AST [UPnP] UPnP discovery timed out 2005/01/19 16:55 AST [UPnP] no UPnP found! 2005/01/19 16:55 AST [-] (Port 0 Closed) 2005/01/19 16:55 AST [-] Stopping protocol 2005/01/19 16:55 AST [stun] got STUN response from ('69.90.168.14', 3478) 2005/01/19 16:55 AST [-] Debug: Got a SIP packet from 198.49.126.192:5060 2005/01/19 16:55 AST [-] Debug: SIP PACKET SIP/2.0 401 Unauthorized Via: SIP/2.0/UDP 24.215.68.128:5066;received=24.215.68.128;rport=5066 To: sip:zooko at divmod.com:5060 From: sip:zooko at divmod.com:5060 Call-ID: 400993727 at 24.215.68.128 CSeq: 2697 REGISTER WWW-Authenticate: Digest nonce="10345170551339095801663502492",opaque="657028545",qop="auth",algo rithm="MD5",realm="divmod.com" 2005/01/19 16:55 AST [-] Debug: got SIP response 401: Unauthorized 2005/01/19 16:55 AST [-] Debug: got SIP response SIP/2.0 401 Unauthorized Via: SIP/2.0/UDP 24.215.68.128:5066;received=24.215.68.128;rport=5066 To: sip:zooko at divmod.com:5060 From: sip:zooko at divmod.com:5060 Call-ID: 400993727 at 24.215.68.128 CSeq: 2697 REGISTER WWW-Authenticate: Digest nonce="10345170551339095801663502492",opaque="657028545",qop="auth",algo rithm="MD5",realm="divmod.com" 2005/01/19 16:55 AST [-] Debug: register sent REGISTER sip:divmod.com:5060 SIP/2.0 Via: SIP/2.0/UDP 24.215.68.128:5066;rport CSeq: 2698 REGISTER To: sip:zooko at divmod.com:5060 From: sip:zooko at divmod.com:5060 Expires: 900 Call-ID: 400993727 at 24.215.68.128 Authorization: Digest username="zooko", realm="divmod.com", nonce="10345170551339095801663502492", uri="sip:divmod.com:5060", response="01acfb74354433ff7b7a2efd6a0d47f2", opaque="657028545", qop=auth, nc=00000001, cnonce="ed00" User-Agent: Shtoom/0.3alpha0 Contact: Content-Length: 0 2005/01/19 16:55 AST [stun] got STUN response from ('69.90.168.13', 3479) 2005/01/19 16:55 AST [nat] detectNAT got [(True, None), (True, )] 2005/01/19 16:55 AST [nat] using STUN mapper 2005/01/19 16:55 AST [-] starting on 0 2005/01/19 16:55 AST [-] Starting protocol 2005/01/19 16:55 AST [-] (Port 0 Closed) 2005/01/19 16:55 AST [-] Stopping protocol 2005/01/19 16:55 AST [-] twisted.internet.protocol.ConnectedDatagramProtocol starting on 0 2005/01/19 16:55 AST [-] Starting protocol 2005/01/19 16:55 AST [stun] got STUN response from ('69.90.168.14', 3478) 2005/01/19 16:55 AST [-] (Port 0 Closed) 2005/01/19 16:55 AST [-] Stopping protocol 2005/01/19 16:55 AST [-] Debug: Got a SIP packet from 198.49.126.192:5060 2005/01/19 16:55 AST [-] Debug: SIP PACKET SIP/2.0 200 OK Via: SIP/2.0/UDP 24.215.68.128:5066;received=24.215.68.128;rport=5066 To: sip:zooko at divmod.com:5060 From: sip:zooko at divmod.com:5060 Call-ID: 400993727 at 24.215.68.128 CSeq: 2698 REGISTER Contact: sip:zooko at 24.215.68.128:5066 Expires: 900 Content-length: 0 2005/01/19 16:55 AST [-] Debug: got SIP response 200: OK 2005/01/19 16:55 AST [-] Debug: got SIP response SIP/2.0 200 OK Via: SIP/2.0/UDP 24.215.68.128:5066;received=24.215.68.128;rport=5066 To: sip:zooko at divmod.com:5060 From: sip:zooko at divmod.com:5060 Call-ID: 400993727 at 24.215.68.128 CSeq: 2698 REGISTER Contact: sip:zooko at 24.215.68.128:5066 Expires: 900 Content-Length: 0 2005/01/19 16:55 AST [stun] got STUN response from ('69.90.168.13', 3479) 2005/01/19 16:55 AST [-] (Port 0 Closed) 2005/01/19 16:55 AST [-] Stopping protocol 2005/01/19 16:55 AST [stun] got STUN response from ('69.90.168.14', 3478) 2005/01/19 16:55 AST [sip] late stun packet, ignoring 2005/01/19 16:55 AST [sip] late stun packet, ignoring 2005/01/19 16:55 AST [-] Annnnd we're dying 2005/01/19 16:55 AST [-] stopping SIP, and unmapping it (True) 2005/01/19 16:55 AST [-] unmapping sip () 2005/01/19 16:55 AST [nevow.appserver.NevowSite] (Port 0 Closed) 2005/01/19 16:55 AST [nevow.appserver.NevowSite] Stopping factory 2005/01/19 16:55 AST [shtoom.upnp.UPnPProtocol (UDP)] (Port 1900 Closed) 2005/01/19 16:55 AST [shtoom.upnp.UPnPProtocol (UDP)] Stopping protocol From zooko at zooko.com Wed Jan 19 22:03:29 2005 From: zooko at zooko.com (Zooko O'Whielacronx) Date: 19 Jan 2005 17:03:29 -0400 Subject: [Shtoom] followup: shtoominfo from NAT Message-ID: <919A363C-6A5D-11D9-B175-000A95E2A184@zooko.com> Here is the result of shtoominfo,py when behind my Linksys wrt54g NAT. Note the time to complete. The Linksys has firmware revision 3.01.3. Earlier firmwares in this box reached into SIP packets and mangled the RTP port number -- it added 2 to the media port number. Err.. Actually shtoominfo.py is taking too long to complete so I'm going to send this mail without it. The progress so far is: HACK draco:~/playground/shtoom/svnworld/trunk$ time ./shtoom/scripts/shtoominfo.py 'upnp response has no urlbase?!?' 'upnp response has no urlbase?!?' 'upnp response has no urlbase?!?' From anthony at interlink.com.au Thu Jan 20 11:22:56 2005 From: anthony at interlink.com.au (Anthony Baxter) Date: Thu, 20 Jan 2005 21:22:56 +1100 Subject: [Shtoom] bug report: Shtoom doesn't register on startup In-Reply-To: References: Message-ID: <200501202122.57562.anthony@interlink.com.au> On Thursday 20 January 2005 07:49, Zooko O'Whielacronx wrote: > Current SVN head doesn't register with a SIP server on startup. Here > is a complete log of Shtoom starting and not registering. I made some changes to the NAT code yesterday to attempt to better handle Symmetric NATs. As far as I can test it, it works fine - you might try backing out to r1145 and see if that makes it better. (Aside: Testing this NAT stuff is a FRICKING NIGHTMARE!!!!) -- Anthony Baxter It's never too late to have a happy childhood. From liste at zerozone.it Fri Jan 21 12:48:27 2005 From: liste at zerozone.it (O-Zone) Date: Fri, 21 Jan 2005 12:48:27 +0100 Subject: [Shtoom] Data FLow Message-ID: <200501211248.27340@X-Blurb> Hi Shtoom developers, i'm working on a SIP client (in Python and WX) heavily based on Shtoom. I decide to do this for some reasons: 1) Shtoom is not very user-friedly 2) Shtoom have a lot of GUIs that can confuse dummy users 3) Shtoom isn't very beatiful (GUI) so my SIP client (UniversalSIPClient) try to resolve this tree points to have a professiona GPL product to share. At this point REGISTRATION works and also CALL ACKs but i need to do something abount codecs and audio managment. Because i want to do a portable client, i decide to use pyMedia package for audio (perhaps not the best solution available !) but this don't have CODECS support. I'm a bit confused also on AUDIO FLOW: what happen after user call acceptCall() function ? Where i get the audio data ? Thanks! Oz -- ------ O-Zone ! www.zerozone.it From anthony at interlink.com.au Sat Jan 22 05:11:44 2005 From: anthony at interlink.com.au (Anthony Baxter) Date: Sat, 22 Jan 2005 15:11:44 +1100 Subject: [Shtoom] Data FLow In-Reply-To: <200501211248.27340@X-Blurb> References: <200501211248.27340@X-Blurb> Message-ID: <200501221511.45340.anthony@interlink.com.au> On Friday 21 January 2005 22:48, O-Zone wrote: > At this point REGISTRATION works > and also CALL ACKs but i need to do something abount codecs and audio > managment. Because i want to do a portable client, i decide to use pyMedia > package for audio (perhaps not the best solution available !) but this > don't have CODECS support. I'm a bit confused also on AUDIO FLOW: what > happen after user call acceptCall() function ? Where i get the audio data ? I doubt the pymedia package is suitable for this. The codec support is in shtoom.audio.converters. Note that in the next few weeks I'll be making some fairly fundamental refactorings that will make the process of plugging in, say, a new GUI a much much more trivial exercise. Stay tuned. Anthony -- Anthony Baxter It's never too late to have a happy childhood. From zooko at zooko.com Sat Jan 22 17:19:18 2005 From: zooko at zooko.com (Zooko O'Whielacronx) Date: 22 Jan 2005 12:19:18 -0400 Subject: [Shtoom] bug report: test_stunmapper et al. sporadic failure Message-ID: <5E11CDD6-6C91-11D9-9811-000A95E2A184@zooko.com> I thought that test_stunmapper et al. were failing due to their timeout being too short. I thought this because they failed, I doubled the timeout, and then they passed. However, right now I've set the timeout on test_stunmapper() up to 64 seconds, and it still fails about 1 out of 3 runs. Regards, Zooko From zooko at zooko.com Sat Jan 22 17:28:07 2005 From: zooko at zooko.com (Zooko O'Whielacronx) Date: 22 Jan 2005 12:28:07 -0400 Subject: [Shtoom] Re: bug report: test_stunmapper et al. sporadic failure In-Reply-To: <5E11CDD6-6C91-11D9-9811-000A95E2A184@zooko.com> References: <5E11CDD6-6C91-11D9-9811-000A95E2A184@zooko.com> Message-ID: <99625A7E-6C92-11D9-9811-000A95E2A184@zooko.com> Whoops -- I sent that msg before I meant to. Actually, test_stunmapper has never yet failed with timeout 64. I've run it five times. --Z From zooko at zooko.com Sat Jan 22 17:42:15 2005 From: zooko at zooko.com (Zooko O'Whielacronx) Date: 22 Jan 2005 12:42:15 -0400 Subject: [Shtoom] Re: bug report: test_stunmapper et al. sporadic failure In-Reply-To: <99625A7E-6C92-11D9-9811-000A95E2A184@zooko.com> References: <5E11CDD6-6C91-11D9-9811-000A95E2A184@zooko.com> <99625A7E-6C92-11D9-9811-000A95E2A184@zooko.com> Message-ID: <92A2E1EE-6C94-11D9-9811-000A95E2A184@zooko.com> > Whoops -- I sent that msg before I meant to. Actually, > test_stunmapper has never yet failed with timeout 64. I've run it > five times. But it *does* sporadically fail around 1 out of 3 times with timeout == 32. --Z From zooko at zooko.com Sat Jan 22 17:51:22 2005 From: zooko at zooko.com (Zooko O'Whielacronx) Date: 22 Jan 2005 12:51:22 -0400 Subject: [Shtoom] Re: bug report: test_stunmapper et al. sporadic failure In-Reply-To: <92A2E1EE-6C94-11D9-9811-000A95E2A184@zooko.com> References: <5E11CDD6-6C91-11D9-9811-000A95E2A184@zooko.com> <99625A7E-6C92-11D9-9811-000A95E2A184@zooko.com> <92A2E1EE-6C94-11D9-9811-000A95E2A184@zooko.com> Message-ID: Okay, now it failed once with timeout == 64. From seberino at spawar.navy.mil Sat Jan 22 19:39:37 2005 From: seberino at spawar.navy.mil (seberino at spawar.navy.mil) Date: Sat, 22 Jan 2005 10:39:37 -0800 Subject: [Shtoom] Shtoom/SIP working (thru NAT!) ???? In-Reply-To: <5E11CDD6-6C91-11D9-9811-000A95E2A184@zooko.com> References: <5E11CDD6-6C91-11D9-9811-000A95E2A184@zooko.com> Message-ID: <20050122183937.GA10154@spawar.navy.mil> Is Shtoom working behind my NATing firewall?? Looks like perhaps yes... Here is my .shtoomrc and my shtoomphone.py output... [shtoom] audio=oss ui=qt [identity] username=seberino [register] register_uri=sip:switch-2.nufone.net register_authuser=seberino register_user=seberino register_authpasswd=XXXXX =================================================== 2005/01/22 10:32 PST [-] Log opened. 2005/01/22 10:32 PST [-] starting on 5060 2005/01/22 10:32 PST [-] Starting protocol 2005/01/22 10:32 PST [app] sip listener installed on 5060 2005/01/22 10:32 PST [-] no outstanding registrations, registering 2005/01/22 10:32 PST [-] twisted.internet.protocol.ConnectedDatagramProtocol starting on 0 2005/01/22 10:32 PST [-] Starting protocol 2005/01/22 10:32 PST [sip] discovered local address ('192.168.100.3', 5060), remote ('switch-2.nufone.net', 5060) 2005/01/22 10:32 PST [sip] stun policy says yes, use STUN 2005/01/22 10:32 PST [-] (Port 0 Closed) 2005/01/22 10:32 PST [-] Stopping protocol 2005/01/22 10:32 PST [stun] got STUN response from ('64.69.76.23', 3478) 2005/01/22 10:32 PST [sip] according to STUN, local address is 66.159.194.51:5060 2005/01/22 10:32 PST [ui] register sent REGISTER sip:seberino at switch-2.nufone.net SIP/2.0 Via: SIP/2.0/UDP 66.159.194.51:5060 CSeq: 3363 REGISTER To: sip:seberino at switch-2.nufone.net From: sip:seberino at switch-2.nufone.net Expires: 900 Call-ID: 401507385 at 66.159.194.51 User-Agent: Shtoom/0.3alpha0 Contact: Content-Length: 0 2005/01/22 10:32 PST [ui] Got a SIP packet from 198.22.67.70:5060 2005/01/22 10:32 PST [ui] SIP PACKET SIP/2.0 100 Trying Via: SIP/2.0/UDP 66.159.194.51:5060;received=66.159.194.51;rport=5060 From: sip:seberino at switch-2.nufone.net To: sip:seberino at switch-2.nufone.net;tag=as4a099353 Call-ID: 401507385 at 66.159.194.51 CSeq: 3363 REGISTER User-Agent: Asterisk PBX Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER Contact: Content-Length: 0 2005/01/22 10:32 PST [ui] got SIP response 100: Trying 2005/01/22 10:32 PST [ui] got SIP response SIP/2.0 100 Trying Via: SIP/2.0/UDP 66.159.194.51:5060;received=66.159.194.51;rport=5060 From: sip:seberino at switch-2.nufone.net To: sip:seberino at switch-2.nufone.net;tag=as4a099353 Call-ID: 401507385 at 66.159.194.51 CSeq: 3363 REGISTER User-Agent: Asterisk PBX Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER Contact: Content-Length: 0 2005/01/22 10:32 PST [ui] Got a SIP packet from 198.22.67.70:5060 2005/01/22 10:32 PST [ui] SIP PACKET SIP/2.0 401 Unauthorized Via: SIP/2.0/UDP 66.159.194.51:5060;received=66.159.194.51;rport=5060 From: sip:seberino at switch-2.nufone.net To: sip:seberino at switch-2.nufone.net;tag=as4a099353 Call-ID: 401507385 at 66.159.194.51 CSeq: 3363 REGISTER User-Agent: Asterisk PBX Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER Contact: WWW-Authenticate: Digest realm="asterisk", nonce="2f70b9ac" Content-Length: 0 2005/01/22 10:32 PST [ui] got SIP response 401: Unauthorized 2005/01/22 10:32 PST [ui] got SIP response SIP/2.0 401 Unauthorized Via: SIP/2.0/UDP 66.159.194.51:5060;received=66.159.194.51;rport=5060 From: sip:seberino at switch-2.nufone.net To: sip:seberino at switch-2.nufone.net;tag=as4a099353 Call-ID: 401507385 at 66.159.194.51 CSeq: 3363 REGISTER User-Agent: Asterisk PBX Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER Contact: WWW-Authenticate: Digest realm="asterisk", nonce="2f70b9ac" Content-Length: 0 2005/01/22 10:32 PST [ui] register sent REGISTER sip:seberino at switch-2.nufone.net SIP/2.0 Via: SIP/2.0/UDP 66.159.194.51:5060 CSeq: 3364 REGISTER To: sip:seberino at switch-2.nufone.net From: sip:seberino at switch-2.nufone.net Expires: 900 Call-ID: 401507385 at 66.159.194.51 Authorization: Digest username="seberino", realm="asterisk", nonce="2f70b9ac", uri="sip:seberino at switch-2.nufone.net", response="513a840ef683366e7be5c06d3a1286ea" User-Agent: Shtoom/0.3alpha0 Contact: Content-Length: 0 2005/01/22 10:32 PST [ui] Got a SIP packet from 198.22.67.70:5060 2005/01/22 10:32 PST [ui] SIP PACKET SIP/2.0 100 Trying Via: SIP/2.0/UDP 66.159.194.51:5060;received=66.159.194.51;rport=5060 From: sip:seberino at switch-2.nufone.net To: sip:seberino at switch-2.nufone.net;tag=as4a099353 Call-ID: 401507385 at 66.159.194.51 CSeq: 3364 REGISTER User-Agent: Asterisk PBX Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER Contact: Content-Length: 0 2005/01/22 10:32 PST [ui] got SIP response 100: Trying 2005/01/22 10:32 PST [ui] got SIP response SIP/2.0 100 Trying Via: SIP/2.0/UDP 66.159.194.51:5060;received=66.159.194.51;rport=5060 From: sip:seberino at switch-2.nufone.net To: sip:seberino at switch-2.nufone.net;tag=as4a099353 Call-ID: 401507385 at 66.159.194.51 CSeq: 3364 REGISTER User-Agent: Asterisk PBX Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER Contact: Content-Length: 0 2005/01/22 10:32 PST [ui] Got a SIP packet from 198.22.67.70:5060 2005/01/22 10:32 PST [ui] SIP PACKET SIP/2.0 200 OK Via: SIP/2.0/UDP 66.159.194.51:5060;received=66.159.194.51;rport=5060 From: sip:seberino at switch-2.nufone.net To: sip:seberino at switch-2.nufone.net;tag=as4a099353 Call-ID: 401507385 at 66.159.194.51 CSeq: 3364 REGISTER User-Agent: Asterisk PBX Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER Expires: 900 Contact: ;expires=900 Date: Sat, 22 Jan 2005 18:32:26 GMT Content-Length: 0 2005/01/22 10:32 PST [ui] got SIP response 200: OK 2005/01/22 10:32 PST [ui] got SIP response SIP/2.0 200 OK Via: SIP/2.0/UDP 66.159.194.51:5060;received=66.159.194.51;rport=5060 From: sip:seberino at switch-2.nufone.net To: sip:seberino at switch-2.nufone.net;tag=as4a099353 Call-ID: 401507385 at 66.159.194.51 CSeq: 3364 REGISTER User-Agent: Asterisk PBX Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER Expires: 900 Contact: ;expires=900 Date: Sat, 22 Jan 2005 18:32:26 GMT Content-Length: 0 From anthony at interlink.com.au Sun Jan 23 06:18:53 2005 From: anthony at interlink.com.au (Anthony Baxter) Date: Sun, 23 Jan 2005 16:18:53 +1100 Subject: [Shtoom] Shtoom/SIP working (thru NAT!) ???? In-Reply-To: <20050122183937.GA10154@spawar.navy.mil> References: <5E11CDD6-6C91-11D9-9811-000A95E2A184@zooko.com> <20050122183937.GA10154@spawar.navy.mil> Message-ID: <200501231618.54347.anthony@interlink.com.au> On Sunday 23 January 2005 05:39, seberino at spawar.navy.mil wrote: > Is Shtoom working behind my NATing firewall?? Looks like perhaps yes... There's been a lot of work on this recently - please svn up, and include the output of shtoominfo.py. Anthony -- Anthony Baxter It's never too late to have a happy childhood. From zooko at zooko.com Sun Jan 23 12:35:07 2005 From: zooko at zooko.com (Zooko O'Whielacronx) Date: 23 Jan 2005 07:35:07 -0400 Subject: [Shtoom] patch: refactor packets Message-ID: Anthony: This patch (as discussed on IRC) refactors the RTP Packet object and the parser in a way that I like. It separates the PT (Payload Type) byte from the Content Type object. It makes parsing a stateless function instead of a parser object. It makes all values of an RTP packet passed as ctor args instead of poked into place after construction. It handles up to one RTP extension header. It puts the RTP header stuff into a separate object, which is convenient if you have a function that needs to get the netbytes for the header separately from the netbytes for the payload (which I have). This patch also refactors the "send an RTP packet" functionality of RTP Protocol. There is a nice unified "_send_packet()" and a nice "_send_cn_packet()". I've been using this patch on my proprietary branch since last October. Shtoom passes unit tests after application of this patch. I made a test call with Shtoom after application of this patch and it worked. Further patches will be forthcoming which depend on and complement this patch. Please apply. Regards, Zooko The patch is inlined *and* attached: P.S. If you don't like nested classes, move Header outside of Packet, or mention it and I'll do so. Index: shtoom/test/test_playout.py =================================================================== --- shtoom/test/test_playout.py (revision 1157) +++ shtoom/test/test_playout.py (working copy) @@ -68,8 +68,7 @@ ts = 0 seq = 10017 while True: - p = RTPPacket(data='', pt=None, ts=ts) - p.seq = seq + p = RTPPacket(0, seq, ts, '') yield p ts += 160 seq += 1 Index: shtoom/test/test_codecs.py =================================================================== --- shtoom/test/test_codecs.py (revision 1157) +++ shtoom/test/test_codecs.py (working copy) @@ -56,10 +56,10 @@ ae = self.assertEquals ae(p.encode('frobozulate'), 'frobozulate') ae(p.decode('frobozulate'), 'frobozulate') - p = RTPPacket(PT_RAW, 'farnarkling', ts=None) + p = RTPPacket(0, 0, 0, 'farnarkling', ct=PT_RAW) ae(c.decode(p), 'farnarkling') ae(c.encode('farnarkling').data, 'farnarkling') - ae(c.encode('farnarkling').pt, PT_RAW) + ae(c.encode('farnarkling').header.pt, PT_RAW.pt) # XXX testing other codecs - endianness issues? crap. @@ -72,7 +72,7 @@ ae(c.getDefaultFormat(), PT_PCMU) ae(len(c.encode(instr).data), 160) ae(c.encode(instr).data, ulawout) - ae(c.encode(instr).pt, PT_PCMU) + ae(c.encode(instr).header.ct, PT_PCMU) def testGSMCodec(self): if codecs.gsm is None: Index: shtoom/test/test_rtp.py =================================================================== --- shtoom/test/test_rtp.py (revision 1157) +++ shtoom/test/test_rtp.py (working copy) @@ -45,33 +45,29 @@ ae(pt, RTPDict[(pt.name.lower(),pt.clock,pt.params or 1)]) def testRTPPacketRoundTrip(self): - from shtoom.rtp.packets import RTPParser, RTPPacket + from shtoom.rtp.packets import RTPPacket + from shtoom.rtp.protocol import parse_rtppacket from shtoom.rtp.formats import PT_PCMU, PT_SPEEX, PT_GSM, PT_CN ae = self.assertEquals - ptdict = {} - for pt, byte in ((PT_PCMU, 0),(PT_GSM,3),(PT_SPEEX,101),(PT_CN,13)): - ptdict[pt] = byte - ptdict[byte] = pt - parser = RTPParser(ptdict) ts = 12345678 seq = 12345 ssrc = 100001 packets = [ - RTPPacket(PT_PCMU, ''.join([chr(x) for x in range(160)]), 0), - RTPPacket(PT_GSM, '\0'*33, 0, 1), - RTPPacket(PT_GSM, '\0'*33, 0, 0), - RTPPacket(PT_CN, chr(127), 0, 0), - RTPPacket(PT_CN, chr(127), 0, 1), + RTPPacket(ssrc, seq, ts, ''.join([chr(x) for x in range(160)]), 0, ct=PT_PCMU), + RTPPacket(ssrc, seq, ts, '\0'*33, 1, ct=PT_GSM), + RTPPacket(ssrc, seq, ts, '\0'*33, 0, ct=PT_GSM), + RTPPacket(ssrc, seq, ts, chr(127), 0, ct=PT_CN), + RTPPacket(ssrc, seq, ts, chr(127), 1, ct=PT_CN), ] for pack in packets: - rpack = parser.fromnet(parser.tonet(pack, seq, ts, ssrc), None) - ae(pack.pt, rpack.pt) - ae(pack.marker, rpack.marker) + rpack = parse_rtppacket(pack.netbytes()) + ae(pack.header.pt, rpack.header.pt) + ae(pack.header.marker, rpack.header.marker) ae(pack.data, rpack.data) - ae(rpack.seq, seq) - ae(rpack.ts, ts) - ae(rpack.ssrc, ssrc) + ae(rpack.header.seq, seq) + ae(rpack.header.ts, ts) + ae(rpack.header.ssrc, ssrc) def testSDPGen(self): from shtoom.rtp.formats import SDPGenerator, PTMarker Index: shtoom/stun.py =================================================================== --- shtoom/stun.py (revision 1157) +++ shtoom/stun.py (working copy) @@ -16,7 +16,7 @@ from shtoom.defcache import DeferredCache from shtoom.nat import BaseMapper -STUNVERBOSE = True +STUNVERBOSE = False # If we're going to follow RFC recommendation, make this 7 MAX_RETRANSMIT = 5 @@ -397,7 +397,10 @@ else: if STUNVERBOSE: print "giving up on %r"%(address,) - del self._potentialStuns[tid] + if hasattr(self, '_potentialStuns') and self._potentialStuns.has_key(tid): + del self._potentialStuns[tid] + else: + print "xxxxx what's going on here? getattr(self, '_potentialStuns'): %s, val: %s" % (getattr(self, '_potentialStuns'), getattr(self, '_potentialStuns', {}).get(tid),) if not self._potentialStuns: if STUNVERBOSE: print "stun state 1 timeout - no internet UDP possible" Index: shtoom/app/phone.py =================================================================== --- shtoom/app/phone.py (revision 1157) +++ shtoom/app/phone.py (working copy) @@ -35,7 +35,7 @@ self._currentCall = None self._muted = False self._rtpProtocolClass = None - self._debugrev = 10 + self._debugrev = 17 def needsThreadedUI(self): return self.ui.threadedUI Index: shtoom/audio/converters.py =================================================================== --- shtoom/audio/converters.py (revision 1157) +++ shtoom/audio/converters.py (working copy) @@ -202,15 +202,15 @@ encaudio = codec.encode(bytes) if not encaudio: return None - return RTPPacket(self.format, encaudio, ts=None) + return RTPPacket(0, 0, 0, encaudio, ct=self.format) def decode(self, packet): "Accepts an RTPPacket, emits audio as bytes" if not packet.data: return None - codec = self.codecs.get(packet.pt) + codec = self.codecs.get(packet.header.ct) if not codec: - raise ValueError("can't decode format %r"%packet.pt) + raise ValueError("can't decode format %r"%packet.header.ct) encaudio = codec.decode(packet.data) return encaudio Index: shtoom/audio/playout.py =================================================================== --- shtoom/audio/playout.py (revision 1157) +++ shtoom/audio/playout.py (working copy) @@ -61,22 +61,22 @@ raise ValueError("playout got %s instead of bytes"%(type(bytes))) if self.expect_seq == None: - self.expect_seq = packet.seq # First packet. Initialize seq + self.expect_seq = packet.header.seq # First packet. Initialize seq backlog = len(self.queue) - if packet.seq == self.expect_seq: - self.expect_seq = packet.seq+1 + if packet.header.seq == self.expect_seq: + self.expect_seq = packet.header.seq+1 if backlog < self.backlog+1: self.queue.append(bytes) elif DEBUG: log.msg("BacklogPlayout discarding") else: - offset = packet.seq-self.expect_seq + offset = packet.header.seq-self.expect_seq if offset > 0 and offset < 3: # Fill with empty packets self.queue += [None]*offset self.queue.append(bytes) - self.expect_seq = packet.seq+1 + self.expect_seq = packet.header.seq+1 if DEBUG: log.msg("BacklogPlayout got hole at %d"%offset) elif offset < 0 and offset > -backlog: Index: shtoom/rtp/packets.py =================================================================== --- shtoom/rtp/packets.py (revision 1157) +++ shtoom/rtp/packets.py (working copy) @@ -6,75 +6,80 @@ import struct from time import sleep, time +# This class supports extension headers, but only one per packet. class RTPPacket: - "An RTPPacket contains RTP data to/from the RTP object" - def __init__(self, pt, data, ts, marker=0): - self.pt = pt - self.data = data - self.ts = ts - self.marker = marker - self.ssrc = None - self.seq = None + """ Contains RTP data. """ + class Header: + def __init__(self, ssrc, pt, ct, seq, ts, marker=0, xhdrtype=None, xhdrdata=''): + """ + If xhdrtype is not None then it is required to be an int >= 0 and < 2**16 and xhdrdata is required to be a string. + """ + assert isinstance(ts, (int, long,)), "ts: %s :: %s" % (ts, type(ts),) + assert isinstance(ssrc, (int, long,)) + assert xhdrtype is None or isinstance(xhdrtype, int) and xhdrtype >= 0 and xhdrtype < 2**16 + assert xhdrtype is None or isinstance(xhdrdata, str) - def __repr__(self): - return ""%(self.pt, id(self)) + self.ssrc, self.pt, self.ct, self.seq, self.ts, self.marker, self.xhdrtype, self.xhdrdata = ssrc, pt, ct, seq, ts, marker, xhdrtype, xhdrdata + def netbytes(self): + "Return network-formatted header." + assert isinstance(self.pt, int) and self.pt >= 0 and self.pt < 2**8, "pt is required to be a simple byte, suitable for stuffing into an RTP packet and sending. pt: %s" % self.pt + if self.xhdrtype is not None: + firstbyte = 0x90 + xhdrnetbytes = struct.pack('!HH', self.xhdrtype, len(self.xhdrdata)) + self.xhdrdata + else: + firstbyte = 0x80 + xhdrnetbytes = '' + return struct.pack('!BBHII', firstbyte, self.pt | self.marker << 7, self.seq % 2**16, self.ts, self.ssrc) + xhdrnetbytes -class RTPParser: - """ An RTPParser creates RTPPacket objects from a bytestring. It is - created with a mapping of RTP PT bytes to PT markers""" - def __init__(self, ptdict): - self.ptdict = ptdict + def __init__(self, ssrc, seq, ts, data, pt=None, ct=None, marker=0, authtag='', xhdrtype=None, xhdrdata=''): + assert pt is None or isinstance(pt, int) and pt >= 0 and pt < 2**8, "pt is required to be a simple byte, suitable for stuffing into an RTP packet and sending. pt: %s" % pt + self.header = RTPPacket.Header(ssrc, pt, ct, seq, ts, marker, xhdrtype, xhdrdata) + self.data = data + self.authtag = authtag # please leave this alone even if it appears unused -- it is required for SRTP - def tonet(self, packet, seq, ts, ssrc): - "Return network formatted packet" - pt = packet.pt - # XXX handle cc and x! - byte0 = 0x80 - fmt = self.ptdict[pt] & 127 - if packet.marker: fmt = fmt | 128 - hdr = struct.pack('!BBHII', byte0, fmt, seq, ts, ssrc) - # Padding? - return hdr + packet.data + def __repr__(self): + if self.header.ct is not None: + ptrepr = "%r" % (self.header.ct,) + else: + ptrepr = "pt %d" % (self.header.pt,) - # XXX Note that the MediaLayer will create it's own RTPPackets - this is - # purely for packets coming off the network. - def fromnet(self, bytes, fromaddr): - hdr = struct.unpack('!BBHII', bytes[:12]) - padding = hdr[0]&32 and 1 or 0 - cc = hdr[0]&15 and 1 or 0 - x = hdr[0]&16 and 1 or 0 - pt = hdr[1]&127 - if not self.ptdict.get(pt): - # Could be any old garbage, such as a late STUN packet - return None - pt = self.ptdict[pt] - marker = hdr[1]&128 and 1 or 0 - seq = hdr[2] - ts = hdr[3] - ssrc = hdr[4] - headerlen = 12 - if cc > 1: - headerlen = headerlen + 4 * cc - data = bytes[headerlen:] - if x: - # Mmm. Tasty tasty header extensions. We eats them. - xhdrtype,xhdrlen = struct.unpack('!HH', data[:4]) - data = data[4+4*xhdrlen:] - if padding: - padcount = ord(data[-1]) - if padcount: - data = data[:-padcount] - packet = RTPPacket(pt, data, ts, marker) - packet.ssrc = ssrc - packet.seq = seq - return packet + if self.header.xhdrtype is not None: + return "<%s #%d (%s) %s [%s] at %x>"%(self.__class__.__name__, self.header.seq, self.header.xhdrtype, ptrepr, repr(self.header.xhdrdata), id(self)) + else: + return "<%s #%d %s at %x>"%(self.__class__.__name__, self.header.seq, ptrepr, id(self)) - def haspt(self, key): - return self.ptdict.has_key(key) + def netbytes(self): + "Return network-formatted packet." + return self.header.netbytes() + self.data + self.authtag +def parse_rtppacket(bytes): + hdr = struct.unpack('!BBHII', bytes[:12]) + padding = hdr[0]&32 and 1 or 0 + cc = hdr[0]&15 and 1 or 0 + x = hdr[0]&16 and 1 or 0 + pt = hdr[1]&127 + marker = hdr[1]&128 and 1 or 0 + seq = hdr[2] + ts = hdr[3] + ssrc = hdr[4] + headerlen = 12 + if cc > 1: + headerlen = headerlen + 4 * cc + data = bytes[headerlen:] + if x: + # Mmm. Tasty tasty header extensions. We eats them. Except for the first one. + xhdrtype,xhdrlen = struct.unpack('!HH', data[:4]) + xhdrdata = data[4:4+4*xhdrlen] + data = data[4+4*xhdrlen:] + else: + xhdrtype, xhdrdata = None, None + if padding: + padcount = ord(data[-1]) + if padcount: + data = data[:-padcount] + return RTPPacket(ssrc, seq, ts, data, marker=marker, pt=pt, xhdrtype=xhdrtype, xhdrdata=xhdrdata) - class NTE: "An object representing an RTP NTE (rfc2833)" # XXX at some point, this should be hooked into the RTPPacketFactory. Index: shtoom/rtp/protocol.py =================================================================== --- shtoom/rtp/protocol.py (revision 1157) +++ shtoom/rtp/protocol.py (working copy) @@ -12,7 +12,7 @@ from twisted.python import log from shtoom.rtp.formats import SDPGenerator, PT_CN, PT_xCN -from shtoom.rtp.packets import RTPPacket, RTPParser +from shtoom.rtp.packets import RTPPacket, parse_rtppacket TWO_TO_THE_16TH = 2<<16 TWO_TO_THE_32ND = 2<<32 @@ -46,14 +46,12 @@ def setSDP(self, sdp): "This is the canonical SDP for the call" - from shtoom.rtp.packets import RTPParser self.app.selectDefaultFormat(self.cookie, sdp) rtpmap = sdp.getMediaDescription('audio').rtpmap - ptdict = {} + self.ptdict = {} for pt, (text, marker) in rtpmap.items(): - ptdict[pt] = marker - ptdict[marker] = pt - self.rtpParser = RTPParser(ptdict) + self.ptdict[pt] = marker + self.ptdict[marker] = pt def createRTPSocket(self, locIP, needSTUN=False): """ Start listening on UDP ports for RTP and RTCP. @@ -226,6 +224,26 @@ d.addCallback(lambda x: self.rtpListener.stopListening()) d.addCallback(lambda x: self.rtcpListener.stopListening()) + def _send_packet(self, pt, data, xhdrtype=None, xhdrdata=''): + packet = RTPPacket(self.ssrc, self.seq, self.ts, data, pt=pt, xhdrtype=xhdrtype, xhdrdata=xhdrdata) + + self.seq += 1 + self.transport.write(packet.netbytes(), self.dest) + + def _send_cn_packet(self): + # PT 13 is CN. + if self.ptdict.has_key(PT_CN): + cnpt = PT_CN.pt + elif self.ptdict.has_key(PT_xCN): + cnpt = PT_xCN.pt + else: + # We need to send SOMETHING!?! + cnpt = 0 + + log.msg("sending CN(%s) to seed firewall to %s:%d"%(cnpt, self.dest[0], self.dest[1]), system='rtp') + + self._send_packet(cnpt, chr(127)) + def startSendingAndReceiving(self, dest, fp=None): self.dest = dest self.prevInTime = self.prevOutTime = time() @@ -248,32 +266,14 @@ self.LC.start(0.020) # Now send a single CN packet to seed any firewalls that might # need an outbound packet to let the inbound back. - # PT 13 is CN. - if self.rtpParser.haspt(PT_CN): - cnpt = PT_CN.pt - elif self.rtpParser.haspt(PT_xCN): - cnpt = PT_xCN.pt - else: - cnpt = None - if cnpt: - log.msg("sending CN(%s) to seed firewall to %s:%d"%(cnpt, - self.dest[0], self.dest[1]), system='rtp') - hdr = struct.pack('!BBHII', 0x80, cnpt, self.seq, self.ts,self.ssrc) - self.transport.write(hdr+chr(0), self.dest) - else: - log.msg("hack - seeding firewall with PT_PCMU") - hdr = struct.pack('!BBHII', 0x80, 0, self.seq, self.ts,self.ssrc) - self.transport.write(hdr+(160*chr(0)), self.dest) - # We need to send SOMETHING!?! + self._send_cn_packet() if hasattr(self.transport, 'connect'): self.transport.connect(*self.dest) def datagramReceived(self, datagram, addr): # XXX check for late STUN packets here. see, e.g datagramReceived in sip.py - if self.rtpParser is None: - log.msg("early(?) rtp packet, no rtpParser available") - return - packet = self.rtpParser.fromnet(datagram, addr) + packet = parse_rtppacket(datagram) + packet.header.ct = self.ptdict[packet.header.pt] if packet: self.app.receiveRTP(self.cookie, packet) @@ -340,26 +340,19 @@ # when we go from silent->talking, set the marker bit. Other end # can use this as an excuse to adjust playout buffer. if self.sample is not None: - packet = self.sample + pt = self.ptdict[self.sample.header.ct] + self._send_packet(pt, self.sample.data) self.sent += 1 - data = self.rtpParser.tonet(packet, self.seq, self.ts, self.ssrc) - self.transport.write(data, self.dest) self.sample = None - else: - if (self.packets - self.sent) % 100 == 0: - if self.rtpParser.haspt(PT_CN): - cn = RTPPacket(PT_CN, chr(127), 0) - cn = self.rtpParser.tonet(cn, self.seq, self.ts, self.ssrc) - self.transport.write(cn, self.dest) - self.seq += 1 + elif (self.packets - self.sent) % 100 == 0: + self._send_cn_packet() + # Now send any pending DTMF keystrokes if self._pendingDTMF: payload = self._pendingDTMF[0].getPayload(self.ts) if payload: # XXX Hack. telephone-event isn't always 101! - hdr = struct.pack('!BBHII', 0x80, 101, self.seq, self.ts, self.ssrc) - self.transport.write(hdr+payload, self.dest) - self.seq += 1 + self._send_packet(pt=101, data=payload) if self._pendingDTMF[0].isDone(): self._pendingDTMF = self._pendingDTMF[1:] try: -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: refactor-packets.patch.txt URL: From anthony at interlink.com.au Mon Jan 24 12:27:51 2005 From: anthony at interlink.com.au (Anthony Baxter) Date: Mon, 24 Jan 2005 22:27:51 +1100 Subject: [Shtoom] patch: refactor packets In-Reply-To: References: Message-ID: <200501242227.52176.anthony@interlink.com.au> On Sunday 23 January 2005 22:35, Zooko O'Whielacronx wrote: > It separates the PT (Payload Type) byte from the Content Type object. ? > It makes parsing a stateless function instead of a parser object. ?It > makes all values of an RTP packet passed as ctor args instead of poked > into place after construction. ?It handles up to one RTP extension > header. ?It puts the RTP header stuff into a separate object, which is > convenient if you have a function that needs to get the netbytes for > the header separately from the netbytes for the payload (which I have). > > This patch also refactors the "send an RTP packet" functionality of RTP > Protocol. ?There is a nice unified "_send_packet()" and a nice > "_send_cn_packet()". This is now checked in. Thanks for the patch! Anthony -- Anthony Baxter It's never too late to have a happy childhood. From zooko at zooko.com Tue Jan 25 19:26:32 2005 From: zooko at zooko.com (Zooko O'Whielacronx) Date: 25 Jan 2005 14:26:32 -0400 Subject: [Shtoom] playout algorithm Message-ID: I noticed a comment about anthony wanting to improve the playout object. I've written a completely new playout object which I've used successfully for months now, but only with PCMU. I'll be submitting it in a patch via e-mail very soon. --Z From zooko at zooko.com Tue Jan 25 20:58:00 2005 From: zooko at zooko.com (Zooko O'Whielacronx) Date: 25 Jan 2005 15:58:00 -0400 Subject: [Shtoom] local ip determination Message-ID: <6A90B42E-6F0B-11D9-9370-000A95E2A184@zooko.com> Should sip.Call.setLocalIP() be refactored to use the new nat.getLocalIPAddress()? By the way, you might be able to glean useful ideas or code from this venerable and battle-tested module: http://mnetproject.org/repos/mnet/egtp/ipaddresslib.py I don't really know most of what is in that hairy module, but I do know that it worked well enough on all supported platforms at Mojo Nation and then Mnet for many years. The authors Greg Smith and Hauke Johannknecht (with help from others) have my respect for their network fu. --Z From anthony at interlink.com.au Wed Jan 26 10:56:49 2005 From: anthony at interlink.com.au (Anthony Baxter) Date: Wed, 26 Jan 2005 20:56:49 +1100 Subject: [Shtoom] local ip determination In-Reply-To: <6A90B42E-6F0B-11D9-9370-000A95E2A184@zooko.com> References: <6A90B42E-6F0B-11D9-9370-000A95E2A184@zooko.com> Message-ID: <200501262056.49814.anthony@interlink.com.au> On Wednesday 26 January 2005 06:58, Zooko O'Whielacronx wrote: > Should sip.Call.setLocalIP() be refactored to use the new > nat.getLocalIPAddress()? > > By the way, you might be able to glean useful ideas or code from this > venerable and battle-tested module: > > http://mnetproject.org/repos/mnet/egtp/ipaddresslib.py > > I don't really know most of what is in that hairy module, but I do know > that it worked well enough on all supported platforms at Mojo Nation > and then Mnet for many years. Hm. They try the connected UDP socket, and then attempt to parse ifconfig and netstat output. I really want to stay away from the latter - it strikes me as an incredibly brittle and painful approach (indeed, the module has a huge pile of parsing code for all sorts of different platforms to parse the output. Yuk.) Anthony -- Anthony Baxter It's never too late to have a happy childhood. From anthony at interlink.com.au Wed Jan 26 10:58:40 2005 From: anthony at interlink.com.au (Anthony Baxter) Date: Wed, 26 Jan 2005 20:58:40 +1100 Subject: [Shtoom] playout algorithm In-Reply-To: References: Message-ID: <200501262058.40902.anthony@interlink.com.au> On Wednesday 26 January 2005 05:26, Zooko O'Whielacronx wrote: > I noticed a comment about anthony wanting to improve the playout > object. I've written a completely new playout object which I've used > successfully for months now, but only with PCMU. I'll be submitting it > in a patch via e-mail very soon. Great! For now, I've switched the default back to BrainDeadPlayout - I've received a number of complaints about the BacklogPlayout causing audio to just stop after several minutes of talking, and I haven't the time to dig into why it's failing. -- Anthony Baxter It's never too late to have a happy childhood. From zooko at zooko.com Sun Jan 30 21:40:16 2005 From: zooko at zooko.com (Zooko O'Whielacronx) Date: 30 Jan 2005 16:40:16 -0400 Subject: [Shtoom] upnp leaking mappings Message-ID: Whenever I do UPnP, I see a list of "existing mappings" which is one greater than the last time I did UPnP. Also the most recent time I did it my linksys didn't respond to the upnp discovery broadcast at all until I disabled and re-enabled upnp in the linksys admin web page. I had assumed that these mappings would time-out if they weren't refreshed, but they've lived for days now. Ought they to be cleaned up, and if so how? --Z From tedbukov at gmail.com Sun Jan 30 23:36:42 2005 From: tedbukov at gmail.com (Todor Bukov) Date: Sun, 30 Jan 2005 22:36:42 +0000 Subject: [Shtoom] About the present shtoom/doug status Message-ID: <3e1091d050130143656aaf85d@mail.gmail.com> Hi folks, I was looking for SIP/voice libraries to include it into a Python project and I was quite surprised to find out that there is already a complete application - shtoom. I read the paper in python.org and the project home page, but I found that 0.2 version is rather old and 0.3 is yet to come. Could someone give me more information about the current status of the project and when the next version is expeted to be released? I also consider to get involved into this project and would like to review the documentation. I'll be very thankfull if you inform me whether the project is still in active development and who maintain it (is sourceforge.net information up to date)? Thanks in advance for your answer. --- Ted --- From anthony at interlink.com.au Mon Jan 31 13:58:48 2005 From: anthony at interlink.com.au (Anthony Baxter) Date: Mon, 31 Jan 2005 23:58:48 +1100 Subject: [Shtoom] About the present shtoom/doug status In-Reply-To: <3e1091d050130143656aaf85d@mail.gmail.com> References: <3e1091d050130143656aaf85d@mail.gmail.com> Message-ID: <200501312358.49620.anthony@interlink.com.au> On Monday 31 January 2005 09:36, Todor Bukov wrote: > I was looking for SIP/voice libraries to include it into a Python > project and I was quite surprised to find out that there is already a > complete application - shtoom. I read the paper in python.org and the > project home page, but I found that 0.2 version is rather old and 0.3 > is yet to come. Yes - getting a new release out has turned into quite the nightmare. I'm working very hard on finishing off the bits I still have to do to make this happen. > Could someone give me more information about the > current status of the project and when the next version is expeted to > be released? "Soon" is the best answer I can give you, I'm afraid - I'd be very disappointed if it's not during February some time. Having said that, the current SVN trunk (see instructions on the webpage at shtoom.divmod.org) is pretty stable, and there's been a huge amount of stuff added since 0.2 > I also consider to get involved into this project and > would like to review the documentation. I'll be very thankfull if you > inform me whether the project is still in active development and who > maintain it (is sourceforge.net information up to date)? The project is no longer at sourceforge, but at shtoom.divmod.org. It's very much a live project. Anthony -- Anthony Baxter It's never too late to have a happy childhood.