private void SIPTCPMessageReceived(SIPChannel channel, SIPEndPoint remoteEndPoint, byte[] buffer) { if (m_connectionFailures.ContainsKey(remoteEndPoint.GetIPEndPoint().ToString())) { m_connectionFailures.Remove(remoteEndPoint.GetIPEndPoint().ToString()); } if (m_connectionFailureStrikes.ContainsKey(remoteEndPoint.GetIPEndPoint().ToString())) { m_connectionFailureStrikes.Remove(remoteEndPoint.GetIPEndPoint().ToString()); } SIPMessageReceived?.Invoke(channel, remoteEndPoint, buffer); }
/// <summary> /// 确认接收视频请求 /// </summary> /// <param name="response">响应消息</param> /// <returns></returns> public void AckRequest(SIPResponse response) { _rtpChannel = new RTPChannel(_remoteEndPoint.GetIPEndPoint(), _mediaPort[0], _mediaPort[1], FrameTypesEnum.H264); _rtpChannel.OnFrameReady += _rtpChannel_OnFrameReady; _rtpChannel.Start(); SIPURI localUri = new SIPURI(_msgCore.LocalSIPId, _msgCore.LocalEndPoint.ToHost(), ""); SIPURI remoteUri = new SIPURI(_deviceId, _remoteEndPoint.ToHost(), ""); SIPRequest ackReq = _msgCore.Transport.GetRequest(SIPMethodsEnum.ACK, remoteUri); SIPFromHeader from = new SIPFromHeader(null, response.Header.From.FromURI, response.Header.From.FromTag); SIPToHeader to = new SIPToHeader(null, remoteUri, response.Header.To.ToTag); SIPContactHeader contactHeader = new SIPContactHeader(null, localUri); SIPHeader header = new SIPHeader(from, to, response.Header.CSeq, response.Header.CallId); header.CSeqMethod = SIPMethodsEnum.ACK; header.Contact = response.Header.Contact; header.Contact.Clear(); header.Contact.Add(contactHeader); header.Vias = response.Header.Vias; header.MaxForwards = response.Header.MaxForwards; header.ContentLength = response.Header.ContentLength; header.UserAgent = _msgCore.UserAgent; header.Allow = null; ackReq.Header = header; _okTag = response.Header.To.ToTag; _contact = header.Contact.FirstOrDefault(); _via = header.Vias; _msgCore.Transport.SendRequest(_remoteEndPoint, ackReq); }
public async Task UacTxCheckRemoteSocketProxyReceivedUnitTestUnitTest() { logger.LogDebug("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name); logger.BeginScope(System.Reflection.MethodBase.GetCurrentMethod().Name); SIPEndPoint dummyEP = new SIPEndPoint(new IPEndPoint(IPAddress.Any, 5060)); string inviteReqStr = @"INVITE sip:[email protected]:12014 SIP/2.0 Via: SIP/2.0/UDP 127.0.0.1:1234;branch=z9hG4bK5f37455955ca433a902f8fea0ce2dc27 To: <sip:[email protected]:12014> From: <sip:[email protected]>;tag=2062917371 Call-ID: 8ae45c15425040179a4285d774ccbaf6 CSeq: 1 INVITE Contact: <sip:127.0.0.1:1234> Max-Forwards: 70 User-Agent: unittest Content-Length: 5 Content-Type: application/sdp dummy"; var sipReqBuffer = SIPMessageBuffer.ParseSIPMessage(inviteReqStr, dummyEP, dummyEP); SIPRequest inviteReq = SIPRequest.ParseSIPRequest(sipReqBuffer); string okRespStr = @"SIP/2.0 200 OK Via: SIP/2.0/UDP 127.0.0.1:1234;branch=z9hG4bK5f37455955ca433a902f8fea0ce2dc27;rport=12013 To: <sip:[email protected]:12014> From: <sip:[email protected]>;tag=2062917371 Call-ID: 8ae45c15425040179a4285d774ccbaf6 Contact: <sip:127.0.0.1:1234> CSeq: 1 INVITE Content-Length: 5 Content-Type: application/sdp Proxy-ReceivedFrom: udp:192.168.0.50:5080 dummy"; var sipRespBuffer = SIPMessageBuffer.ParseSIPMessage(okRespStr, dummyEP, dummyEP); SIPResponse okResponse = SIPResponse.ParseSIPResponse(sipRespBuffer); SIPTransport transport = new SIPTransport(); transport.AddSIPChannel(new MockSIPChannel(dummyEP.GetIPEndPoint())); UACInviteTransaction uacTx = new UACInviteTransaction(transport, inviteReq, null); await uacTx.GotResponse(dummyEP, dummyEP, okResponse); var dialogue = new SIPDialogue(uacTx); Assert.NotNull(dialogue); Assert.Equal(SIPURI.ParseSIPURI("sip:127.0.0.1:1234"), dialogue.RemoteTarget); Assert.Equal(SIPEndPoint.ParseSIPEndPoint("udp:192.168.0.50:5080"), dialogue.RemoteSIPEndPoint); logger.LogDebug("---------------------------------------------------"); }
/// <summary> /// This constructor is used by server user agents or SIP elements acting in a server user agent role. When /// acting as a server user agent the local fields are contained in the To header and the remote fields are /// in the From header. /// </summary> public SIPDialogue( UASInviteTransaction uasInviteTransaction, string owner, string adminMemberId) { Id = Guid.NewGuid(); CallId = uasInviteTransaction.TransactionRequest.Header.CallId; RouteSet = (uasInviteTransaction.TransactionFinalResponse != null && uasInviteTransaction.TransactionFinalResponse.Header.RecordRoutes != null) ? uasInviteTransaction.TransactionFinalResponse.Header.RecordRoutes.Reversed() : null; LocalUserField = uasInviteTransaction.TransactionFinalResponse.Header.To.ToUserField; LocalTag = uasInviteTransaction.TransactionFinalResponse.Header.To.ToTag; RemoteUserField = uasInviteTransaction.TransactionFinalResponse.Header.From.FromUserField; RemoteTag = uasInviteTransaction.TransactionFinalResponse.Header.From.FromTag; CSeq = uasInviteTransaction.TransactionRequest.Header.CSeq; CDRId = uasInviteTransaction.CDR.CDRId; Owner = owner; AdminMemberId = adminMemberId; ContentType = uasInviteTransaction.TransactionFinalResponse.Header.ContentType; SDP = uasInviteTransaction.TransactionFinalResponse.Body; RemoteSDP = uasInviteTransaction.TransactionRequest.Body; Inserted = DateTimeOffset.UtcNow; Direction = SIPCallDirection.In; //DialogueId = GetDialogueId(CallId, LocalTag, RemoteTag); RemoteTarget = new SIPURI(uasInviteTransaction.TransactionRequest.URI.Scheme, SIPEndPoint.ParseSIPEndPoint(uasInviteTransaction.RemoteEndPoint.ToString())); ProxySendFrom = uasInviteTransaction.TransactionRequest.Header.ProxyReceivedOn; if (uasInviteTransaction.TransactionRequest.Header.Contact != null && uasInviteTransaction.TransactionRequest.Header.Contact.Count > 0) { RemoteTarget = uasInviteTransaction.TransactionRequest.Header.Contact[0].ContactURI.CopyOf(); if (!uasInviteTransaction.TransactionRequest.Header.ProxyReceivedFrom.IsNullOrBlank()) { // Setting the Proxy-ReceivedOn header is how an upstream proxy will let an agent know it should mangle the contact. // Don't mangle private contacts if there is a Record-Route header. If a proxy is putting private IP's in a Record-Route header that's its problem. if (RouteSet == null && IPSocket.IsPrivateAddress(RemoteTarget.Host)) { SIPEndPoint remoteUASSIPEndPoint = SIPEndPoint.ParseSIPEndPoint(uasInviteTransaction.TransactionRequest.Header .ProxyReceivedFrom); RemoteTarget.Host = remoteUASSIPEndPoint.GetIPEndPoint().ToString(); } } } }
/// <summary> /// Customises the Contact header for an INVITE request or response based on the destination /// it is being sent to. /// </summary> /// <param name="dstEP">The destination end point for the send.</param> /// <param name="inviteHeader">The original header from the INVITE request or response.</param> /// <returns>If an adjustment was made then a new SIP header instance is returned. If not, null is returned.</returns> private SIPHeader CustomiseInviteContactHeader(SIPEndPoint dstEP, SIPHeader inviteHeader) { var dstAddress = dstEP.GetIPEndPoint().Address; // Don't customise if the destination is a private IP address (which means it's staying // on the same subnet or virtual subnet). if (!_isPrivateSubnet(dstAddress) && inviteHeader.Contact != null && inviteHeader.Contact.Count == 1) { // The priority is use the public IP address fields if they are available (saves DNS lookups) and // falls back to the hostname if they are not. The exception is if the Contact URI is using a secure // SIP scheme "sips" in which case the priority is to use any available hostname first. // Port of 0 is set when user agents set Contact Host to "0.0.0.0:0" which is the method to // get the transport layer to set it at send time. bool isDefaultPort = inviteHeader.Contact[0].ContactURI.IsDefaultPort() || inviteHeader.Contact[0].ContactURI.HostPort == "0"; if (inviteHeader.Contact[0].ContactURI.Scheme == SIPSchemesEnum.sips && !string.IsNullOrWhiteSpace(_publicContactHostname)) { var copy = inviteHeader.Copy(); copy.Contact[0].ContactURI.Host = _publicContactHostname; return(copy); } else if (_publicContactIPv4 != null && (dstAddress.AddressFamily == AddressFamily.InterNetwork || dstAddress.IsIPv4MappedToIPv6)) { var copy = inviteHeader.Copy(); copy.Contact[0].ContactURI.Host = isDefaultPort ? _publicContactIPv4.ToString() : $"{_publicContactIPv4}:{inviteHeader.Contact[0].ContactURI.HostPort}"; return(copy); } else if (dstAddress.AddressFamily == AddressFamily.InterNetworkV6 && _publicContactIPv6 != null) { var copy = inviteHeader.Copy(); copy.Contact[0].ContactURI.Host = isDefaultPort ? $"[{_publicContactIPv6}]" : $"[{_publicContactIPv6}]:{inviteHeader.Contact[0].ContactURI.HostPort}"; return(copy); } else if (!string.IsNullOrWhiteSpace(_publicContactHostname)) { var copy = inviteHeader.Copy(); copy.Contact[0].ContactURI.Host = _publicContactHostname; return(copy); } } return(null); }
public async Task TestSetRequestCustomHeaderFuncUnitTest() { logger.LogDebug("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name); logger.BeginScope(System.Reflection.MethodBase.GetCurrentMethod().Name); SIPEndPoint dummyEP = new SIPEndPoint(new IPEndPoint(IPAddress.Any, 5060)); string inviteReqStr = @"INVITE sip:[email protected]:12014 SIP/2.0 Via: SIP/2.0/UDP 127.0.0.1:1234;branch=z9hG4bK5f37455955ca433a902f8fea0ce2dc27 To: <sip:[email protected]:12014> From: <sip:[email protected]>;tag=2062917371 Call-ID: 8ae45c15425040179a4285d774ccbaf6 CSeq: 1 INVITE Contact: <sip:127.0.0.1:1234> Max-Forwards: 70 User-Agent: unittest Content-Length: 5 Content-Type: application/sdp dummy"; var sipReqBuffer = SIPMessageBuffer.ParseSIPMessage(inviteReqStr, dummyEP, dummyEP); SIPRequest inviteReq = SIPRequest.ParseSIPRequest(sipReqBuffer); using (var transport = new SIPTransport()) { transport.AddSIPChannel(new MockSIPChannel(dummyEP.GetIPEndPoint())); string contactHost = "devcall.sipsorcery.com"; transport.CustomiseRequestHeader = (local, dst, req) => { var hdr = req.Header.Copy(); hdr.Contact[0].ContactURI.Host = contactHost; return(hdr); }; await transport.SendRequestAsync(inviteReq); logger.LogDebug(inviteReq.ToString()); Assert.Equal(contactHost, inviteReq.Header.Contact[0].ContactURI.Host); } }
//public Dictionary<Guid, object> Load(XmlDocument dom) //{ // return SIPAssetXMLPersistor<SIPRegistrarBinding>.LoadAssetsFromXMLRecordSet(dom); //} #endif /// <summary> /// Refreshes a binding when the remote network information of the remote or proxy end point has changed. /// </summary> public void RefreshBinding(int expiry, SIPEndPoint remoteSIPEndPoint, SIPEndPoint proxySIPEndPoint, SIPEndPoint registrarSIPEndPoint, bool dontMangle) { LastUpdate = DateTimeOffset.UtcNow; RemoteSIPEndPoint = remoteSIPEndPoint; m_proxySIPEndPoint = proxySIPEndPoint; m_registrarSIPEndPoint = registrarSIPEndPoint; RemovalReason = SIPBindingRemovalReason.Unknown; m_expiry = expiry; //if (SIPTransport.IsPrivateAddress(sipRequest.Header.Contact[0].ContactURI.Host) && m_mangleUACContact) if (!dontMangle && Regex.Match(m_mangledContactURI.Host, @"(\d+\.){3}\d+").Success) { // The Contact URI Host is used by registrars as the contact socket for the user so it needs to be changed to reflect the socket // the intial request was received on in order to work around NAT. It's no good just relying on private addresses as a lot of User Agents // determine their public IP but NOT their public port so they send the wrong port in the Contact header. //logger.Debug("Mangling contact header from " + m_mangledContactURI.Host + " to " + IPSocket.GetSocketString(uacRecvdEndPoint) + "."); m_mangledContactURI.Host = remoteSIPEndPoint.GetIPEndPoint().ToString(); } }
/// <summary></summary> /// <param name="uacRecvdEndPoint">If this is non-null it indicates the contact header should be mangled based on the public socket the register request was demmed /// to have originated from rather then relying on the contact value recieved from the uac.</param> public SIPRegistrarBinding( SIPAccount sipAccount, SIPURI bindingURI, string callId, int cseq, string userAgent, SIPEndPoint remoteSIPEndPoint, SIPEndPoint proxySIPEndPoint, SIPEndPoint registrarSIPEndPoint, int expiry) { Id = Guid.NewGuid(); LastUpdate = DateTime.UtcNow; SIPAccountId = sipAccount.Id; SIPAccountName = sipAccount.SIPUsername + "@" + sipAccount.SIPDomain; Owner = sipAccount.Owner; AdminMemberId = sipAccount.AdminMemberId; m_contactURI = bindingURI.CopyOf(); m_mangledContactURI = m_contactURI.CopyOf(); CallId = callId; CSeq = cseq; UserAgent = userAgent; RemoteSIPEndPoint = remoteSIPEndPoint; m_proxySIPEndPoint = proxySIPEndPoint; m_registrarSIPEndPoint = registrarSIPEndPoint; //if (SIPTransport.IsPrivateAddress(sipRequest.Header.Contact[0].ContactURI.Host) && m_mangleUACContact) if (!sipAccount.DontMangleEnabled && Regex.Match(m_mangledContactURI.Host, @"(\d+\.){3}\d+").Success) { // The Contact URI Host is used by registrars as the contact socket for the user so it needs to be changed to reflect the socket // the intial request was received on in order to work around NAT. It's no good just relying on private addresses as a lot of User Agents // determine their public IP but NOT their public port so they send the wrong port in the Contact header. //logger.Debug("Mangling contact header from " + m_mangledContactURI.Host + " to " + IPSocket.GetSocketString(uacRecvdEndPoint) + "."); m_mangledContactURI.Host = remoteSIPEndPoint.GetIPEndPoint().ToString(); } m_expiry = expiry; }
/// <summary> /// This constructor is used to create non-INVITE dialogues for example the dialogues used in SIP event interactions /// where the dialogue is created based on a SUBSCRIBE request. /// </summary> public SIPDialogue( SIPRequest nonInviteRequest, string owner, string adminMemberId, string toTag) { Id = Guid.NewGuid(); CallId = nonInviteRequest.Header.CallId; RouteSet = (nonInviteRequest.Header.RecordRoutes != null) ? nonInviteRequest.Header.RecordRoutes.Reversed() : null; RemoteUserField = nonInviteRequest.Header.From.FromUserField; RemoteTag = nonInviteRequest.Header.From.FromTag; LocalUserField = nonInviteRequest.Header.To.ToUserField; LocalUserField.Parameters.Set("tag", toTag); LocalTag = toTag; CSeq = nonInviteRequest.Header.CSeq; Owner = owner; AdminMemberId = adminMemberId; Inserted = DateTimeOffset.UtcNow; Direction = SIPCallDirection.Out; // Set the dialogue remote target and take care of mangling if an upstream proxy has indicated it's required. RemoteTarget = nonInviteRequest.Header.Contact[0].ContactURI; ProxySendFrom = nonInviteRequest.Header.ProxyReceivedOn; if (!nonInviteRequest.Header.ProxyReceivedFrom.IsNullOrBlank()) { // Setting the Proxy-ReceivedOn header is how an upstream proxy will let an agent know it should mangle the contact. // Don't mangle private contacts if there is a Record-Route header. If a proxy is putting private IP's in a Record-Route header that's its problem. if (RouteSet == null && IPSocket.IsPrivateAddress(RemoteTarget.Host)) { SIPEndPoint remoteUASIPEndPoint = SIPEndPoint.ParseSIPEndPoint(nonInviteRequest.Header.ProxyReceivedFrom); RemoteTarget.Host = remoteUASIPEndPoint.GetIPEndPoint().ToString(); } } }
public void Send2xxAckRequest(string content, string contentType) { var sipResponse = m_transactionFinalResponse; if (sipResponse.Header.To != null) { m_remoteTag = sipResponse.Header.To.ToTag; } SIPURI ackURI = m_transactionRequest.URI; if (sipResponse.Header.Contact != null && sipResponse.Header.Contact.Count > 0) { ackURI = sipResponse.Header.Contact[0].ContactURI; // Don't mangle private contacts if there is a Record-Route header. If a proxy is putting private IP's in a Record-Route header that's its problem. if ((sipResponse.Header.RecordRoutes == null || sipResponse.Header.RecordRoutes.Length == 0) && IPSocket.IsPrivateAddress(ackURI.Host) && !sipResponse.Header.ProxyReceivedFrom.IsNullOrBlank()) { // Setting the Proxy-ReceivedOn header is how an upstream proxy will let an agent know it should mangle the contact. SIPEndPoint remoteUASSIPEndPoint = SIPEndPoint.ParseSIPEndPoint(sipResponse.Header.ProxyReceivedFrom); ackURI.Host = remoteUASSIPEndPoint.GetIPEndPoint().ToString(); } } // ACK for 2xx response needs to be a new transaction and gets routed based on SIP request fields. var ackRequest = GetNewTransactionACKRequest(sipResponse, ackURI, LocalSIPEndPoint); if (content.NotNullOrBlank()) { ackRequest.Body = content; ackRequest.Header.ContentLength = ackRequest.Body.Length; ackRequest.Header.ContentType = contentType; } base.SendRequest(ackRequest); }
public async Task TestSetResponseContactHostIPAddressUnitTest() { logger.LogDebug("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name); logger.BeginScope(System.Reflection.MethodBase.GetCurrentMethod().Name); SIPEndPoint dummyEP = new SIPEndPoint(new IPEndPoint(IPAddress.Any, 5060)); string okRespStr = @"SIP/2.0 200 OK Via: SIP/2.0/UDP 127.0.0.1:1234;branch=z9hG4bK5f37455955ca433a902f8fea0ce2dc27;rport=12013 To: <sip:[email protected]:12014> From: <sip:[email protected]>;tag=2062917371 Call-ID: 8ae45c15425040179a4285d774ccbaf6 Contact: <sip:127.0.0.1:1234> CSeq: 1 INVITE Content-Length: 5 Content-Type: application/sdp dummy"; var sipRespBuffer = SIPMessageBuffer.ParseSIPMessage(okRespStr, dummyEP, dummyEP); SIPResponse okResponse = SIPResponse.ParseSIPResponse(sipRespBuffer); using (var transport = new SIPTransport()) { transport.AddSIPChannel(new MockSIPChannel(dummyEP.GetIPEndPoint())); transport.ContactHost = "192.168.0.12"; await transport.SendResponseAsync(okResponse); logger.LogDebug(okResponse.ToString()); Assert.Equal($"{transport.ContactHost}:5060", okResponse.Header.Contact[0].ContactURI.Host); } }
public void AckRecognitionUnitTest() { SIPTransport clientTransport = null; SIPTransport serverTransport = null; try { SIPTransactionEngine clientEngine = new SIPTransactionEngine(); // Client side of the INVITE. SIPEndPoint clientEndPoint = new SIPEndPoint(SIPProtocolsEnum.udp, new IPEndPoint(IPAddress.Loopback, 12013)); clientTransport = new SIPTransport(MockSIPDNSManager.Resolve, clientEngine, new SIPUDPChannel(clientEndPoint.GetIPEndPoint()), false); SetTransportTraceEvents(clientTransport); SIPTransactionEngine serverEngine = new SIPTransactionEngine(); // Server side of the INVITE. UASInviteTransaction serverTransaction = null; SIPEndPoint serverEndPoint = new SIPEndPoint(new IPEndPoint(IPAddress.Loopback, 12014)); serverTransport = new SIPTransport(MockSIPDNSManager.Resolve, serverEngine, new SIPUDPChannel(serverEndPoint.GetIPEndPoint()), false); SetTransportTraceEvents(serverTransport); serverTransport.SIPTransportRequestReceived += (localEndPoint, remoteEndPoint, sipRequest) => { Console.WriteLine("Server Transport Request In: " + sipRequest.Method + "."); serverTransaction = serverTransport.CreateUASTransaction(sipRequest, remoteEndPoint, localEndPoint, null); SetTransactionTraceEvents(serverTransaction); serverTransaction.GotRequest(localEndPoint, remoteEndPoint, sipRequest); }; SIPURI dummyURI = SIPURI.ParseSIPURI("sip:dummy@" + serverEndPoint); SIPRequest inviteRequest = GetDummyINVITERequest(dummyURI); inviteRequest.LocalSIPEndPoint = clientTransport.GetDefaultTransportContact(SIPProtocolsEnum.udp); // Send the invite to the server side. UACInviteTransaction clientTransaction = new UACInviteTransaction(clientTransport, inviteRequest, serverEndPoint, clientEndPoint, null); SetTransactionTraceEvents(clientTransaction); clientEngine.AddTransaction(clientTransaction); clientTransaction.SendInviteRequest(serverEndPoint, inviteRequest); Thread.Sleep(500); Assert.IsTrue(clientTransaction.TransactionState == SIPTransactionStatesEnum.Completed, "Client transaction in incorrect state."); Assert.IsTrue(serverTransaction.TransactionState == SIPTransactionStatesEnum.Confirmed, "Server transaction in incorrect state."); } finally { if (clientTransport != null) { clientTransport.Shutdown(); } if (serverTransport != null) { serverTransport.Shutdown(); } } }
/// <summary> /// Refreshes a binding when the remote network information of the remote or proxy end point has changed. /// </summary> public void RefreshBinding(int expiry, SIPEndPoint remoteSIPEndPoint, SIPEndPoint proxySIPEndPoint, SIPEndPoint registrarSIPEndPoint, bool dontMangle) { LastUpdate = DateTimeOffset.UtcNow; RemoteSIPEndPoint = remoteSIPEndPoint; m_proxySIPEndPoint = proxySIPEndPoint; m_registrarSIPEndPoint = registrarSIPEndPoint; RemovalReason = SIPBindingRemovalReason.Unknown; m_expiry = expiry; //if (SIPTransport.IsPrivateAddress(sipRequest.Header.Contact[0].ContactURI.Host) && m_mangleUACContact) if (!dontMangle && Regex.Match(m_mangledContactURI.Host, @"(\d+\.){3}\d+").Success) { // The Contact URI Host is used by registrars as the contact socket for the user so it needs to be changed to reflect the socket // the intial request was received on in order to work around NAT. It's no good just relying on private addresses as a lot of User Agents // determine their public IP but NOT their public port so they send the wrong port in the Contact header. //logger.Debug("Mangling contact header from " + m_mangledContactURI.Host + " to " + IPSocket.GetSocketString(uacRecvdEndPoint) + "."); m_mangledContactURI.Host = remoteSIPEndPoint.GetIPEndPoint().ToString(); } }
/// <summary> /// Establishes a new call with the client end tied to the proxy. Since the proxy will not be sending any audio the idea is that once /// the call is up it should be re-INVITED off somewhere else pronto to avoid the callee sitting their listening to dead air. /// </summary> /// <param name="dest1">The dial string of the first call to place.</param> /// <param name="dest2">The dial string of the second call to place.</param> /// <param name="delaySeconds">Delay in seconds before placing the first call. Gives the user a chance to hangup their phone if they are calling themselves back.</param> /// <param name="ringTimeoutLeg1">The ring timeout for the first call leg, If 0 the max timeout will be used.</param> /// <param name="ringTimeoutLeg1">The ring timeout for the second call leg, If 0 the max timeout will be used.</param> /// <param name="customHeadersCallLeg1">A | delimited string that contains a list of custom SIP headers to add to the INVITE request sent for the first call leg.</param> /// /// <param name="customHeadersCallLeg2">A | delimited string that contains a list of custom SIP headers to add to the INVITE request sent for the second call leg.</param> /// <returns>The result of the call.</returns> public void Callback(string dest1, string dest2, int delaySeconds, int ringTimeoutLeg1, int ringTimeoutLeg2, string customHeadersCallLeg1, string customHeadersCallLeg2) { var ts = new CancellationTokenSource(); CancellationToken ct = ts.Token; try { if (delaySeconds > 0) { delaySeconds = (delaySeconds > MAXCALLBACK_DELAY_SECONDS) ? MAXCALLBACK_DELAY_SECONDS : delaySeconds; Log("Callback app delaying by " + delaySeconds + "s."); Thread.Sleep(delaySeconds * 1000); } Log("Callback app commencing first leg to " + dest1 + "."); SIPEndPoint defaultUDPEP = m_sipTransport.GetDefaultSIPEndPoint(SIPProtocolsEnum.udp); SIPRequest firstLegDummyInviteRequest = GetCallbackInviteRequest(defaultUDPEP.GetIPEndPoint(), null); ForkCall firstLegCall = new ForkCall(m_sipTransport, Log_External, m_callManager.QueueNewCall, null, m_username, m_adminMemberId, m_outboundProxy, m_callManager, null); m_firstLegDialogue = Dial(firstLegCall, dest1, ringTimeoutLeg1, 0, firstLegDummyInviteRequest, SIPCallDescriptor.ParseCustomHeaders(customHeadersCallLeg1)); if (m_firstLegDialogue == null) { Log("The first call leg to " + dest1 + " was unsuccessful."); return; } // Persist the dialogue to the database so any hangup can be detected. m_sipDialoguePersistor.Add(new SIPDialogueAsset(m_firstLegDialogue)); SDP firstLegSDP = SDP.ParseSDPDescription(m_firstLegDialogue.RemoteSDP); string call1SDPIPAddress = firstLegSDP.Connection.ConnectionAddress; int call1SDPPort = firstLegSDP.Media[0].Port; Log("The first call leg to " + dest1 + " was successful, audio socket=" + call1SDPIPAddress + ":" + call1SDPPort + "."); Log("Callback app commencing second leg to " + dest2 + "."); SIPRequest secondLegDummyInviteRequest = GetCallbackInviteRequest(defaultUDPEP.GetIPEndPoint(), m_firstLegDialogue.RemoteSDP); ForkCall secondLegCall = new ForkCall(m_sipTransport, Log_External, m_callManager.QueueNewCall, null, m_username, m_adminMemberId, m_outboundProxy, m_callManager, null); Task.Factory.StartNew(() => { while (true) { Thread.Sleep(CHECK_FIRST_LEG_FOR_HANGUP_PERIOD); Console.WriteLine("Checking if first call leg is still up..."); if (ct.IsCancellationRequested) { Console.WriteLine("Checking first call leg task was cancelled."); break; } else { // Check that the first call leg hasn't been hung up. var dialog = m_sipDialoguePersistor.Get(m_firstLegDialogue.Id); if (dialog == null) { Console.WriteLine("First call leg has been hungup."); // The first call leg has been hungup while waiting for the second call. Log("The first call leg was hungup while the second call leg was waiting for an answer."); secondLegCall.CancelNotRequiredCallLegs(CallCancelCause.ClientCancelled); break; } } } Console.WriteLine("Checking first call leg task finished..."); }, ct); SIPDialogue secondLegDialogue = Dial(secondLegCall, dest2, ringTimeoutLeg2, 0, secondLegDummyInviteRequest, SIPCallDescriptor.ParseCustomHeaders(customHeadersCallLeg2)); ts.Cancel(); if (secondLegDialogue == null) { Log("The second call leg to " + dest2 + " was unsuccessful."); m_firstLegDialogue.Hangup(m_sipTransport, m_outboundProxy); return; } // Check that the first call leg hasn't been hung up. var firstLegDialog = m_sipDialoguePersistor.Get(m_firstLegDialogue.Id); if (firstLegDialog == null) { // The first call leg has been hungup while waiting for the second call. Log("The first call leg was hungup while waiting for the second call leg."); secondLegDialogue.Hangup(m_sipTransport, m_outboundProxy); return; } SDP secondLegSDP = SDP.ParseSDPDescription(secondLegDialogue.RemoteSDP); string call2SDPIPAddress = secondLegSDP.Connection.ConnectionAddress; int call2SDPPort = secondLegSDP.Media[0].Port; Log("The second call leg to " + dest2 + " was successful, audio socket=" + call2SDPIPAddress + ":" + call2SDPPort + "."); // Persist the second leg dialogue and update the bridge ID on the first call leg. Guid bridgeId = Guid.NewGuid(); secondLegDialogue.BridgeId = bridgeId; m_sipDialoguePersistor.Add(new SIPDialogueAsset(secondLegDialogue)); m_sipDialoguePersistor.UpdateProperty(firstLegDialog.Id, "BridgeID", bridgeId.ToString()); //m_callManager.CreateDialogueBridge(m_firstLegDialogue, secondLegDialogue, m_username); Log("Re-inviting Callback dialogues to each other."); m_callManager.ReInvite(m_firstLegDialogue, secondLegDialogue); //m_callManager.ReInvite(secondLegDialogue, m_firstLegDialogue.RemoteSDP); SendRTPPacket(call2SDPIPAddress + ":" + call2SDPPort, call1SDPIPAddress + ":" + call1SDPPort); SendRTPPacket(call1SDPIPAddress + ":" + call1SDPPort, call2SDPIPAddress + ":" + call2SDPPort); } catch (Exception excp) { logger.Error("Exception CallbackApp. " + excp); Log("Exception in Callback. " + excp); } finally { if (!ts.IsCancellationRequested) { ts.Cancel(); } } }
/// <summary> /// Authenticates a SIP request. /// </summary> public static SIPRequestAuthenticationResult AuthenticateSIPRequest(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest sipRequest, SIPAccount sipAccount, SIPMonitorLogDelegate logSIPMonitorEvent) { try { if (sipAccount == null) { return(new SIPRequestAuthenticationResult(SIPResponseStatusCodesEnum.Forbidden, null)); } else if (sipAccount.IsDisabled) { if (logSIPMonitorEvent != null) { logSIPMonitorEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Authoriser, SIPMonitorEventTypesEnum.DialPlan, "SIP account " + sipAccount.SIPUsername + "@" + sipAccount.SIPDomain + " is disabled for " + sipRequest.Method + ".", sipAccount.Owner)); } return(new SIPRequestAuthenticationResult(SIPResponseStatusCodesEnum.Forbidden, null)); } else { SIPAuthenticationHeader reqAuthHeader = sipRequest.Header.AuthenticationHeader; if (reqAuthHeader == null) { // Check for IP address authentication. if (!sipAccount.IPAddressACL.IsNullOrBlank()) { SIPEndPoint uaEndPoint = (!sipRequest.Header.ProxyReceivedFrom.IsNullOrBlank()) ? SIPEndPoint.ParseSIPEndPoint(sipRequest.Header.ProxyReceivedFrom) : remoteEndPoint; if (Regex.Match(uaEndPoint.GetIPEndPoint().ToString(), sipAccount.IPAddressACL).Success) { // Successfully authenticated return(new SIPRequestAuthenticationResult(true, true)); } } SIPAuthenticationHeader authHeader = new SIPAuthenticationHeader(SIPAuthorisationHeadersEnum.WWWAuthenticate, sipAccount.SIPDomain, GetNonce()); return(new SIPRequestAuthenticationResult(SIPResponseStatusCodesEnum.Unauthorised, authHeader)); } else { // Check for IP address authentication. if (!sipAccount.IPAddressACL.IsNullOrBlank()) { SIPEndPoint uaEndPoint = (!sipRequest.Header.ProxyReceivedFrom.IsNullOrBlank()) ? SIPEndPoint.ParseSIPEndPoint(sipRequest.Header.ProxyReceivedFrom) : remoteEndPoint; if (Regex.Match(uaEndPoint.GetIPEndPoint().ToString(), sipAccount.IPAddressACL).Success) { // Successfully authenticated return(new SIPRequestAuthenticationResult(true, true)); } } string requestNonce = reqAuthHeader.SIPDigest.Nonce; string uri = reqAuthHeader.SIPDigest.URI; string response = reqAuthHeader.SIPDigest.Response; // Check for stale nonces. if (IsNonceStale(requestNonce)) { if (logSIPMonitorEvent != null) { logSIPMonitorEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Authoriser, SIPMonitorEventTypesEnum.Warn, "Authentication failed stale nonce for realm=" + sipAccount.SIPDomain + ", username="******", uri=" + uri + ", nonce=" + requestNonce + ", method=" + sipRequest.Method + ".", null)); } SIPAuthenticationHeader authHeader = new SIPAuthenticationHeader(SIPAuthorisationHeadersEnum.WWWAuthenticate, sipAccount.SIPDomain, GetNonce()); return(new SIPRequestAuthenticationResult(SIPResponseStatusCodesEnum.Unauthorised, authHeader)); } else { SIPAuthorisationDigest checkAuthReq = reqAuthHeader.SIPDigest; checkAuthReq.SetCredentials(sipAccount.SIPUsername, sipAccount.SIPPassword, uri, sipRequest.Method.ToString()); string digest = checkAuthReq.Digest; if (digest == response) { // Successfully authenticated return(new SIPRequestAuthenticationResult(true, false)); } else { if (logSIPMonitorEvent != null) { logSIPMonitorEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Authoriser, SIPMonitorEventTypesEnum.Warn, "Authentication token check failed for realm=" + sipAccount.SIPDomain + ", username="******", uri=" + uri + ", nonce=" + requestNonce + ", method=" + sipRequest.Method + ".", sipAccount.Owner)); } SIPAuthenticationHeader authHeader = new SIPAuthenticationHeader(SIPAuthorisationHeadersEnum.WWWAuthenticate, sipAccount.SIPDomain, GetNonce()); return(new SIPRequestAuthenticationResult(SIPResponseStatusCodesEnum.Unauthorised, authHeader)); } } } } } catch (Exception excp) { if (logSIPMonitorEvent != null) { logSIPMonitorEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Authoriser, SIPMonitorEventTypesEnum.Error, "Exception AuthoriseSIPRequest. " + excp.Message, null)); } return(new SIPRequestAuthenticationResult(SIPResponseStatusCodesEnum.InternalServerError, null)); } }
public void Start() { try { logger.Debug("pid=" + Process.GetCurrentProcess().Id + "."); logger.Debug("os=" + System.Environment.OSVersion + "."); logger.Debug("current directory=" + m_currentDirectory + "."); logger.Debug("base directory=" + AppDomain.CurrentDomain.BaseDirectory + "."); SIPDNSManager.SIPMonitorLogEvent = FireSIPMonitorEvent; m_sipSorceryPersistor = new SIPSorceryPersistor(m_storageType, m_connectionString); m_customerSessionManager = new CustomerSessionManager(m_storageType, m_connectionString); m_cdrDataLayer = new Entities.CDRDataLayer(); if (m_sipProxyEnabled) { m_sipProxyDaemon = new SIPProxyDaemon(); m_sipProxyDaemon.Start(); if (m_sipProxyDaemon.PublicIPAddress != null) { m_publicIPAddress = m_sipProxyDaemon.PublicIPAddress; DialStringParser.PublicIPAddress = m_sipProxyDaemon.PublicIPAddress; DialPlanScriptFacade.PublicIPAddress = m_sipProxyDaemon.PublicIPAddress; SIPDialogueManager.PublicIPAddress = m_sipProxyDaemon.PublicIPAddress; } else { m_sipProxyDaemon.PublicIPAddressUpdated += (ipAddress) => { if (ipAddress != null && (m_publicIPAddress == null || ipAddress.ToString() != m_publicIPAddress.ToString())) { m_publicIPAddress = ipAddress; DialStringParser.PublicIPAddress = ipAddress; DialPlanScriptFacade.PublicIPAddress = ipAddress; SIPDialogueManager.PublicIPAddress = ipAddress; } }; } } if (m_sipMonitorEnabled) { m_sipMonitorPublisher = new SIPMonitorClientManager(null); m_sipMonitorDaemon = new SIPMonitorDaemon(m_sipMonitorPublisher); m_sipMonitorDaemon.Start(); } if (m_sipRegistrarEnabled) { m_sipRegistrarDaemon = new SIPRegistrarDaemon( m_sipSorceryPersistor.SIPDomainManager.GetDomain, m_sipSorceryPersistor.SIPAccountsPersistor.Get, m_sipSorceryPersistor.SIPRegistrarBindingPersistor, SIPRequestAuthenticator.AuthenticateSIPRequest, m_customerSessionManager.CustomerPersistor); m_sipRegistrarDaemon.Start(); } if (m_sipRegAgentEnabled) { m_sipRegAgentDaemon = new SIPRegAgentDaemon( m_sipSorceryPersistor.SIPProvidersPersistor, m_sipSorceryPersistor.SIPProviderBindingsPersistor); m_sipRegAgentDaemon.Start(); } if (m_sipNotifierEnabled) { m_sipNotifierDaemon = new SIPNotifierDaemon( m_customerSessionManager.CustomerPersistor.Get, m_sipSorceryPersistor.SIPDialoguePersistor.Get, m_sipSorceryPersistor.SIPDialoguePersistor.Get, m_sipSorceryPersistor.SIPDomainManager.GetDomain, m_sipSorceryPersistor.SIPAccountsPersistor, m_sipSorceryPersistor.SIPRegistrarBindingPersistor.Get, m_sipSorceryPersistor.SIPAccountsPersistor.Get, m_sipSorceryPersistor.SIPRegistrarBindingPersistor.Count, SIPRequestAuthenticator.AuthenticateSIPRequest, m_sipMonitorPublisher); //new SIPMonitorUDPSink("127.0.0.1:10003")); m_sipNotifierDaemon.Start(); } if (m_sshServerEnabled) { SSHServerDaemon daemon = new SSHServerDaemon(m_customerSessionManager, m_sipMonitorPublisher); // Uses memory to transfer events. //SSHServerDaemon daemon = new SSHServerDaemon(m_customerSessionManager, new SIPMonitorUDPSink("127.0.0.1:10002")); daemon.Start(); } #region Initialise the SIP Application Server and its logging mechanisms including CDRs. logger.Debug("Initiating SIP Application Server Agent."); // Send events from this process to the monitoring socket. if (m_monitorEventLoopbackPort != 0) { m_monitorEventWriter = new SIPMonitorEventWriter(m_monitorEventLoopbackPort); } if (m_cdrDataLayer != null) { SIPCDR.CDRCreated += m_cdrDataLayer.Add; SIPCDR.CDRAnswered += m_cdrDataLayer.Update; SIPCDR.CDRHungup += m_cdrDataLayer.Update; SIPCDR.CDRUpdated += m_cdrDataLayer.Update; } #region Initialise the SIPTransport layers. m_sipTransport = new SIPTransport(SIPDNSManager.ResolveSIPService, new SIPTransactionEngine(), true); if (m_appServerEndPoint != null) { if (m_appServerEndPoint.Protocol == SIPProtocolsEnum.udp) { logger.Debug("Using single SIP transport socket for App Server " + m_appServerEndPoint.ToString() + "."); m_sipTransport.AddSIPChannel(new SIPUDPChannel(m_appServerEndPoint.GetIPEndPoint())); } else if (m_appServerEndPoint.Protocol == SIPProtocolsEnum.tcp) { logger.Debug("Using single SIP transport socket for App Server " + m_appServerEndPoint.ToString() + "."); m_sipTransport.AddSIPChannel(new SIPTCPChannel(m_appServerEndPoint.GetIPEndPoint())); } else { throw new ApplicationException("The SIP End Point of " + m_appServerEndPoint + " cannot be used with the App Server transport layer."); } } else if (m_sipAppServerSocketsNode != null) { m_sipTransport.AddSIPChannel(SIPTransportConfig.ParseSIPChannelsNode(m_sipAppServerSocketsNode)); } else { throw new ApplicationException("The SIP App Server could not be started, no SIP sockets have been configured."); } m_sipTransport.SIPRequestInTraceEvent += LogSIPRequestIn; m_sipTransport.SIPRequestOutTraceEvent += LogSIPRequestOut; m_sipTransport.SIPResponseInTraceEvent += LogSIPResponseIn; m_sipTransport.SIPResponseOutTraceEvent += LogSIPResponseOut; m_sipTransport.SIPBadRequestInTraceEvent += LogSIPBadRequestIn; m_sipTransport.SIPBadResponseInTraceEvent += LogSIPBadResponseIn; #endregion m_dialPlanEngine = new DialPlanEngine( m_sipTransport, m_sipSorceryPersistor.SIPDomainManager.GetDomain, FireSIPMonitorEvent, m_sipSorceryPersistor, //m_sipSorceryPersistor.SIPAccountsPersistor, //m_sipSorceryPersistor.SIPRegistrarBindingPersistor.Get, //m_sipSorceryPersistor.SIPDialPlanPersistor, //m_sipSorceryPersistor.SIPDialoguePersistor, m_outboundProxy, m_rubyScriptCommonPath, m_dialplanImpersonationUsername, m_dialplanImpersonationPassword, m_maxDialPlanExecutionLimit); m_sipDialogueManager = new SIPDialogueManager( m_sipTransport, m_outboundProxy, FireSIPMonitorEvent, m_sipSorceryPersistor.SIPDialoguePersistor, m_sipSorceryPersistor.SIPCDRPersistor, SIPRequestAuthenticator.AuthenticateSIPRequest, m_sipSorceryPersistor.SIPAccountsPersistor.Get, m_sipSorceryPersistor.SIPDomainManager.GetDomain); m_callManager = new SIPCallManager( m_sipTransport, m_outboundProxy, FireSIPMonitorEvent, m_sipDialogueManager, m_sipSorceryPersistor.SIPDialoguePersistor, m_sipSorceryPersistor.SIPCDRPersistor, m_dialPlanEngine, m_sipSorceryPersistor.SIPDialPlanPersistor.Get, m_sipSorceryPersistor.SIPAccountsPersistor.Get, m_sipSorceryPersistor.SIPRegistrarBindingPersistor.Get, m_sipSorceryPersistor.SIPProvidersPersistor.Get, m_sipSorceryPersistor.SIPDomainManager.GetDomain, m_customerSessionManager.CustomerPersistor, m_sipSorceryPersistor.SIPDialPlanPersistor, m_traceDirectory, m_monitorCalls, m_dailyCallLimit); m_callManager.Start(); m_appServerCore = new SIPAppServerCore( m_sipTransport, m_sipSorceryPersistor.SIPDomainManager.GetDomain, m_sipSorceryPersistor.SIPAccountsPersistor.Get, FireSIPMonitorEvent, m_callManager, m_sipDialogueManager, SIPRequestAuthenticator.AuthenticateSIPRequest, m_outboundProxy); m_rtccCore = new RTCCCore( FireSIPMonitorEvent, m_sipDialogueManager, m_sipSorceryPersistor.SIPDialoguePersistor); m_rtccCore.Start(); m_rateUpdater = new RateBulkUpdater(FireSIPMonitorEvent); m_rateUpdater.Start(); #endregion #region Initialise WCF services. try { if (WCFUtility.DoesWCFServiceExist(typeof(SIPProvisioningWebService).FullName.ToString())) { if (m_sipSorceryPersistor == null) { logger.Warn("Provisioning hosted service could not be started as Persistor object was null."); } else { SIPProviderBindingSynchroniser sipProviderBindingSynchroniser = new SIPProviderBindingSynchroniser(m_sipSorceryPersistor.SIPProviderBindingsPersistor); m_sipSorceryPersistor.SIPProvidersPersistor.Added += sipProviderBindingSynchroniser.SIPProviderAdded; m_sipSorceryPersistor.SIPProvidersPersistor.Updated += sipProviderBindingSynchroniser.SIPProviderUpdated; m_sipSorceryPersistor.SIPProvidersPersistor.Deleted += sipProviderBindingSynchroniser.SIPProviderDeleted; ProvisioningServiceInstanceProvider instanceProvider = new ProvisioningServiceInstanceProvider( m_sipSorceryPersistor.SIPAccountsPersistor, m_sipSorceryPersistor.SIPDialPlanPersistor, m_sipSorceryPersistor.SIPProvidersPersistor, m_sipSorceryPersistor.SIPProviderBindingsPersistor, m_sipSorceryPersistor.SIPRegistrarBindingPersistor, m_sipSorceryPersistor.SIPDialoguePersistor, m_sipSorceryPersistor.SIPCDRPersistor, m_customerSessionManager, m_sipSorceryPersistor.SIPDomainManager, FireSIPMonitorEvent, 0, false); m_sipProvisioningHost = new ServiceHost(typeof(SIPProvisioningWebService)); m_sipProvisioningHost.Description.Behaviors.Add(instanceProvider); m_sipProvisioningHost.Open(); if (m_sipRegAgentDaemon == null) { m_sipRegAgentDaemon = new SIPRegAgentDaemon( m_sipSorceryPersistor.SIPProvidersPersistor, m_sipSorceryPersistor.SIPProviderBindingsPersistor); } logger.Debug("Provisioning hosted service successfully started on " + m_sipProvisioningHost.BaseAddresses[0].AbsoluteUri + "."); } } } catch (Exception excp) { logger.Warn("Exception starting Provisioning hosted service. " + excp.Message); } try { if (WCFUtility.DoesWCFServiceExist(typeof(CrossDomainService).FullName.ToString())) { m_accessPolicyHost = new ServiceHost(typeof(CrossDomainService)); m_accessPolicyHost.Open(); logger.Debug("CrossDomain hosted service successfully started on " + m_accessPolicyHost.BaseAddresses[0].AbsoluteUri + "."); } } catch (Exception excp) { logger.Warn("Exception starting CrossDomain hosted service. " + excp.Message); } try { if (WCFUtility.DoesWCFServiceExist(typeof(CallManagerServices).FullName.ToString())) { CallManagerServiceInstanceProvider callManagerSvcInstanceProvider = new CallManagerServiceInstanceProvider(m_callManager, m_sipDialogueManager); Uri callManagerBaseAddress = null; if (m_callManagerServiceAddress != null) { logger.Debug("Adding service address to Call Manager Service " + m_callManagerServiceAddress + "."); callManagerBaseAddress = new Uri(m_callManagerServiceAddress); } if (callManagerBaseAddress != null) { m_callManagerSvcHost = new ServiceHost(typeof(CallManagerServices), callManagerBaseAddress); } else { m_callManagerSvcHost = new ServiceHost(typeof(CallManagerServices)); } m_callManagerSvcHost.Description.Behaviors.Add(callManagerSvcInstanceProvider); m_callManagerSvcHost.Open(); logger.Debug("CallManager hosted service successfully started on " + m_callManagerSvcHost.BaseAddresses[0].AbsoluteUri + "."); } } catch (Exception excp) { logger.Warn("Exception starting CallManager hosted service. " + excp.Message); } if (WCFUtility.DoesWCFServiceExist(typeof(SIPNotifierService).FullName.ToString())) { if (m_sipMonitorPublisher != null) { try { SIPNotifierService notifierService = new SIPNotifierService(m_sipMonitorPublisher, m_customerSessionManager); m_sipNotificationsHost = new ServiceHost(notifierService); m_sipNotificationsHost.Open(); logger.Debug("SIPNotificationsService hosted service successfully started on " + m_sipNotificationsHost.BaseAddresses[0].AbsoluteUri + "."); } catch (Exception excp) { logger.Warn("Exception starting SIPNotificationsService hosted service. " + excp.Message); } } } #endregion } catch (Exception excp) { logger.Error("Exception SIPAppServerDaemon Start. " + excp.Message); throw excp; } }
/// <summary> /// Sends the SIP INVITE probe request. /// </summary> public void SendProbe() { try { if (WorkerProcess == null) { logger.Debug("When attempting to send probe the worker process was null. Marking for immediate restart."); NeedsImmediateRestart = true; } else if (WorkerProcess.HasExited) { logger.Debug("When attempting to send probe the worker had exited. Marking for immediate restart."); NeedsImmediateRestart = true; } else if (m_probeUAC != null && !m_probeUAC.IsUACAnswered) { // A probe call has timed out. m_probeUAC.Cancel(); m_missedProbes++; if (m_missedProbes >= m_missedProbesLimit) { logger.Warn(m_missedProbes + " probes missed for " + AppServerEndpoint.ToString() + ". Marking for immediate restart."); NeedsImmediateRestart = true; } } if (!NeedsImmediateRestart && !NeedsToRestart) { m_probeCount++; //logger.Debug("Sending probe " + m_probeCount + " to " + AppServerEndpoint.GetIPEndPoint().ToString() + "."); DateTime probeSentAt = DateTime.Now; SIPCallDescriptor callDescriptor = new SIPCallDescriptor(m_dispatcherUsername, null, "sip:" + m_dispatcherUsername + "@" + AppServerEndpoint.GetIPEndPoint().ToString(), "sip:" + m_dispatcherUsername + "@sipcalldispatcher", "sip:" + AppServerEndpoint.GetIPEndPoint().ToString(), null, null, null, SIPCallDirection.Out, null, null, null); m_probeUAC = new SIPClientUserAgent(m_sipTransport, null, null, null, null, null, null, null, null, null); m_probeUAC.CallAnswered += (call, sipResponse) => { //logger.Debug("Probe response received for " + AppServerEndpoint.ToString() + "."); if (sipResponse.Status != SIPResponseStatusCodesEnum.BadExtension) //if (sipResponse.Status != SIPResponseStatusCodesEnum.InternalServerError) { logger.Warn("Probe to " + AppServerEndpoint.ToString() + " answered incorrectly on probe number " + m_probeCount + " after " + DateTime.Now.Subtract(probeSentAt).TotalSeconds.ToString("0.##") + "s, unexpected response of " + ((int)sipResponse.StatusCode) + "."); NeedsImmediateRestart = true; } else { m_gotInitialProbeResponse = true; } if (m_initialResponseMRE != null) { m_initialResponseMRE.Set(); } }; m_probeUAC.Call(callDescriptor); } } catch (Exception excp) { logger.Error("Exception SendProbe. " + excp.Message); } }
public void Start() { try { logger.Debug("pid=" + Process.GetCurrentProcess().Id + "."); logger.Debug("os=" + System.Environment.OSVersion + "."); logger.Debug("current directory=" + m_currentDirectory + "."); logger.Debug("base directory=" + AppDomain.CurrentDomain.BaseDirectory + "."); SIPDNSManager.SIPMonitorLogEvent = FireSIPMonitorEvent; m_sipSorceryPersistor = new SIPSorceryPersistor(m_storageType, m_connectionString); m_customerSessionManager = new CustomerSessionManager(m_storageType, m_connectionString); m_cdrDataLayer = new Entities.CDRDataLayer(); #region Initialise the SIP Application Server and its logging mechanisms including CDRs. logger.Debug("Initiating SIP Application Server Agent."); // Send events from this process to the monitoring socket. if (m_monitorEventLoopbackPort != 0) { m_monitorEventWriter = new SIPMonitorEventWriter(m_monitorEventLoopbackPort); } if (m_cdrDataLayer != null) { SIPCDR.CDRCreated += m_cdrDataLayer.Add; SIPCDR.CDRAnswered += m_cdrDataLayer.Update; SIPCDR.CDRHungup += m_cdrDataLayer.Update; SIPCDR.CDRUpdated += m_cdrDataLayer.Update; } #region Initialise the SIPTransport layers. m_sipTransport = new SIPTransport(SIPDNSManager.ResolveSIPService, new SIPTransactionEngine(), true); if (m_appServerEndPoint != null) { if (m_appServerEndPoint.Protocol == SIPProtocolsEnum.udp) { logger.Debug("Using single SIP transport socket for App Server " + m_appServerEndPoint.ToString() + "."); m_sipTransport.AddSIPChannel(new SIPUDPChannel(m_appServerEndPoint.GetIPEndPoint())); } else if (m_appServerEndPoint.Protocol == SIPProtocolsEnum.tcp) { logger.Debug("Using single SIP transport socket for App Server " + m_appServerEndPoint.ToString() + "."); m_sipTransport.AddSIPChannel(new SIPTCPChannel(m_appServerEndPoint.GetIPEndPoint())); } else { throw new ApplicationException("The SIP End Point of " + m_appServerEndPoint + " cannot be used with the App Server transport layer."); } } else if (m_sipAppServerSocketsNode != null) { m_sipTransport.AddSIPChannel(SIPTransportConfig.ParseSIPChannelsNode(m_sipAppServerSocketsNode)); } else { throw new ApplicationException("The SIP App Server could not be started, no SIP sockets have been configured."); } m_sipTransport.SIPRequestInTraceEvent += LogSIPRequestIn; m_sipTransport.SIPRequestOutTraceEvent += LogSIPRequestOut; m_sipTransport.SIPResponseInTraceEvent += LogSIPResponseIn; m_sipTransport.SIPResponseOutTraceEvent += LogSIPResponseOut; m_sipTransport.SIPBadRequestInTraceEvent += LogSIPBadRequestIn; m_sipTransport.SIPBadResponseInTraceEvent += LogSIPBadResponseIn; #endregion m_dialPlanEngine = new DialPlanEngine( m_sipTransport, m_sipSorceryPersistor.SIPDomainManager.GetDomain, FireSIPMonitorEvent, m_sipSorceryPersistor, m_outboundProxy, m_rubyScriptCommonPath, m_dialplanImpersonationUsername, m_dialplanImpersonationPassword, m_maxDialPlanExecutionLimit); m_sipDialogueManager = new SIPDialogueManager( m_sipTransport, m_outboundProxy, FireSIPMonitorEvent, m_sipSorceryPersistor.SIPDialoguePersistor, m_sipSorceryPersistor.SIPCDRPersistor, SIPRequestAuthenticator.AuthenticateSIPRequest, m_sipSorceryPersistor.SIPAccountsPersistor.Get, m_sipSorceryPersistor.SIPDomainManager.GetDomain); m_callManager = new SIPCallManager( m_sipTransport, m_outboundProxy, FireSIPMonitorEvent, m_sipDialogueManager, m_sipSorceryPersistor.SIPDialoguePersistor, m_sipSorceryPersistor.SIPCDRPersistor, m_dialPlanEngine, m_sipSorceryPersistor.SIPDialPlanPersistor.Get, m_sipSorceryPersistor.SIPAccountsPersistor.Get, m_sipSorceryPersistor.SIPRegistrarBindingPersistor.Get, m_sipSorceryPersistor.SIPProvidersPersistor.Get, m_sipSorceryPersistor.SIPDomainManager.GetDomain, m_customerSessionManager.CustomerPersistor, m_sipSorceryPersistor.SIPDialPlanPersistor, m_traceDirectory, m_monitorCalls, m_dailyCallLimit); m_callManager.Start(); GetSIPAccountDelegate getSIPAccount = (username, domain) => { return(m_sipSorceryPersistor.SIPAccountsPersistor.Get(x => x.SIPUsername == username && x.SIPDomain == domain).SIPAccount); }; m_appServerCore = new SIPAppServerCore( m_sipTransport, m_sipSorceryPersistor.SIPDomainManager.GetDomain, getSIPAccount, FireSIPMonitorEvent, m_callManager, m_sipDialogueManager, SIPRequestAuthenticator.AuthenticateSIPRequest, m_outboundProxy); #endregion #region Initialise WCF services. try { if (WCFUtility.DoesWCFServiceExist(typeof(CallManagerServices).FullName.ToString())) { CallManagerServiceInstanceProvider callManagerSvcInstanceProvider = new CallManagerServiceInstanceProvider(m_callManager, m_sipDialogueManager); Uri callManagerBaseAddress = null; if (m_callManagerServiceAddress != null) { logger.Debug("Adding service address to Call Manager Service " + m_callManagerServiceAddress + "."); callManagerBaseAddress = new Uri(m_callManagerServiceAddress); } if (callManagerBaseAddress != null) { m_callManagerSvcHost = new ServiceHost(typeof(CallManagerServices), callManagerBaseAddress); } else { m_callManagerSvcHost = new ServiceHost(typeof(CallManagerServices)); } m_callManagerSvcHost.Description.Behaviors.Add(callManagerSvcInstanceProvider); m_callManagerSvcHost.Open(); logger.Debug("CallManager hosted service successfully started on " + m_callManagerSvcHost.BaseAddresses[0].AbsoluteUri + "."); } } catch (Exception excp) { logger.Warn("Exception starting CallManager hosted service. " + excp.Message); } #endregion } catch (Exception excp) { logger.Error("Exception SIPAppServerDaemon Start. " + excp.Message); throw excp; } }
/// <summary> /// Sends the SIP INVITE probe request. /// </summary> private void ProbeWorker(SIPAppServerWorker worker, bool isInitialProbe) { try { if (isInitialProbe) { worker.InitialProbeCount++; } int workerProcessID = worker.WorkerProcess.Id; SIPEndPoint workerEndPoint = worker.AppServerEndpoint; DateTime probeSentAt = DateTime.Now; SIPCallDescriptor callDescriptor = new SIPCallDescriptor(m_dispatcherUsername, null, "sip:" + m_dispatcherUsername + "@" + workerEndPoint.GetIPEndPoint().ToString(), "sip:" + m_dispatcherUsername + "@sipcalldispatcher", "sip:" + workerEndPoint.GetIPEndPoint().ToString(), null, null, null, SIPCallDirection.Out, null, null, null); SIPClientUserAgent uac = new SIPClientUserAgent(m_sipTransport, null, null, null, null); uac.CallFailed += (failedUAC, errorMessage) => { AppServerCallFailed(failedUAC, errorMessage, workerProcessID, probeSentAt, isInitialProbe); }; uac.CallAnswered += (call, sipResponse) => { if (sipResponse.Status != SIPResponseStatusCodesEnum.BadExtension) { //logger.Warn("Probe call answered with unexpected response code of " + sipResponse.StatusCode + "."); AppServerCallFailed(call, "Unexpected response of " + ((int)sipResponse.StatusCode) + " on probe call.", workerProcessID, probeSentAt, isInitialProbe); } else { AppServerCallSucceeded(call); } }; uac.Call(callDescriptor); } catch (Exception excp) { logger.Error("Exception SIPAppServerManager ProberWorker. " + excp.Message); } }