/// <summary> /// Raises event <b>IncomingCall</b>. /// </summary> /// <param name="call">Incoming call.</param> private void OnIncomingCall(SIP_UA_Call call) { if (IncomingCall != null) { IncomingCall(this, new SIP_UA_Call_EventArgs(call)); } }
/// <summary> /// Default constructor. /// </summary> /// <param name="call">SIP UA call.</param> /// <exception cref="ArgumentNullException">Is called when <b>call</b> is null reference.</exception> public SIP_UA_Call_EventArgs(SIP_UA_Call call) { if (call == null) { throw new ArgumentNullException("call"); } m_pCall = call; }
/// <summary> /// Thsi method is called when call state has chnaged. /// </summary> /// <param name="sender">Sender.</param> /// <param name="e">Event data.</param> private void Call_StateChanged(object sender, EventArgs e) { SIP_UA_Call call = (SIP_UA_Call)sender; if (call.State == SIP_UA_CallState.Terminated) { m_pCalls.Remove(call); } }
/// <summary> /// Creates call to <b>invite</b> specified recipient. /// </summary> /// <param name="invite">INVITE request.</param> /// <returns>Returns created call.</returns> /// <exception cref="ArgumentNullException">Is raised when <b>invite</b> is null reference.</exception> /// <exception cref="ArgumentException">Is raised when any of the argumnets has invalid value.</exception> public SIP_UA_Call CreateCall(SIP_Request invite) { if (invite == null) { throw new ArgumentNullException("invite"); } if (invite.RequestLine.Method != SIP_Methods.INVITE) { throw new ArgumentException("Argument 'invite' is not INVITE request."); } lock (m_pLock) { SIP_UA_Call call = new SIP_UA_Call(this, invite); call.StateChanged += Call_StateChanged; m_pCalls.Add(call); return(call); } }
/// <summary> /// This method is called when SIP stack received new message. /// </summary> /// <param name="sender">Sender.</param> /// <param name="e">Event data.</param> private void m_pStack_RequestReceived(object sender, SIP_RequestReceivedEventArgs e) { // TODO: Performance: rise events on thread pool or see if this method called on pool aready, then we may not keep lock for events ? if (e.Request.RequestLine.Method == SIP_Methods.CANCEL) { /* RFC 3261 9.2. * If the UAS did not find a matching transaction for the CANCEL * according to the procedure above, it SHOULD respond to the CANCEL * with a 481 (Call Leg/Transaction Does Not Exist). * * Regardless of the method of the original request, as long as the * CANCEL matched an existing transaction, the UAS answers the CANCEL * request itself with a 200 (OK) response. */ SIP_ServerTransaction trToCancel = m_pStack.TransactionLayer.MatchCancelToTransaction(e.Request); if (trToCancel != null) { trToCancel.Cancel(); e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x200_Ok, e.Request)); } else { e.ServerTransaction.SendResponse( m_pStack.CreateResponse(SIP_ResponseCodes.x481_Call_Transaction_Does_Not_Exist, e.Request)); } } else if (e.Request.RequestLine.Method == SIP_Methods.BYE) { /* RFC 3261 15.1.2. * If the BYE does not match an existing dialog, the UAS core SHOULD generate a 481 * (Call/Transaction Does Not Exist) response and pass that to the server transaction. */ // TODO: SIP_Dialog dialog = m_pStack.TransactionLayer.MatchDialog(e.Request); if (dialog != null) { e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x200_Ok, e.Request)); dialog.Terminate(); } else { e.ServerTransaction.SendResponse( m_pStack.CreateResponse(SIP_ResponseCodes.x481_Call_Transaction_Does_Not_Exist, e.Request)); } } else if (e.Request.RequestLine.Method == SIP_Methods.INVITE) { SIP_ServerTransaction transaction = e.ServerTransaction; transaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x180_Ringing, e.Request)); // TODO: See if we support SDP media. // Create call. SIP_UA_Call call = new SIP_UA_Call(this, transaction); call.StateChanged += Call_StateChanged; m_pCalls.Add(call); OnIncomingCall(call); } else { OnRequestReceived(e); } }
/// <summary> /// This method is called when SIP stack received new message. /// </summary> /// <param name="sender">Sender.</param> /// <param name="e">Event data.</param> private void m_pStack_RequestReceived(object sender, SIP_RequestReceivedEventArgs e) { // TODO: Performance: rise events on thread pool or see if this method called on pool aready, then we may not keep lock for events ? if (e.Request.RequestLine.Method == SIP_Methods.CANCEL) { /* RFC 3261 9.2. If the UAS did not find a matching transaction for the CANCEL according to the procedure above, it SHOULD respond to the CANCEL with a 481 (Call Leg/Transaction Does Not Exist). Regardless of the method of the original request, as long as the CANCEL matched an existing transaction, the UAS answers the CANCEL request itself with a 200 (OK) response. */ SIP_ServerTransaction trToCancel = m_pStack.TransactionLayer.MatchCancelToTransaction(e.Request); if (trToCancel != null) { trToCancel.Cancel(); e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x200_Ok, e.Request)); } else { e.ServerTransaction.SendResponse( m_pStack.CreateResponse(SIP_ResponseCodes.x481_Call_Transaction_Does_Not_Exist, e.Request)); } } else if (e.Request.RequestLine.Method == SIP_Methods.BYE) { /* RFC 3261 15.1.2. If the BYE does not match an existing dialog, the UAS core SHOULD generate a 481 (Call/Transaction Does Not Exist) response and pass that to the server transaction. */ // TODO: SIP_Dialog dialog = m_pStack.TransactionLayer.MatchDialog(e.Request); if (dialog != null) { e.ServerTransaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x200_Ok, e.Request)); dialog.Terminate(); } else { e.ServerTransaction.SendResponse( m_pStack.CreateResponse(SIP_ResponseCodes.x481_Call_Transaction_Does_Not_Exist, e.Request)); } } else if (e.Request.RequestLine.Method == SIP_Methods.INVITE) { SIP_ServerTransaction transaction = e.ServerTransaction; transaction.SendResponse(m_pStack.CreateResponse(SIP_ResponseCodes.x180_Ringing, e.Request)); // TODO: See if we support SDP media. // Create call. SIP_UA_Call call = new SIP_UA_Call(this, transaction); call.StateChanged += Call_StateChanged; m_pCalls.Add(call); OnIncomingCall(call); } else { OnRequestReceived(e); } }
/// <summary> /// Creates call to <b>invite</b> specified recipient. /// </summary> /// <param name="invite">INVITE request.</param> /// <returns>Returns created call.</returns> /// <exception cref="ArgumentNullException">Is raised when <b>invite</b> is null reference.</exception> /// <exception cref="ArgumentException">Is raised when any of the argumnets has invalid value.</exception> public SIP_UA_Call CreateCall(SIP_Request invite) { if (invite == null) { throw new ArgumentNullException("invite"); } if (invite.RequestLine.Method != SIP_Methods.INVITE) { throw new ArgumentException("Argument 'invite' is not INVITE request."); } lock (m_pLock) { SIP_UA_Call call = new SIP_UA_Call(this, invite); call.StateChanged += Call_StateChanged; m_pCalls.Add(call); return call; } }