Hi, I just 'finished' writing the first part of my SIP client.. this is useful for the audio conference that uses SIP and RTP (not the one with audio and video which uses msnp2p and is being developped on a separate branch).
So here's the deal.. I have two phases for the client, first phase is being able to make a call (send an invite) and it already works pretty good! second phase is to be able to receive a call (receive an invite) and that won't be too difficult... I consider the first phase complete, and I like the API and the design a lot! :) What I would need now is to have you guys test it.. so here's how you can do a voice call with aMSN : - first, you need to update to SVN r9697 or later.. - Download the latest version of farsight and compile it.. (with gst-plugins-farsight of course) - Open the amsn console and type 'source sip.tcl' Now you have everything you need to make a voice call.. - Enable MSNP15 support and connect so you can have your authentification token... The easy part : - type in the console : 'createSIP' which will create a new SIP connection object called 'sip' - then type 'inviteSIP $email' to invite someone from WLM. You should then see status messages on the console, once it gets accepted on the other side, you'll see a status OK with the list of codecs and candidates (ip/port combinations). For example : "Invite SIP Response : OK -- {{{} 1 {} UDP 1 192.168.1.100 123456} {{} 2 {} UDP 1 192.168.1.100 123457}} {{PCMA 8 8000} {PCMU 0 8000} {telephone-event 101 8000}} The first list is the candidate list, you take the first one ("the one for RTP has a '1' as second element, RTCP has '2') and you have your ip and port.. - Go to farsight's directory and type : ./tests/test-rtp-7 192.168.1.100 123456 1 That's it.. you should start hearing the WLM audio in your PC.. The complicated part : In theory, you should create a new SIP connection with : SIPConnection create %AUTO% -user $your_email -password [[$::sso GetSecurityTokenByName Voice] cget -ticket] The returned object is your SIP connection.. it's not conneced yet.. you could do a : $sip Invite $email $codec_list $candidate_list The codec list is a list containing codecs.. each codec is itself a list of the form [list $encoding_name $payload_type $bitrate] The encoding name and payload types should be following the RTP RFCs.. to make it easy you can use PCMA which has a static payload type of 8 and PCMU with payload type 0. The condidate list is also a list containing candidates (connection info like ip/port), each candidate is a list of the form : [list $candidate_id $component_id $password $transport $qvalue $ip $port] those are ICE candidates, WLM uses ICE draft 6, so the candidate id and password are randomly generated and used to authenticate once the connection is established... you don't need that.. it can work even without ICE, so you can give an empty string as candidate id and password and it will skip ice candidates... the qvalue is just a 'weight'.. the higher the value (between 0.00 and 1.00) the better it is to connect on it (ip/port priority). transport is either UDP or TCP and that's it... So let's say we want to create an object called 'sip' it can be done like this : SIPConnection create sip -user $your_email -password [[$::sso GetSecurityTokenByName Voice] cget -ticket] -error_handler myErrorHandler -request_handler myRequestHandler The error and request handlers should be procs that handle errors and new requests.. you can skip the -request_handler for now (since we don't handle incoming requests for now) but the error_handler should have a prototype of the form : proc myErrorHandler { reason } anyways, once the object is created, it's not connected yet, so you can do it with : sip Connect but you don't really need to do that.. you mainly need to Register.. if you try to register and it's not connected, it will connect automatically.. so just do a : sip Register it will then register itself on the SIP server... If you want to invite someone, you can also skip that and just send the invite, it will automatically connect and register before sending out the invite... So with everything I said so far, here's how you can send an invite : sip Invite $email [list [list "PCMA" 8 8000] [list "PCMU" 0 8000]] [list [list "" 1 "" UDP 1 $my_ip $my_port]] Since we don't use ICE, if you're behind a firewall or a NAT, then you just won't be able to make the connection work, so I was testing between WLM and aMSN inside my local network, so the $my_ip was actually my local ip.. which I was getting with : [::abook::getDemographicField localip] The $port is special though, since we're using a 'test' application from farsight, and that test only takes the destination ip/port, it has a hardcoded value for the port to listen to and it's 7078... so until we write our own application that uses farsight, we have to use the port 7078.. One last thing.. if you want to know what is happening (you must!) then you need to specify one last argument : a callback function with the protocol : proc InviteCallback { status detail } The status tells you what's happening and the detail is an extra detail per status.. for example "ERROR" status will have the reason in the detail.. a "OK" will have a list containing the remote user's candidates and codecs in the $detail variable... So you end up doing this : sip Invite $email [list [list "PCMA" 8 8000] [list "PCMU" 0 8000]] [list [list "" 1 "" UDP 1 [::abook::getDemographicField localip] 7078 InviteCallback Once you do that, the invite gets sent, the other user's WLM starts ringing.. he can accept/decline/not answer/etc... the Tcl client will tell you exactly what happens The rest is the same as the 'easy method', you just look at what you receive in your callback, when you get the OK, you parse the remote candidates, get the ip/port and use that with farsight : ./tests/test-rtp-7 $ip $port 1 Now To summarize everything I've just explained.. let's look at the last few functions in sip.tcl which serve as test and are what are being used for the 'easy method' : proc createSIP { {host "vp.sip.messenger.msn.com"} } { global sso set token [$sso GetSecurityTokenByName Voice] catch {sip destroy} return [SIPConnection create sip -user [::config::getKey login] -password [$token cget -ticket] -error_handler errorSIP -request_handler requestSIP -host $host] } This helper function just creates the 'sip' object for you just like I said before... proc inviteSIP { email } { sip Invite $email [list [list "PCMA" 8 8000] [list "PCMU" 0 8000]] [list [list "" 1 "" UDP 1 [::abook::getDemographicField localip] 7078]] inviteSIPCB } and this one invites the user without having you type in the list of codecs/candidates everytime... proc inviteSIPCB { status detail} { puts "Invite SIP Response : $status -- $detail" } invite callback which tells you what's happening... proc requestSIP { request headers body } { puts "Received Request : $request" } Request handler.. This will tell you if you receive a request from the other user (assuming you are connected to the same SIP proxy but it does nothing else...) proc errorSIP { reason } { puts "Error in SIP : $reason" } Error handler which will tell you what happened when something goes wrong... That's about it.. if you follow these instructions, you should *in theory* be able to do a voice call with WLM... problem now is that WLM will not play your sound, and that's because farsight doesn't send RTCP and without it, WLM doesn't know if your SSRC (and id in the rtp header) is yours... with farsight 2 (which we'll use), we'll have RTCP so WLM will play our sound too... yeay! If you have any questions.. you will find me tomorrow after I wake up on IRC... or write to the ML... Feedback appreciated!!! Thanks KaKaRoTo ------------------------------------------------------------------------- This SF.net email is sponsored by the 2008 JavaOne(SM) Conference Register now and save $200. Hurry, offer ends at 11:59 p.m., Monday, April 7! Use priority code J8TLD2. http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone _______________________________________________ Amsn-devel mailing list Amsn-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/amsn-devel