Example #1
0
        public async Task <int> InsertAsync(Sip item)
        {
            using (var conn = new SqlConnection(ConfigurationManager.GetEnvironmentVariable("OalConnectionString")))
                using (var cmd = new SqlCommand(@"INSERT INTO [dbo].[sip_log] (
                               [version],
                              [beat_no],
                              [consignment_no],
                              [courier_id],
                              [data_entry_beat_no],
                              [data_entry_location_id],
                              [data_entry_staff_id],
                              [date_created],
                              [date_created_ori],
                              [date_generated],
                              [date_time],
                              [filename],
                              [last_updated],
                              [location_id],
                              [status],
                              [confirm_location]
                )
                VALUES(
                          @version,
                          @beat_no,
                          @consignment_no,
                          @courier_id,
                          @data_entry_beat_no,
                          @data_entry_location_id,
                          @data_entry_staff_id,
                          @date_created,
                          @date_created_ori,
                          @date_generated,
                          @date_time,
                          @filename,
                          @last_updated,
                          @location_id,
                          @status,
                          @confirm_location
            )", conn))
                {
                    await conn.OpenAsync();

                    cmd.Parameters.Add("@beat_no", SqlDbType.VarChar, 3).Value               = item.beat_no;
                    cmd.Parameters.Add("@courier_id", SqlDbType.VarChar, 255).Value          = item.courier_id;
                    cmd.Parameters.Add("data_entry_location_id", SqlDbType.VarChar, 4).Value = item.data_entry_location_id;
                    cmd.Parameters.Add("@data_entry_staff_id", SqlDbType.VarChar, 255).Value = item.data_entry_staff_id;
                    cmd.Parameters.Add("date_created", SqlDbType.DateTime, 8).Value          = DateTime.Now;
                    cmd.Parameters.Add("@date_created_ori", SqlDbType.DateTime, 8).Value     = item.date_created;
                    cmd.Parameters.Add("@date_generated", SqlDbType.DateTime, 8).Value       = DateTime.Now;
                    cmd.Parameters.Add("@date_time", SqlDbType.DateTime, 8).Value            = item.date_time;
                    cmd.Parameters.Add("@last_updated", SqlDbType.DateTime, 8).Value         = item.last_updated;
                    cmd.Parameters.Add("@filename", SqlDbType.VarChar, 255).Value            = item.filename;
                    cmd.Parameters.Add("@location_id", SqlDbType.VarChar, 4).Value           = item.location_id;
                    cmd.Parameters.Add("@status", SqlDbType.VarChar, 255).Value              = item.status;
                    cmd.Parameters.Add("@data_entry_beat_no", SqlDbType.VarChar, 3).Value    = item.data_entry_beat_no;
                    cmd.Parameters.Add("@confirm_location", SqlDbType.VarChar, 2000).Value   = item.confirm_location;
                    cmd.Parameters.Add("@version", SqlDbType.Int, 19).Value = item.version;
                    return(await cmd.ExecuteNonQueryAsync());
                }
        }
Example #2
0
        public void ProcessResponse(IInternalSoftPhone softPhone, Sip.Stack.SipResponseEvent responseEvent)
        {
            SipStatusLine statusLine = responseEvent.Response.StatusLine;

            _logger.Debug("processing response: {0} ...", statusLine.ResponseCode);

            int statusCodeDiv100 = statusLine.StatusCode / 100;

            if (responseEvent.ClientTransaction == null)
            {
                if (_logger.IsInfoEnabled) _logger.Info("Processing ABORTED. In this state, the ResponseEvent is expected to have a 'NOT NULL' ClientTx. DebugInfo: TxId created from RESPONSE: '{1}'. This Id could not be matched to a clienttransaction in the provider's clienttransactiontable.", statusCodeDiv100, SipProvider.GetClientTransactionId(responseEvent.Response));
                return;
            }

            /*wait for ok on bye*/

            if (_logger.IsInfoEnabled) _logger.Info("'{0}XX' response. Begin processing...", statusCodeDiv100);

            if (statusCodeDiv100 != 2)
            {
                if (_logger.IsInfoEnabled) _logger.Info("Processing ABORTED. Only 'x200-299' responses are processed in this state.");
                return;
            }

            if (responseEvent.ClientTransaction.Request.CSeq.Command == SipMethods.Bye)
            {
                if (_logger.IsInfoEnabled) _logger.Info("Received final response on 'BYE' request.Transitioning to Idle...");

                softPhone.ChangeState(softPhone.StateProvider.GetIdle());
            }
            else
            {
                if (_logger.IsDebugEnabled) _logger.Debug("Response ignored. This is not the response to the 'BYE' request.");
            }
        }
        public void ProcessResponse(IInternalSoftPhone softPhone, Sip.Stack.SipResponseEvent responseEvent)
        {
            SipStatusLine statusLine = responseEvent.Response.StatusLine;

            _logger.Debug("processing response: {0} ...", statusLine.ResponseCode);

            int statusCodeDiv100 = statusLine.StatusCode / 100;

            if (responseEvent.ClientTransaction == null)
            {
                if (_logger.IsInfoEnabled) _logger.Info("Processing ABORTED. In this state, the ResponseEvent is expected to have a 'NOT NULL' ClientTx. DebugInfo: TxId created from RESPONSE: '{1}'. This Id could not be matched to a clienttransaction in the provider's clienttransactiontable.", statusCodeDiv100, SipProvider.GetClientTransactionId(responseEvent.Response));
                return;
            }

            /*wait for ok on cancel + 487 for invite*/

            if (_logger.IsInfoEnabled) _logger.Info("'{0}XX' response. Begin processing...", statusCodeDiv100);

            if (statusCodeDiv100 < 2)
            {
                if (_logger.IsInfoEnabled) _logger.Info("Processing ABORTED. Only FINAL (x200-x500) responses are processed in this state.");
                return;
            }

            if (responseEvent.ClientTransaction.GetId() == softPhone.PendingInvite.CancelTransaction.GetId())
            {
                _receivedFinalCancelStatusCode = responseEvent.Response.StatusLine.StatusCode;

                if (_logger.IsInfoEnabled) _logger.Info("Received final response on 'CANCEL' request. StatusCode: {0}", _receivedFinalCancelStatusCode);
            }

            if (responseEvent.ClientTransaction.GetId() == softPhone.PendingInvite.InviteClientTransaction.GetId())
            {
                if (_logger.IsInfoEnabled) _logger.Info("Received final response on 'INVITE' request.");

                _receivedFinalInviteResponse = true;

                if (_logger.IsDebugEnabled) _logger.Debug("Terminating the Dialog...");

                softPhone.PendingInvite.Dialog.Terminate();

                if (_logger.IsDebugEnabled) _logger.Debug("Dialog terminated.");
            }

            //TODO: use locks.
            if (_receivedFinalCancelStatusCode == 481  || /*when cancel-tx x481 is received, the invite will NOT receive a final response. => go to idle immediately*/
                (_receivedFinalCancelStatusCode == 200 && _receivedFinalInviteResponse))  /*when cancel-tx x200 is received, the invite will receive a final response. => wait for x487  before going to idle*/
            {
                 if (_logger.IsDebugEnabled) _logger.Debug("Changing CallState to 'Cancelled'");

                softPhone.PendingCall.RaiseCallStateChanged(CallState.Cancelled);

                /*go to idle*/
                if (_logger.IsDebugEnabled) _logger.Debug("Both 'CANCEL' & 'INVITE' Tx have received a final response. Transitioning to Idle...");
                softPhone.ChangeState(softPhone.StateProvider.GetIdle());
            }
        }
Example #4
0
        public void TestEmptyElement()
        {
            var elem = new Sip();

            Assert.AreEqual(
                "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + Environment.NewLine +
                "<Sip></Sip>",
                elem.ToString()
                );
        }
Example #5
0
 private async Task DeleteSipRowAsync(Sip item)
 {
     using (var conn = new SqlConnection(ConfigurationManager.GetEnvironmentVariable("OalConnectionString")))
         //using (var conn = new SqlConnection(ConfigurationManager.GetEnvironmentVariable("ConnectionString")))
         using (SqlCommand cmd = new SqlCommand("DELETE FROM dbo.Sip WHERE Id=@Id", conn))
         {
             cmd.Parameters.Add("@id", SqlDbType.Int, 4).Value = item.id;
             await conn.OpenAsync().ConfigureAwait(false);
         }
 }
Example #6
0
    static void Main()
    {
        var response = new VoiceResponse();
        var dial     = new Dial();
        var sip      = new Sip(new Uri("http://example.com"), "jack");

        dial.Append(sip);
        response.Append(dial);

        Console.WriteLine(response.ToString());;
    }
Example #7
0
        public void TestElementWithTextNode()
        {
            var elem = new Sip();

            elem.AddText("Here is the content");

            Assert.AreEqual(
                "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + Environment.NewLine +
                "<Sip>Here is the content</Sip>",
                elem.ToString()
                );
        }
Example #8
0
        public void ProcessRequest(IInternalSoftPhone softPhone, Sip.Stack.SipRequestEvent requestEvent)
        {
            string method = requestEvent.Request.RequestLine.Method;

            _logger.Debug("processing request: {0} ...", method);

            if (method != SipMethods.Bye)
            {
                if (_logger.IsDebugEnabled) _logger.Debug("Received request: '{0}'. Request ignored.", method);
                return;
            }

            if (_logger.IsInfoEnabled)
            {
                _logger.Info("'BYE' received. Begin processing...");
            }

            if (requestEvent.Dialog == null)
            {
                if (_logger.IsInfoEnabled) _logger.Info("Processing ABORTED. A 'BYE' RequestEvent is expected to have a 'NOT NULL' dialog. DebugInfo: DialogId created from BYE: '{0}'. This Id could not be matched to a dialog in the provider's dialogtable.", SipProvider.GetDialogId(requestEvent.Request, true));
                return;
            }

            if (requestEvent.Dialog.GetId() != softPhone.PendingInvite.Dialog.GetId())
            {
                if (_logger.IsInfoEnabled) _logger.Info("Processing ABORTED. The 'BYE' RequestEvent.Dialog, is expected to match only to the Dialog of the PendingInvite. DebugInfo: DialogId created from BYE: '{0}'. This case is not supposed to occur, since the phone can only process ONE dialog at a time. Check what's going on !!", SipProvider.GetDialogId(requestEvent.Request, true));
                return;
            }

            if (_logger.IsDebugEnabled) _logger.Debug("Sending OK response to BYE..");

            var okResponse = requestEvent.Request.CreateResponse(SipResponseCodes.x200_Ok);

            var tx = softPhone.SipProvider.CreateServerTransaction(requestEvent.Request);

            tx.SendResponse(okResponse);

            requestEvent.IsSent = true;

            softPhone.PendingInvite.Dialog.Terminate();

            softPhone.PendingCall.RaiseCallStateChanged(CallState.Completed);

            if (_logger.IsDebugEnabled) _logger.Debug("OK Send.");

            if (_logger.IsInfoEnabled)
            {
                 _logger.Info("Transitioning to 'IDLE'...");
            }

            softPhone.ChangeState(softPhone.StateProvider.GetIdle());
        }
Example #9
0
    static void Main()
    {
        var response = new VoiceResponse();
        var dial     = new Dial();
        var sip      = new Sip(
            new Uri("http://example.com?x-mycustomheader=foo&x-myotherheader=bar"),
            "jack");

        response.Append(sip);
        response.Append(dial);

        Console.WriteLine(response.ToString());;
    }
Example #10
0
        public void TestElementWithExtraAttributes()
        {
            var elem = new Sip();

            elem.SetOption("newParam1", "value");
            elem.SetOption("newParam2", 1);

            Assert.AreEqual(
                "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + Environment.NewLine +
                "<Sip newParam1=\"value\" newParam2=\"1\"></Sip>",
                elem.ToString()
                );
        }
Example #11
0
        public void TestMixedContent()
        {
            var elem = new Sip();

            elem.AddText("before")
            .AddChild("Child").AddText("content");
            elem.AddText("after");

            Assert.AreEqual(
                "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + Environment.NewLine +
                "<Sip>before<Child>content</Child>after</Sip>",
                elem.ToString()
                );
        }
Example #12
0
        public void TestAllowGenericChildNodes()
        {
            var elem = new Sip();

            elem.AddChild("generic-tag").AddText("Content").SetOption("tag", true);

            Assert.AreEqual(
                "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + Environment.NewLine +
                "<Sip>" + Environment.NewLine +
                "  <generic-tag tag=\"True\">Content</generic-tag>" + Environment.NewLine +
                "</Sip>",
                elem.ToString()
                );
        }
Example #13
0
        public void ProcessRequest(IInternalSoftPhone softPhone, Sip.Stack.SipRequestEvent requestEvent)
        {
            string method = requestEvent.Request.RequestLine.Method;

            _logger.Debug("processing request: {0} ...", method);

            if (method != SipMethods.Invite)
            {
                if (_logger.IsDebugEnabled) _logger.Debug("Received request: '{0}'. Request ignored.", method);
                return;
            }

            if(_logger.IsInfoEnabled) _logger.Info("'INVITE' received. Creating 'RINGING' response...");

            var ringingResponse = requestEvent.Request.CreateResponse(SipResponseCodes.x180_Ringing);
            ringingResponse.To.Tag = SipUtil.CreateTag();
            var contactUri = softPhone.AddressFactory.CreateUri("", softPhone.ListeningPoint.ToString());
            ringingResponse.Contacts.Add(softPhone.HeaderFactory.CreateContactHeader(contactUri));

            if (_logger.IsDebugEnabled) _logger.Debug("Sending response ... ");

            var serverTransaction = softPhone.SipProvider.CreateServerTransaction(requestEvent.Request);
            var dialog = softPhone.SipProvider.CreateServerDialog(serverTransaction as SipInviteServerTransaction);
            serverTransaction.SendResponse(ringingResponse);
            requestEvent.IsSent = true;

            if (_logger.IsInfoEnabled) _logger.Info("Response send. Transitioning to 'RINGING' state.");

            softPhone.PendingInvite = new InviteInfo()
            {
                OriginalRequest = requestEvent.Request,
                RingingResponse = ringingResponse,
                From = requestEvent.Request.From.SipUri,
                To = requestEvent.Request.To.SipUri,
                InviteServerTransaction = (SipInviteServerTransaction) serverTransaction,
                IsIncomingCall = true,
                Dialog = dialog
            };

            softPhone.RaiseIncomingCall();/* !! the incoming call event is raised, before any callstate events can occur*/

            softPhone.ChangeState(softPhone.StateProvider.GetRinging());

            if (_logger.IsDebugEnabled) _logger.Debug("'RINGING' response created. Raising Incoming PhoneCall...");

            if (_logger.IsDebugEnabled) _logger.Debug("Raised.");
        }
Example #14
0
		public WcfVoipProvider(Sip.Server.Configuration.VoipProviderConfigurationElement configElem, Sip.Server.Trunk trunk)
		{
			AuthenticationId = configElem.AuthenticationId.ToString();
			DisplayName = configElem.DisplayName.ToString();
			ForwardCallTo = configElem.ForwardIncomingCallTo.Substring(
				configElem.ForwardIncomingCallTo.StartsWith("sip:") ? 4 : 0);
			LocalEndPoint = configElem.LocalEndpoint;
			OutgoingProxy = configElem.OutboundProxyHostname;
			Password = configElem.Password;
			Transport = configElem.Protocol.ToString();
			Hostname = configElem.ServerHostname;
			Username = configElem.Username;

			if (trunk != null)
				ErrorMessage = trunk.ErrorMessage;
			else
				ErrorMessage = @"Loading...";
		}
Example #15
0
        public void TestElementWithParams()
        {
            var elem = new Sip(
                new Uri("https://example.com"),
                "username",
                "password",
                new Uri("https://example.com"),
                Twilio.Http.HttpMethod.Get,
                Promoter.ListOfOne(Sip.EventEnum.Initiated),
                new Uri("https://example.com"),
                Twilio.Http.HttpMethod.Get
                );

            Assert.AreEqual(
                "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + Environment.NewLine +
                "<Sip username=\"username\" password=\"password\" url=\"https://example.com\" method=\"GET\" statusCallbackEvent=\"initiated\" statusCallback=\"https://example.com\" statusCallbackMethod=\"GET\">https://example.com</Sip>",
                elem.ToString()
                );
        }
Example #16
0
    static void Main()
    {
        var response = new VoiceResponse();
        var dial     = new Dial();
        var sip      = new Sip(
            new Uri("http://example.com"),
            "kate",
            statusCallbackEvent: new List <EventEnum>(
                EventEnum.Initiated,
                EventEnum.Ringing,
                EventEnum.Answered,
                EventEnum.Completed
                ),
            statusCallback: new Uri("https://myapp.com/calls/events"),
            statusCallbackMethod: HttpMethod.Post
            );

        dial.Append(sip);
        response.Append(dial);

        Console.WriteLine(response.ToString());;
    }
Example #17
0
        public void ProcessRequest(IInternalSoftPhone softPhone, Sip.Stack.SipRequestEvent requestEvent)
        {
            string method = requestEvent.Request.RequestLine.Method;

            _logger.Debug("processing request: {0} ...", method);

            if (method != SipMethods.Ack)
            {
                if (_logger.IsDebugEnabled) _logger.Debug("Received request: '{0}'. Request ignored.", method);
                return;
            }

            if (_logger.IsInfoEnabled)
            {
                _logger.Info("'ACK' received. Begin processing...");
            }

            if (requestEvent.Dialog == null)
            {
                if (_logger.IsInfoEnabled) _logger.Info("Processing ABORTED. An 'ACK' RequestEvent is expected to have a 'NOT NULL' dialog. DebugInfo: DialogId created from ACK: '{0}'. This Id could not be matched to a dialog in the provider's dialogtable.", SipProvider.GetDialogId(requestEvent.Request, true));
                return;
            }

            if (requestEvent.Dialog.GetId() != softPhone.PendingInvite.Dialog.GetId())
            {
                if (_logger.IsInfoEnabled) _logger.Info("Processing ABORTED. The 'ACK' RequestEvent it's Dialog, is expected to match only to the Dialog of the PendingInvite. DebugInfo: DialogId created from ACK: '{0}'. This case is not supposed to occur, since the phone can only process ONE dialog at a time. Check what's going on !!", SipProvider.GetDialogId(requestEvent.Request, true));
                return;
            }

            if (_logger.IsInfoEnabled)
            {
                _logger.Info("Transitioning to 'ESTABLISHED'...");
            }

            softPhone.ChangeState(softPhone.StateProvider.GetEstablished());
        }
Example #18
0
    static void Main()
    {
        var response = new VoiceResponse();
        var dial     = new Dial(
            record: "record-from-answer",
            timeout: 10,
            hangupOnStar: true,
            callerId: "bob",
            method: HttpMethod.Post,
            action: new Uri("http://example.com/handle_post_dial")
            );

        var sip = new Sip(
            new Uri("http://example.com?customheader=foo"),
            "kate",
            url: new Uri("http://example.com/handle_screening_on_answer"),
            method: HttpMethod.Post
            );

        response.Append(sip);
        response.Append(dial);

        Console.WriteLine(response.ToString());;
    }
Example #19
0
 public void ProcessResponse(Sip.Stack.SipResponseEvent responseEvent)
 {
 }
Example #20
0
 public void ProcessRequest(IInternalSoftPhone softPhone, Sip.Stack.SipRequestEvent requestEvent)
 {
 }
Example #21
0
		public void WriteFrom(Sip.Message.Header header, ByteArrayPart tag)
		{
			if (header.Name.IsValid == true)
			{
				Write(header.Name, C.HCOLON, header.Value);
				if (tag.IsValid == true)
				{
					Write(C.SEMI, C.tag, C.EQUAL, tag);
				}
				Write(C.CRLF);
			}
		}
Example #22
0
		public void WriteTo(Sip.Message.Header header, ByteArrayPart epid1)
		{
			if (header.Name.IsValid == true)
			{
				Write(header.Name, C.HCOLON, header.Value);
				if (epid1.IsValid == true)
				{
					Write(C.SEMI, C.epid, C.EQUAL);
					toEpid = new Range(end, epid1.Length);
					Write(epid1);
				}
				Write(C.CRLF);
			}
		}
Example #23
0
        public void ProcessResponse(IInternalSoftPhone softPhone, Sip.Stack.SipResponseEvent responseEvent)
        {
            SipStatusLine statusLine = responseEvent.Response.StatusLine;

            _logger.Debug("processing response: {0} ...", statusLine.ResponseCode);

            int statusCodeDiv100 = statusLine.StatusCode / 100;

            if (_logger.IsInfoEnabled)
            {
                _logger.Info("'{0}XX' response. Begin processing...", statusCodeDiv100);
            }

            if (responseEvent.ClientTransaction == null)
            {
                if (_logger.IsInfoEnabled) _logger.Info("Processing ABORTED. A '{0}XX' ResponseEvent is expected to have a 'NOT NULL' ClientTx. DebugInfo: TxId created from RESPONSE: '{1}'. This Id could not be matched to a clienttransaction in the provider's clienttransactiontable.", statusCodeDiv100, SipProvider.GetClientTransactionId(responseEvent.Response));
                return;
            }

            if (responseEvent.ClientTransaction.GetId() != softPhone.PendingInvite.InviteClientTransaction.GetId())
            {
                if (_logger.IsInfoEnabled) _logger.Info("Processing ABORTED. The '{0}XX' ResponseEvent.ClientTransaction, is expected to match only to the InviteSendTransaction of the PendingInvite. DebugInfo: TxId created from RESPONSE: '{1}'. This case is not supposed to occur, since the phone can only process ONE PendingInvite at a time. Check what's going on !!", statusCodeDiv100, SipProvider.GetClientTransactionId(responseEvent.Response));
                return;
            }

            if (responseEvent.Dialog == null)
            {
                if (_logger.IsInfoEnabled) _logger.Info("Processing ABORTED. In this state the 'ResponseEvent' is expected to have a 'NOT NULL' dialog. DebugInfo: DialogId created from Response: '{0}'. This Id could not be matched to a dialog in the provider's dialogtable.", SipProvider.GetDialogId(responseEvent.Response, false));
                return;
            }

            if (responseEvent.Dialog.GetId() != softPhone.PendingInvite.Dialog.GetId())
            {
                if (_logger.IsInfoEnabled) _logger.Info("Processing ABORTED. In this state the 'ResponseEvent' it's Dialog, is expected to match only to the Dialog of the PendingInvite. DebugInfo: DialogId created from response: '{0}'. This case is not supposed to occur, since the phone can only process ONE dialog at a time. Check what's going on !!", SipProvider.GetDialogId(responseEvent.Response, false));
                return;
            }

            if (statusCodeDiv100 == 1)
            {
                if (_logger.IsInfoEnabled) _logger.Info("Do nothing");
            }
            else if (statusCodeDiv100 == 2)
            {
                if (_logger.IsInfoEnabled) _logger.Info("Transitioning to 'ESTABLISHED'...");

                Check.IsTrue(responseEvent.Dialog is SipInviteClientDialog, "Failed to respond to '200' response with ACK request. The 'ACK' can not be created. The responseEvent.Dialog is expected to be of type SipInviteClientDialog.");

                var clientDialog = (SipInviteClientDialog) softPhone.PendingInvite.Dialog;
                var ack = clientDialog.CreateAck();
                clientDialog.SendAck(ack);

                softPhone.ChangeState(softPhone.StateProvider.GetEstablished());
            }
            else
            {
                //change callstate. Don't go automatically to 'IDLE' state, but wait for the api user to invoke Call.Stop()
                if (statusLine.ResponseCode == SipResponseCodes.x486_Busy_Here)
                {
                    if (_logger.IsDebugEnabled) _logger.Debug("Changing CallState to 'BusyHere'");
                    softPhone.PendingCall.RaiseCallStateChanged(CallState.BusyHere);
                }
                else
                {
                    if (_logger.IsDebugEnabled) _logger.Debug("Changing CallState to 'Error'");
                    softPhone.PendingCall.RaiseCallStateChanged(CallState.Error);
                }

                softPhone.PendingInvite.Dialog.Terminate();
            }
        }
Example #24
0
 public void ProcessResponse(IInternalSoftPhone softPhone, Sip.Stack.SipResponseEvent responseEvent)
 {
 }
Example #25
0
		public WcfVoipProvider(Sip.Server.Trunk trunk)
		{
			Hostname = trunk.Domain.ToString();
			Username = trunk.Username;
			ErrorMessage = trunk.ErrorMessage;
		}
Example #26
0
 public void TrunkUpdated(Sip.Server.Trunk trunk)
 {
     if (callback != null)
     {
         try
         {
             callback.VoipProviderUpdated(new WcfVoipProvider(trunk));
         }
         catch
         {
             callback = null;
         }
     }
 }