source

You are currently browsing the archive for the source category.

The version 1.1 release of sipsorcery has been made and can be downloaded from codeplex. While there have been a month’s worth of minor fixes since the v1.0 release the main reason for the v1.1 release is so anyone interested can use the GoogleVoiceCall application in their dialplans.

Update: Spurred on by pagemen’s comment I looked into the character encoding of the POST requests and I WAS making a mistake by not escaping the data fields. The reason I didn’t twig to that previously was that some accounts would work without the need to escape the data. It will come down to whether the unescaped data contains an illegal character sequence such as t. Since correcting that bug I have not seen any 500 errors from sipsorcery.

Some people are getting a (500) Internal Server Error when attempting to place a Google Voice Call using the sipsorcery dialplan application. One person has passed along their account details so I could take a look and I’m sorry to say that 4 hours later I’m still none the wiser. As far as I can see the failing account is identical to my working account. Mine can place calls and works every time. The identical account can login and retrieve the key but fails every time with the Internal Server Error when placing the call request.

There are people around with more perserverance than me for this kind of thing (I’m generally happier creating my own bugs than reverse engineering or fixing other people’s, no suprise there) so below is the relevant C# source code that the sipsorcery dialplan application uses to place the call. Running the console application with my own account details works everytime.

using System;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;

namespace GoogleVoiceCall {
    class Program {

        private const string LOGIN_URL = "https://www.google.com/accounts/ServiceLoginAuth?service=grandcentral";
        private const string GOOGLE_VOICE_HOME_URL = "https://www.google.com/voice";
        private const string CALL_URL = "https://www.google.com/voice/call/connect";

        private static string m_emailAddress = "your email address";
        private static string m_password = "your password";
        private static string m_gizmoNumber = "your gizmo number"; 
        private static string m_destinationNumber = "your destination number";

        static void Main(string[] args) {
            try {
                Console.WriteLine("Attempting Google Voice Call");

                CookieContainer cookies = new CookieContainer();

                // First send a login request to get the necessary cookies.
                string loginData = "Email=" + Uri.EscapeDataString(m_emailAddress)
                      + "&Passwd=" + Uri.EscapeDataString(m_password);
                HttpWebRequest loginRequest = (HttpWebRequest)WebRequest.Create(LOGIN_URL);
                loginRequest.CookieContainer = cookies;
                loginRequest.AllowAutoRedirect = true;
                loginRequest.Method = "POST";
                loginRequest.ContentType = "application/x-www-form-urlencoded;charset=utf-8";
                loginRequest.ContentLength = loginData.Length;
                loginRequest.GetRequestStream().Write(Encoding.UTF8.GetBytes(loginData), 0, loginData.Length);

                HttpWebResponse loginResponse = (HttpWebResponse)loginRequest.GetResponse();
                if (loginResponse.StatusCode != HttpStatusCode.OK) {
                    throw new ApplicationException("Login failed.");
                }
                else {
                    Console.WriteLine("Login request was successful.");
                }

                // Second send a request to the Google Voice home page to get a string key needed when placing a callback.
                HttpWebRequest keyRequest = (HttpWebRequest)WebRequest.Create(GOOGLE_VOICE_HOME_URL);
                keyRequest.CookieContainer = cookies;

                HttpWebResponse keyResponse = (HttpWebResponse)keyRequest.GetResponse();
                if (keyResponse.StatusCode != HttpStatusCode.OK) {
                    throw new ApplicationException("_rnr_se key request failed.");
                }
                else {
                    Console.WriteLine("Key request was successful.");
                }

                StreamReader reader = new StreamReader(keyResponse.GetResponseStream());
                string keyResponseHTML = reader.ReadToEnd();
                Match rnrMatch = Regex.Match(keyResponseHTML, @"name=""_rnr_se"".*?value=""(?<rnrvalue>.*?)""");
                if (!rnrMatch.Success) {
                    throw new ApplicationException("_rnr_se key was not found on your Google Voice home page.");
                }
                string rnr = rnrMatch.Result("${rnrvalue}");
                Console.WriteLine("_rnr_se key=" + rnr);

                // Thirdly (and lastly) submit the request to initiate the callback.
                string callData = "outgoingNumber=" + Uri.EscapeDataString(m_destinationNumber) + 
             "&forwardingNumber=" + Uri.EscapeDataString(m_gizmoNumber) +
             "&subscriberNumber=undefined&remember=0&_rnr_se=" + Uri.EscapeDataString(rnr);
                HttpWebRequest callRequest = (HttpWebRequest)WebRequest.Create(CALL_URL);
                callRequest.CookieContainer = cookies;
                callRequest.Method = "POST";
                callRequest.ContentType = "application/x-www-form-urlencoded;charset=utf-8";
                callRequest.ContentLength = callData.Length;
                callRequest.GetRequestStream().Write(Encoding.UTF8.GetBytes(callData), 0, callData.Length);

                HttpWebResponse callResponse = (HttpWebResponse)callRequest.GetResponse();
                if (callResponse.StatusCode != HttpStatusCode.OK) {
                    Console.WriteLine("Call request failed.");
                }
                else {
                    Console.WriteLine("Call request was successful.");
                }
            }
            catch (Exception excp) {
                Console.WriteLine("Exception Main. " + excp.Message);
            }
            finally {
                Console.WriteLine("finished, press any key to exit...");
                Console.ReadLine();
            }
        }
    }
}

v1.0 release

I’ve just uploaded a v1.0 release of sipsorcery that’s designed for local installs. The release is available at sipsorcery v1.0.

Newer entries »