private void Answered(SDP sdp)
        {
            Console.WriteLine("XMPP client call answered.");

            IsUACAnswered = true;

            SIPResponse okResponse = new SIPResponse(SIPResponseStatusCodesEnum.Ok, "Ok", new SIPEndPoint(new IPEndPoint(IPAddress.Loopback, 0)));
            okResponse.Header.ContentType = SDP.SDP_MIME_CONTENTTYPE;
            okResponse.Body = sdp.ToString();

            SIPDialogue = new SIPDialogue(null, null, null, null, -1, null, null, null, Guid.NewGuid(), Owner, AdminMemberId, null, sdp.ToString());
            SIPDialogue.CallDurationLimit = CallDescriptor.CallDurationLimit;

            CallAnswered(this, okResponse);
        }
Exemple #2
0
        private RegisterResultEnum Register(SIPTransaction registerTransaction)
        {
            try
            {
                SIPRequest  sipRequest      = registerTransaction.TransactionRequest;
                SIPURI      registerURI     = sipRequest.URI;
                SIPToHeader toHeader        = sipRequest.Header.To;
                string      toUser          = toHeader.ToURI.User;
                string      canonicalDomain = toHeader.ToURI.Host;
                int         requestedExpiry = GetRequestedExpiry(sipRequest);

                if (canonicalDomain == null)
                {
                    SIPResponse noDomainResponse = GetErrorResponse(sipRequest, SIPResponseStatusCodesEnum.Forbidden,
                                                                    "Domain not serviced");
                    registerTransaction.SendFinalResponse(noDomainResponse);
                    return(RegisterResultEnum.DomainNotServiced);
                }

                SIPAccount sipAccount = new SIPAccount
                {
                    Id          = Guid.NewGuid(),
                    Owner       = "admin",
                    SIPUsername = toUser,
                    SIPDomain   = canonicalDomain
                };
                SIPRequestAuthenticationResult authenticationResult =
                    _sipRequestAuthenticator_External?.Invoke(registerTransaction.LocalSIPEndPoint,
                                                              registerTransaction.RemoteEndPoint, sipRequest, sipAccount);

                if (!_needAuthentication)
                {
                    SIPResponse okRes = GetOkResponse(sipRequest);

                    registerTransaction.SendFinalResponse(okRes);


                    if (requestedExpiry > 0)
                    {
                        CacheDeviceItem(sipRequest);

                        RegisterReceived?.Invoke(sipRequest, _localSipAccount);
                    }

                    if (requestedExpiry == 0)
                    {
                        RemoveDeviceItem(sipRequest);
                        UnRegisterReceived?.Invoke(sipRequest, _localSipAccount);
                    }


                    return(RegisterResultEnum.AuthenticationRequired);
                }

                if (!authenticationResult.Authenticated)
                {
                    // 401 Response with a fresh nonce needs to be sent.
                    SIPResponse authReqdResponse =
                        SIPTransport.GetResponse(sipRequest, authenticationResult.ErrorResponse, null);
                    authReqdResponse.Header.AuthenticationHeader = authenticationResult.AuthenticationRequiredHeader;
                    registerTransaction.SendFinalResponse(authReqdResponse);

                    if (authenticationResult.ErrorResponse == SIPResponseStatusCodesEnum.Forbidden)
                    {
                        return(RegisterResultEnum.Forbidden);
                    }
                    else
                    {
                        return(RegisterResultEnum.AuthenticationRequired);
                    }
                }
                else
                {
                    if (sipRequest.Header.Contact == null || sipRequest.Header.Contact.Count == 0)
                    {
                        SIPResponse okResponse = GetOkResponse(sipRequest);

                        registerTransaction.SendFinalResponse(okResponse);


                        if (requestedExpiry > 0)
                        {
                            CacheDeviceItem(sipRequest);
                            RegisterReceived?.Invoke(sipRequest, _localSipAccount);
                        }

                        if (requestedExpiry == 0)
                        {
                            RemoveDeviceItem(sipRequest);
                            UnRegisterReceived?.Invoke(sipRequest, _localSipAccount);
                        }
                    }
                    else
                    {
                        SIPEndPoint uacRemoteEndPoint = SIPEndPoint.TryParse(sipRequest.Header.ProxyReceivedFrom) ??
                                                        registerTransaction.RemoteEndPoint;
                        SIPEndPoint proxySIPEndPoint            = SIPEndPoint.TryParse(sipRequest.Header.ProxyReceivedOn);
                        SIPEndPoint registrarEndPoint           = registerTransaction.LocalSIPEndPoint;
                        SIPResponseStatusCodesEnum updateResult = SIPResponseStatusCodesEnum.Ok;
                        DateTime startTime = DateTime.Now;
                        TimeSpan duration  = DateTime.Now.Subtract(startTime);

                        if (updateResult == SIPResponseStatusCodesEnum.Ok)
                        {
                            string proxySocketStr = (proxySIPEndPoint != null)
                                ? " (proxy=" + proxySIPEndPoint.ToString() + ")"
                                : null;
                            SIPResponse okResponse = GetOkResponse(sipRequest);
                            registerTransaction.SendFinalResponse(okResponse);
                            if (requestedExpiry > 0)
                            {
                                CacheDeviceItem(sipRequest);
                                RegisterReceived?.Invoke(sipRequest, _localSipAccount);
                            }

                            if (requestedExpiry == 0)
                            {
                                RemoveDeviceItem(sipRequest);
                                UnRegisterReceived?.Invoke(sipRequest, _localSipAccount);
                            }
                        }
                        else
                        {
                            sipRequest.Header.Contact[0].Expires = m_minimumBindingExpiry;
                            SIPResponse okResponse = GetOkResponse(sipRequest);
                            registerTransaction.SendFinalResponse(okResponse);
                        }
                    }

                    return(RegisterResultEnum.Authenticated);
                }
            }
            catch (Exception excp)
            {
                string regErrorMessage = "Exception registrarcore registering. ->" + excp.Message + "->" +
                                         registerTransaction.TransactionRequest.ToString();
                Logger.Logger.Error(regErrorMessage);

                try
                {
                    SIPResponse errorResponse = GetErrorResponse(registerTransaction.TransactionRequest,
                                                                 SIPResponseStatusCodesEnum.InternalServerError, null);
                    registerTransaction.SendFinalResponse(errorResponse);
                }
                catch
                {
                }

                return(RegisterResultEnum.Error);
            }
        }
Exemple #3
0
 /// <summary>
 /// A ringing response has been received from the remote SIP UAS on an outgoing call.
 /// </summary>
 private void CallRinging(ISIPClientUserAgent uac, SIPResponse sipResponse)
 {
     StatusMessage(this, "Call ringing: " + sipResponse.StatusCode + " " + sipResponse.ReasonPhrase + ".");
 }
Exemple #4
0
        /// <summary>
        /// Handles responses to our re-INVITE requests.
        /// </summary>
        /// <param name="localSIPEndPoint">The local end point the response was received on.</param>
        /// <param name="remoteEndPoint">The remote end point the response came from.</param>
        /// <param name="sipTransaction">The UAS transaction the response is part of.</param>
        /// <param name="sipResponse">The SIP response.</param>
        private Task <SocketError> ReinviteRequestFinalResponseReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse)
        {
            if (sipResponse.Status == SIPResponseStatusCodesEnum.Ok)
            {
                // Update the remote party's SDP.
                Dialogue.RemoteSDP = sipResponse.Body;
                MediaSession.setRemoteDescription(new RTCSessionDescription {
                    sdp = SDP.ParseSDPDescription(sipResponse.Body), type = RTCSdpType.answer
                });
            }
            else
            {
                logger.LogWarning($"Re-INVITE request failed with response {sipResponse.ShortDescription}.");
            }

            return(Task.FromResult(SocketError.Success));
        }
 private void FireCallAnswered(SIPClientUserAgent uac, SIPResponse answeredResponse)
 {
     if (CallAnswered != null)
     {
         CallAnswered(uac, answeredResponse);
     }
 }
Exemple #6
0
        /// <summary>
        /// The event handler for responses to the initial register request.
        /// </summary>
        private void ServerResponseReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse)
        {
            try
            {
                Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterInProgress, "Server response " + sipResponse.Status + " received for " + m_sipAccountAOR.ToString() + ".", m_owner));

                if (sipResponse.Status == SIPResponseStatusCodesEnum.ProxyAuthenticationRequired || sipResponse.Status == SIPResponseStatusCodesEnum.Unauthorised)
                {
                    if (sipResponse.Header.AuthenticationHeader != null)
                    {
                        if (m_attempts >= MAX_REGISTER_ATTEMPTS)
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Registration to " + m_sipAccountAOR.ToString() + " reached the maximum number of allowed attempts without a failure condition.", m_owner));
                            m_isRegistered = false;
                            if (RegistrationTemporaryFailure != null)
                            {
                                RegistrationTemporaryFailure(m_sipAccountAOR, "Registration reached the maximum number of allowed attempts.");
                            }
                            m_waitForRegistrationMRE.Set();
                        }
                        else
                        {
                            m_attempts++;
                            SIPRequest authenticatedRequest            = GetAuthenticatedRegistrationRequest(sipTransaction.TransactionRequest, sipResponse);
                            SIPNonInviteTransaction regAuthTransaction = m_sipTransport.CreateNonInviteTransaction(authenticatedRequest, sipTransaction.RemoteEndPoint, localSIPEndPoint, m_outboundProxy);
                            regAuthTransaction.NonInviteTransactionFinalResponseReceived += (lep, rep, tn, rsp) => { ThreadPool.QueueUserWorkItem(delegate { AuthResponseReceived(lep, rep, tn, rsp); }); };
                            regAuthTransaction.NonInviteTransactionTimedOut += (tn) => { ThreadPool.QueueUserWorkItem(delegate { RegistrationTimedOut(tn); }); };
                            m_sipTransport.SendSIPReliable(regAuthTransaction);
                        }
                    }
                    else
                    {
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Registration failed with " + sipResponse.Status + " but no authentication header was supplied for " + m_sipAccountAOR.ToString() + ".", m_owner));
                        m_isRegistered = false;
                        if (RegistrationTemporaryFailure != null)
                        {
                            RegistrationTemporaryFailure(m_sipAccountAOR, "Registration failed with " + sipResponse.Status + " but no authentication header was supplied.");
                        }
                        m_waitForRegistrationMRE.Set();
                    }
                }
                else
                {
                    if (sipResponse.Status == SIPResponseStatusCodesEnum.Ok)
                    {
                        if (m_expiry > 0)
                        {
                            m_isRegistered = true;
                            m_expiry       = GetUpdatedExpiry(sipResponse);
                            //if (sipResponse.Header.SwitchboardToken != null && m_lastServerNonce != null)
                            //{
                            //    SwitchboardToken = Crypto.SymmetricDecrypt(m_password, m_lastServerNonce, sipResponse.Header.SwitchboardToken);
                            //}
                            RegistrationSuccessful(m_sipAccountAOR);
                        }
                        else
                        {
                            m_isRegistered = false;
                            RegistrationRemoved(m_sipAccountAOR);
                        }

                        m_waitForRegistrationMRE.Set();
                    }
                    else if (sipResponse.Status == SIPResponseStatusCodesEnum.Forbidden || sipResponse.Status == SIPResponseStatusCodesEnum.NotFound)
                    {
                        // SIP account does not appear to exist.
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Registration failed with " + sipResponse.Status + " for " + m_sipAccountAOR.ToString() + ", no further registration attempts will be made.", m_owner));
                        string reasonPhrase = (sipResponse.ReasonPhrase.IsNullOrBlank()) ? sipResponse.Status.ToString() : sipResponse.ReasonPhrase;
                        if (RegistrationFailed != null)
                        {
                            RegistrationFailed(m_sipAccountAOR, "Registration failed with " + (int)sipResponse.Status + " " + reasonPhrase + ".");
                        }
                        m_exit = true;
                        m_waitForRegistrationMRE.Set();
                    }
                    else if (sipResponse.Status == SIPResponseStatusCodesEnum.IntervalTooBrief && m_expiry != 0)
                    {
                        m_expiry = GetUpdatedExpiryForIntervalTooBrief(sipResponse);
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterInProgress, "Registration for " + m_sipAccountAOR.ToString() + " had a too short expiry, updated to +" + m_expiry + " and trying again.", m_owner));
                        SendInitialRegister();
                    }
                    else
                    {
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Registration failed with " + sipResponse.Status + " for " + m_sipAccountAOR.ToString() + ".", m_owner));
                        m_isRegistered = false;
                        if (RegistrationTemporaryFailure != null)
                        {
                            RegistrationTemporaryFailure(m_sipAccountAOR, "Registration failed with " + sipResponse.Status + ".");
                        }
                        m_waitForRegistrationMRE.Set();
                    }
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception SIPRegistrationUserAgent ServerResponseReceived (" + remoteEndPoint + "). " + excp.Message);
            }
        }
Exemple #7
0
        /// <summary>
        /// The event handler for responses to the authenticated register request.
        /// </summary>
        private void AuthResponseReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse)
        {
            string reasonPhrase = (sipResponse.ReasonPhrase.IsNullOrBlank()) ? sipResponse.Status.ToString() : sipResponse.ReasonPhrase;

            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Server response " + sipResponse.Status + " " + reasonPhrase + " received for authenticated " + sipTransaction.TransactionRequest.Method + " to " + m_callDescriptor.Uri + ".", m_owner));

            if (ResponseReceived != null)
            {
                ResponseReceived(sipResponse);
            }
        }
Exemple #8
0
        static void Main(string[] args)
        {
            Console.WriteLine("SIPSorcery user agent server example.");
            Console.WriteLine("Press h to hangup a call or ctrl-c to exit.");

            EnableConsoleLogger();

            IPAddress listenAddress     = IPAddress.Any;
            IPAddress listenIPv6Address = IPAddress.IPv6Any;

            if (args != null && args.Length > 0)
            {
                if (!IPAddress.TryParse(args[0], out var customListenAddress))
                {
                    Log.LogWarning($"Command line argument could not be parsed as an IP address \"{args[0]}\"");
                    listenAddress = IPAddress.Any;
                }
                else
                {
                    if (customListenAddress.AddressFamily == AddressFamily.InterNetwork)
                    {
                        listenAddress = customListenAddress;
                    }
                    if (customListenAddress.AddressFamily == AddressFamily.InterNetworkV6)
                    {
                        listenIPv6Address = customListenAddress;
                    }
                }
            }

            // Set up a default SIP transport.
            var sipTransport = new SIPTransport();

            var localhostCertificate = new X509Certificate2("localhost.pfx");

            // IPv4 channels.
            sipTransport.AddSIPChannel(new SIPUDPChannel(new IPEndPoint(listenAddress, SIP_LISTEN_PORT)));
            sipTransport.AddSIPChannel(new SIPTCPChannel(new IPEndPoint(listenAddress, SIP_LISTEN_PORT)));
            sipTransport.AddSIPChannel(new SIPTLSChannel(localhostCertificate, new IPEndPoint(listenAddress, SIPS_LISTEN_PORT)));
            sipTransport.AddSIPChannel(new SIPWebSocketChannel(IPAddress.Any, SIP_WEBSOCKET_LISTEN_PORT));
            sipTransport.AddSIPChannel(new SIPWebSocketChannel(IPAddress.Any, SIP_SECURE_WEBSOCKET_LISTEN_PORT, localhostCertificate));

            // IPv6 channels.
            sipTransport.AddSIPChannel(new SIPUDPChannel(new IPEndPoint(listenIPv6Address, SIP_LISTEN_PORT)));
            sipTransport.AddSIPChannel(new SIPTCPChannel(new IPEndPoint(listenIPv6Address, SIP_LISTEN_PORT)));
            sipTransport.AddSIPChannel(new SIPTLSChannel(localhostCertificate, new IPEndPoint(listenIPv6Address, SIPS_LISTEN_PORT)));
            sipTransport.AddSIPChannel(new SIPWebSocketChannel(IPAddress.IPv6Any, SIP_WEBSOCKET_LISTEN_PORT));
            sipTransport.AddSIPChannel(new SIPWebSocketChannel(IPAddress.IPv6Any, SIP_SECURE_WEBSOCKET_LISTEN_PORT, localhostCertificate));

            EnableTraceLogs(sipTransport);

            // To keep things a bit simpler this example only supports a single call at a time and the SIP server user agent
            // acts as a singleton
            SIPServerUserAgent      uas        = null;
            CancellationTokenSource rtpCts     = null; // Cancellation token to stop the RTP stream.
            RTPMediaSession         rtpSession = null;

            // Because this is a server user agent the SIP transport must start listening for client user agents.
            sipTransport.SIPTransportRequestReceived += async(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest sipRequest) =>
            {
                try
                {
                    if (sipRequest.Method == SIPMethodsEnum.INVITE)
                    {
                        SIPSorcery.Sys.Log.Logger.LogInformation($"Incoming call request: {localSIPEndPoint}<-{remoteEndPoint} {sipRequest.URI}.");

                        // Check there's a codec we support in the INVITE offer.
                        var        offerSdp       = SDP.ParseSDPDescription(sipRequest.Body);
                        IPEndPoint dstRtpEndPoint = SDP.GetSDPRTPEndPoint(sipRequest.Body);
                        string     audioFile      = null;

                        if (offerSdp.Media.Any(x => x.Media == SDPMediaTypesEnum.audio && x.HasMediaFormat((int)SDPMediaFormatsEnum.G722)))
                        {
                            Log.LogDebug($"Using G722 RTP media type and audio file {AUDIO_FILE_G722}.");
                            rtpSession = new RTPMediaSession(SDPMediaTypesEnum.audio, (int)SDPMediaFormatsEnum.G722, dstRtpEndPoint.AddressFamily);
                            audioFile  = AUDIO_FILE_G722;
                        }
                        else if (offerSdp.Media.Any(x => x.Media == SDPMediaTypesEnum.audio && x.HasMediaFormat((int)SDPMediaFormatsEnum.PCMU)))
                        {
                            Log.LogDebug($"Using PCMU RTP media type and audio file {AUDIO_FILE_PCMU}.");
                            rtpSession = new RTPMediaSession(SDPMediaTypesEnum.audio, (int)SDPMediaFormatsEnum.PCMU, dstRtpEndPoint.AddressFamily);
                            audioFile  = AUDIO_FILE_PCMU;
                        }

                        if (rtpSession == null)
                        {
                            // Didn't get a match on the codecs we support.
                            SIPResponse noMatchingCodecResponse = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.NotAcceptableHere, null);
                            await sipTransport.SendResponseAsync(noMatchingCodecResponse);
                        }
                        else
                        {
                            // If there's already a call in progress hang it up. Of course this is not ideal for a real softphone or server but it
                            // means this example can be kept simpler.
                            if (uas?.IsHungup == false)
                            {
                                uas?.Hangup(false);
                            }
                            rtpCts?.Cancel();
                            rtpCts = new CancellationTokenSource();

                            UASInviteTransaction uasTransaction = new UASInviteTransaction(sipTransport, sipRequest, null);
                            uas = new SIPServerUserAgent(sipTransport, null, null, null, SIPCallDirection.In, null, null, null, uasTransaction);
                            uas.CallCancelled += (uasAgent) =>
                            {
                                rtpCts?.Cancel();
                                rtpSession.CloseSession(null);
                            };
                            rtpSession.OnRtpClosed += (reason) => uas?.Hangup(false);
                            uas.Progress(SIPResponseStatusCodesEnum.Trying, null, null, null, null);
                            uas.Progress(SIPResponseStatusCodesEnum.Ringing, null, null, null, null);

                            // The RTP socket is listening on IPAddress.Any but the IP address placed into the SDP needs to be one the caller can reach.
                            IPAddress rtpAddress = NetServices.GetLocalAddressForRemote(dstRtpEndPoint.Address);

                            // Only set the remote RTP end point if there hasn't already been a packet received on it.
                            if (rtpSession.DestinationEndPoint == null)
                            {
                                rtpSession.SetRemoteSDP(SDP.ParseSDPDescription(sipRequest.Body));
                                Log.LogDebug($"Remote RTP socket {rtpSession.DestinationEndPoint}.");
                            }

                            rtpSession.SetRemoteSDP(SDP.ParseSDPDescription(sipRequest.Body));

                            _ = Task.Run(() => SendRtp(rtpSession, dstRtpEndPoint, audioFile, rtpCts))
                                .ContinueWith(_ =>
                            {
                                if (uas?.IsHungup == false)
                                {
                                    uas?.Hangup(false);
                                    rtpSession?.CloseSession(null);
                                }
                            });

                            uas.Answer(SDP.SDP_MIME_CONTENTTYPE, rtpSession.GetSDP(rtpAddress).ToString(), null, SIPDialogueTransferModesEnum.NotAllowed);
                        }
                    }
                    else if (sipRequest.Method == SIPMethodsEnum.BYE)
                    {
                        SIPSorcery.Sys.Log.Logger.LogInformation("Call hungup.");
                        SIPResponse byeResponse = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null);
                        await sipTransport.SendResponseAsync(byeResponse);

                        uas?.Hangup(true);
                        rtpSession?.CloseSession(null);
                        rtpCts?.Cancel();
                    }
                    else if (sipRequest.Method == SIPMethodsEnum.SUBSCRIBE)
                    {
                        SIPResponse notAllowededResponse = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.MethodNotAllowed, null);
                        await sipTransport.SendResponseAsync(notAllowededResponse);
                    }
                    else if (sipRequest.Method == SIPMethodsEnum.OPTIONS || sipRequest.Method == SIPMethodsEnum.REGISTER)
                    {
                        SIPResponse optionsResponse = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null);
                        await sipTransport.SendResponseAsync(optionsResponse);
                    }
                }
                catch (Exception reqExcp)
                {
                    SIPSorcery.Sys.Log.Logger.LogWarning($"Exception handling {sipRequest.Method}. {reqExcp.Message}");
                }
            };

            ManualResetEvent exitMre = new ManualResetEvent(false);

            Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e)
            {
                e.Cancel = true;

                SIPSorcery.Sys.Log.Logger.LogInformation("Exiting...");

                Hangup(uas).Wait();

                rtpSession?.CloseSession(null);
                rtpCts?.Cancel();

                if (sipTransport != null)
                {
                    SIPSorcery.Sys.Log.Logger.LogInformation("Shutting down SIP transport...");
                    sipTransport.Shutdown();
                }

                exitMre.Set();
            };

            // Task to handle user key presses.
            Task.Run(() =>
            {
                try
                {
                    while (!exitMre.WaitOne(0))
                    {
                        var keyProps = Console.ReadKey();
                        if (keyProps.KeyChar == 'h' || keyProps.KeyChar == 'q')
                        {
                            Console.WriteLine();
                            Console.WriteLine("Hangup requested by user...");

                            Hangup(uas).Wait();

                            rtpSession?.CloseSession(null);
                            rtpCts?.Cancel();
                        }

                        if (keyProps.KeyChar == 'q')
                        {
                            SIPSorcery.Sys.Log.Logger.LogInformation("Quitting...");

                            if (sipTransport != null)
                            {
                                SIPSorcery.Sys.Log.Logger.LogInformation("Shutting down SIP transport...");
                                sipTransport.Shutdown();
                            }

                            exitMre.Set();
                        }
                    }
                }
                catch (Exception excp)
                {
                    SIPSorcery.Sys.Log.Logger.LogError($"Exception Key Press listener. {excp.Message}.");
                }
            });

            exitMre.WaitOne();
        }
        /*[OperationContract]
       public List<SIPRegistrationAgentRecord> GetRegistrationAgentRegistrations(string owner)
       {
           try
           {
               return m_regAgent.GetOwnerRegistrations(owner);
           }
           catch (Exception excp)
           {
               logger.Error("Exception GetRegistrationAgentRegistrations. " + excp.Message);
               throw excp;
           }
       }

      [OperationContract]
       public void RemoveRegistrationAgentContact(Guid registrationId, string contactToRemove)
       {
           try
           {
               logger.Debug("RemoveRegistrarContact webservice called for " + registrationId + " and " + contactToRemove + ".");

               SIPRegistrationAgentRecord registration = m_regAgent.Get(registrationId);

               if (registration != null)
               {
                   // Look through the current contacts to try and find one to match this contact.
                   foreach (SIPContactHeader contact in registration.ContactsList)
                   {
                       logger.Debug("Comparing: " + contact.ContactURI.ToString() + " to " + contactToRemove);

                       if (contactToRemove == null || contact.ContactURI.ToString() == contactToRemove)
                       {
                           logger.Debug("Attempting removal of registrar contact " + contact.ContactURI.ToString() + ".");
                           m_regAgent.SendContactRemovalRequest(registrationId, contact.ContactURI);
                       }
                   }
               }
               else
               {
                   logger.Warn("Could not find the registration record for " + registrationId + " in RemoveSIPContact.");
               }
           }
           catch (Exception excp)
           {
               logger.Error("Exception RemoveRegistrarContact. " + excp.Message);
               throw excp;
           }
       }

       [OperationContract]
       public void RefreshRegistrationAgentContact(Guid registrationId)
       {
           try
           {
               logger.Debug("RefreshRegistrationView webservice called for " + registrationId + ".");

               UserRegistration registration = m_regAgent.Get(registrationId);

               if (registration != null)
               {
                   m_regAgent.SendEmptyRegistrationRequest(registrationId);
               }
               else
               {
                   logger.Warn("Could not find the registration record for " + registrationId + " in RefreshRegistrationView.");
               }
           }
           catch (Exception excp)
           {
               logger.Error("Exception RefreshRegistrationView. " + excp.Message);
               throw excp;
           }
       }*/

        /// <summary>
        /// Send a Message Waiting Indicator request to the specified user agent URI. If setMWI is true the number of messages indicated will
        /// be one otherwise 0.
        /// </summary>
        /*[OperationContract]
        public void SendMWIRequest(string userAgentURI, bool setMWI, string username)
        {
            try
            {
                logger.Debug("Attempting SendMWIRequest for " + userAgentURI + " as " + setMWI + ".");

                SIPURI clientURI = SIPURI.ParseSIPURI(userAgentURI);
                SIPRequest mwiRequest = SIPNotificationAgent.GetNotifyRequest(m_sipTransport.GetTransportContact(null), null, clientURI, username, setMWI);
                SIPNonInviteTransaction mwiTransaction = m_sipTransport.CreateNonInviteTransaction(mwiRequest, clientURI.GetURIEndPoint(), m_sipTransport.GetTransportContact(null), SIPProtocolsEnum.UDP);
                mwiTransaction.NonInviteTransactionFinalResponseReceived += new SIPTransactionResponseReceivedDelegate(MWIFinalResponseReceived);

                FireProxyLogEvent(new ProxyMonitorEvent(ProxyServerTypesEnum.StatefulProxy, ProxyEventTypesEnum.MWI, "Sending " + setMWI + " mwi to " + SIPURI.ParseSIPURI(userAgentURI).CanonicalAddress, username));

                m_sipTransport.SendRequest(mwiRequest, SIPProtocolsEnum.UDP);
            }
            catch (Exception excp)
            {
                logger.Error("Exception SendMWIRequest. " + excp.Message + ".");
            }
        }*/

        /*private void MWIFinalResponseReceived(IPEndPoint localEndPoint,  IPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse)
        {
            try
            {
                string username = sipResponse.Header.From.FromURI.User;

                logger.Debug("MWI response received from " + IPSocket.GetSocketString(remoteEndPoint) + " " + sipResponse.StatusCode + " " + sipResponse.ReasonPhrase + " for " + username + ".");

                FireProxyLogEvent(new ProxyMonitorEvent(ProxyServerTypesEnum.StatefulProxy, ProxyEventTypesEnum.MWI, "MWI response received from " + IPSocket.GetSocketString(remoteEndPoint) + " " + sipResponse.StatusCode + " " + sipResponse.ReasonPhrase, username));
            }
            catch (Exception excp)
            {
                logger.Error("Exception MWIFinalResponseReceived. " + excp.Message);
            }
        }*/

        /// <summary>
        /// Send a Message Waiting Indicator request to the specified user agent URI. If setMWI is true the number of messages indicated will
        /// be one otherwise 0.
        /// </summary>
        /*[OperationContract]
        public void SendInviteRequest(string userAgentURI, string callerIdName, string callerIdUser, string username)
        {
            try
            {
                logger.Debug("Attempting SendInviteRequest for " + userAgentURI + " as " + callerIdName + " and " + callerIdUser  + ".");

                SIPURI clientURI = SIPURI.ParseSIPURI(userAgentURI);
                SIPRequest inviteRequest = GetInviteRequest(clientURI, callerIdName, callerIdUser, SERVER_STRING);
                UACInviteTransaction inviteTransaction = m_sipTransport.CreateUACTransaction(inviteRequest, clientURI.GetURIEndPoint(), m_sipTransport.GetTransportContact(null), SIPProtocolsEnum.UDP);
                inviteTransaction.UACInviteTransactionFinalResponseReceived += new SIPTransactionResponseReceivedDelegate(InviteFinalResponseReceived);

                FireProxyLogEvent(new ProxyMonitorEvent(ProxyServerTypesEnum.StatefulProxy, ProxyEventTypesEnum.NewCall, "Sending INVITE to " + SIPURI.ParseSIPURI(userAgentURI).ToString(), username));

                inviteTransaction.SendInviteRequest(inviteRequest.GetRequestEndPoint(), inviteRequest);
            }
            catch (Exception excp)
            {
                logger.Error("Exception SendInviteRequest. " + excp.Message + ".");
            }
        }*/

        private void InviteFinalResponseReceived(IPEndPoint localEndPoint,  IPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse)
        {
            try
            {
                logger.Debug("FinalResponseReceived for INVITE to " + sipTransaction.TransactionRequest.URI.ToString() + " " + sipResponse.Status + " " + sipResponse.ReasonPhrase + ".");
            }
            catch (Exception excp)
            {
                logger.Error("Exception InviteFinalResponseReceived. " + excp.Message);
            }
        }
        private void ServerInformationResponseReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse)
        {
            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Information response " + sipResponse.StatusCode + " " + sipResponse.ReasonPhrase + " for " + m_serverTransaction.TransactionRequest.URI.ToString() + ".", Owner));

            if (m_callCancelled)
            {
                // Call was cancelled in the interim.
                Cancel();
            }
            else
            {
                if (sipResponse.Status == SIPResponseStatusCodesEnum.Ringing || sipResponse.Status == SIPResponseStatusCodesEnum.SessionProgress)
                {
                    FireCallRinging(this, sipResponse);
                }
                else
                {
                    FireCallTrying(this, sipResponse);
                }
            }
        }
        private void ServerFinalResponseReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse)
        {
            try
            {
                //if (Thread.CurrentThread.Name.IsNullOrBlank())
                //{
                //    Thread.CurrentThread.Name = THREAD_NAME + DateTime.Now.ToString("HHmmss") + "-" + Crypto.GetRandomString(3);
                //}

                Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Response " + sipResponse.StatusCode + " " + sipResponse.ReasonPhrase + " for " + m_serverTransaction.TransactionRequest.URI.ToString() + ".", Owner));
                //m_sipTrace += "Received " + DateTime.Now.ToString("dd MMM yyyy HH:mm:ss") + " " + localEndPoint + "<-" + remoteEndPoint + "\r\n" + sipResponse.ToString();

                m_serverTransaction.UACInviteTransactionInformationResponseReceived -= ServerInformationResponseReceived;
                m_serverTransaction.UACInviteTransactionFinalResponseReceived -= ServerFinalResponseReceived;
                m_serverTransaction.TransactionTraceMessage -= TransactionTraceMessage;

                if (m_callCancelled && sipResponse.Status == SIPResponseStatusCodesEnum.RequestTerminated)
                {
                    // No action required. Correctly received request terminated on an INVITE we cancelled.
                }
                else if (m_callCancelled)
                {
                    #region Call has been cancelled, hangup.

                    if (m_hungupOnCancel)
                    {
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "A cancelled call to " + m_sipCallDescriptor.Uri + " has been answered AND has already been hungup, no further action being taken.", Owner));
                    }
                    else
                    {
                        m_hungupOnCancel = true;

                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "A cancelled call to " + m_sipCallDescriptor.Uri + " has been answered, hanging up.", Owner));

                        if (sipResponse.Header.Contact != null && sipResponse.Header.Contact.Count > 0)
                        {
                            SIPURI byeURI = sipResponse.Header.Contact[0].ContactURI;
                            SIPRequest byeRequest = GetByeRequest(sipResponse, byeURI, localSIPEndPoint);

                            //SIPEndPoint byeEndPoint = m_sipTransport.GetRequestEndPoint(byeRequest, m_outboundProxy, true);

                            // if (byeEndPoint != null)
                            // {
                            SIPNonInviteTransaction byeTransaction = m_sipTransport.CreateNonInviteTransaction(byeRequest, null, localSIPEndPoint, m_outboundProxy);
                            byeTransaction.SendReliableRequest();
                            // }
                            // else
                            // {
                            //     Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Could not end BYE on cancelled call as request end point could not be determined " + byeRequest.URI.ToString(), Owner));
                            //}
                        }
                        else
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "No contact header provided on response for cancelled call to " + m_sipCallDescriptor.Uri + " no further action.", Owner));
                        }
                    }

                    #endregion
                }
                else if (sipResponse.Status == SIPResponseStatusCodesEnum.ProxyAuthenticationRequired || sipResponse.Status == SIPResponseStatusCodesEnum.Unauthorised)
                {
                    #region Authenticate client call to third party server.

                    if (!m_callCancelled)
                    {
                        if (m_sipCallDescriptor.Password.IsNullOrBlank())
                        {
                            // No point trying to authenticate if there is no password to use.
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Forward leg failed, authentication was requested but no credentials were available.", Owner));
                            FireCallFailed(this, "Authentication requested when no credentials available");
                        }
                        else if (m_serverAuthAttempts == 0)
                        {
                            m_serverAuthAttempts = 1;

                            // Resend INVITE with credentials.
                            string username = (m_sipCallDescriptor.AuthUsername != null && m_sipCallDescriptor.AuthUsername.Trim().Length > 0) ? m_sipCallDescriptor.AuthUsername : m_sipCallDescriptor.Username;
                            SIPAuthorisationDigest authRequest = sipResponse.Header.AuthenticationHeader.SIPDigest;
                            authRequest.SetCredentials(username, m_sipCallDescriptor.Password, m_sipCallDescriptor.Uri, SIPMethodsEnum.INVITE.ToString());

                            SIPRequest authInviteRequest = m_serverTransaction.TransactionRequest;
                            authInviteRequest.Header.AuthenticationHeader = new SIPAuthenticationHeader(authRequest);
                            authInviteRequest.Header.AuthenticationHeader.SIPDigest.Response = authRequest.Digest;
                            authInviteRequest.Header.Vias.TopViaHeader.Branch = CallProperties.CreateBranchId();
                            authInviteRequest.Header.CSeq = authInviteRequest.Header.CSeq + 1;

                            // Create a new UAC transaction to establish the authenticated server call.
                            var originalCallTransaction = m_serverTransaction;
                            m_serverTransaction = m_sipTransport.CreateUACTransaction(authInviteRequest, m_serverEndPoint, localSIPEndPoint, m_outboundProxy);
                            if (m_serverTransaction.CDR != null)
                            {
                                m_serverTransaction.CDR.Owner = Owner;
                                m_serverTransaction.CDR.AdminMemberId = AdminMemberId;
                                m_serverTransaction.CDR.DialPlanContextID = m_sipCallDescriptor.DialPlanContextID;

                                m_serverTransaction.CDR.Updated();

                                if (AccountCode != null)
                                {
            #if !SILVERLIGHT
                                    RtccUpdateCdr_External?.Invoke(originalCallTransaction.CDR?.CDRId.ToString(), m_serverTransaction.CDR);
            #endif
                                }

                                logger.Debug("RTCC reservation was reallocated from CDR " + originalCallTransaction.CDR?.CDRId + " to " + m_serverTransaction.CDR?.CDRId + " for owner " + Owner + ".");
                            }
                            m_serverTransaction.UACInviteTransactionInformationResponseReceived += ServerInformationResponseReceived;
                            m_serverTransaction.UACInviteTransactionFinalResponseReceived += ServerFinalResponseReceived;
                            m_serverTransaction.UACInviteTransactionTimedOut += ServerTimedOut;
                            m_serverTransaction.TransactionTraceMessage += TransactionTraceMessage;

                            m_serverTransaction.SendInviteRequest(m_serverEndPoint, authInviteRequest);
                        }
                        else
                        {
                            FireCallFailed(this, "Authentication with provided credentials failed");
                        }
                    }

                    #endregion
                }
                else
                {
                    if (sipResponse.StatusCode >= 200 && sipResponse.StatusCode <= 299)
                    {
                        if (sipResponse.Body.IsNullOrBlank())
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Body on UAC response was empty.", Owner));
                        }
                        else if (m_sipCallDescriptor.ContentType == m_sdpContentType)
                        {
                            if (!m_sipCallDescriptor.MangleResponseSDP)
                            {
                                IPEndPoint sdpEndPoint = SDP.GetSDPRTPEndPoint(sipResponse.Body);
                                string sdpSocket = (sdpEndPoint != null) ? sdpEndPoint.ToString() : "could not determine";
                                Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "SDP on UAC response was set to NOT mangle, RTP socket " + sdpEndPoint.ToString() + ".", Owner));
                            }
                            else
                            {
                                //m_callInProgress = false; // the call is now established
                                //logger.Debug("Final response " + sipResponse.StatusCode + " " + sipResponse.ReasonPhrase + " for " + ForwardedTransaction.TransactionRequest.URI.ToString() + ".");
                                // Determine of response SDP should be mangled.

                                IPEndPoint sdpEndPoint = SDP.GetSDPRTPEndPoint(sipResponse.Body);
                                //Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "UAC response SDP was mangled from sdp=" + sdpEndPoint.Address.ToString() + ", proxyfrom=" + sipResponse.Header.ProxyReceivedFrom + ", mangle=" + m_sipCallDescriptor.MangleResponseSDP + ".", null));
                                if (sdpEndPoint != null)
                                {
                                    if (!IPSocket.IsPrivateAddress(sdpEndPoint.Address.ToString()))
                                    {
                                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "SDP on UAC response had public IP not mangled, RTP socket " + sdpEndPoint.ToString() + ".", Owner));
                                    }
                                    else
                                    {
                                        bool wasSDPMangled = false;
                                        string publicIPAddress = null;

                                        if (!sipResponse.Header.ProxyReceivedFrom.IsNullOrBlank())
                                        {
                                            IPAddress remoteUASAddress = SIPEndPoint.ParseSIPEndPoint(sipResponse.Header.ProxyReceivedFrom).Address;
                                            if (IPSocket.IsPrivateAddress(remoteUASAddress.ToString()) && m_sipCallDescriptor.MangleIPAddress != null)
                                            {
                                                // If the response has arrived here on a private IP address then it must be
                                                // for a local version install and an incoming call that needs it's response mangled.
                                                if(!IPSocket.IsPrivateAddress(m_sipCallDescriptor.MangleIPAddress.ToString()))
                                                {
                                                    publicIPAddress = m_sipCallDescriptor.MangleIPAddress.ToString();
                                                }
                                            }
                                            else
                                            {
                                                publicIPAddress = remoteUASAddress.ToString();
                                            }
                                        }
                                        else if (!IPSocket.IsPrivateAddress(remoteEndPoint.Address.ToString()) && remoteEndPoint.Address != IPAddress.Any)
                                        {
                                            publicIPAddress = remoteEndPoint.Address.ToString();
                                        }
                                        else if (m_sipCallDescriptor.MangleIPAddress != null)
                                        {
                                            publicIPAddress = m_sipCallDescriptor.MangleIPAddress.ToString();
                                        }

                                        if (publicIPAddress != null)
                                        {
                                            sipResponse.Body = SIPPacketMangler.MangleSDP(sipResponse.Body, publicIPAddress, out wasSDPMangled);
                                        }

                                        if (wasSDPMangled)
                                        {
                                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "SDP on UAC response had RTP socket mangled from " + sdpEndPoint.ToString() + " to " + publicIPAddress + ":" + sdpEndPoint.Port + ".", Owner));
                                        }
                                        else if (sdpEndPoint != null)
                                        {
                                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "SDP on UAC response could not be mangled, RTP socket " + sdpEndPoint.ToString() + ".", Owner));
                                        }
                                    }
                                }
                                else
                                {
                                    Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "SDP RTP socket on UAC response could not be determined.", Owner));
                                }
                            }
                        }

                        m_sipDialogue = new SIPDialogue(m_serverTransaction, Owner, AdminMemberId);
                        m_sipDialogue.CallDurationLimit = m_sipCallDescriptor.CallDurationLimit;

                        // Set switchboard dialogue values from the answered response or from dialplan set values.
                        //m_sipDialogue.SwitchboardCallerDescription = sipResponse.Header.SwitchboardCallerDescription;
                        m_sipDialogue.SwitchboardLineName = sipResponse.Header.SwitchboardLineName;
                        m_sipDialogue.CRMPersonName = sipResponse.Header.CRMPersonName;
                        m_sipDialogue.CRMCompanyName = sipResponse.Header.CRMCompanyName;
                        m_sipDialogue.CRMPictureURL = sipResponse.Header.CRMPictureURL;

                        if (m_sipCallDescriptor.SwitchboardHeaders != null)
                        {
                            //if (!m_sipCallDescriptor.SwitchboardHeaders.SwitchboardDialogueDescription.IsNullOrBlank())
                            //{
                            //    m_sipDialogue.SwitchboardDescription = m_sipCallDescriptor.SwitchboardHeaders.SwitchboardDialogueDescription;
                            //}

                            m_sipDialogue.SwitchboardLineName = m_sipCallDescriptor.SwitchboardHeaders.SwitchboardLineName;
                            m_sipDialogue.SwitchboardOwner = m_sipCallDescriptor.SwitchboardHeaders.SwitchboardOwner;
                        }
                    }

                    FireCallAnswered(this, sipResponse);
                }
            }
            catch (Exception excp)
            {
                Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.Error, "Exception ServerFinalResponseReceived. " + excp.Message, Owner));
            }
        }
        private SIPRequest GetByeRequest(SIPResponse inviteResponse, SIPURI byeURI, SIPEndPoint localSIPEndPoint)
        {
            SIPRequest byeRequest = new SIPRequest(SIPMethodsEnum.BYE, byeURI);
            byeRequest.LocalSIPEndPoint = localSIPEndPoint;

            SIPFromHeader byeFromHeader = inviteResponse.Header.From;
            SIPToHeader byeToHeader = inviteResponse.Header.To;
            int cseq = inviteResponse.Header.CSeq + 1;

            SIPHeader byeHeader = new SIPHeader(byeFromHeader, byeToHeader, cseq, inviteResponse.Header.CallId);
            byeHeader.CSeqMethod = SIPMethodsEnum.BYE;
            byeHeader.ProxySendFrom = m_serverTransaction.TransactionRequest.Header.ProxySendFrom;
            byeRequest.Header = byeHeader;

            byeRequest.Header.Routes = (inviteResponse.Header.RecordRoutes != null) ? inviteResponse.Header.RecordRoutes.Reversed() : null;

            SIPViaHeader viaHeader = new SIPViaHeader(localSIPEndPoint, CallProperties.CreateBranchId());
            byeRequest.Header.Vias.PushViaHeader(viaHeader);

            return byeRequest;
        }
 private void FireCallTrying(SIPClientUserAgent uac, SIPResponse tryingResponse)
 {
     if (CallTrying != null)
     {
         CallTrying(uac, tryingResponse);
     }
 }
 private void FireCallRinging(SIPClientUserAgent uac, SIPResponse ringingResponse)
 {
     if (CallRinging != null)
     {
         CallRinging(uac, ringingResponse);
     }
 }
Exemple #15
0
        private void ProcessRedirect(ISIPClientUserAgent answeredUAC, SIPResponse answeredResponse)
        {
            try
            {
                SIPURI redirectURI = answeredResponse.Header.Contact[0].ContactURI;

                if (redirectURI == null)
                {
                    FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Redirect target could not be determined from redirect response, ignoring.", m_username));
                }
                else
                {
                    //string canincalDomain = m_dialPlanContext.GetCanonicalDomain_External(redirectURI.Host, false);

                    if (answeredUAC.CallDescriptor.RedirectMode == SIPCallRedirectModesEnum.NewDialPlan)
                    {
                        m_dialPlanContext.ExecuteDialPlanForRedirect(answeredResponse);
                    }
                    else if (answeredUAC.CallDescriptor.RedirectMode == SIPCallRedirectModesEnum.Manual)
                    {
                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Redirect response with URI " + redirectURI.ToString() + " was not acted on as redirect mode set to manual in dial string.", m_username));
                        CallLegCompleted();
                    }
                    else
                    {
                        // The redirect was not explicitly allowed so will be processed as an anonymous call.
                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Redirect response to " + redirectURI.ToString() + " accepted.", m_username));
                        var redirectCalls = m_dialStringParser.GetForwardsForRedirect(redirectURI, answeredUAC.CallDescriptor);
                        //SIPCallDescriptor redirectCallDescriptor = answeredUAC.CallDescriptor.CopyOf();
                        //redirectCallDescriptor.Uri = redirectURI.ToString();
                        //StartNewCallAsync(redirectCallDescriptor);
                        if (redirectCalls != null && redirectCalls.Count > 0)
                        {
                            foreach (var redirectCall in redirectCalls)
                            {
                                StartNewCallAsync(redirectCall);
                            }
                        }
                    }
                    //else if (answeredUAC.CallDescriptor.RedirectMode == SIPCallRedirectModesEnum.Replace)
                    //{
                    //    // In the Replace redirect mode the existing dialplan execution needs to be cancelled and the single redirect call be used to replace it.
                    //    FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Redirect response rejected as Replace mode not yet implemented.", m_username));
                    //    CallLegCompleted();
                    //}
                    //else
                    //{
                    //    FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Redirect response with URI " + redirectURI.ToString() + " was not acted on as not enabled in dial string.", m_username));
                    //    CallLegCompleted();
                    //}

                    // A redirect response was received. Create a new call leg(s) using the SIP URIs in the contact header of the response.
                    //if (m_dialStringParser != null)
                    //{
                    //    // If there is a dial string parser available it will be used to generate a list of call destination from the redirect URI.
                    //    SIPCallDescriptor redirectCallDescriptor = answeredUAC.CallDescriptor.CopyOf();
                    //    Queue<List<SIPCallDescriptor>> redirectQueue = m_dialStringParser.ParseDialString(DialPlanContextsEnum.Script, null, redirectURI.ToString(), redirectCallDescriptor.CustomHeaders,
                    //        redirectCallDescriptor.ContentType, redirectCallDescriptor.Content, null, redirectCallDescriptor.FromDisplayName, redirectCallDescriptor.FromURIUsername, redirectCallDescriptor.FromURIHost, null, CustomerServiceLevels.None);

                    //    if (redirectQueue != null && redirectQueue.Count > 0)
                    //    {
                    //        // Only the first list in the queue is used (and there should only be a single list since it's generated from a redirect SIP URI and not
                    //        // a full dial string).
                    //        List<SIPCallDescriptor> callDescriptors = redirectQueue.Dequeue();
                    //        for (int index = 0; index < callDescriptors.Count; index++)
                    //        {
                    //            callDescriptors[index].MangleIPAddress = redirectCallDescriptor.MangleIPAddress;
                    //            callDescriptors[index].MangleResponseSDP = redirectCallDescriptor.MangleResponseSDP;
                    //            callDescriptors[index].TransferMode = redirectCallDescriptor.TransferMode;
                    //        }
                    //        Start(callDescriptors);
                    //    }
                    //    else
                    //    {
                    //        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "A redirect response to " + redirectURI.ToString() + " did not generate any new call leg destinations.", m_username));
                    //    }
                    //}
                    //else
                    //{
                    //    FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Redirect response to " + redirectURI.ToString() + " accepted.", m_username));
                    //    SIPCallDescriptor redirectCallDescriptor = answeredUAC.CallDescriptor.CopyOf();
                    //    redirectCallDescriptor.Uri = redirectURI.ToString();
                    //    StartNewCallAsync(redirectCallDescriptor);
                    //}
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception ForkCall ProcessRedirect. " + excp.Message);
            }
        }
        private Task <SocketError> SubscribeTransactionFinalResponseReceived(SIPEndPoint localSIPEndPoint,
                                                                             SIPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse)
        {
            try
            {
                if (sipResponse.Status == SIPResponseStatusCodesEnum.IntervalTooBrief)
                {
                    // The expiry interval used was too small. Adjust and try again.
                    m_expiry = (sipResponse.Header.MinExpires > 0) ? sipResponse.Header.MinExpires : m_expiry * 2;
                    logger.LogWarning("A subscribe request was rejected with IntervalTooBrief, adjusting expiry to " +
                                      m_expiry + " and trying again.");
                    Subscribe(m_resourceURI, m_expiry, m_sipEventPackage, m_subscribeCallID, null);
                }
                else if (sipResponse.Status == SIPResponseStatusCodesEnum.Forbidden)
                {
                    // The subscription is never going to succeed so cancel it.
                    SubscriptionFailed(m_resourceURI, sipResponse.Status,
                                       "A Forbidden response was received on a subscribe attempt to " + m_resourceURI.ToString() +
                                       " for user " + m_authUsername + ".");
                    m_exit = true;
                    m_waitForSubscribeResponse.Set();
                }
                else if (sipResponse.Status == SIPResponseStatusCodesEnum.BadEvent)
                {
                    // The subscription is never going to succeed so cancel it.
                    SubscriptionFailed(m_resourceURI, sipResponse.Status,
                                       "A BadEvent response was received on a subscribe attempt to " + m_resourceURI.ToString() +
                                       " for event package " + m_sipEventPackage.ToString() + ".");
                    m_exit = true;
                    m_waitForSubscribeResponse.Set();
                }
                else if (sipResponse.Status == SIPResponseStatusCodesEnum.CallLegTransactionDoesNotExist)
                {
                    // The notifier server does not have a record for the existing subscription.
                    SubscriptionFailed(m_resourceURI, sipResponse.Status,
                                       "Subscribe failed with response " + sipResponse.StatusCode + " " + sipResponse.ReasonPhrase +
                                       ".");
                    m_waitForSubscribeResponse.Set();
                }
                else if (sipResponse.Status == SIPResponseStatusCodesEnum.ProxyAuthenticationRequired ||
                         sipResponse.Status == SIPResponseStatusCodesEnum.Unauthorised)
                {
                    if (m_authUsername.IsNullOrBlank() || m_authPassword.IsNullOrBlank())
                    {
                        // No point trying to authenticate if there are no credentials to use.
                        SubscriptionFailed(m_resourceURI, sipResponse.Status,
                                           "Authentication requested on subscribe request when no credentials available.");
                        m_waitForSubscribeResponse.Set();
                    }
                    else if (sipResponse.Header.AuthenticationHeader != null)
                    {
                        if (m_attempts >= MAX_SUBSCRIBE_ATTEMPTS)
                        {
                            m_subscribed = false;
                            SubscriptionFailed(m_resourceURI, SIPResponseStatusCodesEnum.InternalServerError,
                                               "Subscription reached the maximum number of allowed attempts.");
                            m_waitForSubscribeResponse.Set();
                        }
                        else
                        {
                            logger.LogDebug("Attempting authentication for subscribe request for event package " +
                                            m_sipEventPackage.ToString() + " and " + m_resourceURI.ToString() + ".");

                            m_attempts++;

                            // Resend SUBSCRIBE with credentials.
                            SIPAuthorisationDigest authRequest = sipResponse.Header.AuthenticationHeader.SIPDigest;
                            authRequest.SetCredentials(m_authUsername, m_authPassword, m_resourceURI.ToString(),
                                                       SIPMethodsEnum.SUBSCRIBE.ToString());

                            SIPRequest authSubscribeRequest = sipTransaction.TransactionRequest;
                            authSubscribeRequest.Header.AuthenticationHeader = new SIPAuthenticationHeader(authRequest);
                            authSubscribeRequest.Header.AuthenticationHeader.SIPDigest.Response = authRequest.Digest;
                            authSubscribeRequest.Header.Vias.TopViaHeader.Branch = CallProperties.CreateBranchId();
                            m_localCSeq = sipTransaction.TransactionRequest.Header.CSeq + 1;
                            authSubscribeRequest.Header.CSeq   = m_localCSeq;
                            authSubscribeRequest.Header.CallId = m_subscribeCallID;

                            if (!m_filter.IsNullOrBlank())
                            {
                                authSubscribeRequest.Body = m_filter;
                                authSubscribeRequest.Header.ContentLength = m_filter.Length;
                                authSubscribeRequest.Header.ContentType   = m_filterTextType;
                            }

                            // Create a new transaction to establish the authenticated server call.
                            SIPNonInviteTransaction subscribeTransaction =
                                new SIPNonInviteTransaction(m_sipTransport, authSubscribeRequest, m_outboundProxy);
                            subscribeTransaction.NonInviteTransactionFinalResponseReceived +=
                                SubscribeTransactionFinalResponseReceived;
                            subscribeTransaction.NonInviteTransactionTimedOut += SubsribeTransactionTimedOut;

                            m_sipTransport.SendTransaction(subscribeTransaction);
                        }
                    }
                    else
                    {
                        SubscriptionFailed(sipTransaction.TransactionRequestURI, sipResponse.Status,
                                           "Subscribe requested authentication but did not provide an authentication header.");
                        m_waitForSubscribeResponse.Set();
                    }
                }
                else if (sipResponse.StatusCode >= 200 && sipResponse.StatusCode <= 299)
                {
                    logger.LogDebug("Authenticating subscribe request for event package " +
                                    m_sipEventPackage.ToString() + " and " + m_resourceURI.ToString() +
                                    " was successful.");

                    m_subscribed        = true;
                    m_subscriptionToTag = sipResponse.Header.To.ToTag;
                    SubscriptionSuccessful(m_resourceURI);
                    m_waitForSubscribeResponse.Set();
                }
                else
                {
                    SubscriptionFailed(m_resourceURI, sipResponse.Status,
                                       "Subscribe failed with response " + sipResponse.StatusCode + " " + sipResponse.ReasonPhrase +
                                       ".");
                    m_waitForSubscribeResponse.Set();
                }

                return(Task.FromResult(SocketError.Success));
            }
            catch (Exception excp)
            {
                logger.LogError("Exception SubscribeTransactionFinalResponseReceived. " + excp.Message);
                SubscriptionFailed(m_resourceURI, SIPResponseStatusCodesEnum.InternalServerError,
                                   "Exception processing subscribe response. " + excp.Message);
                m_waitForSubscribeResponse.Set();

                return(Task.FromResult(SocketError.Fault));
            }
        }
        public SIPRequest GetAuthenticatedRequest(SIPRequest origRequest, SIPResponse authReqdResponse, string username, string password)
        {
            SIPRequest authRequest = origRequest;
            authRequest.Header.Via.TopViaHeader.Branch = CallProperties.CreateBranchId();
            authRequest.Header.From.FromTag = CallProperties.CreateNewTag();
            authRequest.Header.CSeq = origRequest.Header.CSeq + 1;

            AuthorizationRequest authorizationRequest = authReqdResponse.Header.AuthenticationHeader.AuthRequest;
            authorizationRequest.SetCredentials(username, password, origRequest.URI.ToString(), origRequest.Method.ToString());

            authRequest.Header.AuthenticationHeader = new SIPAuthenticationHeader(authorizationRequest);
            authRequest.Header.AuthenticationHeader.AuthRequest.Response = authorizationRequest.Digest;

            return authRequest;
        }
        public bool AuthenticateCall()
        {
            m_isAuthenticated = false;

            try
            {
                if (SIPAuthenticateRequest_External == null)
                {
                    // No point trying to authenticate if we haven't been given an authentication delegate.
                    Reject(SIPResponseStatusCodesEnum.InternalServerError, null, null);
                }
                else if (GetSIPAccount_External == null)
                {
                    // No point trying to authenticate if we haven't been given a  delegate to load the SIP account.
                    Reject(SIPResponseStatusCodesEnum.InternalServerError, null, null);
                }
                else
                {
                    m_sipAccount = GetSIPAccount_External(m_sipUsername, m_sipDomain);

                    if (m_sipAccount == null)
                    {
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Rejecting authentication required call for " + m_sipUsername + "@" + m_sipDomain + ", SIP account not found.", null));
                        Reject(SIPResponseStatusCodesEnum.Forbidden, null, null);
                    }
                    else
                    {
                        SIPRequest  sipRequest       = m_uasTransaction.TransactionRequest;
                        SIPEndPoint localSIPEndPoint = (!sipRequest.Header.ProxyReceivedOn.IsNullOrBlank()) ? SIPEndPoint.ParseSIPEndPoint(sipRequest.Header.ProxyReceivedOn) : sipRequest.LocalSIPEndPoint;
                        SIPEndPoint remoteEndPoint   = (!sipRequest.Header.ProxyReceivedFrom.IsNullOrBlank()) ? SIPEndPoint.ParseSIPEndPoint(sipRequest.Header.ProxyReceivedFrom) : sipRequest.RemoteSIPEndPoint;

                        SIPRequestAuthenticationResult authenticationResult = SIPAuthenticateRequest_External(localSIPEndPoint, remoteEndPoint, sipRequest, m_sipAccount, Log_External);
                        if (authenticationResult.Authenticated)
                        {
                            if (authenticationResult.WasAuthenticatedByIP)
                            {
                                Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "New call from " + remoteEndPoint.ToString() + " successfully authenticated by IP address.", m_sipAccount.Owner));
                            }
                            else
                            {
                                Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "New call from " + remoteEndPoint.ToString() + " successfully authenticated by digest.", m_sipAccount.Owner));
                            }

                            SetOwner(m_sipAccount.Owner, m_sipAccount.AdminMemberId);
                            m_isAuthenticated = true;
                        }
                        else
                        {
                            // Send authorisation failure or required response
                            SIPResponse authReqdResponse = SIPTransport.GetResponse(sipRequest, authenticationResult.ErrorResponse, null);
                            authReqdResponse.Header.AuthenticationHeader = authenticationResult.AuthenticationRequiredHeader;
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call not authenticated for " + m_sipUsername + "@" + m_sipDomain + ", responding with " + authenticationResult.ErrorResponse + ".", null));
                            m_uasTransaction.SendFinalResponse(authReqdResponse);
                        }
                    }
                }
            }
            catch (Exception excp)
            {
                logger.LogError("Exception SIPServerUserAgent AuthenticateCall. " + excp.Message);
                Reject(SIPResponseStatusCodesEnum.InternalServerError, null, null);
            }

            return(m_isAuthenticated);
        }
        public SIPRequest GetByeRequest(SIPResponse inviteResponse)
        {
            SIPRequest byeRequest = new SIPRequest(SIPMethodsEnum.BYE, inviteResponse.Header.Contact[0].ContactURI);
            SIPHeader byeHeader = new SIPHeader(inviteResponse.Header.From, inviteResponse.Header.To, inviteResponse.Header.CSeq + 1, inviteResponse.Header.CallId);
            byeHeader.CSeqMethod = SIPMethodsEnum.BYE;

            IPEndPoint localSIPEndPoint = m_sipTransport.GetIPEndPointsList()[0];
            SIPViaHeader viaHeader = new SIPViaHeader(localSIPEndPoint.Address.ToString(), localSIPEndPoint.Port, CallProperties.CreateBranchId());
            byeHeader.Via.PushViaHeader(viaHeader);

            byeRequest.Header = byeHeader;

            return byeRequest;
        }
Exemple #20
0
 private void TransactionInformationResponseReceived(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse)
 {
     m_lastInfoResponse = sipResponse;
     m_waitForSIPInfoResponse.Set();
 }
        public SIPRequest GetReferRequest(SIPRequest inviteRequest, SIPResponse inviteResponse, string referToURI)
        {
            SIPRequest referRequest = new SIPRequest(SIPMethodsEnum.REFER, inviteRequest.URI);
            SIPHeader referHeader = new SIPHeader(inviteResponse.Header.From, inviteResponse.Header.To, inviteRequest.Header.CSeq + 1, inviteRequest.Header.CallId);
            referHeader.Contact = inviteRequest.Header.Contact;
            referHeader.CSeqMethod = SIPMethodsEnum.REFER;
            referHeader.ReferTo = referToURI;
            SIPFromHeader referredBy = new SIPFromHeader(inviteRequest.Header.From.FromName, inviteRequest.Header.From.FromURI, null);
            referHeader.ReferredBy = referredBy.ToString();
            referHeader.AuthenticationHeader = inviteRequest.Header.AuthenticationHeader;

            IPEndPoint localSIPEndPoint = m_sipTransport.GetIPEndPointsList()[0];
            SIPViaHeader viaHeader = new SIPViaHeader(localSIPEndPoint.Address.ToString(), localSIPEndPoint.Port, CallProperties.CreateBranchId());
            referHeader.Via.PushViaHeader(viaHeader);

            referRequest.Header = referHeader;

            return referRequest;
        }
Exemple #22
0
        private SIPRequest GetAuthenticatedRegistrationRequest(SIPRequest registerRequest, SIPResponse sipResponse)
        {
            try
            {
                SIPAuthorisationDigest authRequest = sipResponse.Header.AuthenticationHeader.SIPDigest;
                m_lastServerNonce = authRequest.Nonce;
                string username = (m_authUsername != null) ? m_authUsername : m_sipAccountAOR.User;
                authRequest.SetCredentials(username, m_password, registerRequest.URI.ToString(), SIPMethodsEnum.REGISTER.ToString());

                SIPRequest regRequest = registerRequest.Copy();
                regRequest.LocalSIPEndPoint = registerRequest.LocalSIPEndPoint;
                regRequest.Header.Vias.TopViaHeader.Branch = CallProperties.CreateBranchId();
                regRequest.Header.From.FromTag             = CallProperties.CreateNewTag();
                regRequest.Header.To.ToTag = null;
                regRequest.Header.CSeq     = ++m_cseq;

                regRequest.Header.AuthenticationHeader = new SIPAuthenticationHeader(authRequest);
                regRequest.Header.AuthenticationHeader.SIPDigest.Response = authRequest.Digest;

                //if (RequestSwitchboardToken)
                //{
                //    regRequest.Header.SwitchboardTokenRequest = m_expiry;
                //}

                return(regRequest);
            }
            catch (Exception excp)
            {
                logger.Error("Exception GetAuthenticatedRegistrationRequest. " + excp.Message);
                throw excp;
            }
        }
 private void TransactionInformationResponseReceived(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse)
 {
     m_lastInfoResponse = sipResponse;
     m_waitForSIPInfoResponse.Set();
 }
Exemple #24
0
        /// <summary>
        /// Handler for when an in dialog request is received on an established call.
        /// Typical types of request will be re-INVITES for things like putting a call on or
        /// off hold and REFER requests for transfers. Some in dialog request types, such
        /// as re-INVITES have specific events so they can be bubbled up to the
        /// application to deal with.
        /// </summary>
        /// <param name="sipRequest">The in dialog request received.</param>
        private async Task DialogRequestReceivedAsync(SIPRequest sipRequest)
        {
            if (sipRequest.Method == SIPMethodsEnum.BYE)
            {
                logger.LogInformation($"Remote call party hungup {sipRequest.StatusLine}.");
                Dialogue.DialogueState = SIPDialogueStateEnum.Terminated;

                SIPNonInviteTransaction byeTx = new SIPNonInviteTransaction(m_transport, sipRequest, null);
                byeTx.SendResponse(SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null));

                CallEnded();
            }
            else if (sipRequest.Method == SIPMethodsEnum.INVITE)
            {
                logger.LogDebug($"Re-INVITE request received {sipRequest.StatusLine}.");

                UASInviteTransaction reInviteTransaction = new UASInviteTransaction(m_transport, sipRequest, m_outboundProxy);

                try
                {
                    MediaSession.setRemoteDescription(new RTCSessionDescription {
                        sdp = SDP.ParseSDPDescription(sipRequest.Body), type = RTCSdpType.offer
                    });

                    CheckRemotePartyHoldCondition(MediaSession.remoteDescription.sdp);

                    var answerSdp = await MediaSession.createAnswer(null).ConfigureAwait(false);

                    Dialogue.RemoteSDP  = sipRequest.Body;
                    Dialogue.SDP        = answerSdp.ToString();
                    Dialogue.RemoteCSeq = sipRequest.Header.CSeq;

                    var okResponse = reInviteTransaction.GetOkResponse(SDP.SDP_MIME_CONTENTTYPE, Dialogue.SDP);
                    reInviteTransaction.SendFinalResponse(okResponse);
                }
                catch (Exception ex)
                {
                    logger.LogError(ex, "MediaSession can't process the re-INVITE request.");

                    if (OnReinviteRequest == null)
                    {
                        // The application isn't prepared to accept re-INVITE requests and we can't work out what it was for.
                        // We'll reject as gently as we can to try and not lose the call.
                        SIPResponse notAcceptableResponse = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.NotAcceptable, null);
                        reInviteTransaction.SendFinalResponse(notAcceptableResponse);
                    }
                    else
                    {
                        // The application is going to handle the re-INVITE request. We'll send a Trying response as a precursor.
                        SIPResponse tryingResponse = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Trying, null);
                        await reInviteTransaction.SendProvisionalResponse(tryingResponse).ConfigureAwait(false);

                        OnReinviteRequest.Invoke(reInviteTransaction);
                    }
                }
            }
            else if (sipRequest.Method == SIPMethodsEnum.OPTIONS)
            {
                //Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "OPTIONS request for established dialogue " + dialogue.DialogueName + ".", dialogue.Owner));
                SIPResponse okResponse = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null);
                okResponse.Body = Dialogue.RemoteSDP;
                okResponse.Header.ContentLength = okResponse.Body.Length;
                okResponse.Header.ContentType   = m_sdpContentType;
                await SendResponseAsync(okResponse).ConfigureAwait(false);
            }
            else if (sipRequest.Method == SIPMethodsEnum.MESSAGE)
            {
                //Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "MESSAGE for call " + sipRequest.URI.ToString() + ": " + sipRequest.Body + ".", dialogue.Owner));
                SIPResponse okResponse = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null);
                await m_transport.SendResponseAsync(okResponse).ConfigureAwait(false);
            }
            else if (sipRequest.Method == SIPMethodsEnum.REFER)
            {
                if (sipRequest.Header.ReferTo.IsNullOrBlank())
                {
                    // A REFER request must have a Refer-To header.
                    //Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Bad REFER request, no Refer-To header.", dialogue.Owner));
                    SIPResponse invalidResponse = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.BadRequest, "Missing mandatory Refer-To header");
                    await SendResponseAsync(invalidResponse).ConfigureAwait(false);
                }
                else
                {
                    //TODO: Add handling logic for in transfer requests from the remote call party.
                }
            }
            else if (sipRequest.Method == SIPMethodsEnum.NOTIFY)
            {
                SIPResponse okResponse = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null);
                await SendResponseAsync(okResponse).ConfigureAwait(false);

                if (sipRequest.Body?.Length > 0 && sipRequest.Header.ContentType?.Contains(m_sipReferContentType) == true)
                {
                    OnTransferNotify?.Invoke(sipRequest.Body);
                }
            }
        }
 private void TransactionFinalResponseReceived(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse)
 {
     m_lastFinalResponse = sipResponse;
     m_waitForSIPFinalResponse.Set(); 
 }
Exemple #26
0
        private RegisterResultEnum Register(SIPTransaction registerTransaction)
        {
            try
            {
                SIPRequest  sipRequest  = registerTransaction.TransactionRequest;
                SIPURI      registerURI = sipRequest.URI;
                SIPToHeader toHeader    = sipRequest.Header.To;
                string      toUser      = toHeader.ToURI.User;
                //string canonicalDomain = (m_strictRealmHandling) ? GetCanonicalDomain_External(toHeader.ToURI.Host, true) : toHeader.ToURI.Host;
                string canonicalDomain = toHeader.ToURI.Host;
                int    requestedExpiry = GetRequestedExpiry(sipRequest);

                if (canonicalDomain == null)
                {
                    FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Warn, "Register request for " + toHeader.ToURI.Host + " rejected as no matching domain found.", null));
                    SIPResponse noDomainResponse = GetErrorResponse(sipRequest, SIPResponseStatusCodesEnum.Forbidden, "Domain not serviced");
                    registerTransaction.SendFinalResponse(noDomainResponse);
                    return(RegisterResultEnum.DomainNotServiced);
                }

                //SIPAccount sipAccount = GetSIPAccount_External(s => s.SIPUsername == toUser && s.SIPDomain == canonicalDomain);
                SIPAccount sipAccount = new SIPAccount
                {
                    Id          = Guid.NewGuid(),
                    Owner       = "admin",
                    SIPUsername = toUser,
                    SIPDomain   = canonicalDomain
                };
                //SIPAccount sipAccount = GetSIPAccount_External(s => s.SIPUsername == toUser);
                SIPRequestAuthenticationResult authenticationResult = _sipRequestAuthenticator_External?.Invoke(registerTransaction.LocalSIPEndPoint, registerTransaction.RemoteEndPoint, sipRequest, sipAccount, FireProxyLogEvent);

                if (!_needAuthentication)
                {
                    SIPResponse okRes = GetOkResponse(sipRequest);

                    registerTransaction.SendFinalResponse(okRes);

                    //Add Camera Item Into Cache
                    CacheDeviceItem(sipRequest);

                    return(RegisterResultEnum.AuthenticationRequired);
                }

                if (!authenticationResult.Authenticated)
                {
                    // 401 Response with a fresh nonce needs to be sent.
                    SIPResponse authReqdResponse = SIPTransport.GetResponse(sipRequest, authenticationResult.ErrorResponse, null);
                    authReqdResponse.Header.AuthenticationHeader = authenticationResult.AuthenticationRequiredHeader;
                    registerTransaction.SendFinalResponse(authReqdResponse);

                    if (authenticationResult.ErrorResponse == SIPResponseStatusCodesEnum.Forbidden)
                    {
                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Warn, "Forbidden " + toUser + "@" + canonicalDomain + " does not exist, " + sipRequest.Header.ProxyReceivedFrom + ", " + sipRequest.Header.UserAgent + ".", null));
                        return(RegisterResultEnum.Forbidden);
                    }
                    else
                    {
                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Registrar, "Authentication required for " + toUser + "@" + canonicalDomain + " from " + sipRequest.Header.ProxyReceivedFrom + ".", toUser));
                        return(RegisterResultEnum.AuthenticationRequired);
                    }
                }
                else
                {
                    // Authenticated.
                    //if (!sipRequest.Header.UserAgent.IsNullOrBlank() && !m_switchboarduserAgentPrefix.IsNullOrBlank() && sipRequest.Header.UserAgent.StartsWith(m_switchboarduserAgentPrefix))
                    //{
                    //    // Check that the switchboard user is authorised.
                    //    var customer = CustomerPersistor_External.Get(x => x.CustomerUsername == sipAccount.Owner);
                    //    if (!(customer.ServiceLevel == CustomerServiceLevels.Switchboard.ToString() || customer.ServiceLevel == CustomerServiceLevels.Gold.ToString()))
                    //    {
                    //        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Warn, "Register request for switchboard from " + toHeader.ToURI.Host + " rejected as not correct service level.", sipAccount.Owner));
                    //        SIPResponse payReqdResponse = GetErrorResponse(sipRequest, SIPResponseStatusCodesEnum.PaymentRequired, "You need to purchase a Switchboard service");
                    //        registerTransaction.SendFinalResponse(payReqdResponse);
                    //        return RegisterResultEnum.SwitchboardPaymentRequired;
                    //    }
                    //}

                    if (sipRequest.Header.Contact == null || sipRequest.Header.Contact.Count == 0)
                    {
                        // No contacts header to update bindings with, return a list of the current bindings.
                        //List<SIPRegistrarBinding> bindings = m_registrarBindingsManager.GetBindings(sipAccount.Id);
                        ////List<SIPContactHeader> contactsList = m_registrarBindingsManager.GetContactHeader(); // registration.GetContactHeader(true, null);
                        //if (bindings != null)
                        //{
                        //    sipRequest.Header.Contact = GetContactHeader(bindings);
                        //}

                        SIPResponse okResponse = GetOkResponse(sipRequest);

                        registerTransaction.SendFinalResponse(okResponse);

                        //Add Camera Item Into Cache
                        CacheDeviceItem(sipRequest);

                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.RegisterSuccess, "Empty registration request successful for " + toUser + "@" + canonicalDomain + " from " + sipRequest.Header.ProxyReceivedFrom + ".", toUser));
                    }
                    else
                    {
                        SIPEndPoint uacRemoteEndPoint           = SIPEndPoint.TryParse(sipRequest.Header.ProxyReceivedFrom) ?? registerTransaction.RemoteEndPoint;
                        SIPEndPoint proxySIPEndPoint            = SIPEndPoint.TryParse(sipRequest.Header.ProxyReceivedOn);
                        SIPEndPoint registrarEndPoint           = registerTransaction.LocalSIPEndPoint;
                        SIPResponseStatusCodesEnum updateResult = SIPResponseStatusCodesEnum.Ok;
                        // string updateMessage = null;
                        DateTime startTime = DateTime.Now;

                        //List<SIPRegistrarBinding> bindingsList = m_registrarBindingsManager.UpdateBindings(
                        //    sipAccount,
                        //    proxySIPEndPoint,
                        //    uacRemoteEndPoint,
                        //    registrarEndPoint,
                        //    //sipRequest.Header.Contact[0].ContactURI.CopyOf(),
                        //    sipRequest.Header.Contact,
                        //    sipRequest.Header.CallId,
                        //    sipRequest.Header.CSeq,
                        //    //sipRequest.Header.Contact[0].Expires,
                        //    sipRequest.Header.Expires,
                        //    sipRequest.Header.UserAgent,
                        //    out updateResult,
                        //    out updateMessage);
                        //int bindingExpiry = GetBindingExpiry(bindingsList, sipRequest.Header.Contact[0].ContactURI.ToString());
                        TimeSpan duration = DateTime.Now.Subtract(startTime);
                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.RegistrarTiming, "Binding update time for " + toUser + "@" + canonicalDomain + " took " + duration.TotalMilliseconds + "ms.", null));

                        if (updateResult == SIPResponseStatusCodesEnum.Ok)
                        {
                            string proxySocketStr = (proxySIPEndPoint != null) ? " (proxy=" + proxySIPEndPoint.ToString() + ")" : null;

                            //  int bindingCount = 1;
                            //foreach (SIPRegistrarBinding binding in bindingsList)
                            //{
                            //    string bindingIndex = (bindingsList.Count == 1) ? String.Empty : " (" + bindingCount + ")";
                            //    //FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.RegisterSuccess, "Registration successful for " + toUser + "@" + canonicalDomain + " from " + uacRemoteEndPoint + proxySocketStr + ", binding " + binding.ContactSIPURI.ToParameterlessString() + ";expiry=" + binding.Expiry + bindingIndex + ".", toUser));
                            //    FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.RegisterSuccess, "Registration successful for " + toUser + "@" + canonicalDomain + " from " + uacRemoteEndPoint + ", binding " + binding.ContactSIPURI.ToParameterlessString() + ";expiry=" + binding.Expiry + bindingIndex + ".", toUser));
                            //    //FireProxyLogEvent(new SIPMonitorMachineEvent(SIPMonitorMachineEventTypesEnum.SIPRegistrarBindingUpdate, toUser, uacRemoteEndPoint, sipAccount.Id.ToString()));
                            //    bindingCount++;
                            //}

                            // The standard states that the Ok response should contain the list of current bindings but that breaks some UAs. As a
                            // compromise the list is returned with the Contact that UAC sent as the first one in the list.
                            //bool contactListSupported = m_userAgentConfigs.GetUserAgentContactListSupport(sipRequest.Header.UserAgent);
                            //if (contactListSupported)
                            //{
                            //    sipRequest.Header.Contact = GetContactHeader(bindingsList);
                            //}
                            //else
                            //{
                            //    // Some user agents can't match the contact header if the expiry is added to it.
                            //    sipRequest.Header.Contact[0].Expires = GetBindingExpiry(bindingsList, sipRequest.Header.Contact[0].ContactURI.ToString()); ;
                            //}

                            SIPResponse okResponse = GetOkResponse(sipRequest);

                            // If a request was made for a switchboard token and a certificate is available to sign the tokens then generate it.
                            //if (sipRequest.Header.SwitchboardTokenRequest > 0 && m_switchbboardRSAProvider != null)
                            //{
                            //    SwitchboardToken token = new SwitchboardToken(sipRequest.Header.SwitchboardTokenRequest, sipAccount.Owner, uacRemoteEndPoint.Address.ToString());

                            //    lock (m_switchbboardRSAProvider)
                            //    {
                            //        token.SignedHash = Convert.ToBase64String(m_switchbboardRSAProvider.SignHash(Crypto.GetSHAHash(token.GetHashString()), null));
                            //    }

                            //    string tokenXML = token.ToXML(true);
                            //    logger.Debug("Switchboard token set for " + sipAccount.Owner + " with expiry of " + token.Expiry + "s.");
                            //    okResponse.Header.SwitchboardToken = Crypto.SymmetricEncrypt(sipAccount.SIPPassword, sipRequest.Header.AuthenticationHeader.SIPDigest.Nonce, tokenXML);
                            //}

                            registerTransaction.SendFinalResponse(okResponse);

                            //Add Camera Item Into Cache
                            CacheDeviceItem(sipRequest);
                        }
                        else
                        {
                            // The binding update failed even though the REGISTER request was authorised. This is probably due to a
                            // temporary problem connecting to the bindings data store. Send Ok but set the binding expiry to the minimum so
                            // that the UA will try again as soon as possible.
                            FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Error, "Registration request successful but binding update failed for " + toUser + "@" + canonicalDomain + " from " + registerTransaction.RemoteEndPoint + ".", toUser));
                            sipRequest.Header.Contact[0].Expires = m_minimumBindingExpiry;
                            SIPResponse okResponse = GetOkResponse(sipRequest);
                            registerTransaction.SendFinalResponse(okResponse);
                        }
                    }

                    return(RegisterResultEnum.Authenticated);
                }
            }
            catch (Exception excp)
            {
                string regErrorMessage = "Exception registrarcore registering. " + excp.Message + "\r\n" + registerTransaction.TransactionRequest.ToString();
                logger.Error(regErrorMessage);
                FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Error, regErrorMessage, null));

                try
                {
                    SIPResponse errorResponse = GetErrorResponse(registerTransaction.TransactionRequest, SIPResponseStatusCodesEnum.InternalServerError, null);
                    registerTransaction.SendFinalResponse(errorResponse);
                }
                catch { }

                return(RegisterResultEnum.Error);
            }
        }
        public SIPResponse WaitForFinalResponse(int waitSeconds, SIPRequest sipRequest)
        {
            DateTime startWaitTime = DateTime.Now;
            m_waitForSIPFinalResponse.Reset();
            m_lastFinalResponse = null;

            while (m_lastFinalResponse == null && DateTime.Now.Subtract(startWaitTime).TotalSeconds < waitSeconds)
            {
                m_waitForSIPFinalResponse.WaitOne(Convert.ToInt32((waitSeconds - DateTime.Now.Subtract(startWaitTime).TotalSeconds) * 1000), false);

                if (m_lastFinalResponse != null && m_lastFinalResponse.Header.CallId == sipRequest.Header.CallId)
                {
                    break;
                }
                else
                {
                    m_lastFinalResponse = null;
                }
            }

            return m_lastFinalResponse;
        }
Exemple #28
0
        public void AddRegisterRequest(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint,
                                       SIPRequest registerRequest)
        {
            try
            {
                if (registerRequest.Method == SIPMethodsEnum.REGISTER)
                {
                    SIPSorceryPerformanceMonitor.IncrementCounter(SIPSorceryPerformanceMonitor
                                                                  .REGISTRAR_REGISTRATION_REQUESTS_PER_SECOND);

                    int requestedExpiry = GetRequestedExpiry(registerRequest);

                    if (registerRequest.Header.To == null)
                    {
                        Logger.Logger.Debug("Bad register request, no To header from " + remoteEndPoint + ".");
                        SIPResponse badReqResponse = SIPTransport.GetResponse(registerRequest,
                                                                              SIPResponseStatusCodesEnum.BadRequest, "Missing To header");
                        _sipTransport.SendResponse(badReqResponse);
                    }
                    else if (registerRequest.Header.To.ToURI.User.IsNullOrBlank())
                    {
                        Logger.Logger.Debug("Bad register request, no To user from " + remoteEndPoint + ".");
                        SIPResponse badReqResponse = SIPTransport.GetResponse(registerRequest,
                                                                              SIPResponseStatusCodesEnum.BadRequest, "Missing username on To header");
                        _sipTransport.SendResponse(badReqResponse);
                    }
                    else if (registerRequest.Header.Contact == null || registerRequest.Header.Contact.Count == 0)
                    {
                        Logger.Logger.Debug("Bad register request, no Contact header from " + remoteEndPoint + ".");
                        SIPResponse badReqResponse = SIPTransport.GetResponse(registerRequest,
                                                                              SIPResponseStatusCodesEnum.BadRequest, "Missing Contact header");
                        _sipTransport.SendResponse(badReqResponse);
                    }
                    else if (requestedExpiry > 0 && requestedExpiry < m_minimumBindingExpiry)
                    {
                        Logger.Logger.Debug("Bad register request, no expiry of " + requestedExpiry +
                                            " to small from " +
                                            remoteEndPoint + ".");
                        SIPResponse tooFrequentResponse = GetErrorResponse(registerRequest,
                                                                           SIPResponseStatusCodesEnum.IntervalTooBrief, null);
                        tooFrequentResponse.Header.MinExpires = m_minimumBindingExpiry;
                        _sipTransport.SendResponse(tooFrequentResponse);
                    }
                    else
                    {
                        if (m_registerQueue.Count < MAX_REGISTER_QUEUE_SIZE)
                        {
                            var registrarTransaction = _sipTransport.CreateNonInviteTransaction(registerRequest,
                                                                                                remoteEndPoint, localSIPEndPoint, null);
                            lock (m_registerQueue)
                            {
                                m_registerQueue.Enqueue(registrarTransaction);
                            }
                        }
                        else
                        {
                            Logger.Logger.Error("Register queue exceeded max queue size " + MAX_REGISTER_QUEUE_SIZE +
                                                ", overloaded response sent.");
                            SIPResponse overloadedResponse = SIPTransport.GetResponse(registerRequest,
                                                                                      SIPResponseStatusCodesEnum.TemporarilyUnavailable,
                                                                                      "Registrar overloaded, please try again shortly");
                            _sipTransport.SendResponse(overloadedResponse);
                        }

                        m_registerARE.Set();
                    }
                }
            }
            catch (Exception excp)
            {
                Logger.Logger.Error("Exception AddRegisterRequest (" + remoteEndPoint.ToString() + "). ->" +
                                    excp.Message);
            }
        }
        private SIPResponse GetResponse(SIPHeader requestHeader, SIPResponseStatusCodesEnum responseCode)
        {
            try
            {
                SIPResponse response = new SIPResponse(responseCode);

                response.Header = new SIPHeader(requestHeader.Contact, requestHeader.From, requestHeader.To, requestHeader.CSeq, requestHeader.CallId);
                response.Header.CSeqMethod = requestHeader.CSeqMethod;
                response.Header.Via = requestHeader.Via;
                response.Header.MaxForwards = Int32.MinValue;

                return response;
            }
            catch (Exception excp)
            {
                logger.Error("Exception GetResponse. " + excp.Message);
                throw excp;
            }
        }
Exemple #30
0
        private void UACCallAnswered(ISIPClientUserAgent answeredUAC, SIPResponse answeredResponse)
        {
            try
            {
                // Remove the current call from the pending list.
                lock (m_switchCalls)
                {
                    m_switchCalls.Remove(answeredUAC);
                }

                if (m_switchCallTransactions != null && answeredUAC.ServerTransaction != null)
                {
                    m_switchCallTransactions.Add(answeredUAC.ServerTransaction);
                }

                if (answeredResponse != null && answeredResponse.StatusCode >= 200 && answeredResponse.StatusCode <= 299)
                {
                    #region 2xx final response.

                    if (!m_callAnswered && !m_commandCancelled)
                    {
                        // This is the first call we've got an answer on.
                        m_callAnswered      = true;
                        m_answeredUAC       = answeredUAC;
                        AnsweredSIPResponse = answeredResponse;

                        SIPDialogueTransferModesEnum uasTransferMode = SIPDialogueTransferModesEnum.Default;
                        if (m_answeredUAC.CallDescriptor.TransferMode == SIPDialogueTransferModesEnum.NotAllowed)
                        {
                            answeredUAC.SIPDialogue.TransferMode = SIPDialogueTransferModesEnum.NotAllowed;
                            uasTransferMode = SIPDialogueTransferModesEnum.NotAllowed;
                        }
                        else if (m_answeredUAC.CallDescriptor.TransferMode == SIPDialogueTransferModesEnum.BlindPlaceCall)
                        {
                            answeredUAC.SIPDialogue.TransferMode = SIPDialogueTransferModesEnum.BlindPlaceCall;
                            uasTransferMode = SIPDialogueTransferModesEnum.BlindPlaceCall;
                        }
                        else if (m_answeredUAC.CallDescriptor.TransferMode == SIPDialogueTransferModesEnum.PassThru)
                        {
                            answeredUAC.SIPDialogue.TransferMode = SIPDialogueTransferModesEnum.PassThru;
                            uasTransferMode = SIPDialogueTransferModesEnum.PassThru;
                        }

                        /*else if (m_answeredUAC.CallDescriptor.TransferMode == SIPCallTransferModesEnum.Caller)
                         * {
                         *  answeredUAC.SIPDialogue.TransferMode = SIPDialogueTransferModesEnum.NotAllowed;
                         *  uasTransferMode = SIPDialogueTransferModesEnum.Allowed;
                         * }
                         * else if (m_answeredUAC.CallDescriptor.TransferMode == SIPCallTransferModesEnum.Callee)
                         * {
                         *  answeredUAC.SIPDialogue.TransferMode = SIPDialogueTransferModesEnum.Allowed;
                         *  uasTransferMode = SIPDialogueTransferModesEnum.NotAllowed;
                         * }
                         * else if (m_answeredUAC.CallDescriptor.TransferMode == SIPCallTransferModesEnum.Both)
                         * {
                         *  answeredUAC.SIPDialogue.TransferMode = SIPDialogueTransferModesEnum.Allowed;
                         *  uasTransferMode = SIPDialogueTransferModesEnum.Allowed;
                         * }*/

                        if (CallAnswered != null)
                        {
                            logger.Debug("Transfer mode=" + m_answeredUAC.CallDescriptor.TransferMode + ".");
                            CallAnswered(answeredResponse.Status, answeredResponse.ReasonPhrase, null, null, answeredResponse.Header.ContentType, answeredResponse.Body, answeredUAC.SIPDialogue, uasTransferMode);
                        }

                        // Cancel/hangup and other calls on this leg that are still around.
                        CancelNotRequiredCallLegs(CallCancelCause.NormalClearing);
                    }
                    else
                    {
                        // Call already answered or cancelled, hangup (send BYE).
                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call leg " + answeredUAC.CallDescriptor.Uri + " answered but call was already answered or cancelled, hanging up.", m_username));
                        SIPDialogue sipDialogue = new SIPDialogue(answeredUAC.ServerTransaction, m_username, m_adminMemberId);
                        sipDialogue.Hangup(m_sipTransport, m_outboundProxySocket);
                    }

                    #endregion

                    CallLegCompleted();
                }
                else if (answeredUAC.SIPDialogue != null)
                {
                    // Google Voice calls create the dialogue without using a SIP response.
                    if (!m_callAnswered && !m_commandCancelled)
                    {
                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call leg for Google Voice call to " + answeredUAC.CallDescriptor.Uri + " answered.", m_username));

                        // This is the first call we've got an answer on.
                        m_callAnswered = true;
                        m_answeredUAC  = answeredUAC;

                        if (CallAnswered != null)
                        {
                            CallAnswered(SIPResponseStatusCodesEnum.Ok, null, null, null, answeredUAC.SIPDialogue.ContentType, answeredUAC.SIPDialogue.RemoteSDP, answeredUAC.SIPDialogue, SIPDialogueTransferModesEnum.NotAllowed);
                        }

                        // Cancel/hangup and other calls on this leg that are still around.
                        CancelNotRequiredCallLegs(CallCancelCause.NormalClearing);
                    }
                    else
                    {
                        // Call already answered or cancelled, hangup (send BYE).
                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call leg for Google Voice call to " + answeredUAC.CallDescriptor.Uri + " answered but call was already answered or cancelled, hanging up.", m_username));
                        answeredUAC.SIPDialogue.Hangup(m_sipTransport, m_outboundProxySocket);
                    }
                }
                else if (answeredResponse != null && answeredResponse.StatusCode >= 300 && answeredResponse.StatusCode <= 399)
                {
                    ProcessRedirect(answeredUAC, answeredResponse);
                }
                else if (answeredResponse != null)
                {
                    // This call leg failed, record the failure status and reason.
                    m_lastFailureStatus = answeredResponse.Status;
                    m_lastFailureReason = answeredResponse.ReasonPhrase;

                    if (m_switchCallTransactions != null && answeredUAC.ServerTransaction != null)
                    {
                        m_switchCallTransactions.Add(answeredUAC.ServerTransaction);
                    }

                    CallLegCompleted();
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception ForkCall UACCallAnswered. " + excp);
            }
        }
 void transport_SIPResponseInTraceEvent(SIPEndPoint localEndPoint, SIPEndPoint fromEndPoint, SIPResponse sipResponse)
 {
     logger.LogDebug("Response In: " + localEndPoint + "<-" + fromEndPoint.ToString() + "\n" + sipResponse.ToString());
 }
        public void ProcessNotifyRequest(SIPRequest sipRequest)
        {
            try
            {
                // Hack to work around MWI request from callcentric not having a trailing CRLF and breaking some softphones like the Bria.
                if (sipRequest.Header.Event == MWI_EVENT_TYPE && sipRequest.Body.NotNullOrBlank() && sipRequest.Body.Substring(sipRequest.Body.Length - 2) != m_crlf)
                {
                    sipRequest.Body += m_crlf;
                }

                string fromURI = (sipRequest.Header.From != null && sipRequest.Header.From.FromURI != null) ? sipRequest.Header.From.FromURI.ToString() : "unknown";

                string domain = GetCanonicalDomain_External(sipRequest.URI.Host, true);
                if (domain != null)
                {
                    SIPAccountAsset sipAccount = GetSIPAccount_External(s => s.SIPUsername == sipRequest.URI.User && s.SIPDomain == domain);

                    if (sipAccount != null)
                    {
                        List <SIPRegistrarBinding> bindings = GetSIPAccountBindings_External(b => b.SIPAccountId == sipAccount.Id, null, 0, MAX_FORWARD_BINDINGS);

                        if (bindings != null)
                        {
                            foreach (SIPRegistrarBinding binding in bindings)
                            {
                                SIPURI      dstURI           = binding.MangledContactSIPURI;
                                SIPEndPoint localSIPEndPoint = (m_outboundProxy != null) ? m_sipTransport.GetDefaultSIPEndPoint(m_outboundProxy.Protocol) : m_sipTransport.GetDefaultSIPEndPoint(dstURI.Protocol);

                                SIPEndPoint dstSIPEndPoint = null;

                                // If the outbound proxy is a loopback address, as it will normally be for local deployments, then it cannot be overriden.
                                if (m_outboundProxy != null && IPAddress.IsLoopback(m_outboundProxy.Address))
                                {
                                    dstSIPEndPoint = m_outboundProxy;
                                }
                                else if (binding.ProxySIPEndPoint != null)
                                {
                                    // If the binding has a specific proxy end point sent then the request needs to be forwarded to the proxy's default end point for it to take care of.
                                    dstSIPEndPoint = new SIPEndPoint(SIPProtocolsEnum.udp, new IPEndPoint(binding.ProxySIPEndPoint.Address, m_defaultSIPPort));
                                }
                                else if (m_outboundProxy != null)
                                {
                                    dstSIPEndPoint = m_outboundProxy;
                                }
                                else
                                {
                                    SIPDNSLookupResult lookupResult = m_sipTransport.GetURIEndPoint(dstURI, false);
                                    if (lookupResult.LookupError != null)
                                    {
                                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.MWI, "A NOTIFY request from " + fromURI + " was not forwarded due to DNS failure for " + dstURI.Host + ", " + lookupResult.LookupError + ".", sipAccount.Owner));
                                    }
                                    else
                                    {
                                        dstSIPEndPoint = lookupResult.GetSIPEndPoint();
                                    }
                                }

                                if (dstSIPEndPoint != null)
                                {
                                    // Rather than create a brand new request copy the received one and modify the headers that need to be unique.
                                    SIPRequest notifyRequest = sipRequest.Copy();
                                    notifyRequest.URI            = dstURI;
                                    notifyRequest.Header.Contact = SIPContactHeader.CreateSIPContactList(new SIPURI(dstURI.Scheme, localSIPEndPoint));
                                    notifyRequest.Header.To      = new SIPToHeader(null, dstURI, null);
                                    notifyRequest.Header.CallId  = CallProperties.CreateNewCallId();
                                    SIPViaHeader viaHeader = new SIPViaHeader(localSIPEndPoint, CallProperties.CreateBranchId());
                                    notifyRequest.Header.Vias = new SIPViaSet();
                                    notifyRequest.Header.Vias.PushViaHeader(viaHeader);

                                    // If the binding has a proxy socket defined set the header to ask the upstream proxy to use it.
                                    if (binding.ProxySIPEndPoint != null)
                                    {
                                        notifyRequest.Header.ProxySendFrom = binding.ProxySIPEndPoint.ToString();

                                        // If the binding has a specific proxy end point sent then the request needs to be forwarded to the proxy's default end point for it to take care of.
                                        dstSIPEndPoint = new SIPEndPoint(SIPProtocolsEnum.udp, new IPEndPoint(binding.ProxySIPEndPoint.Address, m_defaultSIPPort));
                                    }

                                    Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.MWI, "Forwarding NOTIFY request from " + fromURI + " to registered binding at " + dstURI.ToString() + ", proxy " + dstSIPEndPoint.ToString() + ".", sipAccount.Owner));
                                    SIPNonInviteTransaction notifyTransaction = m_sipTransport.CreateNonInviteTransaction(notifyRequest, dstSIPEndPoint, localSIPEndPoint, dstSIPEndPoint);
                                    notifyTransaction.SendReliableRequest();
                                }
                                else
                                {
                                    Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.MWI, "A NOTIFY request from " + fromURI + " was not forwarded as no destination end point was resolved.", sipAccount.Owner));
                                }
                            }

                            // Send OK response to server.
                            SIPResponse okResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null);
                            m_sipTransport.SendResponse(okResponse);
                        }
                        else
                        {
                            // Send unavailable response to server.
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.MWI, "NOTIFY request from " + fromURI + " for " + sipAccount.SIPUsername + "@" + sipAccount.SIPDomain + " but no bindings available, responding with temporarily unavailable.", sipAccount.Owner));
                            SIPResponse notAvailableResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.TemporarilyUnavailable, null);
                            m_sipTransport.SendResponse(notAvailableResponse);
                        }
                    }
                    else
                    {
                        // Send Not found response to server.
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.MWI, "NOTIFY request from " + fromURI + " for " + sipRequest.URI.ToString() + " but no matching SIP account, responding with not found.", null));
                        SIPResponse notFoundResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.NotFound, null);
                        m_sipTransport.SendResponse(notFoundResponse);
                    }
                }
                else
                {
                    // Send Not Serviced response to server.
                    Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.MWI, "NOTIFY request from " + fromURI + " for a non-serviced domain responding with not found.", null));
                    SIPResponse notServicedResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.NotFound, "Domain not serviced");
                    m_sipTransport.SendResponse(notServicedResponse);
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception SIPNotifyManager ProcessNotifyRequest. " + excp.Message);
            }
        }
Exemple #33
0
        static void Main(string[] args)
        {
            Console.WriteLine("SIPSorcery SIP to WebRTC example.");
            Console.WriteLine("Press ctrl-c to exit.");

            // Plumbing code to facilitate a graceful exit.
            CancellationTokenSource exitCts = new CancellationTokenSource(); // Cancellation token to stop the SIP transport and RTP stream.

            AddConsoleLogger();

            // Start web socket.
            Console.WriteLine("Starting web socket server...");
            _webSocketServer = new WebSocketServer(IPAddress.Any, WEBSOCKET_PORT, true);
            _webSocketServer.SslConfiguration.ServerCertificate          = new X509Certificate2(WEBSOCKET_CERTIFICATE_PATH);
            _webSocketServer.SslConfiguration.CheckCertificateRevocation = false;
            //_webSocketServer.Log.Level = WebSocketSharp.LogLevel.Debug;
            _webSocketServer.AddWebSocketService <SDPExchange>("/", (sdpExchanger) =>
            {
                sdpExchanger.WebSocketOpened   += SendSDPOffer;
                sdpExchanger.SDPAnswerReceived += SDPAnswerReceived;
            });
            _webSocketServer.Start();

            Console.WriteLine($"Waiting for browser web socket connection to {_webSocketServer.Address}:{_webSocketServer.Port}...");

            // Set up a default SIP transport.
            var sipTransport = new SIPTransport();

            sipTransport.AddSIPChannel(new SIPUDPChannel(new IPEndPoint(IPAddress.Any, SIP_LISTEN_PORT)));

            //EnableTraceLogs(sipTransport);

            RTPMediaSession RtpMediaSession = null;

            // Create a SIP user agent to receive a call from a remote SIP client.
            // Wire up event handlers for the different stages of the call.
            var userAgent = new SIPUserAgent(sipTransport, null);

            // We're only answering SIP calls, not placing them.
            userAgent.OnCallHungup += () =>
            {
                Log.LogInformation($"Call hungup by remote party.");
                exitCts.Cancel();
            };
            userAgent.ServerCallCancelled += (uas) => Log.LogInformation("Incoming call cancelled by caller.");

            sipTransport.SIPTransportRequestReceived += async(localEndPoint, remoteEndPoint, sipRequest) =>
            {
                if (sipRequest.Header.From != null &&
                    sipRequest.Header.From.FromTag != null &&
                    sipRequest.Header.To != null &&
                    sipRequest.Header.To.ToTag != null)
                {
                    // This is an in-dialog request that will be handled directly by a user agent instance.
                }
                else if (sipRequest.Method == SIPMethodsEnum.INVITE)
                {
                    if (userAgent?.IsCallActive == true)
                    {
                        Log.LogWarning($"Busy response returned for incoming call request from {remoteEndPoint}: {sipRequest.StatusLine}.");
                        // If we are already on a call return a busy response.
                        UASInviteTransaction uasTransaction = new UASInviteTransaction(sipTransport, sipRequest, null);
                        SIPResponse          busyResponse   = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.BusyHere, null);
                        uasTransaction.SendFinalResponse(busyResponse);
                    }
                    else
                    {
                        Log.LogInformation($"Incoming call request from {remoteEndPoint}: {sipRequest.StatusLine}.");
                        var incomingCall = userAgent.AcceptCall(sipRequest);

                        RtpMediaSession = new RTPMediaSession(SDPMediaTypesEnum.audio, new SDPMediaFormat(SDPMediaFormatsEnum.PCMU), AddressFamily.InterNetwork);
                        await userAgent.Answer(incomingCall, RtpMediaSession);

                        RtpMediaSession.OnRtpPacketReceived += (mediaType, rtpPacket) => OnMediaSampleReady?.Invoke(mediaType, rtpPacket.Header.Timestamp, rtpPacket.Payload);

                        Log.LogInformation($"Answered incoming call from {sipRequest.Header.From.FriendlyDescription()} at {remoteEndPoint}.");
                    }
                }
                else
                {
                    Log.LogDebug($"SIP {sipRequest.Method} request received but no processing has been set up for it, rejecting.");
                    SIPResponse notAllowedResponse = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.MethodNotAllowed, null);
                    await sipTransport.SendResponseAsync(notAllowedResponse);
                }
            };

            // Ctrl-c will gracefully exit the call at any point.
            Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e)
            {
                e.Cancel = true;
                exitCts.Cancel();
            };

            // Wait for a signal saying the call failed, was cancelled with ctrl-c or completed.
            exitCts.Token.WaitHandle.WaitOne();

            #region Cleanup.

            Log.LogInformation("Exiting...");

            RtpMediaSession?.Close();

            if (userAgent != null)
            {
                if (userAgent.IsCallActive)
                {
                    Log.LogInformation($"Hanging up call to {userAgent?.CallDescriptor?.To}.");
                    userAgent.Hangup();
                }

                // Give the BYE or CANCEL request time to be transmitted.
                Log.LogInformation("Waiting 1s for call to clean up...");
                Task.Delay(1000).Wait();
            }

            SIPSorcery.Net.DNSManager.Stop();

            if (sipTransport != null)
            {
                Log.LogInformation("Shutting down SIP transport...");
                sipTransport.Shutdown();
            }

            #endregion
        }
Exemple #34
0
        public SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum serverType, SIPMonitorEventTypesEnum eventType, string message, SIPRequest sipRequest, SIPResponse sipResponse, SIPEndPoint localEndPoint, SIPEndPoint remoteEndPoint, SIPCallDirection callDirection)
        {
            m_serialisationPrefix = SERIALISATION_PREFIX;
            ClientType            = SIPMonitorClientTypesEnum.Console;

            ServerType     = serverType;
            EventType      = eventType;
            Message        = message;
            RemoteEndPoint = remoteEndPoint;
            ServerEndPoint = localEndPoint;
            Created        = DateTimeOffset.UtcNow;
#if !SILVERLIGHT
            ProcessID = Process.GetCurrentProcess().Id;
#endif

            string dirn = (callDirection == SIPCallDirection.In) ? CALLDIRECTION_IN_STRING : CALLDIRECTION_OUT_STRING;
            if (sipRequest != null)
            {
                Message = "REQUEST (" + Created.ToString("HH:mm:ss:fff") + "): " + localEndPoint + dirn + remoteEndPoint + "\r\n" + sipRequest.ToString();
            }
            else if (sipResponse != null)
            {
                Message = "RESPONSE (" + Created.ToString("HH:mm:ss:fff") + "): " + localEndPoint + dirn + remoteEndPoint + "\r\n" + sipResponse.ToString();
            }
        }
Exemple #35
0
        /// <summary>
        /// Handler for processing incoming SIP requests.
        /// </summary>
        /// <param name="localSIPEndPoint">The end point the request was received on.</param>
        /// <param name="remoteEndPoint">The end point the request came from.</param>
        /// <param name="sipRequest">The SIP request received.</param>
        private void SIPTransportRequestReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest sipRequest)
        {
            if (sipRequest.Method == SIPMethodsEnum.BYE)
            {
                if (m_uac != null && m_uac.SIPDialogue != null && sipRequest.Header.CallId == m_uac.SIPDialogue.CallId)
                {
                    // Call has been hungup by remote end.
                    StatusMessage("Call hungup by remote end.");
                    SIPNonInviteTransaction byeTransaction = m_sipTransport.CreateNonInviteTransaction(sipRequest, remoteEndPoint, localSIPEndPoint, null);
                    SIPResponse             byeResponse    = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null);
                    byeTransaction.SendFinalResponse(byeResponse);
                    CallFinished();
                }
                else if (m_uas != null && m_uas.SIPDialogue != null && sipRequest.Header.CallId == m_uas.SIPDialogue.CallId)
                {
                    // Call has been hungup by remote end.
                    StatusMessage("Call hungup.");
                    SIPNonInviteTransaction byeTransaction = m_sipTransport.CreateNonInviteTransaction(sipRequest, remoteEndPoint, localSIPEndPoint, null);
                    SIPResponse             byeResponse    = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null);
                    byeTransaction.SendFinalResponse(byeResponse);
                    CallFinished();
                }
                else
                {
                    logger.Debug("Unmatched BYE request received for " + sipRequest.URI.ToString() + ".");
                    SIPResponse noCallLegResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.CallLegTransactionDoesNotExist, null);
                    m_sipTransport.SendResponse(noCallLegResponse);
                }
            }
            else if (sipRequest.Method == SIPMethodsEnum.INVITE)
            {
                StatusMessage("Incoming call request: " + localSIPEndPoint + "<-" + remoteEndPoint + " " + sipRequest.URI.ToString() + ".");
                UASInviteTransaction uasTransaction = m_sipTransport.CreateUASTransaction(sipRequest, remoteEndPoint, localSIPEndPoint, null);
                m_uas = new SIPServerUserAgent(m_sipTransport, null, null, null, SIPCallDirection.In, null, null, null, uasTransaction);
                m_uas.CallCancelled += UASCallCancelled;

                m_uas.Progress(SIPResponseStatusCodesEnum.Trying, null, null, null, null);
                m_uas.Progress(SIPResponseStatusCodesEnum.Ringing, null, null, null, null);

                IncomingCall();
            }
            else if (sipRequest.Method == SIPMethodsEnum.CANCEL)
            {
                UASInviteTransaction inviteTransaction = (UASInviteTransaction)m_sipTransport.GetTransaction(SIPTransaction.GetRequestTransactionId(sipRequest.Header.Vias.TopViaHeader.Branch, SIPMethodsEnum.INVITE));

                if (inviteTransaction != null)
                {
                    StatusMessage("Call was cancelled by remote end.");
                    SIPCancelTransaction cancelTransaction = m_sipTransport.CreateCancelTransaction(sipRequest, remoteEndPoint, localSIPEndPoint, inviteTransaction);
                    cancelTransaction.GotRequest(localSIPEndPoint, remoteEndPoint, sipRequest);
                }
                else
                {
                    logger.Debug("No matching transaction was found for CANCEL to " + sipRequest.URI.ToString() + ".");
                    SIPResponse noCallLegResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.CallLegTransactionDoesNotExist, null);
                    m_sipTransport.SendResponse(noCallLegResponse);
                }

                CallFinished();
            }
            else
            {
                logger.Debug("SIP " + sipRequest.Method + " request received but no processing has been set up for it, rejecting.");
                SIPResponse notAllowedResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.MethodNotAllowed, null);
                m_sipTransport.SendResponse(notAllowedResponse);
            }
        }
Exemple #36
0
        static void Main()
        {
            Console.WriteLine("SIPSorcery client user agent example.");
            Console.WriteLine("Press ctrl-c to exit.");

            // Plumbing code to facilitate a graceful exit.
            CancellationTokenSource rtpCts = new CancellationTokenSource(); // Cancellation token to stop the RTP stream.
            bool isCallHungup  = false;
            bool hasCallFailed = false;

            AddConsoleLogger();

            SIPURI callUri = SIPURI.ParseSIPURI(DEFAULT_DESTINATION_SIP_URI);

            Log.LogInformation($"Call destination {callUri}.");

            // Set up a default SIP transport.
            var sipTransport = new SIPTransport();

            sipTransport.AddSIPChannel(new SIPUDPChannel(new IPEndPoint(IPAddress.Any, 0)));

            // Un/comment this line to see/hide each SIP message sent and received.
            EnableTraceLogs(sipTransport);

            // Note this relies on the callURI host being an IP address. If it's a hostname a DNS lookup is required.
            IPAddress localIPAddress = NetServices.GetLocalAddressForRemote(callUri.ToSIPEndPoint().Address);

            // Initialise an RTP session to receive the RTP packets from the remote SIP server.
            var rtpSession = new RTPMediaSession(SDPMediaTypesEnum.audio, (int)SDPMediaFormatsEnum.PCMU, localIPAddress.AddressFamily);
            var offerSDP   = rtpSession.GetSDP(localIPAddress);

            // Create a client user agent to place a call to a remote SIP server along with event handlers for the different stages of the call.
            var uac = new SIPClientUserAgent(sipTransport);

            uac.CallTrying += (uac, resp) =>
            {
                Log.LogInformation($"{uac.CallDescriptor.To} Trying: {resp.StatusCode} {resp.ReasonPhrase}.");
            };
            uac.CallRinging += (uac, resp) => Log.LogInformation($"{uac.CallDescriptor.To} Ringing: {resp.StatusCode} {resp.ReasonPhrase}.");
            uac.CallFailed  += (uac, err) =>
            {
                Log.LogWarning($"{uac.CallDescriptor.To} Failed: {err}");
                hasCallFailed = true;
            };
            uac.CallAnswered += (uac, resp) =>
            {
                if (resp.Status == SIPResponseStatusCodesEnum.Ok)
                {
                    Log.LogInformation($"{uac.CallDescriptor.To} Answered: {resp.StatusCode} {resp.ReasonPhrase}.");
                    rtpSession.SetRemoteSDP(SDP.ParseSDPDescription(resp.Body));
                    Log.LogDebug($"Remote RTP socket {rtpSession.DestinationEndPoint}.");
                }
                else
                {
                    Log.LogWarning($"{uac.CallDescriptor.To} Answered: {resp.StatusCode} {resp.ReasonPhrase}.");
                }
            };

            // The only incoming request that needs to be explicitly handled for this example is if the remote end hangs up the call.
            sipTransport.SIPTransportRequestReceived += async(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest sipRequest) =>
            {
                if (sipRequest.Method == SIPMethodsEnum.BYE)
                {
                    SIPResponse okResponse = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null);
                    await sipTransport.SendResponseAsync(okResponse);

                    if (uac.IsUACAnswered)
                    {
                        Log.LogInformation("Call was hungup by remote server.");
                        isCallHungup = true;
                        rtpCts.Cancel();
                    }
                }
            };

            // Wire up the RTP receive session to the default speaker.
            var(audioOutEvent, audioOutProvider) = GetAudioOutputDevice();
            rtpSession.OnRtpPacketReceived      += (rtpPacket) =>
            {
                var sample = rtpPacket.Payload;
                for (int index = 0; index < sample.Length; index++)
                {
                    short  pcm       = NAudio.Codecs.MuLawDecoder.MuLawToLinearSample(sample[index]);
                    byte[] pcmSample = new byte[] { (byte)(pcm & 0xFF), (byte)(pcm >> 8) };
                    audioOutProvider.AddSamples(pcmSample, 0, 2);
                }
            };

            // Send audio packets (in this case silence) to the callee.
            Task.Run(() => SendSilence(rtpSession, rtpCts));

            // Start the thread that places the call.
            SIPCallDescriptor callDescriptor = new SIPCallDescriptor(
                SIPConstants.SIP_DEFAULT_USERNAME,
                null,
                callUri.ToString(),
                SIPConstants.SIP_DEFAULT_FROMURI,
                null, null, null, null,
                SIPCallDirection.Out,
                SDP.SDP_MIME_CONTENTTYPE,
                offerSDP.ToString(),
                null);

            uac.Call(callDescriptor);

            // Ctrl-c will gracefully exit the call at any point.
            Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e)
            {
                e.Cancel = true;
                rtpCts.Cancel();
            };

            // Give the call some time to answer.
            Task.Delay(3000).Wait();

            // Send some DTMF key presses via RTP events.
            var dtmf5 = new RTPEvent(0x05, false, RTPEvent.DEFAULT_VOLUME, 1200, RTPMediaSession.DTMF_EVENT_PAYLOAD_ID);

            rtpSession.SendDtmfEvent(dtmf5, rtpCts.Token).Wait();
            Task.Delay(2000, rtpCts.Token).Wait();

            var dtmf9 = new RTPEvent(0x09, false, RTPEvent.DEFAULT_VOLUME, 1200, RTPMediaSession.DTMF_EVENT_PAYLOAD_ID);

            rtpSession.SendDtmfEvent(dtmf9, rtpCts.Token).Wait();
            Task.Delay(2000, rtpCts.Token).Wait();

            var dtmf2 = new RTPEvent(0x02, false, RTPEvent.DEFAULT_VOLUME, 1200, RTPMediaSession.DTMF_EVENT_PAYLOAD_ID);

            rtpSession.SendDtmfEvent(dtmf2, rtpCts.Token).Wait();
            Task.Delay(2000, rtpCts.Token).ContinueWith((task) => { }).Wait(); // Don't care about the exception if the cancellation token is set.

            Log.LogInformation("Exiting...");

            rtpCts.Cancel();
            audioOutEvent?.Stop();
            rtpSession.CloseSession(null);

            if (!isCallHungup && uac != null)
            {
                if (uac.IsUACAnswered)
                {
                    Log.LogInformation($"Hanging up call to {uac.CallDescriptor.To}.");
                    uac.Hangup();
                }
                else if (!hasCallFailed)
                {
                    Log.LogInformation($"Cancelling call to {uac.CallDescriptor.To}.");
                    uac.Cancel();
                }

                // Give the BYE or CANCEL request time to be transmitted.
                Log.LogInformation("Waiting 1s for call to clean up...");
                Task.Delay(1000).Wait();
            }

            SIPSorcery.Net.DNSManager.Stop();

            if (sipTransport != null)
            {
                Log.LogInformation("Shutting down SIP transport...");
                sipTransport.Shutdown();
            }
        }
        private void SIPResponseOutTraceEvent(SIPEndPoint localEP, SIPEndPoint remoteEP, SIPResponse sipResponse)
        {
            logger.LogDebug($"Response Sent {localEP}<-{remoteEP}: {sipResponse.ShortDescription}.");

            if (_homerSIPClient != null)
            {
                var hepBuffer = HepPacket.GetBytes(localEP, remoteEP, DateTime.Now, 333, "myHep", sipResponse.ToString());
                _homerSIPClient.SendAsync(hepBuffer, hepBuffer.Length, HOMER_SERVER_ADDRESS, HOMER_SERVER_PORT);
            }
        }
        private void ByeServerFinalResponseReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse)
        {
            try
            {
                Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentServer, SIPMonitorEventTypesEnum.DialPlan, "Response " + sipResponse.StatusCode + " " + sipResponse.ReasonPhrase + " for " + sipTransaction.TransactionRequest.URI.ToString() + ".", Owner));

                SIPNonInviteTransaction byeTransaction = sipTransaction as SIPNonInviteTransaction;
                byeTransaction.NonInviteTransactionFinalResponseReceived -= ByeServerFinalResponseReceived;

                if ((sipResponse.Status == SIPResponseStatusCodesEnum.ProxyAuthenticationRequired || sipResponse.Status == SIPResponseStatusCodesEnum.Unauthorised) && SIPAccount != null)
                {
                    // Resend BYE with credentials.
                    SIPAuthorisationDigest authRequest = sipResponse.Header.AuthenticationHeader.SIPDigest;
                    SIPURI contactUri = sipResponse.Header.Contact.Any() ? sipResponse.Header.Contact[0].ContactURI : sipResponse.Header.From.FromURI;

                    authRequest.SetCredentials(SIPAccount.SIPUsername, SIPAccount.SIPPassword, contactUri.ToString(), SIPMethodsEnum.BYE.ToString());

                    SIPRequest authByeRequest = byeTransaction.TransactionRequest;
                    authByeRequest.Header.AuthenticationHeader = new SIPAuthenticationHeader(authRequest);
                    authByeRequest.Header.AuthenticationHeader.SIPDigest.Response = authRequest.Digest;
                    authByeRequest.Header.Vias.TopViaHeader.Branch = CallProperties.CreateBranchId();
                    authByeRequest.Header.CSeq = authByeRequest.Header.CSeq + 1;

                    SIPNonInviteTransaction bTransaction = m_sipTransport.CreateNonInviteTransaction(authByeRequest, null, localSIPEndPoint, null);
                    bTransaction.SendReliableRequest();
                }
            }
            catch (Exception excp)
            {
                Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.Error, "Exception ByServerFinalResponseReceived. " + excp.Message, Owner));
            }
        }
        /// <summary>
        /// The event handler for responses to the initial register request.
        /// </summary>
        private void ServerResponseReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse)
        {
            try
            {
                Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterInProgress, "Server response " + sipResponse.Status + " received for " + m_sipAccountAOR.ToString() + ".", null));

                if (sipResponse.Status == SIPResponseStatusCodesEnum.ProxyAuthenticationRequired || sipResponse.Status == SIPResponseStatusCodesEnum.Unauthorised)
                {
                    if (sipResponse.Header.AuthenticationHeader != null)
                    {
                        if (m_attempts >= m_maxRegisterAttempts)
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Registration to " + m_sipAccountAOR.ToString() + " reached the maximum number of allowed attempts without a failure condition.", null));
                            m_isRegistered = false;
                            RegistrationTemporaryFailure?.Invoke(m_sipAccountAOR, "Registration reached the maximum number of allowed attempts.");
                            m_waitForRegistrationMRE.Set();
                        }
                        else
                        {
                            m_attempts++;
                            SIPRequest  authenticatedRequest = GetAuthenticatedRegistrationRequest(sipTransaction.TransactionRequest, sipResponse);
                            SIPEndPoint registrarSIPEndPoint = m_outboundProxy;
                            if (registrarSIPEndPoint == null)
                            {
                                //SIPDNSLookupResult lookupResult = m_sipTransport.GetHostEndPoint(m_registrarHost, false);
                                SIPURI uri          = SIPURI.ParseSIPURIRelaxed(m_registrarHost);
                                var    lookupResult = m_sipTransport.ResolveSIPUriAsync(uri).ConfigureAwait(false).GetAwaiter().GetResult();
                                if (lookupResult == null)
                                {
                                    Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Could not resolve " + m_registrarHost + ".", null));
                                }
                                else
                                {
                                    registrarSIPEndPoint = lookupResult;
                                }
                            }
                            if (registrarSIPEndPoint == null)
                            {
                                logger.LogWarning("SIPRegistrationAgent could not resolve " + m_registrarHost + ".");

                                RegistrationFailed?.Invoke(m_sipAccountAOR, "Could not resolve " + m_registrarHost + ".");
                            }
                            else
                            {
                                SIPNonInviteTransaction regAuthTransaction = new SIPNonInviteTransaction(m_sipTransport, authenticatedRequest, registrarSIPEndPoint);
                                regAuthTransaction.NonInviteTransactionFinalResponseReceived += (lep, rep, tn, rsp) => { ThreadPool.QueueUserWorkItem(delegate { AuthResponseReceived(lep, rep, tn, rsp); }); return(Task.FromResult(SocketError.Success)); };
                                regAuthTransaction.NonInviteTransactionTimedOut += (tn) => { ThreadPool.QueueUserWorkItem(delegate { RegistrationTimedOut(tn); }); };
                                m_sipTransport.SendTransaction(regAuthTransaction);
                            }
                        }
                    }
                    else
                    {
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Registration failed with " + sipResponse.Status + " but no authentication header was supplied for " + m_sipAccountAOR.ToString() + ".", null));
                        m_isRegistered = false;
                        RegistrationTemporaryFailure?.Invoke(m_sipAccountAOR, "Registration failed with " + sipResponse.Status + " but no authentication header was supplied.");
                        m_waitForRegistrationMRE.Set();
                    }
                }
                else
                {
                    if (sipResponse.Status == SIPResponseStatusCodesEnum.Ok)
                    {
                        if (m_expiry > 0)
                        {
                            m_isRegistered = true;
                            m_expiry       = GetUpdatedExpiry(sipResponse);
                            RegistrationSuccessful?.Invoke(m_sipAccountAOR);
                        }
                        else
                        {
                            m_isRegistered = false;
                            RegistrationRemoved?.Invoke(m_sipAccountAOR);
                        }

                        m_waitForRegistrationMRE.Set();
                    }
                    else if (sipResponse.Status == SIPResponseStatusCodesEnum.Forbidden || sipResponse.Status == SIPResponseStatusCodesEnum.NotFound)
                    {
                        // SIP account does not appear to exist.
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Registration failed with " + sipResponse.Status + " for " + m_sipAccountAOR.ToString() + ", no further registration attempts will be made.", null));
                        string reasonPhrase = (sipResponse.ReasonPhrase.IsNullOrBlank()) ? sipResponse.Status.ToString() : sipResponse.ReasonPhrase;
                        RegistrationFailed?.Invoke(m_sipAccountAOR, "Registration failed with " + (int)sipResponse.Status + " " + reasonPhrase + ".");
                        m_exit = true;
                        m_waitForRegistrationMRE.Set();
                    }
                    else if (sipResponse.Status == SIPResponseStatusCodesEnum.IntervalTooBrief && m_expiry != 0)
                    {
                        m_expiry = GetUpdatedExpiryForIntervalTooBrief(sipResponse);
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterInProgress, "Registration for " + m_sipAccountAOR.ToString() + " had a too short expiry, updated to +" + m_expiry + " and trying again.", null));
                        SendInitialRegister();
                    }
                    else
                    {
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Registration failed with " + sipResponse.Status + " for " + m_sipAccountAOR.ToString() + ".", null));
                        m_isRegistered = false;
                        RegistrationTemporaryFailure?.Invoke(m_sipAccountAOR, "Registration failed with " + sipResponse.Status + ".");
                        m_waitForRegistrationMRE.Set();
                    }
                }
            }
            catch (Exception excp)
            {
                logger.LogError("Exception SIPRegistrationUserAgent ServerResponseReceived (" + remoteEndPoint + "). " + excp.Message);
            }
        }
Exemple #40
0
        private void ServerResponseReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse)
        {
            try
            {
                string reasonPhrase = (sipResponse.ReasonPhrase.IsNullOrBlank()) ? sipResponse.Status.ToString() : sipResponse.ReasonPhrase;
                Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Server response " + sipResponse.StatusCode + " " + reasonPhrase + " received for " + sipTransaction.TransactionRequest.Method + " to " + m_callDescriptor.Uri + ".", m_owner));

                if (sipResponse.Status == SIPResponseStatusCodesEnum.ProxyAuthenticationRequired || sipResponse.Status == SIPResponseStatusCodesEnum.Unauthorised)
                {
                    if (sipResponse.Header.AuthenticationHeader != null)
                    {
                        if ((m_callDescriptor.Username != null || m_callDescriptor.AuthUsername != null) && m_callDescriptor.Password != null)
                        {
                            SIPRequest authenticatedRequest         = GetAuthenticatedRequest(sipTransaction.TransactionRequest, sipResponse);
                            SIPNonInviteTransaction authTransaction = m_sipTransport.CreateNonInviteTransaction(authenticatedRequest, sipTransaction.RemoteEndPoint, localSIPEndPoint, m_outboundProxy);
                            authTransaction.NonInviteTransactionFinalResponseReceived += AuthResponseReceived;
                            authTransaction.NonInviteTransactionTimedOut += RequestTimedOut;
                            m_sipTransport.SendSIPReliable(authTransaction);
                        }
                        else
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Send request received an authentication required response but no credentials were available.", m_owner));

                            if (ResponseReceived != null)
                            {
                                ResponseReceived(sipResponse);
                            }
                        }
                    }
                    else
                    {
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Send request failed with " + sipResponse.StatusCode + " but no authentication header was supplied for " + sipTransaction.TransactionRequest.Method + " to " + m_callDescriptor.Uri + ".", m_owner));

                        if (ResponseReceived != null)
                        {
                            ResponseReceived(sipResponse);
                        }
                    }
                }
                else
                {
                    if (ResponseReceived != null)
                    {
                        ResponseReceived(sipResponse);
                    }
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception SIPNonInviteClientUserAgent ServerResponseReceived (" + remoteEndPoint + "). " + excp.Message);
            }
        }
        private SIPRequest GetAuthenticatedRegistrationRequest(SIPRequest registerRequest, SIPResponse sipResponse)
        {
            try
            {
                SIPAuthorisationDigest authRequest = sipResponse.Header.AuthenticationHeader.SIPDigest;
                string username = (m_authUsername != null) ? m_authUsername : m_sipAccountAOR.User;
                authRequest.SetCredentials(username, m_password, registerRequest.URI.ToString(), SIPMethodsEnum.REGISTER.ToString());
                if (!this.m_realm.IsNullOrBlank())
                {
                    authRequest.Realm = this.m_realm;
                }

                SIPRequest regRequest = registerRequest.Copy();
                regRequest.SetSendFromHints(registerRequest.LocalSIPEndPoint);

                regRequest.Header.Vias.TopViaHeader.Branch = CallProperties.CreateBranchId();
                regRequest.Header.From.FromTag             = CallProperties.CreateNewTag();
                regRequest.Header.To.ToTag = null;
                regRequest.Header.CSeq     = ++m_cseq;

                regRequest.Header.AuthenticationHeader = new SIPAuthenticationHeader(authRequest);
                regRequest.Header.AuthenticationHeader.SIPDigest.Response = authRequest.Digest;

                return(regRequest);
            }
            catch (Exception excp)
            {
                logger.LogError("Exception GetAuthenticatedRegistrationRequest. " + excp.Message);
                throw excp;
            }
        }
Exemple #42
0
 private void TransactionFinalResponseReceived(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse)
 {
     m_lastFinalResponse = sipResponse;
     m_waitForSIPFinalResponse.Set();
 }
Exemple #43
0
        static void Main()
        {
            Console.WriteLine("SIPSorcery client user agent example.");
            Console.WriteLine("Press ctrl-c to exit.");

            CancellationTokenSource exitCts = new CancellationTokenSource(); // Cancellation token to stop the SIP transport and RTP stream.

            AddConsoleLogger();

            // Set up a default SIP transport.
            var sipTransport = new SIPTransport();

            sipTransport.AddSIPChannel(new SIPUDPChannel(new IPEndPoint(IPAddress.Any, SIP_LISTEN_PORT)));

            // Un/comment this line to see/hide each SIP message sent and received.
            EnableTraceLogs(sipTransport);

            // To keep things a bit simpler this example only supports a single call at a time and the SIP server user agent
            // acts as a singleton
            SIPUserAgent            userAgent = new SIPUserAgent(sipTransport, null);
            CancellationTokenSource rtpCts    = null; // Cancellation token to stop the RTP stream.
            Socket rtpSocket     = null;
            Socket controlSocket = null;

            // Because this is a server user agent the SIP transport must start listening for client user agents.
            sipTransport.SIPTransportRequestReceived += (SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest sipRequest) =>
            {
                try
                {
                    if (sipRequest.Header.From != null &&
                        sipRequest.Header.From.FromTag != null &&
                        sipRequest.Header.To != null &&
                        sipRequest.Header.To.ToTag != null)
                    {
                        userAgent.InDialogRequestReceivedAsync(sipRequest).Wait();
                    }
                    if (sipRequest.Method == SIPMethodsEnum.INVITE)
                    {
                        SIPSorcery.Sys.Log.Logger.LogInformation($"Incoming call request: {localSIPEndPoint}<-{remoteEndPoint} {sipRequest.URI}.");

                        // Check there's a codec we support in the INVITE offer.
                        var        offerSdp       = SDP.ParseSDPDescription(sipRequest.Body);
                        IPEndPoint dstRtpEndPoint = SDP.GetSDPRTPEndPoint(sipRequest.Body);
                        RTPSession rtpSession     = null;
                        string     audioFile      = null;

                        if (offerSdp.Media.Any(x => x.Media == SDPMediaTypesEnum.audio && x.HasMediaFormat((int)RTPPayloadTypesEnum.PCMU)))
                        {
                            Log.LogDebug($"Using PCMU RTP media type and audio file {AUDIO_FILE_PCMU}.");
                            rtpSession = new RTPSession((int)RTPPayloadTypesEnum.PCMU, null, null);
                            audioFile  = AUDIO_FILE_PCMU;
                        }

                        if (rtpSession == null)
                        {
                            // Didn't get a match on the codecs we support.
                            SIPResponse noMatchingCodecResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.NotAcceptableHere, null);
                            sipTransport.SendResponse(noMatchingCodecResponse);
                        }
                        else
                        {
                            // If there's already a call in progress hang it up. Of course this is not ideal for a real softphone or server but it
                            // means this example can be kept simpler.
                            if (userAgent?.IsAnswered == true)
                            {
                                userAgent?.Hangup();
                            }
                            rtpCts?.Cancel();

                            UASInviteTransaction uasTransaction = sipTransport.CreateUASTransaction(sipRequest, null);
                            if (userAgent.AcceptCall(uasTransaction))
                            {
                                rtpCts = new CancellationTokenSource();

                                // The RTP socket is listening on IPAddress.Any but the IP address placed into the SDP needs to be one the caller can reach.
                                IPAddress rtpAddress = NetServices.GetLocalAddressForRemote(dstRtpEndPoint.Address);
                                // Initialise an RTP session to receive the RTP packets from the remote SIP server.
                                NetServices.CreateRtpSocket(rtpAddress, RTP_PORT_START, RTP_PORT_END, false, out rtpSocket, out controlSocket);

                                var rtpRecvSession = new RTPSession((int)RTPPayloadTypesEnum.PCMU, null, null);
                                var rtpSendSession = new RTPSession((int)RTPPayloadTypesEnum.PCMU, null, null);
                                rtpSendSession.DestinationEndPoint           = dstRtpEndPoint;
                                rtpRecvSession.OnReceiveFromEndPointChanged += (oldEP, newEP) =>
                                {
                                    Log.LogDebug($"RTP destination end point changed from {oldEP} to {newEP}.");
                                    rtpSendSession.DestinationEndPoint = newEP;
                                };

                                Task.Run(() => RecvRtp(rtpSocket, rtpRecvSession, rtpCts));
                                Task.Run(() => SendRtp(rtpSocket, rtpSendSession, rtpCts));

                                userAgent.Answer(GetSDP(rtpSocket.LocalEndPoint as IPEndPoint));
                            }
                        }
                    }
                    else if (sipRequest.Method == SIPMethodsEnum.SUBSCRIBE)
                    {
                        SIPResponse notAllowededResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.MethodNotAllowed, null);
                        sipTransport.SendResponse(notAllowededResponse);
                    }
                    else if (sipRequest.Method == SIPMethodsEnum.OPTIONS || sipRequest.Method == SIPMethodsEnum.REGISTER)
                    {
                        SIPResponse optionsResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null);
                        sipTransport.SendResponse(optionsResponse);
                    }
                }
                catch (Exception reqExcp)
                {
                    SIPSorcery.Sys.Log.Logger.LogWarning($"Exception handling {sipRequest.Method}. {reqExcp.Message}");
                }
            };

            // Ctrl-c will gracefully exit the call at any point.
            Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e)
            {
                e.Cancel = true;
                exitCts.Cancel();
                rtpCts?.Cancel();
            };

            // At this point the call has been initiated and everything will be handled in an event handler.
            Task.Run(async() =>
            {
                try
                {
                    while (!exitCts.Token.WaitHandle.WaitOne(0))
                    {
                        var keyProps = Console.ReadKey();
                        if (keyProps.KeyChar == 't')
                        {
                            // Initiate a transfer.
                            bool transferResult = await userAgent.Transfer(SIPURI.ParseSIPURI(TRANSFER_DESTINATION_SIP_URI), new TimeSpan(0, 0, TRANSFER_TIMEOUT_SECONDS), exitCts.Token);
                            if (transferResult)
                            {
                                // If the transfer was accepted the original call will already have been hungup.
                                userAgent = null;
                                exitCts.Cancel();
                            }
                            else
                            {
                                Log.LogWarning($"Transfer to {TRANSFER_DESTINATION_SIP_URI} failed.");
                            }
                        }
                        else if (keyProps.KeyChar == 'q')
                        {
                            // Quit application.
                            exitCts.Cancel();
                        }
                    }
                }
                catch (Exception excp)
                {
                    Log.LogError($"Exception Key Press listener. {excp.Message}.");
                }
            });

            // Wait for a signal saying the call failed, was cancelled with ctrl-c or completed.
            exitCts.Token.WaitHandle.WaitOne();

            Log.LogInformation("Exiting...");

            rtpSocket?.Close();
            controlSocket?.Close();

            if (userAgent != null)
            {
                if (userAgent.IsAnswered)
                {
                    Log.LogInformation($"Hanging up call to {userAgent?.CallDescriptor?.To}.");
                    userAgent.Hangup();
                }

                // Give the final request time to be transmitted.
                Log.LogInformation("Waiting 1s for call to clean up...");
                Task.Delay(1000).Wait();
            }

            SIPSorcery.Net.DNSManager.Stop();

            if (sipTransport != null)
            {
                Log.LogInformation("Shutting down SIP transport...");
                sipTransport.Shutdown();
            }
        }
Exemple #44
0
        /// <summary>
        /// The event handler for responses to the authenticated register request.
        /// </summary>
        private void AuthResponseReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse)
        {
            try
            {
                Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterInProgress, "Server auth response " + sipResponse.Status + " received for " + m_sipAccountAOR.ToString() + ".", m_owner));

                if (sipResponse.Status == SIPResponseStatusCodesEnum.Ok)
                {
                    if (m_expiry > 0)
                    {
                        m_isRegistered = true;
                        m_expiry       = GetUpdatedExpiry(sipResponse);
                        //if (sipResponse.Header.SwitchboardToken != null && m_lastServerNonce != null)
                        //{
                        //    SwitchboardToken = Crypto.SymmetricDecrypt(m_password, m_lastServerNonce, sipResponse.Header.SwitchboardToken);
                        //}

                        if (RegistrationSuccessful != null)
                        {
                            RegistrationSuccessful(m_sipAccountAOR);
                        }
                    }
                    else
                    {
                        m_isRegistered = false;

                        if (RegistrationRemoved != null)
                        {
                            RegistrationRemoved(m_sipAccountAOR);
                        }
                    }

                    m_waitForRegistrationMRE.Set();
                }
                else if (sipResponse.Status == SIPResponseStatusCodesEnum.IntervalTooBrief && m_expiry != 0)
                {
                    m_expiry = GetUpdatedExpiryForIntervalTooBrief(sipResponse);
                    Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterInProgress, "Registration for " + m_sipAccountAOR.ToString() + " had a too short expiry, updated to +" + m_expiry + " and trying again.", m_owner));
                    SendInitialRegister();
                }
                else if (sipResponse.Status == SIPResponseStatusCodesEnum.Forbidden || sipResponse.Status == SIPResponseStatusCodesEnum.NotFound || sipResponse.Status == SIPResponseStatusCodesEnum.PaymentRequired)
                {
                    // SIP account does not appear to exist.
                    Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Registration failed with " + sipResponse.Status + " for " + m_sipAccountAOR.ToString() + ", no further registration attempts will be made.", m_owner));
                    string reasonPhrase = (sipResponse.ReasonPhrase.IsNullOrBlank()) ? sipResponse.Status.ToString() : sipResponse.ReasonPhrase;
                    if (RegistrationFailed != null)
                    {
                        RegistrationFailed(m_sipAccountAOR, "Registration failed with " + (int)sipResponse.Status + " " + reasonPhrase + ".");
                    }
                    m_exit = true;
                    m_waitForRegistrationMRE.Set();
                }
                else if (sipResponse.Status == SIPResponseStatusCodesEnum.ProxyAuthenticationRequired || sipResponse.Status == SIPResponseStatusCodesEnum.Unauthorised)
                {
                    // SIP account credentials failed.
                    Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Registration failed with " + sipResponse.Status + " for " + m_sipAccountAOR.ToString() + ", no further registration attempts will be made.", m_owner));
                    string reasonPhrase = (sipResponse.ReasonPhrase.IsNullOrBlank()) ? sipResponse.Status.ToString() : sipResponse.ReasonPhrase;
                    if (RegistrationFailed != null)
                    {
                        RegistrationFailed(m_sipAccountAOR, "Registration failed with " + (int)sipResponse.Status + " " + reasonPhrase + ".");
                    }
                    m_exit = true;
                    m_waitForRegistrationMRE.Set();
                }
                else
                {
                    Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Registration failed with " + sipResponse.Status + " for " + m_sipAccountAOR.ToString() + ".", m_owner));
                    m_isRegistered = false;
                    if (RegistrationTemporaryFailure != null)
                    {
                        RegistrationTemporaryFailure(m_sipAccountAOR, "Registration failed with " + sipResponse.Status + ".");
                    }
                    m_waitForRegistrationMRE.Set();
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception SIPRegistrationUserAgent AuthResponseReceived. " + excp.Message);
            }
        }
Exemple #45
0
        static void Main()
        {
            Console.WriteLine("SIPSorcery Attended Transfer example.");
            Console.WriteLine("Press 'c' to place a call to the default destination.");
            Console.WriteLine("Place two simultaneous SIP calls to this program and then press 't'.");
            Console.WriteLine("Press 'q' or ctrl-c to exit.");

            // Plumbing code to facilitate a graceful exit.
            CancellationTokenSource exitCts = new CancellationTokenSource(); // Cancellation token to stop the SIP transport and RTP stream.

            AddConsoleLogger();

            // Set up a default SIP transport.
            var sipTransport = new SIPTransport();

            sipTransport.AddSIPChannel(new SIPUDPChannel(new IPEndPoint(IPAddress.Any, SIP_LISTEN_PORT)));

            //EnableTraceLogs(sipTransport);

            // Create two user agents. Each gets configured to answer an incoming call.
            var userAgent1 = new SIPUserAgent(sipTransport, null);
            var userAgent2 = new SIPUserAgent(sipTransport, null);

            userAgent1.OnCallHungup        += (dialog) => Log.LogInformation($"UA1: Call hungup by remote party.");
            userAgent1.ServerCallCancelled += (uas) => Log.LogInformation("UA1: Incoming call cancelled by caller.");

            userAgent2.OnCallHungup        += (dialog) => Log.LogInformation($"UA2: Call hungup by remote party.");
            userAgent2.ServerCallCancelled += (uas) => Log.LogInformation("UA2: Incoming call cancelled by caller.");

            userAgent2.OnTransferNotify += (sipFrag) =>
            {
                if (!string.IsNullOrEmpty(sipFrag))
                {
                    Log.LogInformation($"UA2: Transfer status update: {sipFrag.Trim()}.");
                    if (sipFrag?.Contains("SIP/2.0 200") == true)
                    {
                        // The transfer attempt got a successful answer. Can hangup the call.
                        userAgent2.Hangup();
                        exitCts.Cancel();
                    }
                }
            };

            sipTransport.SIPTransportRequestReceived += async(localEndPoint, remoteEndPoint, sipRequest) =>
            {
                if (sipRequest.Header.From != null &&
                    sipRequest.Header.From.FromTag != null &&
                    sipRequest.Header.To != null &&
                    sipRequest.Header.To.ToTag != null)
                {
                    // This is an in-dialog request that will be handled directly by a user agent instance.
                }
                else if (sipRequest.Method == SIPMethodsEnum.INVITE)
                {
                    if (!userAgent1.IsCallActive || !userAgent2.IsCallActive)
                    {
                        SIPUserAgent activeAgent = (!userAgent1.IsCallActive) ? userAgent1 : userAgent2;
                        string       agentDesc   = (!userAgent1.IsCallActive) ? "UA1" : "UA2";

                        Log.LogInformation($"{agentDesc}: Incoming call request from {remoteEndPoint}: {sipRequest.StatusLine}.");
                        var incomingCall = activeAgent.AcceptCall(sipRequest);

                        var rtpAVSession = new RtpAVSession(new AudioOptions {
                            AudioSource = AudioSourcesEnum.CaptureDevice
                        }, null);

                        await activeAgent.Answer(incomingCall, rtpAVSession);

                        Log.LogInformation($"{agentDesc}: Answered incoming call from {sipRequest.Header.From.FriendlyDescription()} at {remoteEndPoint}.");
                    }
                    else
                    {
                        // If both user agents are already on a call return a busy response.
                        Log.LogWarning($"Busy response returned for incoming call request from {remoteEndPoint}: {sipRequest.StatusLine}.");
                        UASInviteTransaction uasTransaction = new UASInviteTransaction(sipTransport, sipRequest, null);
                        SIPResponse          busyResponse   = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.BusyHere, null);
                        uasTransaction.SendFinalResponse(busyResponse);
                    }
                }
                else
                {
                    Log.LogDebug($"SIP {sipRequest.Method} request received but no processing has been set up for it, rejecting.");
                    SIPResponse notAllowedResponse = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.MethodNotAllowed, null);
                    await sipTransport.SendResponseAsync(notAllowedResponse);
                }
            };

            // At this point the call has been initiated and everything will be handled in an event handler.
            Task.Run(async() =>
            {
                try
                {
                    while (!exitCts.Token.WaitHandle.WaitOne(0))
                    {
                        var keyProps = Console.ReadKey();

                        if (keyProps.KeyChar == 'c')
                        {
                            // Place an outgoing call using the first free user agent.
                            SIPUserAgent freeAgent = (!userAgent1.IsCallActive) ? userAgent1 : (!userAgent2.IsCallActive) ? userAgent2 : null;
                            if (freeAgent != null)
                            {
                                var rtpAVSession = new RtpAVSession(new AudioOptions {
                                    AudioSource = AudioSourcesEnum.CaptureDevice
                                }, null);
                                bool callResult = await freeAgent.Call(DEFAULT_DESTINATION_SIP_URI, null, null, rtpAVSession);

                                Log.LogInformation($"Call attempt {((callResult) ? "successfull" : "failed")}.");
                            }
                            else
                            {
                                Log.LogWarning("Both user agents are already on calls.");
                            }
                        }
                        if (keyProps.KeyChar == 't')
                        {
                            // Initiate the attended transfer.
                            if (userAgent1.IsCallActive && userAgent2.IsCallActive)
                            {
                                bool result = await userAgent2.AttendedTransfer(userAgent1.Dialogue, TimeSpan.FromSeconds(TRANSFER_TIMEOUT_SECONDS), exitCts.Token);
                                if (!result)
                                {
                                    Log.LogWarning($"Attended transfer failed.");
                                }
                            }
                            else
                            {
                                Log.LogWarning("There need to be two active calls before the attended transfer can occur.");
                            }
                        }
                        else if (keyProps.KeyChar == 'q')
                        {
                            // Quit application.
                            exitCts.Cancel();
                        }
                    }
                }
                catch (Exception excp)
                {
                    SIPSorcery.Sys.Log.Logger.LogError($"Exception Key Press listener. {excp.Message}.");
                }
            });

            // Ctrl-c will gracefully exit the call at any point.
            Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e)
            {
                e.Cancel = true;
                exitCts.Cancel();
            };

            // Wait for a signal saying the call failed, was cancelled with ctrl-c or completed.
            exitCts.Token.WaitHandle.WaitOne();

            #region Cleanup.

            Log.LogInformation("Exiting...");

            userAgent1?.Hangup();
            userAgent2?.Hangup();

            // Give any BYE or CANCEL requests time to be transmitted.
            Log.LogInformation("Waiting 1s for calls to be cleaned up...");
            Task.Delay(1000).Wait();

            if (sipTransport != null)
            {
                Log.LogInformation("Shutting down SIP transport...");
                sipTransport.Shutdown();
            }

            #endregion
        }
        public SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum serverType, SIPMonitorEventTypesEnum eventType, string message, SIPRequest sipRequest, SIPResponse sipResponse, SIPEndPoint localEndPoint, SIPEndPoint remoteEndPoint, SIPCallDirection callDirection)
        {
            m_serialisationPrefix = SERIALISATION_PREFIX;
            ClientType = SIPMonitorClientTypesEnum.Console;

            ServerType = serverType;
            EventType = eventType;
            Message = message;
            RemoteEndPoint = remoteEndPoint;
            ServerEndPoint = localEndPoint;
            Created = DateTimeOffset.UtcNow;
            #if !SILVERLIGHT
            ProcessID = Process.GetCurrentProcess().Id;
            #endif

            string dirn = (callDirection == SIPCallDirection.In) ? CALLDIRECTION_IN_STRING : CALLDIRECTION_OUT_STRING;
            if (sipRequest != null)
            {
                Message = "REQUEST (" + Created.ToString("HH:mm:ss:fff") + "): " + localEndPoint + dirn + remoteEndPoint + "\r\n" + sipRequest.ToString();
            }
            else if (sipResponse != null)
            {
                Message = "RESPONSE (" + Created.ToString("HH:mm:ss:fff") + "): " + localEndPoint + dirn + remoteEndPoint + "\r\n" + sipResponse.ToString();
            }
        }
 void m_serverTransaction_NonInviteTransactionFinalResponseReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse)
 {
     if (sipResponse.Status == SIPResponseStatusCodesEnum.Accepted)
     {
         FireReferAccepted();
     }
     else if (sipResponse.Status == SIPResponseStatusCodesEnum.Decline)
     {
         FireReferDenied();
     }
     else if (sipResponse.Status == SIPResponseStatusCodesEnum.MethodNotAllowed)
     {
         FireReferDenied();
     }
 }