コード例 #1
0
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="stack">Owner SIP stack.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>stack</b> is null reference.</exception>
        internal SIP_TransportLayer(SIP_Stack stack)
        {
            if (stack == null)
            {
                throw new ArgumentNullException("stack");
            }

            m_pStack = stack;

            m_pUdpServer = new UDP_Server();
            m_pUdpServer.ProcessMode = UDP_ProcessMode.Parallel;
            m_pUdpServer.PacketReceived += m_pUdpServer_PacketReceived;
            m_pUdpServer.Error += m_pUdpServer_Error;

            m_pTcpServer = new TCP_Server<TCP_ServerSession>();
            m_pTcpServer.SessionCreated += m_pTcpServer_SessionCreated;

            m_pFlowManager = new SIP_FlowManager(this);

            m_pBinds = new IPBindInfo[] {};

            m_pRandom = new Random();

            m_pLocalIPv4 = new CircleCollection<IPAddress>();
            m_pLocalIPv6 = new CircleCollection<IPAddress>();
        }
コード例 #2
0
 /// <summary>
 /// Default constructor.
 /// </summary>
 /// <param name="stack">Reference to SIP stack.</param>
 /// <param name="transaction">Client transaction what response it is. This value can be null if no matching client response.</param>
 /// <param name="response">Received response.</param>
 internal SIP_ResponseReceivedEventArgs(SIP_Stack stack,
                                        SIP_ClientTransaction transaction,
                                        SIP_Response response)
 {
     m_pStack = stack;
     m_pResponse = response;
     m_pTransaction = transaction;
 }
コード例 #3
0
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="stack">Owner SIP stack.</param>
        /// <param name="flow">Transaction data flow.</param>
        /// <param name="request">SIP request that transaction will handle.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>stack</b>,<b>flow</b> or <b>request</b> is null reference.</exception>
        public SIP_Transaction(SIP_Stack stack, SIP_Flow flow, SIP_Request request)
        {
            if (stack == null)
            {
                throw new ArgumentNullException("stack");
            }
            if (flow == null)
            {
                throw new ArgumentNullException("flow");
            }
            if (request == null)
            {
                throw new ArgumentNullException("request");
            }

            m_pStack = stack;
            m_pFlow = flow;
            m_pRequest = request;
            m_Method = request.RequestLine.Method;
            m_CreateTime = DateTime.Now;
            m_pResponses = new List<SIP_Response>();

            // Validate Via:
            SIP_t_ViaParm via = request.Via.GetTopMostValue();
            if (via == null)
            {
                throw new ArgumentException("Via: header is missing !");
            }
            if (via.Branch == null)
            {
                throw new ArgumentException("Via: header 'branch' parameter is missing !");
            }

            m_ID = via.Branch;

            if (this is SIP_ServerTransaction)
            {
                /*
                    We use branch and sent-by as indexing key for transaction, the only special what we need to 
                    do is to handle CANCEL, because it has same branch as transaction to be canceled.
                    For avoiding key collision, we add branch + '-' + 'sent-by' + CANCEL for cancel index key.
                    ACK has also same branch, but we won't do transaction for ACK, so it isn't problem.
                */
                string key = request.Via.GetTopMostValue().Branch + '-' + request.Via.GetTopMostValue().SentBy;
                if (request.RequestLine.Method == SIP_Methods.CANCEL)
                {
                    key += "-CANCEL";
                }
                m_Key = key;
            }
            else
            {
                m_Key = m_ID + "-" + request.RequestLine.Method;
            }
        }
コード例 #4
0
 /// <summary>
 /// Default constructor.
 /// </summary>
 /// <param name="stack">Reference to SIP stack.</param>
 /// <param name="flow">SIP data flow.</param>
 /// <param name="request">Recieved request.</param>
 /// <param name="dialog">SIP dialog which received request.</param>
 /// <param name="transaction">SIP server transaction which must be used to send response back to request maker.</param>
 internal SIP_RequestReceivedEventArgs(SIP_Stack stack,
                                       SIP_Flow flow,
                                       SIP_Request request,
                                       SIP_Dialog dialog,
                                       SIP_ServerTransaction transaction)
 {
     m_pStack = stack;
     m_pFlow = flow;
     m_pRequest = request;
     m_pDialog = dialog;
     m_pTransaction = transaction;
 }
コード例 #5
0
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="stack">Owner SIP stack.</param>
        /// <param name="flow">SIP data flow which received request.</param>
        /// <param name="request">SIP request that transaction will handle.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>stack</b>,<b>flow</b> or <b>request</b> is null reference.</exception>
        /// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception>
        public SIP_ServerTransaction(SIP_Stack stack, SIP_Flow flow, SIP_Request request)
            : base(stack, flow, request)
        {
            // Log
            if (Stack.Logger != null)
            {
                Stack.Logger.AddText(ID,
                                     "Transaction [branch='" + ID + "';method='" + Method +
                                     "';IsServer=true] created.");
            }

            Start();
        }
コード例 #6
0
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="stack">Owner SIP stack.</param>
        /// <param name="flow">SIP data flow which is used to send request.</param>
        /// <param name="request">SIP request that transaction will handle.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>stack</b>,<b>flow</b> or <b>request</b> is null reference.</exception>
        /// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception>
        internal SIP_ClientTransaction(SIP_Stack stack, SIP_Flow flow, SIP_Request request)
            : base(stack, flow, request)
        {
            // Log
            if (Stack.Logger != null)
            {
                Stack.Logger.AddText(ID,
                                     "Transaction [branch='" + ID + "';method='" + Method +
                                     "';IsServer=false] created.");
            }

            SetState(SIP_TransactionState.WaitingToStart);
        }
コード例 #7
0
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="stack">Reference to SIP stack.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>stack</b> is null reference.</exception>
        internal SIP_TransactionLayer(SIP_Stack stack)
        {
            if (stack == null)
            {
                throw new ArgumentNullException("stack");
            }

            m_pStack = stack;

            m_pClientTransactions = new Dictionary<string, SIP_ClientTransaction>();
            m_pServerTransactions = new Dictionary<string, SIP_ServerTransaction>();
            m_pDialogs = new Dictionary<string, SIP_Dialog>();

            m_pTimer = new Timer(20000);
            m_pTimer.AutoReset = true;
            m_pTimer.Elapsed += m_pTimer_Elapsed;
        }
コード例 #8
0
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="stack">Owner stack.</param>
        /// <param name="request">SIP request.</param>
        /// <param name="flow">Active data flow what to try before RFC 3261 [4](RFC 3263) methods to use to send request.
        /// This value can be null.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>stack</b> or <b>request</b> is null.</exception>
        internal SIP_RequestSender(SIP_Stack stack, SIP_Request request, SIP_Flow flow)
        {
            if (stack == null)
            {
                throw new ArgumentNullException("stack");
            }
            if (request == null)
            {
                throw new ArgumentNullException("request");
            }

            m_pStack = stack;
            m_pRequest = request;
            m_pFlow = flow;

            m_pCredentials = new List<NetworkCredential>();
            m_pHops = new Queue<SIP_Hop>();
        }
コード例 #9
0
        /// <summary>
        /// Initializes dialog.
        /// </summary>
        /// <param name="stack">Owner stack.</param>
        /// <param name="transaction">Owner transaction.</param>
        /// <param name="response">SIP response what caused dialog creation.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>stack</b>,<b>transaction</b> or <b>response</b>.</exception>
        protected internal override void Init(SIP_Stack stack,
                                              SIP_Transaction transaction,
                                              SIP_Response response)
        {
            if (stack == null)
            {
                throw new ArgumentNullException("stack");
            }
            if (transaction == null)
            {
                throw new ArgumentNullException("transaction");
            }
            if (response == null)
            {
                throw new ArgumentNullException("response");
            }

            base.Init(stack, transaction, response);

            if (transaction is SIP_ServerTransaction)
            {
                if (response.StatusCodeType == SIP_StatusCodeType.Success)
                {
                    SetState(SIP_DialogState.Early, false);

                    // We need to retransmit 2xx response while we get ACK or timeout. (RFC 3261 13.3.1.4.)
                    m_pUasInvite2xxRetransmits.Add(new UasInvite2xxRetransmit(this, response));
                }
                else if (response.StatusCodeType == SIP_StatusCodeType.Provisional)
                {
                    SetState(SIP_DialogState.Early, false);

                    m_pActiveInvite = transaction;
                    m_pActiveInvite.StateChanged += delegate
                                                        {
                                                            if (m_pActiveInvite != null &&
                                                                m_pActiveInvite.State ==
                                                                SIP_TransactionState.Terminated)
                                                            {
                                                                m_pActiveInvite = null;
                                                            }
                                                        };
                    // Once we send 2xx response, we need to retransmit it while get ACK or timeout. (RFC 3261 13.3.1.4.)
                    ((SIP_ServerTransaction) m_pActiveInvite).ResponseSent +=
                        delegate(object s, SIP_ResponseSentEventArgs a)
                            {
                                if (a.Response.StatusCodeType == SIP_StatusCodeType.Success)
                                {
                                    m_pUasInvite2xxRetransmits.Add(new UasInvite2xxRetransmit(this, a.Response));
                                }
                            };
                }
                else
                {
                    throw new ArgumentException(
                        "Argument 'response' has invalid status code, 1xx - 2xx is only allowed.");
                }
            }
            else
            {
                if (response.StatusCodeType == SIP_StatusCodeType.Success)
                {
                    SetState(SIP_DialogState.Confirmed, false);

                    //  Wait for retransmited 2xx responses. (RFC 3261 13.2.2.4.)
                    m_pUacInvite2xxRetransmitWaits.Add(new UacInvite2xxRetransmissionWaiter(this,
                                                                                            transaction.
                                                                                                Request));
                }
                else if (response.StatusCodeType == SIP_StatusCodeType.Provisional)
                {
                    SetState(SIP_DialogState.Early, false);

                    m_pActiveInvite = transaction;
                    m_pActiveInvite.StateChanged += delegate
                                                        {
                                                            if (m_pActiveInvite != null &&
                                                                m_pActiveInvite.State ==
                                                                SIP_TransactionState.Terminated)
                                                            {
                                                                m_pActiveInvite = null;
                                                            }
                                                        };
                    // Once we receive 2xx response, we need to wait for retransmitted 2xx responses. (RFC 3261 13.2.2.4)
                    ((SIP_ClientTransaction) m_pActiveInvite).ResponseReceived +=
                        delegate(object s, SIP_ResponseReceivedEventArgs a)
                            {
                                if (a.Response.StatusCodeType == SIP_StatusCodeType.Success)
                                {
                                    UacInvite2xxRetransmissionWaiter waiter =
                                        new UacInvite2xxRetransmissionWaiter(this, m_pActiveInvite.Request);
                                    m_pUacInvite2xxRetransmitWaits.Add(waiter);
                                    // Force to send initial ACK to 2xx response.
                                    waiter.Process(a.Response);

                                    SetState(SIP_DialogState.Confirmed, true);
                                }
                            };
                }
                else
                {
                    throw new ArgumentException(
                        "Argument 'response' has invalid status code, 1xx - 2xx is only allowed.");
                }
            }
        }
コード例 #10
0
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="stack">Owner SIP stack.</param>
        /// <param name="server">Registrar server URI. For example: sip:domain.com.</param>
        /// <param name="aor">Address of record. For example: [email protected].</param>
        /// <param name="contact">Contact URI.</param>
        /// <param name="expires">Gets after how many seconds reigisration expires.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>ua</b>,<b>server</b>,<b>transport</b>,<b>aor</b> or <b>contact</b> is null reference.</exception>
        /// <exception cref="ArgumentException">Is raised when any of the arguments contains invalid value.</exception>
        internal SIP_UA_Registration(SIP_Stack stack,
                                     SIP_Uri server,
                                     string aor,
                                     AbsoluteUri contact,
                                     int expires)
        {
            if (stack == null)
            {
                throw new ArgumentNullException("stack");
            }
            if (server == null)
            {
                throw new ArgumentNullException("server");
            }
            if (aor == null)
            {
                throw new ArgumentNullException("aor");
            }
            if (aor == string.Empty)
            {
                throw new ArgumentException("Argument 'aor' value must be specified.");
            }
            if (contact == null)
            {
                throw new ArgumentNullException("contact");
            }

            m_pStack = stack;
            m_pServer = server;
            m_AOR = aor;
            m_pContact = contact;
            m_RefreshInterval = expires;

            m_pTimer = new TimerEx((m_RefreshInterval - 15)*1000);
            m_pTimer.AutoReset = false;
            m_pTimer.Elapsed += m_pTimer_Elapsed;
            m_pTimer.Enabled = false;
        }
コード例 #11
0
        /// <summary>
        /// Cleans up any resources being used.
        /// </summary>
        public void Dispose()
        {
            if (m_IsDisposed)
            {
                return;
            }
            m_IsDisposed = true;

            m_pStack = null;
            m_pTimer.Dispose();
            m_pTimer = null;

            SetState(SIP_UA_RegistrationState.Disposed);
            OnDisposed();

            Registered = null;
            Unregistered = null;
            Error = null;
            Disposed = null;
        }
コード例 #12
0
ファイル: SIP_Dialog.cs プロジェクト: vipwan/CommunityServer
        /// <summary>
        /// Cleans up any resources being used.
        /// </summary>
        public virtual void Dispose()
        {
            lock (m_pLock)
            {
                if (State == SIP_DialogState.Disposed)
                {
                    return;
                }

                SetState(SIP_DialogState.Disposed, true);

                m_pStack = null;
                m_CallID = null;
                m_LocalTag = null;
                m_RemoteTag = null;
                m_pLocalUri = null;
                m_pRemoteUri = null;
                m_pLocalContact = null;
                m_pRemoteTarget = null;
                m_pRouteSet = null;
                m_pFlow = null;
                m_pLock = null;
            }
        }
コード例 #13
0
 /// <summary>
 /// Default constructor.
 /// </summary>
 /// <param name="stack">Reference to SIP stack.</param>
 /// <param name="flow">SIP data flow.</param>
 /// <param name="request">Recieved request.</param>
 internal SIP_RequestReceivedEventArgs(SIP_Stack stack, SIP_Flow flow, SIP_Request request)
     : this(stack, flow, request, null, null) {}
コード例 #14
0
ファイル: SIP_Flow.cs プロジェクト: Inzaghi2012/teamlab.v7.5
        /// <summary>
        /// Server TCP,TLS constructor.
        /// </summary>
        /// <param name="stack">Owner stack.</param>
        /// <param name="session">TCP session.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>stack</b> or <b>session</b> is null reference.</exception>
        internal SIP_Flow(SIP_Stack stack, TCP_Session session)
        {
            if (stack == null)
            {
                throw new ArgumentNullException("stack");
            }
            if (session == null)
            {
                throw new ArgumentNullException("session");
            }

            m_pStack = stack;
            m_pTcpSession = session;

            m_IsServer = true;
            m_pLocalEP = session.LocalEndPoint;
            m_pRemoteEP = session.RemoteEndPoint;
            m_Transport = session.IsSecureConnection ? SIP_Transport.TLS : SIP_Transport.TCP;
            m_CreateTime = DateTime.Now;
            m_LastActivity = DateTime.Now;
            m_ID = m_pLocalEP + "-" + m_pRemoteEP + "-" + m_Transport;
            m_pMessage = new MemoryStream();

            BeginReadHeader();
        }
コード例 #15
0
ファイル: SIP_Flow.cs プロジェクト: Inzaghi2012/teamlab.v7.5
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="stack">Owner stack.</param>
        /// <param name="isServer">Specifies if flow is server or client flow.</param>
        /// <param name="localEP">Local IP end point.</param>
        /// <param name="remoteEP">Remote IP end point.</param>
        /// <param name="transport">SIP transport.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>stack</b>,<b>localEP</b>,<b>remoteEP</b>  or <b>transport</b> is null reference.</exception>
        /// <exception cref="ArgumentException">Is raised whena any of the arguments has invalid value.</exception>
        internal SIP_Flow(SIP_Stack stack,
                          bool isServer,
                          IPEndPoint localEP,
                          IPEndPoint remoteEP,
                          string transport)
        {
            if (stack == null)
            {
                throw new ArgumentNullException("stack");
            }
            if (localEP == null)
            {
                throw new ArgumentNullException("localEP");
            }
            if (remoteEP == null)
            {
                throw new ArgumentNullException("remoteEP");
            }
            if (transport == null)
            {
                throw new ArgumentNullException("transport");
            }

            m_pStack = stack;
            m_IsServer = isServer;
            m_pLocalEP = localEP;
            m_pRemoteEP = remoteEP;
            m_Transport = transport.ToUpper();

            m_CreateTime = DateTime.Now;
            m_LastActivity = DateTime.Now;
            m_ID = m_pLocalEP + "-" + m_pRemoteEP + "-" + m_Transport;
            m_pMessage = new MemoryStream();
        }
コード例 #16
0
ファイル: SIP_Dialog.cs プロジェクト: vipwan/CommunityServer
        /// <summary>
        /// Initializes dialog.
        /// </summary>
        /// <param name="stack">Owner stack.</param>
        /// <param name="transaction">Owner transaction.</param>
        /// <param name="response">SIP response what caused dialog creation.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>stack</b>,<b>transaction</b> or <b>response</b>.</exception>
        protected internal virtual void Init(SIP_Stack stack,
                                             SIP_Transaction transaction,
                                             SIP_Response response)
        {
            if (stack == null)
            {
                throw new ArgumentNullException("stack");
            }
            if (transaction == null)
            {
                throw new ArgumentNullException("transaction");
            }
            if (response == null)
            {
                throw new ArgumentNullException("response");
            }

            m_pStack = stack;

            #region UAS

            /* RFC 3261 12.1.1.
                The UAS then constructs the state of the dialog.  This state MUST be
                maintained for the duration of the dialog.

                If the request arrived over TLS, and the Request-URI contained a SIPS
                URI, the "secure" flag is set to TRUE.

                The route set MUST be set to the list of URIs in the Record-Route
                header field from the request, taken in order and preserving all URI
                parameters.  If no Record-Route header field is present in the
                request, the route set MUST be set to the empty set.  This route set,
                even if empty, overrides any pre-existing route set for future
                requests in this dialog.  The remote target MUST be set to the URI
                from the Contact header field of the request.

                The remote sequence number MUST be set to the value of the sequence
                number in the CSeq header field of the request.  The local sequence
                number MUST be empty.  The call identifier component of the dialog ID
                MUST be set to the value of the Call-ID in the request.  The local
                tag component of the dialog ID MUST be set to the tag in the To field
                in the response to the request (which always includes a tag), and the
                remote tag component of the dialog ID MUST be set to the tag from the
                From field in the request.  A UAS MUST be prepared to receive a
                request without a tag in the From field, in which case the tag is
                considered to have a value of null.

                    This is to maintain backwards compatibility with RFC 2543, which
                    did not mandate From tags.

                The remote URI MUST be set to the URI in the From field, and the
                local URI MUST be set to the URI in the To field.
            */

            if (transaction is SIP_ServerTransaction)
            {
                // TODO: Validate request or client transaction must do it ?

                m_IsSecure = ((SIP_Uri) transaction.Request.RequestLine.Uri).IsSecure;
                m_pRouteSet =
                    (SIP_t_AddressParam[]) Core.ReverseArray(transaction.Request.RecordRoute.GetAllValues());
                m_pRemoteTarget = (SIP_Uri) transaction.Request.Contact.GetTopMostValue().Address.Uri;
                m_RemoteSeqNo = transaction.Request.CSeq.SequenceNumber;
                m_LocalSeqNo = 0;
                m_CallID = transaction.Request.CallID;
                m_LocalTag = response.To.Tag;
                m_RemoteTag = transaction.Request.From.Tag;
                m_pRemoteUri = transaction.Request.From.Address.Uri;
                m_pLocalUri = transaction.Request.To.Address.Uri;
                m_pLocalContact = (SIP_Uri) response.Contact.GetTopMostValue().Address.Uri;
            }

                #endregion

                #region UAC

                /* RFC 3261 12.1.2.
                When a UAC receives a response that establishes a dialog, it
                constructs the state of the dialog.  This state MUST be maintained
                for the duration of the dialog.

                If the request was sent over TLS, and the Request-URI contained a
                SIPS URI, the "secure" flag is set to TRUE.

                The route set MUST be set to the list of URIs in the Record-Route
                header field from the response, taken in reverse order and preserving
                all URI parameters.  If no Record-Route header field is present in
                the response, the route set MUST be set to the empty set.  This route
                set, even if empty, overrides any pre-existing route set for future
                requests in this dialog.  The remote target MUST be set to the URI
                from the Contact header field of the response.

                The local sequence number MUST be set to the value of the sequence
                number in the CSeq header field of the request.  The remote sequence
                number MUST be empty (it is established when the remote UA sends a
                request within the dialog).  The call identifier component of the
                dialog ID MUST be set to the value of the Call-ID in the request.
                The local tag component of the dialog ID MUST be set to the tag in
                the From field in the request, and the remote tag component of the
                dialog ID MUST be set to the tag in the To field of the response.  A
                UAC MUST be prepared to receive a response without a tag in the To
                field, in which case the tag is considered to have a value of null.

                    This is to maintain backwards compatibility with RFC 2543, which
                    did not mandate To tags.

                The remote URI MUST be set to the URI in the To field, and the local
                URI MUST be set to the URI in the From field.
            */

            else
            {
                // TODO: Validate request or client transaction must do it ?

                m_IsSecure = ((SIP_Uri) transaction.Request.RequestLine.Uri).IsSecure;
                m_pRouteSet = (SIP_t_AddressParam[]) Core.ReverseArray(response.RecordRoute.GetAllValues());
                m_pRemoteTarget = (SIP_Uri) response.Contact.GetTopMostValue().Address.Uri;
                m_LocalSeqNo = transaction.Request.CSeq.SequenceNumber;
                m_RemoteSeqNo = 0;
                m_CallID = transaction.Request.CallID;
                m_LocalTag = transaction.Request.From.Tag;
                m_RemoteTag = response.To.Tag;
                m_pRemoteUri = transaction.Request.To.Address.Uri;
                m_pLocalUri = transaction.Request.From.Address.Uri;
                m_pLocalContact = (SIP_Uri) transaction.Request.Contact.GetTopMostValue().Address.Uri;
            }

            #endregion

            m_pFlow = transaction.Flow;
        }
コード例 #17
0
        /// <summary>
        /// Cleans up any resources being used.
        /// </summary>
        public void Dispose()
        {
            lock (m_pLock)
            {
                if (m_State == SIP_RequestSenderState.Disposed)
                {
                    return;
                }
                m_State = SIP_RequestSenderState.Disposed;

                OnDisposed();

                ResponseReceived = null;
                Completed = null;
                Disposed = null;

                m_pStack = null;
                m_pRequest = null;
                m_pCredentials = null;
                m_pHops = null;
                m_pTransaction = null;
                m_pLock = null;
            }
        }
コード例 #18
0
        /// <summary>
        /// Cleans up any resources being used.
        /// </summary>
        public virtual void Dispose()
        {
            SetState(SIP_TransactionState.Disposed);
            OnDisposed();

            m_pStack = null;
            m_pFlow = null;
            m_pRequest = null;

            StateChanged = null;
            Disposed = null;
            TimedOut = null;
            TransportError = null;
        }