function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
jarsjars 

Race condition in CTI Toolkit 4.0 on CTI Adapter Connect?

Hi all,

 

I've come across a problem when migrating our current CTI "connector" to the new CTI 4.0 Toolkit.

I spotted a race condition on first connection from Salesforce.com.

 

First I should mentioned that, to solve the problem with user params in older CTI toolkit versions, I had to implement a custom CTIAppExchange class with methdos LoadUserParamsFromCustomSetup and SaveUserParams.

 

The new BrowserConnection on initialization sends an "UPDATE_SID" message to the CTI Adapter. This message starts a chain of events that eventually ends up invoking my LoadUserParamsFromCustomSetup method and get the user information for the Login Form.

However, this code is running concurrently with other requests that are sent by the browser, namely, the CONNECT message.

The CONNECT message kicks up a call to our connection procedure and when this ends an OnConnection event (or OnConnectionFailed) event is fired from our side to inform of a sucessful connection. These calls result on UIRefresh() call which sends the "connection" information to the browser...

 

The problem starts when the OnConnection() event is sent before the part of the initialization code that gets te user params ran... When that happens, and until the BrowserConnector is killed and (with luck) another run doesn't fall in the race condition, the login form is always empty.

 

Here is a log entry illustrating the issue (sorry for all the garbage...):

 

01/25/2012 17:34:18: Connector::Connector(pUI): Created Connector object with an user interface object.
01/25/2012 17:34:18: Connector::Initialize(): Initialized object.
01/25/2012 17:34:18: CreateLoginForm()
01/25/2012 17:34:23: receiving 281 characters in message <?xml version="1.0" encoding="UTF-8"?><MESSAGE ID="UPDATE_SID">
<PARAMETER NAME="SID" VALUE="00D70000000JY7g!ARgAQNu9apLVC.Jm66lkHVEEGhs0sH8AqMzd.cnt4kBoJcD11IZEuB5bn0ky6hgZ6HrdaBqWFZFJwbfcyHZe_QFOI7FTYucG"/><PARAMETER NAME="INSTANCE" VALUE="https://na5.salesforce.com"/></MESSAGE>
01/25/2012 17:34:23: receiving 77 characters in message <?xml version="1.0" encoding="UTF-8"?><MESSAGE ID="SetCtiAppMode">
</MESSAGE>
01/25/2012 17:34:23: CCTIUserInterface::UIHandleMessage: Message received: SetCtiAppMode.  Parameters:
01/25/2012 17:34:23: CCTIUserInterface::UIHandleMessage: Message received: UPDATE_SID.  Parameters: INSTANCE=https://na5.salesforce.com; SID=00D70000000JY7g!ARgAQNu9apLVC.Jm66lkHVEEGhs0sH8AqMzd.cnt4kBoJcD11IZEuB5bn0ky6hgZ6HrdaBqWFZFJwbfcyHZe_QFOI7FTYucG;
01/25/2012 17:34:23: CCTIAppExchange::SetSessionInstanceAndSid: Setting URL to https://na5.salesforce.com/services/Soap/c/17.0
01/25/2012 17:34:24: receiving 1461 characters in message <?xml version="1.0" encoding="UTF-8"?><MESSAGE ID="CONNECT">
<PARAMETER NAME="/displayNameLabel" VALUE="Display Name"/><PARAMETER NAME="/internalNameLabel" VALUE="Internal Name"/><PARAMETER NAME="/reqDialingOptions/reqInternationalPrefix" VALUE="00023"/><PARAMETER NAME="/reqDialingOptions/reqLongDistPrefix" VALUE="0023"/><PARAMETER NAME="/reqDialingOptions/reqOutsidePrefix" VALUE="0"/><PARAMETER NAME="/reqGeneralInfo/reqAdapterUrl" VALUE="http://localhost:11000"/><PARAMETER NAME="/reqGeneralInfo/reqDescription" VALUE="Call Center Adapter"/><PARAMETER NAME="/reqGeneralInfo/reqProgId" VALUE="CTIConnector.Adapter.1"/><PARAMETER NAME="/reqGeneralInfo/reqVersion" VALUE="4.0"/><PARAMETER NAME="/serverInfo/InstanceName" VALUE="opagent573"/><PARAMETER NAME="/serverInfo/InstancePort" VALUE="1500"/><PARAMETER NAME="/serverInfo/IntegrationServerUrl" VALUE="http://blabla/integrationserveroperams"/><PARAMETER NAME="/serverInfo/InternalExtensionLength" VALUE="4"/><PARAMETER NAME="/serverInfo/LogInternalCalls" VALUE="false"/><PARAMETER NAME="/serverInfo/SearchInternalCalls" VALUE="false"/><PARAMETER NAME="/serverInfo/SiteName" VALUE="default"/><PARAMETER NAME="/Mappings/cnpjconta" VALUE="Account.CNPJ__c"/><PARAMETER NAME="/Mappings/cpfconta" VALUE="Account.CPF__pc"/><PARAMETER NAME="/Mappings/cpfcontato" VALUE="Contact.CPF__c"/><PARAMETER NAME="/Mappings/FieldsCount" VALUE="3"/></MESSAGE>
01/25/2012 17:34:24: CCTIUserInterface::UIHandleMessage: Message received: CONNECT.  Parameters: /displayNameLabel=Display Name; /internalNameLabel=Internal Name; /reqDialingOptions/reqInternationalPrefix=00023; /reqDialingOptions/reqLongDistPrefix=0023; /reqDialingOptions/reqOutsidePrefix=0; /reqGeneralInfo/reqAdapterUrl=http://localhost:11000; /reqGeneralInfo/reqDescription=Call Center Adapter; /reqGeneralInfo/reqProgId=CTIConnector.Adapter.1; /reqGeneralInfo/reqVersion=4.0; /serverInfo/InstanceName=opagent573; /serverInfo/InstancePort=1500; /serverInfo/IntegrationServerUrl=http://blabla/integrationserveroperams; /serverInfo/InternalExtensionLength=4; /serverInfo/LogInternalCalls=false; /serverInfo/SearchInternalCalls=false; /serverInfo/SiteName=default; /Mappings/cnpjconta=Account.CNPJ__c; /Mappings/cpfconta=Account.CPF__pc; /Mappings/cpfcontato=Contact.CPF__c; /Mappings/FieldsCount=3;
01/25/2012 17:34:24: Found connection parameter /displayNameLabel=Display Name.
01/25/2012 17:34:24: Found connection parameter /internalNameLabel=Internal Name.
01/25/2012 17:34:24: Found connection parameter /reqDialingOptions/reqInternationalPrefix=00023.
01/25/2012 17:34:24: Found connection parameter /reqDialingOptions/reqLongDistPrefix=0023.
01/25/2012 17:34:24: Found connection parameter /reqDialingOptions/reqOutsidePrefix=0.
01/25/2012 17:34:24: Found connection parameter /reqGeneralInfo/reqAdapterUrl=http://localhost:11000.
01/25/2012 17:34:24: Found connection parameter /reqGeneralInfo/reqDescription=Call Center Adapter.
01/25/2012 17:34:24: Found connection parameter /reqGeneralInfo/reqProgId=CTIConnector.Adapter.1.
01/25/2012 17:34:24: Found connection parameter /reqGeneralInfo/reqVersion=4.0.
01/25/2012 17:34:24: Found connection parameter /serverInfo/InstanceName=opagent573.
01/25/2012 17:34:24: Found connection parameter /serverInfo/InstancePort=1500.
01/25/2012 17:34:24: Found connection parameter /serverInfo/IntegrationServerUrl=http://blabla/integrationserveroperams.
01/25/2012 17:34:24: Found connection parameter /serverInfo/InternalExtensionLength=4.
01/25/2012 17:34:24: Found connection parameter /serverInfo/LogInternalCalls=false.
01/25/2012 17:34:24: Found connection parameter /serverInfo/SearchInternalCalls=false.
01/25/2012 17:34:24: Found connection parameter /serverInfo/SiteName=default.
01/25/2012 17:34:24: Found connection parameter /Mappings/cnpjconta=Account.CNPJ__c.
01/25/2012 17:34:24: Found connection parameter /Mappings/cpfconta=Account.CPF__pc.
01/25/2012 17:34:24: Found connection parameter /Mappings/cpfcontato=Contact.CPF__c.
01/25/2012 17:34:24: Found connection parameter /Mappings/FieldsCount=3.
01/25/2012 17:34:24: CUserInterface::CTIConnect() Adapter version 1.1 - Connect parameters: http://blabla/integrationserveroperams, opagent573:1500, default
01/25/2012 17:34:24: > Connector::Connect( http://blabla/integrationserveroperams )
01/25/2012 17:34:24: > Connector::Connect() -> Auto Wrapup is OFF
01/25/2012 17:34:24: < Connector::Connect( http://blabla/integrationserveroperams )
01/25/2012 17:34:24: OnCTIConnection called.
01/25/2012 17:34:24: Sending XML (len 400): <CTIUserInterface LOGGED_IN="false"><CTIForm><CTIEditBox ID="CUSTOM1" LABEL="Instance Name" VALUE=""/><CTIEditBox ID="AGENT_ID" LABEL="Agent Id" VALUE=""/><CTIEditBox ID="PASSWORD" PASSWORD="true" VALUE=""/><CTIEditBox ID="CUSTOM2" LABEL="Site" VALUE=""/><CTIEditBox ID="EXTENSION" VALUE=""/><CTIButton COLOR="GREEN" ID="LOGIN" LONG_STYLE="true"/></CTIForm><CTILogo/></CTIUserInterface>
01/25/2012 17:34:24: receiving 74 characters in message <?xml version="1.0" encoding="UTF-8"?><MESSAGE ID="UPDATE_XML">
</MESSAGE>
01/25/2012 17:34:24: CCTIUserInterface::UIHandleMessage: Message received: UPDATE_XML.  Parameters:
01/25/2012 17:34:24: Sending XML (len 400): <CTIUserInterface LOGGED_IN="false"><CTIForm><CTIEditBox ID="CUSTOM1" LABEL="Instance Name" VALUE=""/><CTIEditBox ID="AGENT_ID" LABEL="Agent Id" VALUE=""/><CTIEditBox ID="PASSWORD" PASSWORD="true" VALUE=""/><CTIEditBox ID="CUSTOM2" LABEL="Site" VALUE=""/><CTIEditBox ID="EXTENSION" VALUE=""/><CTIButton COLOR="GREEN" ID="LOGIN" LONG_STYLE="true"/></CTIForm><CTILogo/></CTIUserInterface>
01/25/2012 17:34:24: CCTIAppExchange::SetSessionInstanceAndSid: Setting SID to 00D70000000JY7g!ARgAQNu9apLVC.Jm66lkHVEEGhs0sH8AqMzd.cnt4kBoJcD11IZEuB5bn0ky6hgZ6HrdaBqWFZFJwbfcyHZe_QFOI7FTYucG
01/25/2012 17:34:24: CCTIAppExchange::SetSessionInstanceAndSid: Proxy set to http://titan.ascorp.net:8080:
01/25/2012 17:34:24: CCTIAppExchange::SetSessionInstanceAndSid: Setting URL to https://na5.salesforce.com/services/Soap/c/17.0
01/25/2012 17:34:24: CCTIAppExchange::UpdateSid: New user detected!  Updating cached information.
01/25/2012 17:34:24: UserId set to 005700000015PHAAA2.
01/25/2012 17:34:24: CCTIAppExchange::UpdateSid: User SOMEUSER authenticated.
01/25/2012 17:34:24: CCTIAppExchange::SetSessionInstanceAndSid: Setting URL to https://na5.salesforce.com/services/Soap/c/17.0
01/25/2012 17:34:24: CCTIAppExchange::LoadUserParamsFromCustomSetup: parameters[AGENT_ID] = agent2
01/25/2012 17:34:24: CCTIAppExchange::LoadUserParamsFromCustomSetup: parameters[CUSTOM1] = opagent573:1500
01/25/2012 17:34:24: CCTIAppExchange::LoadUserParamsFromCustomSetup: parameters[CUSTOM2] = porto
01/25/2012 17:34:24: CCTIAppExchange::LoadUserParamsFromCustomSetup: parameters[CUSTOM4] = true
01/25/2012 17:34:24: CCTIAppExchange::LoadUserParamsFromCustomSetup: parameters[EXTENSION] = 1
01/25/2012 17:34:24: CCTIAppExchange::LoadUserParamsFromCustomSetup: parameters[PASSWORD] =
01/25/2012 17:34:24: CCTIAppExchange::LoadUserParamsFromCustomSetup: parameters[] =
01/25/2012 17:34:25: CCTIAppExchange::SetSessionInstanceAndSid: Setting SID to 00D70000000JY7g!ARgAQNu9apLVC.Jm66lkHVEEGhs0sH8AqMzd.cnt4kBoJcD11IZEuB5bn0ky6hgZ6HrdaBqWFZFJwbfcyHZe_QFOI7FTYucG
01/25/2012 17:34:25: CCTIAppExchange::SetSessionInstanceAndSid: Proxy set to http://titan.ascorp.net:8080:
01/25/2012 17:34:25: CCTIAppExchange::SetSessionInstanceAndSid: Setting SID to 00D70000000JY7g!ARgAQNu9apLVC.Jm66lkHVEEGhs0sH8AqMzd.cnt4kBoJcD11IZEuB5bn0ky6hgZ6HrdaBqWFZFJwbfcyHZe_QFOI7FTYucG
01/25/2012 17:34:25: CCTIAppExchange::SetSessionInstanceAndSid: Proxy set to http://titan.ascorp.net:8080:

 I worked around this problem by setting an event on the BrowserConnector code, but this doesn't feel right since it takes a few seconds for the login form to be filled and during that time interval it is presented empty...

Nevertheless here is what I did:

//[jars@20120125: Race condition between UPDATE_SID and CONNECT messages results on login form being sent empty before custom user data is retrieved.
        //At least this is the case when a custom LoadUserParamsFromCustomSetup is implemented on a class derived from CCTIAppExchange.
        ManualResetEvent sid_event = new ManualResetEvent(true);

...


        /**
         * callback delegates
         **/
        private void ProcessRequest(IAsyncResult result)
        {
            HttpListenerContext context = httpListener.EndGetContext(result);
            HttpListenerRequest request = context.Request;
            HttpListenerResponse response = context.Response;
            NameValueCollection queryString = getQueryStringFromRequest(request);
            string requestRawUrl = request.RawUrl.ToString();

            sid_event.WaitOne();

...       
        private void initialize(object mapQueryString)
        {
            //[jars]
            sid_event.Reset();
            Logger.WriteLogEntry(Logger.LOGLEVEL_HIGH, "Initializer blocking...");
            AdapterLink.SendCommand(Constants.UpdateSidCmd, (Dictionary<string, string>)mapQueryString);
            sid_event.Set();
            Logger.WriteLogEntry(Logger.LOGLEVEL_HIGH, "Initializaer releasing...");

            MessageDispatcher.MessagePump();
        }

 

It would be nice to have a cleaner solution from Salesforce...

Hope this helps!

 

Cheers,

jars