/// <summary>
 /// Cleans up any resources being used.
 /// </summary>
 public override void Dispose()
 {
     lock(this.SyncRoot){
         if(m_pTimer100 != null){
             m_pTimer100.Dispose();
             m_pTimer100 = null;
         }
         if(m_pTimerG != null){
             m_pTimerG.Dispose();
             m_pTimerG = null;
         }
         if(m_pTimerH != null){
             m_pTimerH.Dispose();
             m_pTimerH = null;
         }
         if(m_pTimerI != null){
             m_pTimerI.Dispose();
             m_pTimerI = null;
         }
         if(m_pTimerJ != null){
             m_pTimerJ.Dispose();
             m_pTimerJ = null;
         }                
         if(m_pTimerL != null){
             m_pTimerL.Dispose();
             m_pTimerL = null;
         }
     }
 }
Esempio n. 2
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_pContacts = new List<AbsoluteUri>();

            m_pTimer = new TimerEx((m_RefreshInterval - 15) * 1000);
            m_pTimer.AutoReset = false;
            m_pTimer.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimer_Elapsed);
            m_pTimer.Enabled = false;
        }
        /// <summary>
        /// Stops TCP server, all active connections will be terminated.
        /// </summary>
        public void Stop()
        {
            if (!m_IsRunning)
            {
                return;
            }
            m_IsRunning = false;

            // Dispose all old binds.
            foreach (ListeningPoint listeningPoint in m_pListeningPoints.ToArray())
            {
                try
                {
                    listeningPoint.Socket.Close();
                }
                catch (Exception x)
                {
                    OnError(x);
                }
            }
            m_pListeningPoints.Clear();

            m_pTimer_IdleTimeout.Dispose();
            m_pTimer_IdleTimeout = null;

            OnStopped();
        }
Esempio n. 4
0
 /// <summary>
 /// Cleans up any resources being used.
 /// </summary>
 public override void Dispose()
 {
     lock (SyncRoot)
     {
         if (m_pTimer100 != null)
         {
             m_pTimer100.Dispose();
             m_pTimer100 = null;
         }
         if (m_pTimerG != null)
         {
             m_pTimerG.Dispose();
             m_pTimerG = null;
         }
         if (m_pTimerH != null)
         {
             m_pTimerH.Dispose();
             m_pTimerH = null;
         }
         if (m_pTimerI != null)
         {
             m_pTimerI.Dispose();
             m_pTimerI = null;
         }
         if (m_pTimerJ != null)
         {
             m_pTimerJ.Dispose();
             m_pTimerJ = null;
         }
     }
 }
Esempio n. 5
0
        /// <summary>
        /// Starts SMTP relay server.
        /// </summary>
        /// <exception cref="ObjectDisposedException">Is raised when this object is disposed and this method is accessed.</exception>
        public virtual void Start()
        {
            if (m_IsDisposed)
            {
                throw new ObjectDisposedException(this.GetType().Name);
            }
            if (m_IsRunning)
            {
                return;
            }
            m_IsRunning = true;

            m_pLocalEndPointIPv4 = new CircleCollection <IPBindInfo>();
            m_pLocalEndPointIPv6 = new CircleCollection <IPBindInfo>();
            m_pSessions          = new TCP_SessionCollection <Relay_Session>();
            m_pConnectionsPerIP  = new Dictionary <IPAddress, long>();

            Thread tr1 = new Thread(new ThreadStart(this.Run));

            tr1.Start();

            m_pTimerTimeout          = new TimerEx(30000);
            m_pTimerTimeout.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimerTimeout_Elapsed);
            m_pTimerTimeout.Start();
        }
Esempio n. 6
0
        /// <summary>
        /// Starts transaction processing.
        /// </summary>
        private void Start()
        {
            #region INVITE

            if (Method == SIP_Methods.INVITE)
            {
                /* RFC 3261 17.2.1.
                 *  When a server transaction is constructed for a request, it enters the "Proceeding" state. The server
                 *  transaction MUST generate a 100 (Trying) response unless it knows that the TU will generate a provisional
                 *  or final response within 200 ms, in which case it MAY generate a 100 (Trying) response.
                 */

                SetState(SIP_TransactionState.Proceeding);

                m_pTimer100          = new TimerEx(200, false);
                m_pTimer100.Elapsed += m_pTimer100_Elapsed;
                m_pTimer100.Enabled  = true;
            }

            #endregion

            #region Non-INVITE

            else
            {
                // RFC 3261 17.2.2. The state machine is initialized in the "Trying" state.
                SetState(SIP_TransactionState.Trying);
            }

            #endregion
        }
        /// <summary>
        /// Is raised when Non-INVITE timer F triggered.
        /// </summary>
        /// <param name="sender">Sender.</param>
        /// <param name="e">Event data.</param>
        private void m_pTimerF_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            /* RFC 3261 17.1.2.2.
             *  If Timer F fires while in the "Trying" state, the client transaction SHOULD inform the TU about the
             *  timeout, and then it SHOULD enter the "Terminated" state.
             *
             *  If timer F fires while in the "Proceeding" state, the TU MUST be informed of a timeout, and the
             *  client transaction MUST transition to the terminated state.
             */

            lock (this.SyncRoot){
                if (this.State == SIP_TransactionState.Trying || this.State == SIP_TransactionState.Proceeding)
                {
                    // Log
                    if (this.Stack.Logger != null)
                    {
                        this.Stack.Logger.AddText(this.ID, "Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=false] timer F(Non-INVITE trying,proceeding state timeout) triggered.");
                    }

                    OnTimedOut();
                    SetState(SIP_TransactionState.Terminated);

                    if (m_pTimerE != null)
                    {
                        m_pTimerE.Dispose();
                        m_pTimerE = null;
                    }
                    if (m_pTimerF != null)
                    {
                        m_pTimerF.Dispose();
                        m_pTimerF = null;
                    }
                }
            }
        }
Esempio n. 8
0
        /// <summary>
        /// Default constructor.
        /// </summary>
        internal DNS_ClientCache()
        {
            m_pCache = new Dictionary<string,CacheEntry>();

            m_pTimerTimeout = new TimerEx(60000);
            m_pTimerTimeout.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimerTimeout_Elapsed);
            m_pTimerTimeout.Start();
        }
Esempio n. 9
0
        /// <summary>
        /// Default constructor.
        /// </summary>
        internal DNS_ClientCache()
        {
            m_pCache = new Dictionary <string, CacheEntry>();

            m_pTimerTimeout          = new TimerEx(60000);
            m_pTimerTimeout.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimerTimeout_Elapsed);
            m_pTimerTimeout.Start();
        }
Esempio n. 10
0
 public void InitTimer()
 {
     productionTimer = TimerEx.Init("Production ", 1.0f, OnProductionTimer, true);
     if (productionTimer != null)
     {
         productionTimer.Pause();
     }
 }
    static void Main(string[] args)
    {
        TimerEx timer = new TimerEx(1000, 1, 2, 3, 4, 5);

        timer.ElapsedEx += new ElapsedExEventHandler(timer_ElapsedEx);
        timer.Start();

        Console.ReadKey();
    }
Esempio n. 12
0
        public DateFileAppender()
        {
            BaseDir  = "Logs";
            Encoding = Encoding.UTF8;
            Pattern  = $"yyyy{Path.DirectorySeparatorChar}yyyy-MM-dd.'txt'";

            timer          = new TimerEx(this.WriteInterval);
            timer.Elapsed += WriteTimer_Elapsed;
        }
Esempio n. 13
0
        /// <summary>
        /// Starts this server.
        /// </summary>
        /// <exception cref="ObjectDisposedException">Is raised when this object is disposed and this property is accessed.</exception>
        public void Start()
        {
            ThrowIfObjectDisposed();

            if (m_IsRunning)
            {
                return;
            }

            m_IsRunning            = true;
            m_StartTime            = DateTime.Now;
            m_ConnectionsProcessed = 0;

            ThreadPool.QueueUserWorkItem((o) =>
            {
                StartListen();
            });


            m_pTimer_IdleTimeout          = new TimerEx(30 * 1000); // 30s
            m_pTimer_IdleTimeout.Elapsed += (sender, e) =>
            {
                try
                {
                    foreach (T session in this.Sessions.ToArray())
                    {
                        try
                        {
                            if (m_SessionIdleTimeout > 0 &&
                                DateTime.Now > session.TcpStream.LastActivity.AddSeconds(m_SessionIdleTimeout))
                            {
                                session.OnTimeout();

                                // Session didn't dispose itself, so dispose it.
                                if (!session.IsDisposed)
                                {
                                    session.Disconnect();
                                    session.Dispose();
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            // just skip.
                            string dummy = ex.Message;
                        }
                    }
                }
                catch (Exception ex)
                { OnError(ex); }
            };

            OnStarted();
        }
        /// <summary>
        /// Cleans up any resources being used.
        /// </summary>
        public override void Dispose()
        {
            lock (this.SyncRoot){
                if (this.IsDisposed)
                {
                    return;
                }

                // Log
                if (this.Stack.Logger != null)
                {
                    this.Stack.Logger.AddText(this.ID, "Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=false] disposed.");
                }

                // Kill timers.
                if (m_pTimerA != null)
                {
                    m_pTimerA.Dispose();
                    m_pTimerA = null;
                }
                if (m_pTimerB != null)
                {
                    m_pTimerB.Dispose();
                    m_pTimerB = null;
                }
                if (m_pTimerD != null)
                {
                    m_pTimerD.Dispose();
                    m_pTimerD = null;
                }
                if (m_pTimerE != null)
                {
                    m_pTimerE.Dispose();
                    m_pTimerE = null;
                }
                if (m_pTimerF != null)
                {
                    m_pTimerF.Dispose();
                    m_pTimerF = null;
                }
                if (m_pTimerK != null)
                {
                    m_pTimerK.Dispose();
                    m_pTimerK = null;
                }

                this.ResponseReceived = null;

                base.Dispose();
            }
        }
Esempio n. 15
0
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            #region 写真をリスト化する

            CreatePhotoList();

            #endregion

            #region 背景用のビットマップを作成、背景は黒で初期化

            _baseBitmap = new Bitmap(Width, Height, PixelFormat.Format24bppRgb);
            _baseBitmap.Clear(Color.Black);

            #endregion

            #region 背景のスクロール用のタイマーを作成

            _baseTimer = new TimerEx {
                Interval = ScrollInterval
            };
            _baseTimer.Tick += BaseTimerOnTick;

            #endregion

            #region 写真を追加するタイマーを作成

            _photoTimer = new TimerEx {
                Interval = PhotoInterval
            };
            _photoTimer.Tick += PhotoTimerOnTick;

            #endregion

            #region 最初の写真を登録

            // 写真を追加するタイマーの間隔が長いため、
            // 先にイベントを呼び出し写真を登録しておく
            PhotoTimerOnTick(this, EventArgs.Empty);

            #endregion

            #region 背景のスクロール用のタイマーと、写真読み込み用のタイマーを起動する

            _baseTimer.Start();
            _photoTimer.Start();

            #endregion
        }
Esempio n. 16
0
            /// <summary>
            /// Cleans up any resource being used.
            /// </summary>
            public void Dispose()
            {
                m_pTimeoutTimer.Dispose();
                m_pTimeoutTimer = null;

                m_pOwner.m_pTransactions.Remove(this.ID);
                m_pOwner = null;

                m_pQuery    = null;
                m_pResponse = null;

                this.Timeout   = null;
                this.Completed = null;
            }
        /// <summary>
        /// Cleans up nay resource being used.
        /// </summary>
        public void Dispose()
        {
            if (m_pNonces == null)
            {
                m_pNonces.Clear();
                m_pNonces = null;
            }

            if (m_pTimer != null)
            {
                m_pTimer.Dispose();
                m_pTimer = null;
            }
        }
Esempio n. 18
0
            /// <summary>
            /// Default constructor.
            /// </summary>
            /// <param name="owner">Owner transport layer.</param>
            /// <exception cref="ArgumentNullException">Is raised when <b>owner</b> is null reference.</exception>
            internal SIP_FlowManager(SIP_TransportLayer owner)
            {
                if(owner == null){
                    throw new ArgumentNullException("owner");
                }

                m_pOwner = owner;

                m_pFlows = new Dictionary<string,SIP_Flow>();

                m_pTimeoutTimer = new TimerEx(15000);
                m_pTimeoutTimer.AutoReset = true;
                m_pTimeoutTimer.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimeoutTimer_Elapsed);
                m_pTimeoutTimer.Enabled = true;
            }
Esempio n. 19
0
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="proxy">Owner proxy.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>proxy</b> is null reference.</exception>
        internal SIP_Registrar(SIP_Proxy proxy)
        {
            if (proxy == null)
            {
                throw new ArgumentNullException("proxy");
            }

            m_pProxy = proxy;
            m_pStack = m_pProxy.Stack;

            m_pRegistrations = new SIP_RegistrationCollection();

            m_pTimer = new TimerEx(m_pTimer_Elapsed, 15000);
            m_pTimer.Start();
        }
Esempio n. 20
0
        public void Dispose()
        {
            if (IsDisposed)
            {
                return;
            }

            IsDisposed = true;

            ClearTimer.Stop();
            ClearTimer = null;

            ItemsByKey.Clear();
            ItemsByKey = null;
        }
Esempio n. 21
0
        public MemoryCache(int capacity = 100000)
        {
            if (capacity < 1000)
            {
                throw new ArgumentException($"Argument '{nameof(capacity)}' value must be >= 1000.");
            }

            MaxCapacity = capacity;
            ItemsByKey  = new Dictionary <string, MemoryCacheItem>(capacity);

            First = Last = new MemoryCacheItem();

            ClearTimer          = new TimerEx(60 * 1000);
            ClearTimer.Elapsed += Clear_Elapsed;
            ClearTimer.Start();
        }
        /// <summary>
        /// Cleans up any resources being used.
        /// </summary>
        public override void Dispose()
        {
            lock(this.SyncRoot){
                if(this.IsDisposed){
                    return;
                }

                // Log
                if(this.Stack.Logger != null){
                    this.Stack.Logger.AddText(this.ID,"Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=false] disposed.");
                }                               
                
                // Kill timers.
                if(m_pTimerA != null){
                    m_pTimerA.Dispose();
                    m_pTimerA = null;
                }
                if(m_pTimerB != null){
                    m_pTimerB.Dispose();
                    m_pTimerB = null;
                }
                if(m_pTimerD != null){
                    m_pTimerD.Dispose();
                    m_pTimerD = null;
                }
                if(m_pTimerE != null){
                    m_pTimerE.Dispose();
                    m_pTimerE = null;
                }
                if(m_pTimerF != null){
                    m_pTimerF.Dispose();
                    m_pTimerF = null;
                }
                if(m_pTimerK != null){
                    m_pTimerK.Dispose();
                    m_pTimerK = null;
                }
                if(m_pTimerM != null){
                    m_pTimerM.Dispose();
                    m_pTimerM = null;
                }

                this.ResponseReceived = null;

                base.Dispose();
            }
        }
Esempio n. 23
0
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="currentNodeName">当前节点名称</param>
        public ProcessNamedPipe(string currentNodeName)
        {
            _mutex = new Mutex(true, currentNodeName, out var isSuccess);

            if (!isSuccess)
            {
                throw new ArgumentOutOfRangeException("currentNodeName", "指定名称的管道已被注册,无法重复注册");
            }

            _pipName = currentNodeName;

            beginwaitForConnection();

            _checkConnect = new TimerEx(checkServer, 5000, 0);

            _checkConnect.Start();
        }
        /// <summary>
        /// Is raised when INVITE 100 (Trying) response must be sent if no response sent by transaction user.
        /// </summary>
        /// <param name="sender">Sender.</param>
        /// <param name="e">Event data.</param>
        private void m_pTimer100_Elapsed(object sender, ElapsedEventArgs e)
        {
            lock (SyncRoot)
            {
                // RFC 3261 17.2.1. TU didn't generate response in 200 ms, send '100 Trying' to stop request retransmission.
                if (State == SIP_TransactionState.Proceeding && Responses.Length == 0)
                {
                    /* RFC 3261 17.2.1.
                     *  The 100 (Trying) response is constructed according to the procedures in Section 8.2.6, except that the
                     *  insertion of tags in the To header field of the response (when none was present in the request)
                     *  is downgraded from MAY to SHOULD NOT.
                     *
                     * RFC 3261 8.2.6.
                     *  When a 100 (Trying) response is generated, any Timestamp header field present in the request MUST
                     *  be copied into this 100 (Trying) response. If there is a delay in generating the response, the UAS
                     *  SHOULD add a delay value into the Timestamp value in the response. This value MUST contain the difference
                     *  between the time of sending of the response and receipt of the request, measured in seconds.
                     */

                    SIP_Response tryingResponse = Stack.CreateResponse(SIP_ResponseCodes.x100_Trying, Request);
                    if (Request.Timestamp != null)
                    {
                        tryingResponse.Timestamp = new SIP_t_Timestamp(Request.Timestamp.Time,
                                                                       (DateTime.Now - CreateTime).Seconds);
                    }

                    try
                    {
                        Stack.TransportLayer.SendResponse(this, tryingResponse);
                    }
                    catch (Exception x)
                    {
                        OnTransportError(x);
                        SetState(SIP_TransactionState.Terminated);
                        return;
                    }
                }

                if (m_pTimer100 != null)
                {
                    m_pTimer100.Dispose();
                    m_pTimer100 = null;
                }
            }
        }
Esempio n. 25
0
            /// <summary>
            /// Cleans up any resources being used.
            /// </summary>
            public void Dispose()
            {
                lock(m_pLock){
                    if(m_IsDisposed){
                        return;
                    }
                    m_IsDisposed = true;

                    foreach(SIP_Flow flow in this.Flows){
                        flow.Dispose();
                    }

                    m_pOwner = null;
                    m_pFlows = null;
                    m_pTimeoutTimer.Dispose();
                    m_pTimeoutTimer = null;
                }
            }
Esempio n. 26
0
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="owner">Owner DNS client.</param>
        /// <param name="id">Transaction ID.</param>
        /// <param name="qtype">QTYPE value.</param>
        /// <param name="qname">QNAME value.</param>
        /// <param name="timeout">Timeout in milliseconds.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>owner</b> or <b>qname</b> is null reference.</exception>
        internal DNS_ClientTransaction(Dns_Client owner,int id,DNS_QType qtype,string qname,int timeout)
        {
            if(owner == null){
                throw new ArgumentNullException("owner");
            }
            if(qname == null){
                throw new ArgumentNullException("qname");
            }

            m_pOwner = owner;
            m_ID     = id;
            m_QName  = qname;
            m_QType  = qtype;
                        
            m_CreateTime    = DateTime.Now;
            m_pTimeoutTimer = new TimerEx(timeout);
            m_pTimeoutTimer.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimeoutTimer_Elapsed);
        }
        public SessionHandler()
        {
            var procAct = new Action(() =>
            {
                var now = DateTime.UtcNow;
                if (IsGameRunning())
                {
                    if (_startSessionTime <= DateTime.MinValue)
                    {
                        _startSessionTime = now;
                    }
                    _lastSessionTime = now;
                }
            });

            procAct.Invoke();
            TimerEx.Every(1f, procAct);
        }
Esempio n. 28
0
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="owner">Owner DNS client.</param>
        /// <param name="id">Transaction ID.</param>
        /// <param name="qtype">QTYPE value.</param>
        /// <param name="qname">QNAME value.</param>
        /// <param name="timeout">Timeout in milliseconds.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>owner</b> or <b>qname</b> is null reference.</exception>
        internal DNS_ClientTransaction(Dns_Client owner, int id, DNS_QType qtype, string qname, int timeout)
        {
            if (owner == null)
            {
                throw new ArgumentNullException("owner");
            }
            if (qname == null)
            {
                throw new ArgumentNullException("qname");
            }

            m_pOwner = owner;
            m_ID     = id;
            m_QName  = qname;
            m_QType  = qtype;

            m_CreateTime             = DateTime.Now;
            m_pTimeoutTimer          = new TimerEx(timeout);
            m_pTimeoutTimer.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimeoutTimer_Elapsed);
        }
Esempio n. 29
0
            /// <summary>
            /// Cleans up any resources being used.
            /// </summary>
            public void Dispose()
            {
                lock (m_pLock){
                    if (m_IsDisposed)
                    {
                        return;
                    }
                    m_IsDisposed = true;

                    m_pDialog.m_pUasInvite2xxRetransmits.Remove(this);

                    if (m_pTimer != null)
                    {
                        m_pTimer.Dispose();
                        m_pTimer = null;
                    }
                    m_pDialog   = null;
                    m_pResponse = null;
                }
            }
Esempio n. 30
0
        /// <summary>
        /// Cleans up any resource being used.
        /// </summary>
        public void Dispose()
        {
            lock(m_pLock){
                if(this.State == DNS_ClientTransactionState.Disposed){
                    return;
                }

                SetState(DNS_ClientTransactionState.Disposed);

                m_pTimeoutTimer.Dispose();
                m_pTimeoutTimer = null;

                m_pOwner = null;

                m_pResponse = null;

                this.StateChanged = null;
                this.Timeout = null;
            }
        }
        /// <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();

            this.Registered   = null;
            this.Unregistered = null;
            this.Error        = null;
            this.Disposed     = null;
        }
Esempio n. 32
0
            /// <summary>
            /// Default constructor.
            /// </summary>
            /// <param name="owner">Owner DNS client.</param>
            /// <param name="id">Transaction ID.</param>
            /// <param name="qname">QNAME value.</param>
            /// <param name="qtype">QTYPE value.</param>
            /// <param name="timeout">Timeout in milliseconds.</param>
            /// <param name="query">Raw DNS query.</param>
            /// <exception cref="ArgumentNullException">Is raised when <b>owner</b> or <b>query</b> is null reference.</exception>
            public DnsTransaction(Dns_Client owner, int id, string qname, int qtype, int timeout, byte[] query)
            {
                if (owner == null)
                {
                    throw new ArgumentNullException("owner");
                }
                if (query == null)
                {
                    throw new ArgumentNullException("query");
                }

                m_pOwner = owner;
                m_ID     = id;
                m_pQuery = query;
                m_QName  = qname;
                m_QType  = qtype;

                m_CreateTime             = DateTime.Now;
                m_pTimeoutTimer          = new TimerEx(timeout);
                m_pTimeoutTimer.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimeoutTimer_Elapsed);
            }
Esempio n. 33
0
        /// <summary>
        /// Cleans up any resource being used.
        /// </summary>
        public void Dispose()
        {
            lock (m_pLock){
                if (this.State == DNS_ClientTransactionState.Disposed)
                {
                    return;
                }

                SetState(DNS_ClientTransactionState.Disposed);

                m_pTimeoutTimer.Dispose();
                m_pTimeoutTimer = null;

                m_pOwner = null;

                m_pResponse = null;

                this.StateChanged = null;
                this.Timeout      = null;
            }
        }
            /// <summary>
            /// Default constructor.
            /// </summary>
            /// <param name="dialog">Owner INVITE dialog.</param>
            /// <param name="invite">INVITE request which 2xx retransmission to wait.</param>
            /// <exception cref="ArgumentNullException">Is raised when <b>dialog</b> or <b>invite</b> is null reference.</exception>
            public UacInvite2xxRetransmissionWaiter(SIP_Dialog_Invite dialog, SIP_Request invite)
            {
                if (dialog == null)
                {
                    throw new ArgumentNullException("dialog");
                }
                if (invite == null)
                {
                    throw new ArgumentNullException("invite");
                }

                m_pDialog = dialog;
                m_pInvite = invite;

                /* RFC 3261 13.2.2.4.
                 *  The UAC core considers the INVITE transaction completed 64*T1 seconds
                 *  after the reception of the first 2xx response.
                 */
                m_pTimer          = new TimerEx(64 * SIP_TimerConstants.T1, false);
                m_pTimer.Elapsed += m_pTimer_Elapsed;
                m_pTimer.Enabled  = true;
            }
Esempio n. 35
0
        /// <summary>
        /// Cleans up any resources being used.
        /// </summary>
        internal void Dispose()
        {
            if (m_IsDisposed)
            {
                return;
            }
            m_IsDisposed = true;

            this.CanRegister     = null;
            this.AorRegistered   = null;
            this.AorUnregistered = null;
            this.AorUpdated      = null;

            m_pProxy         = null;
            m_pStack         = null;
            m_pRegistrations = null;
            if (m_pTimer != null)
            {
                m_pTimer.Dispose();
                m_pTimer = null;
            }
        }
Esempio n. 36
0
    public static TimerEx Init(string timerName, float interval, CALLBACK callback, bool loop = false, System.Object parameter = null)
    {
        if (_timerRoot == null)
        {
            _timerRoot = new GameObject("TimerSpawn");
            MonoBehaviour.DontDestroyOnLoad(_timerRoot);
        }

        GameObject gameObject = new GameObject(TIMEREX_NAME_PREFIX + timerName);

        MonoBehaviour.DontDestroyOnLoad(gameObject);
        gameObject.transform.parent = _timerRoot.transform;

        TimerEx t = gameObject.AddComponent <TimerEx>();

        if (t != null)
        {
            t.Init(interval, callback, loop, parameter);
            return(t);
        }
        return(null);
    }
            /// <summary>
            /// Default constructor.
            /// </summary>
            /// <param name="dialog">Owner INVITE dialog.</param>
            /// <param name="invite">INVITE request which 2xx retransmission to wait.</param>
            /// <exception cref="ArgumentNullException">Is raised when <b>dialog</b> or <b>invite</b> is null reference.</exception>
            public UacInvite2xxRetransmissionWaiter(SIP_Dialog_Invite dialog, SIP_Request invite)
            {
                if (dialog == null)
                {
                    throw new ArgumentNullException("dialog");
                }
                if (invite == null)
                {
                    throw new ArgumentNullException("invite");
                }

                m_pDialog = dialog;
                m_pInvite = invite;

                /* RFC 3261 13.2.2.4.
                    The UAC core considers the INVITE transaction completed 64*T1 seconds
                    after the reception of the first 2xx response.
                */
                m_pTimer = new TimerEx(64*SIP_TimerConstants.T1, false);
                m_pTimer.Elapsed += m_pTimer_Elapsed;
                m_pTimer.Enabled = true;
            }
Esempio n. 38
0
        /// <summary>
        /// Stops this server, all active connections will be terminated.
        /// </summary>
        /// <exception cref="ObjectDisposedException">Is raised when this object is disposed and this property is accessed.</exception>
        public void Stop()
        {
            ThrowIfObjectDisposed();

            if (!m_IsRunning)
            {
                return;
            }

            m_IsRunning = false;

            // Dispose all old TCP acceptors.
            foreach (var acceptor in m_pConnectionAcceptors.ToArray())
            {
                try
                { acceptor.Dispose(); }
                catch (Exception ex)
                { OnError(ex); }
            }
            m_pConnectionAcceptors.Clear();


            // Dispose all old binds.
            foreach (var listeningPoint in m_pListeningPoints.ToArray())
            {
                try
                { listeningPoint.Socket.Dispose(); }
                catch (Exception ex)
                { OnError(ex); }
            }
            m_pListeningPoints.Clear();


            m_pTimer_IdleTimeout.Stop();
            m_pTimer_IdleTimeout.Dispose();
            m_pTimer_IdleTimeout = null;

            OnStopped();
        }
        /// <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;
        }
Esempio n. 40
0
            /// <summary>
            /// Starts IDLE command processing.
            /// </summary>
            private void Start()
            {
                /* RFC 2177 IDLE command example.
                    C: A004 IDLE
                    S: * 2 EXPUNGE
                    S: * 3 EXISTS
                    S: + idling
                    ...time passes; another client expunges message 3...
                    S: * 3 EXPUNGE
                    S: * 2 EXISTS
                    ...time passes; new mail arrives...
                    S: * 3 EXISTS
                    C: DONE
                    S: A004 OK IDLE terminated
                */

                // Send status reponse to connected client if any.
                m_pSession.ProcessMailboxChanges(folder);

                // Send "+ idling" to connected client.
                m_pSession.WriteLine("+ idling");


                // Start timer to poll mailbox changes.
                m_pSession.FolderChanged += m_pSession_FolderChanged;

                m_pTimer = new TimerEx(5000, true);
                m_pTimer.Elapsed += m_pTimer_Elapsed;
                m_pTimer.Enabled = true;

                // Start waiting DONE command from connected client.
                m_pSession.ReadAsync(ReadLineCompleted);
            }
        /// <summary>
        /// Is raised when INVITE timer B triggered.
        /// </summary>
        /// <param name="sender">Sender.</param>
        /// <param name="e">Event data.</param>
        private void m_pTimerB_Elapsed(object sender,System.Timers.ElapsedEventArgs e)
        {
            /* RFC 3261 17.1.1.2.
                If the client transaction is still in the "Calling" state when timer
                B fires, the client transaction SHOULD inform the TU that a timeout
                has occurred.  The client transaction MUST NOT generate an ACK.  The
                value of 64*T1 is equal to the amount of time required to send seven
                requests in the case of an unreliable transport.
            */

            lock(this.SyncRoot){
                if(this.State == SIP_TransactionState.Calling){
                    // Log
                    if(this.Stack.Logger != null){
                        this.Stack.Logger.AddText(this.ID,"Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=false] timer B(INVITE calling state timeout) triggered.");
                    }

                    OnTimedOut();
                    SetState(SIP_TransactionState.Terminated);

                    // Stop timers A,B.
                    if(m_pTimerA != null){
                        m_pTimerA.Dispose();
                        m_pTimerA = null;
                    }
                    if(m_pTimerB != null){
                        m_pTimerB.Dispose();
                        m_pTimerB = null;
                    }                   
                }
            }
        }
Esempio n. 42
0
        private bool IDLE(string cmdTag,string cmdText)
        {
            /* RFC 2177 3. IDLE Command.
                Arguments:  none

                Responses:  continuation data will be requested; the client sends
                            the continuation data "DONE" to end the command

                Result:     OK - IDLE completed after client sent "DONE"
                            NO - failure: the server will not allow the IDLE
                            command at this time
                BAD - command unknown or arguments invalid

                The IDLE command may be used with any IMAP4 server implementation
                that returns "IDLE" as one of the supported capabilities to the
                CAPABILITY command.  If the server does not advertise the IDLE
                capability, the client MUST NOT use the IDLE command and must poll
                for mailbox updates.  In particular, the client MUST continue to be
                able to accept unsolicited untagged responses to ANY command, as
                specified in the base IMAP specification.

                The IDLE command is sent from the client to the server when the
                client is ready to accept unsolicited mailbox update messages.  The
                server requests a response to the IDLE command using the continuation
                ("+") response.  The IDLE command remains active until the client
                responds to the continuation, and as long as an IDLE command is
                active, the server is now free to send untagged EXISTS, EXPUNGE, and
                other messages at any time.

                The IDLE command is terminated by the receipt of a "DONE"
                continuation from the client; such response satisfies the server's
                continuation request.  At that point, the server MAY send any
                remaining queued untagged responses and then MUST immediately send
                the tagged response to the IDLE command and prepare to process other
                commands. As in the base specification, the processing of any new
                command may cause the sending of unsolicited untagged responses,
                subject to the ambiguity limitations.  The client MUST NOT send a
                command while the server is waiting for the DONE, since the server
                will not be able to distinguish a command from a continuation.

                The server MAY consider a client inactive if it has an IDLE command
                running, and if such a server has an inactivity timeout it MAY log
                the client off implicitly at the end of its timeout period.  Because
                of that, clients using IDLE are advised to terminate the IDLE and
                re-issue it at least every 29 minutes to avoid being logged off.
                This still allows a client to receive immediate mailbox updates even
                though it need only "poll" at half hour intervals.

                Example:    C: A001 SELECT INBOX
                            S: * FLAGS (Deleted Seen)
                            S: * 3 EXISTS
                            S: * 0 RECENT
                            S: * OK [UIDVALIDITY 1]
                            S: A001 OK SELECT completed
                            C: A002 IDLE
                            S: + idling
                            ...time passes; new mail arrives...
                            S: * 4 EXISTS
                            C: DONE
                            S: A002 OK IDLE terminated
                            ...another client expunges message 2 now...
                            C: A003 FETCH 4 ALL
                            S: * 4 FETCH (...)
                            S: A003 OK FETCH completed
                            C: A004 IDLE
                            S: * 2 EXPUNGE
                            S: * 3 EXISTS
                            S: + idling
                            ...time passes; another client expunges message 3...
                            S: * 3 EXPUNGE
                            S: * 2 EXISTS
                            ...time passes; new mail arrives...
                            S: * 3 EXISTS
                            C: DONE
                            S: A004 OK IDLE terminated
                            C: A005 FETCH 3 ALL
                            S: * 3 FETCH (...)
                            S: A005 OK FETCH completed
            */

            if(!this.IsAuthenticated){
                m_pResponseSender.SendResponseAsync(new IMAP_r_ServerStatus(cmdTag,"NO","Authentication required."));

                return true;
            }

            m_pResponseSender.SendResponseAsync(new IMAP_r_ServerStatus("+","idling"));

            TimerEx timer = new TimerEx(30000,true);
            timer.Elapsed += new System.Timers.ElapsedEventHandler(delegate(object sender,System.Timers.ElapsedEventArgs e){
                try{
                    UpdateSelectedFolderAndSendChanges();
                }
                catch{
                }
            });
            timer.Enabled = true;

            // Read client response. 
            SmartStream.ReadLineAsyncOP readLineOP = new SmartStream.ReadLineAsyncOP(new byte[32000],SizeExceededAction.JunkAndThrowException);
            readLineOP.Completed += new EventHandler<EventArgs<SmartStream.ReadLineAsyncOP>>(delegate(object sender,EventArgs<SmartStream.ReadLineAsyncOP> e){
                try{
                    if(readLineOP.Error != null){
                        LogAddText("Error: " + readLineOP.Error.Message);
                        timer.Dispose();

                        return;
                    }
                    // Remote host closed connection.
                    else if(readLineOP.BytesInBuffer == 0){
                        LogAddText("Remote host(connected client) closed IMAP connection.");
                        timer.Dispose();
                        Dispose();

                        return;
                    }

                    LogAddRead(readLineOP.BytesInBuffer,readLineOP.LineUtf8);

                    if(string.Equals(readLineOP.LineUtf8,"DONE",StringComparison.InvariantCultureIgnoreCase)){
                        timer.Dispose();

                        m_pResponseSender.SendResponseAsync(new IMAP_r_ServerStatus(cmdTag,"OK","IDLE terminated."));
                        BeginReadCmd();
                    }
                    else{
                        while(this.TcpStream.ReadLine(readLineOP,true)){
                            if(readLineOP.Error != null){
                                LogAddText("Error: " + readLineOP.Error.Message);
                                timer.Dispose();

                                return;
                            }
                            LogAddRead(readLineOP.BytesInBuffer,readLineOP.LineUtf8);

                            if(string.Equals(readLineOP.LineUtf8,"DONE",StringComparison.InvariantCultureIgnoreCase)){
                                timer.Dispose();

                                m_pResponseSender.SendResponseAsync(new IMAP_r_ServerStatus(cmdTag,"OK","IDLE terminated."));
                                BeginReadCmd();

                                break;
                            }
                        }
                    }
                }
                catch(Exception x){
                    timer.Dispose();

                    OnError(x);
                }
            });
            while(this.TcpStream.ReadLine(readLineOP,true)){
                if(readLineOP.Error != null){
                    LogAddText("Error: " + readLineOP.Error.Message);
                    timer.Dispose();

                    break;
                }

                LogAddRead(readLineOP.BytesInBuffer,readLineOP.LineUtf8);

                if(string.Equals(readLineOP.LineUtf8,"DONE",StringComparison.InvariantCultureIgnoreCase)){
                    timer.Dispose();

                    m_pResponseSender.SendResponseAsync(new IMAP_r_ServerStatus(cmdTag,"OK","IDLE terminated."));
                    BeginReadCmd();

                    break;
                }                
            }
            
            return false;            
        }
        /// <summary>
        /// Is raised when Non-INVITE timer F triggered.
        /// </summary>
        /// <param name="sender">Sender.</param>
        /// <param name="e">Event data.</param>
        private void m_pTimerF_Elapsed(object sender,System.Timers.ElapsedEventArgs e)
        {
            /* RFC 3261 17.1.2.2.
                If Timer F fires while in the "Trying" state, the client transaction SHOULD inform the TU about the
                timeout, and then it SHOULD enter the "Terminated" state.
            
                If timer F fires while in the "Proceeding" state, the TU MUST be informed of a timeout, and the
                client transaction MUST transition to the terminated state.
            */

            lock(this.SyncRoot){
                if(this.State == SIP_TransactionState.Trying || this.State == SIP_TransactionState.Proceeding){
                    // Log
                    if(this.Stack.Logger != null){
                        this.Stack.Logger.AddText(this.ID,"Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=false] timer F(Non-INVITE trying,proceeding state timeout) triggered.");
                    }

                    OnTimedOut();

                    // User Disposed this transaction in TimedOut
                    if(this.State == SIP_TransactionState.Disposed){
                        // Do nothing.
                    }
                    // Switch to terminated state.
                    else{
                        SetState(SIP_TransactionState.Terminated);

                        if(m_pTimerE != null){
                             m_pTimerE.Dispose();
                            m_pTimerE = null;
                        }
                        if(m_pTimerF != null){
                             m_pTimerF.Dispose();
                            m_pTimerF = null;
                        }
                    }
                }
            }
        }
Esempio n. 44
0
            /// <summary>
            /// Cleans up any resources being used.
            /// </summary>
            /// 
            public void Dispose()
            {
                if (m_IsDisposed)
                {
                    return;
                }
                m_IsDisposed = true;
                try
                {
                    m_pTimer.Stop();
                    m_pSession.FolderChanged -= m_pSession_FolderChanged;
                    m_pSession.m_pIDLE = null;
                    m_pSession = null;
                    m_pTimer.Dispose();
                    m_pTimer = null;

                }
                catch (Exception)
                {
                    
                }
            }
        /// <summary>
        /// Processes specified request through this transaction.
        /// </summary>
        /// <param name="flow">SIP data flow.</param>
        /// <param name="request">SIP request.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>flow</b> or <b>request</b> is null reference.</exception>
        internal void ProcessRequest(SIP_Flow flow,SIP_Request request)
        {
            if(flow == null){
                throw new ArgumentNullException("flow");
            }
            if(request == null){
                throw new ArgumentNullException("request");
            }

            lock(this.SyncRoot){
                if(this.State == SIP_TransactionState.Disposed){
                    return;
                }

                try{
                    // Log
                    if(this.Stack.Logger != null){
                        byte[] requestData = request.ToByteData();

                        this.Stack.Logger.AddRead(
                            Guid.NewGuid().ToString(),
                            null,
                            0,
                            "Request [transactionID='" +  this.ID + "'; method='" + request.RequestLine.Method + "'; cseq='" + request.CSeq.SequenceNumber + "'; " + 
                            "transport='" + flow.Transport + "'; size='" + requestData.Length + "'; received '" + flow.LocalEP + "' <- '" + flow.RemoteEP + "'.",
                            flow.LocalEP,
                            flow.RemoteEP,
                            requestData
                        );
                    }

                    #region INVITE

                    if(this.Method == SIP_Methods.INVITE){
                        #region INVITE

                        if(request.RequestLine.Method == SIP_Methods.INVITE){
                            if(this.State == SIP_TransactionState.Proceeding){
                                /* RFC 3261 17.2.1.
                                    If a request retransmission is received while in the "Proceeding" state, the most recent provisional 
                                    response that was received from the TU MUST be passed to the transport layer for retransmission.
                                */
                                SIP_Response response = this.LastProvisionalResponse;
                                if(response != null){
                                    this.Stack.TransportLayer.SendResponse(this,response);
                                }
                            }
                            else if(this.State == SIP_TransactionState.Completed){
                                /* RFC 3261 17.2.1.
                                    While in the "Completed" state, if a request retransmission is received, the server SHOULD 
                                    pass the response to the transport for retransmission.
                                */                                
                                this.Stack.TransportLayer.SendResponse(this,this.FinalResponse);
                            }
                        }

                        #endregion

                        #region ACK

                        else if(request.RequestLine.Method == SIP_Methods.ACK){
                            #region Accepeted

                            if(this.State == SIP_TransactionState.Accpeted){
                                
                            }

                            #endregion

                            #region Completed

                            else if(this.State == SIP_TransactionState.Completed){
                                /* RFC 3261 17.2.1
                                    If an ACK is received while the server transaction is in the "Completed" state, the server transaction 
                                    MUST transition to the "Confirmed" state.  As Timer G is ignored in this state, any retransmissions of the 
                                    response will cease.
                         
                                    When this state is entered, timer I is set to fire in T4 seconds for unreliable transports, 
                                    and zero seconds for reliable transports.
                                */

                                SetState(SIP_TransactionState.Confirmed);

                                // Stop timers G,H
                                if(m_pTimerG != null){
                                    m_pTimerG.Dispose();
                                    m_pTimerG = null;

                                    // Log
                                    if(this.Stack.Logger != null){
                                        this.Stack.Logger.AddText(this.ID,"Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=true] timer G(INVITE response(3xx - 6xx) retransmission) stopped.");
                                    }
                                }
                                if(m_pTimerH != null){
                                    m_pTimerH.Dispose();
                                    m_pTimerH = null;

                                    // Log
                                    if(this.Stack.Logger != null){
                                        this.Stack.Logger.AddText(this.ID,"Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=true] timer H(INVITE ACK wait) stopped.");
                                    }
                                }

                                // Start timer I.
                                m_pTimerI = new TimerEx((flow.IsReliable ? 0 : SIP_TimerConstants.T4),false);
                                m_pTimerI.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimerI_Elapsed);
                                // Log
                                if(this.Stack.Logger != null){
                                    this.Stack.Logger.AddText(this.ID,"Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=true] timer I(INVITE ACK retransission wait) started, will trigger after " + m_pTimerI.Interval + ".");
                                }
                                m_pTimerI.Enabled = true;
                            }

                            #endregion
                        }

                        #endregion
                    }

                    #endregion

                    #region Non-INVITE

                    else{
                        // Non-INVITE transaction may have only request retransmission requests.
                        if(this.Method == request.RequestLine.Method){
                            if(this.State == SIP_TransactionState.Proceeding){
                                /* RFC 3261 17.2.2.
                                    If a retransmission of the request is received while in the "Proceeding" state, the most
                                    recently sent provisional response MUST be passed to the transport layer for retransmission.
                                */
                                this.Stack.TransportLayer.SendResponse(this,this.LastProvisionalResponse);
                            }
                            else if(this.State == SIP_TransactionState.Completed){
                                /* RFC 3261 17.2.2.
                                    While in the "Completed" state, the server transaction MUST pass the final response to the transport
                                    layer for retransmission whenever a retransmission of the request is received.
                                */
                                this.Stack.TransportLayer.SendResponse(this,this.FinalResponse);
                            }
                        }
                    }

                    #endregion
                }
                catch(SIP_TransportException x){
                    // Log
                    if(this.Stack.Logger != null){
                        this.Stack.Logger.AddText(this.ID,"Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=true] transport exception: " + x.Message);
                    }

                    OnTransportError(x);
                }
            }
        }
Esempio n. 46
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();

            this.Registered   = null;
            this.Unregistered = null;
            this.Error        = null;
            this.Disposed     = null;
        }
Esempio n. 47
0
        /// <summary>
        /// Cleans up any resources being used.
        /// </summary>
        public void Dispose()
        {
            lock(m_pLock){
                if(m_IsDisposed){
                    return;
                }     
                OnDisposing();
                m_IsDisposed = true;

                if(m_pTcpSession != null){
                    m_pTcpSession.Dispose();
                    m_pTcpSession = null;
                }
                m_pMessage = null;
                if(m_pKeepAliveTimer != null){
                    m_pKeepAliveTimer.Dispose();
                    m_pKeepAliveTimer = null;
                }
            }
        }
        /// <summary>
        /// Sends specified response to remote party.
        /// </summary>
        /// <param name="response">SIP response to send.</param>
        /// <exception cref="ObjectDisposedException">Is raised when this class is Disposed and this method is accessed.</exception>
        /// <exception cref="ArgumentNullException">Is raised when <b>response</b> is null reference.</exception>
        public void SendResponse(SIP_Response response)
        {
            lock(this.SyncRoot){
                if(this.State == SIP_TransactionState.Disposed){
                    throw new ObjectDisposedException(this.GetType().Name);
                }
                if(response == null){
                    throw new ArgumentNullException("response");
                }

                try{
                    #region INVITE

                    /* RFC 6026 7.1. INVITE server transaction. (Udpates RFC 3261)   
                     
                                                             |INVITE
                                                             |pass INV to TU
                                          INVITE             V send 100 if TU won't in 200 ms
                                          send response+------------+
                                              +--------|            |--------+ 101-199 from TU
                                              |        |            |        | send response
                                              +------->|            |<-------+
                                                       | Proceeding |
                                                       |            |--------+ Transport Err.
                                                       |            |        | Inform TU
                                                       |            |<-------+
                                                       +------------+
                                          300-699 from TU |    |2xx from TU
                                          send response   |    |send response
                                           +--------------+    +------------+
                                           |                                |
                          INVITE           V          Timer G fires         |
                          send response +-----------+ send response         |
                               +--------|           |--------+              |
                               |        |           |        |              |
                               +------->| Completed |<-------+      INVITE  |  Transport Err.
                                        |           |               -       |  Inform TU
                               +--------|           |----+          +-----+ |  +---+
                               |        +-----------+    | ACK      |     | v  |   v
                               |          ^   |          | -        |  +------------+
                               |          |   |          |          |  |            |---+ ACK
                               +----------+   |          |          +->|  Accepted  |   | to TU
                               Transport Err. |          |             |            |<--+
                               Inform TU      |          V             +------------+
                                              |      +-----------+        |  ^     |
                                              |      |           |        |  |     |
                                              |      | Confirmed |        |  +-----+
                                              |      |           |        |  2xx from TU
                                Timer H fires |      +-----------+        |  send response
                                -             |          |                |
                                              |          | Timer I fires  |
                                              |          | -              | Timer L fires
                                              |          V                | -
                                              |        +------------+     |
                                              |        |            |<----+
                                              +------->| Terminated |
                                                       |            |
                                                       +------------+

                    */

                    if(this.Method == SIP_Methods.INVITE){
                        #region Proceeding

                        if(this.State == SIP_TransactionState.Proceeding){
                            AddResponse(response);

                            // 1xx
                            if(response.StatusCodeType == SIP_StatusCodeType.Provisional){
                                this.Stack.TransportLayer.SendResponse(this,response);
                                OnResponseSent(response);
                            }
                            // 2xx
                            else if(response.StatusCodeType == SIP_StatusCodeType.Success){
                                this.Stack.TransportLayer.SendResponse(this,response);
                                OnResponseSent(response);
                                SetState(SIP_TransactionState.Accpeted);

                                /* RFC 6025 7.1.
                                    When the "Accepted" state is entered, timer L MUST be set to fire in 64*T1.
                                */
                                m_pTimerL = new TimerEx(64 * SIP_TimerConstants.T1);
                                m_pTimerL.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimerL_Elapsed);
                                m_pTimerL.Enabled = true;

                                // Log
                                if(this.Stack.Logger != null){
                                    this.Stack.Logger.AddText(this.ID,"Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=true] timer L(ACK wait) started, will trigger after " + m_pTimerL.Interval + ".");
                                }
                            }
                            // 3xx - 6xx
                            else{
                                this.Stack.TransportLayer.SendResponse(this,response);
                                OnResponseSent(response);
                                SetState(SIP_TransactionState.Completed);

                                /* RFC 3261 17.2.1.
                                    For unreliable transports, timer G is set to fire in T1 seconds, and is not set to fire for reliable transports.
                                */
                                if(!this.Flow.IsReliable){
                                    m_pTimerG = new TimerEx(SIP_TimerConstants.T1,false);
                                    m_pTimerG.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimerG_Elapsed);
                                    m_pTimerG.Enabled = true;

                                    // Log
                                    if(this.Stack.Logger != null){
                                        this.Stack.Logger.AddText(this.ID,"Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=true] timer G(INVITE response(3xx - 6xx) retransmission) started, will trigger after " + m_pTimerG.Interval + ".");
                                    }
                                }

                                /* RFC 3261 17.2.1.
                                    When the "Completed" state is entered, timer H MUST be set to fire in 64*T1 seconds for all transports.
                                */
                                m_pTimerH = new TimerEx(64 * SIP_TimerConstants.T1);
                                m_pTimerH.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimerH_Elapsed);
                                m_pTimerH.Enabled = true;

                                // Log
                                if(this.Stack.Logger != null){
                                    this.Stack.Logger.AddText(this.ID,"Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=true] timer H(INVITE ACK wait) started, will trigger after " + m_pTimerH.Interval + ".");
                                }
                            }
                        }

                        #endregion

                        #region Accepted

                        else if(this.State == SIP_TransactionState.Accpeted){
                            this.Stack.TransportLayer.SendResponse(this,response);
                            OnResponseSent(response);
                        }

                        #endregion

                        #region Completed

                        else if(this.State == SIP_TransactionState.Completed){
                            // We do nothing here, we just wait ACK to arrive.
                        }

                        #endregion

                        #region Confirmed

                        else if(this.State == SIP_TransactionState.Confirmed){
                            // We do nothing, just wait ACK retransmissions.
                        }

                        #endregion

                        #region Terminated

                        else if(this.State == SIP_TransactionState.Terminated){
                            // We should never rreach here, but if so, skip it.
                        }

                        #endregion
                    }

                    #endregion

                    #region Non-INVITE

                    /* RFC 3261 17.2.2.
                                              |Request received
                                              |pass to TU
                                              V
                                        +-----------+
                                        |           |
                                        | Trying    |-------------+
                                        |           |             |
                                        +-----------+             |200-699 from TU
                                              |                   |send response
                                              |1xx from TU        |
                                              |send response      |
                                              |                   |
                           Request            V      1xx from TU  |
                           send response+-----------+send response|
                               +--------|           |--------+    |
                               |        | Proceeding|        |    |
                               +------->|           |<-------+    |
                        +<--------------|           |             |
                        |Trnsprt Err    +-----------+             |
                        |Inform TU            |                   |
                        |                     |                   |
                        |                     |200-699 from TU    |
                        |                     |send response      |
                        |  Request            V                   |
                        |  send response+-----------+             |
                        |      +--------|           |             |
                        |      |        | Completed |<------------+
                        |      +------->|           |
                        +<--------------|           |
                        |Trnsprt Err    +-----------+
                        |Inform TU            |
                        |                     |Timer J fires
                        |                     |-
                        |                     |
                        |                     V
                        |               +-----------+
                        |               |           |
                        +-------------->| Terminated|
                                        |           |
                                        +-----------+
                    */

                    else{
                        #region Trying

                        if(this.State == SIP_TransactionState.Trying){
                            AddResponse(response);

                            // 1xx
                            if(response.StatusCodeType == SIP_StatusCodeType.Provisional){
                                this.Stack.TransportLayer.SendResponse(this,response);
                                OnResponseSent(response);
                                SetState(SIP_TransactionState.Proceeding);
                            }
                            // 2xx - 6xx
                            else{
                                this.Stack.TransportLayer.SendResponse(this,response);
                                OnResponseSent(response);
                                SetState(SIP_TransactionState.Completed);

                                /* RFC 3261 17.2.2.
                                    When the server transaction enters the "Completed" state, it MUST set
                                    Timer J to fire in 64*T1 seconds for unreliable transports, and zero
                                    seconds for reliable transports.
                                */
                                m_pTimerJ = new TimerEx(64 * SIP_TimerConstants.T1,false);
                                m_pTimerJ.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimerJ_Elapsed);
                                m_pTimerJ.Enabled = true;

                                // Log
                                if(this.Stack.Logger != null){
                                    this.Stack.Logger.AddText(this.ID,"Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=true] timer J(Non-INVITE request retransmission wait) started, will trigger after " + m_pTimerJ.Interval + ".");
                                }
                            }
                        }

                        #endregion

                        #region Proceeding

                        else if(this.State == SIP_TransactionState.Proceeding){
                            AddResponse(response);

                            // 1xx
                            if(response.StatusCodeType == SIP_StatusCodeType.Provisional){
                                this.Stack.TransportLayer.SendResponse(this,response);
                                OnResponseSent(response);
                            }
                            // 2xx - 6xx
                            else{
                                this.Stack.TransportLayer.SendResponse(this,response);
                                OnResponseSent(response);
                                SetState(SIP_TransactionState.Completed);

                                /* RFC 3261 17.2.2.
                                    When the server transaction enters the "Completed" state, it MUST set
                                    Timer J to fire in 64*T1 seconds for unreliable transports, and zero
                                    seconds for reliable transports.
                                */
                                m_pTimerJ = new TimerEx(64 * SIP_TimerConstants.T1,false);
                                m_pTimerJ.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimerJ_Elapsed);
                                m_pTimerJ.Enabled = true;

                                // Log
                                if(this.Stack.Logger != null){
                                    this.Stack.Logger.AddText(this.ID,"Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=true] timer J(Non-INVITE request retransmission wait) started, will trigger after " + m_pTimerJ.Interval + ".");
                                }
                            }
                        }

                        #endregion

                        #region Completed

                        else if(this.State == SIP_TransactionState.Completed){
                            // Do nothing.
                        }

                        #endregion

                        #region Terminated

                        else if(this.State == SIP_TransactionState.Terminated){
                            // Do nothing.
                        }

                        #endregion
                    }

                    #endregion
                }
                catch(SIP_TransportException x){
                    // Log
                    if(this.Stack.Logger != null){
                        this.Stack.Logger.AddText(this.ID,"Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=true] transport exception: " + x.Message);
                    }

                    OnTransportError(x);
                }
            }
        }
        /// <summary>
        /// Starts transaction processing.
        /// </summary>
        /// <exception cref="ObjectDisposedException">Is raised when this class is Disposed and this method is accessed.</exception>
        /// <exception cref="InvalidOperationException">Is raised when <b>Start</b> is called other state than 'WaitingToStart'.</exception>
        public void Start()
        {   
            lock(this.SyncRoot){
                if(this.State == SIP_TransactionState.Disposed){
                    throw new ObjectDisposedException(this.GetType().Name);
                }
                else if(this.State != SIP_TransactionState.WaitingToStart){
                    throw new InvalidOperationException("Start method is valid only in 'WaitingToStart' state.");
                }

                // Move processing to thread pool.
                ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object state){
                    lock(this.SyncRoot){
                        #region INVITE

                        if(this.Method == SIP_Methods.INVITE){
                            /* RFC 3261 17.1.1.2.
                                The initial state, "calling", MUST be entered when the TU
                                initiates a new client transaction with an INVITE request.  The
                                client transaction MUST pass the request to the transport layer for
                                transmission (see Section 18).  If an unreliable transport is being
                                used, the client transaction MUST start timer A with a value of T1.
                                If a reliable transport is being used, the client transaction SHOULD
                                NOT start timer A (Timer A controls request retransmissions).  For
                                any transport, the client transaction MUST start timer B with a value
                                of 64*T1 seconds (Timer B controls transaction timeouts).
                            */

                            SetState(SIP_TransactionState.Calling);

                            try{
                                // Send initial request.
                                this.Stack.TransportLayer.SendRequest(this.Flow,this.Request,this);
                            }
                            catch(Exception x){
                                OnTransportError(x);
                                // NOTE: TransportError event handler could Dispose this transaction, so we need to check it.
                                if(this.State != SIP_TransactionState.Disposed){
                                    SetState(SIP_TransactionState.Terminated);
                                }
                                return;
                            }
                            
                            // Start timer A for unreliable transports.
                            if(!this.Flow.IsReliable){
                                m_pTimerA = new TimerEx(SIP_TimerConstants.T1,false);
                                m_pTimerA.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimerA_Elapsed);
                                m_pTimerA.Enabled = true;

                                // Log
                                if(this.Stack.Logger != null){
                                    this.Stack.Logger.AddText(this.ID,"Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=false] timer A(INVITE request retransmission) started, will trigger after " + m_pTimerA.Interval + ".");
                                }
                            }

                            // Start timer B.
                            m_pTimerB = new TimerEx(64 * SIP_TimerConstants.T1,false);
                            m_pTimerB.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimerB_Elapsed);
                            m_pTimerB.Enabled = true;

                            // Log
                            if(this.Stack.Logger != null){
                                this.Stack.Logger.AddText(this.ID,"Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=false] timer B(INVITE calling state timeout) started, will trigger after " + m_pTimerB.Interval + ".");
                            }
                        }

                        #endregion

                        #region Non-INVITE

                        else{
                            /* RFC 3261 17.1.2.2.
                                The "Trying" state is entered when the TU initiates a new client
                                transaction with a request.  When entering this state, the client
                                transaction SHOULD set timer F to fire in 64*T1 seconds.  The request
                                MUST be passed to the transport layer for transmission.  If an
                                unreliable transport is in use, the client transaction MUST set timer
                                E to fire in T1 seconds.
                            */

                            SetState(SIP_TransactionState.Trying);

                            // Start timer F.
                            m_pTimerF = new TimerEx(64 * SIP_TimerConstants.T1,false);
                            m_pTimerF.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimerF_Elapsed);
                            m_pTimerF.Enabled = true;

                            // Log
                            if(this.Stack.Logger != null){
                                this.Stack.Logger.AddText(this.ID,"Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=false] timer F(Non-INVITE trying,proceeding state timeout) started, will trigger after " + m_pTimerF.Interval + ".");
                            }

                            try{
                                // Send initial request.
                                this.Stack.TransportLayer.SendRequest(this.Flow,this.Request,this);                                 
                            }
                            catch(Exception x){
                                OnTransportError(x);
                                // NOTE: TransportError event handler could Dispose this transaction, so we need to check it.
                                if(this.State != SIP_TransactionState.Disposed){
                                    SetState(SIP_TransactionState.Terminated);
                                }
                                return;
                            }

                            // Start timer E for unreliable transports.
                            if(!this.Flow.IsReliable){ 
                                m_pTimerE = new TimerEx(SIP_TimerConstants.T1,false);
                                m_pTimerE.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimerE_Elapsed);
                                m_pTimerE.Enabled = true;

                                // Log
                                if(this.Stack.Logger != null){
                                    this.Stack.Logger.AddText(this.ID,"Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=false] timer E(Non-INVITE request retransmission) started, will trigger after " + m_pTimerE.Interval + ".");
                                }
                            }
                        }

                        #endregion
                    }
                }));                
            }
        }
        /// <summary>
        /// Processes specified response through this transaction.
        /// </summary>
        /// <param name="flow">SIP data flow what received response.</param>
        /// <param name="response">SIP response to process.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>flow</b>,<b>response</b> is null reference.</exception>
        internal void ProcessResponse(SIP_Flow flow,SIP_Response response)
        {
            if(flow == null){
                throw new ArgumentNullException("flow");
            }
            if(response == null){
                throw new ArgumentNullException("response");
            }

            lock(this.SyncRoot){
                if(this.State == SIP_TransactionState.Disposed){
                    return;
                }
                /* RFC 3261 9.1. CANCEL.
                    *) If provisional response, send CANCEL, we should get '478 Request terminated'.
                    *) If final response, skip canceling, nothing to cancel.
                */
                else if(m_IsCanceling && response.StatusCodeType == SIP_StatusCodeType.Provisional){
                    SendCancel();
                    return;
                }

                // Log
                if(this.Stack.Logger != null){
                    byte[] responseData = response.ToByteData();

                    this.Stack.Logger.AddRead(
                        Guid.NewGuid().ToString(),
                        null,
                        0,
                        "Response [transactionID='" +  this.ID + "'; method='" + response.CSeq.RequestMethod + "'; cseq='" + response.CSeq.SequenceNumber + "'; " + 
                        "transport='" + flow.Transport + "'; size='" + responseData.Length + "'; statusCode='" + response.StatusCode + "'; " + 
                        "reason='" + response.ReasonPhrase + "'; received '" + flow.LocalEP + "' <- '" + flow.RemoteEP + "'.",
                        flow.LocalEP,
                        flow.RemoteEP,
                        responseData
                    );
                }


                #region INVITE

                /* RFC 6026 7.2. INVITE client transaction. (Udpates RFC 3261)
                      +-----------+                        +-----------+
                      |           |                        |           |
                      |  Calling  |                        |  Calling  |
                      |           |----------->+           |           |-----------+
                      +-----------+ 2xx        |           +-----------+ 2xx       |
                                    2xx to TU  |                         2xx to TU |
                                               |                                   |
                                               |                                   |
                                               |                                   |
                                               |                                   |
                      +-----------+            |           +-----------+           |
                      |           |            |           |           |           |
                      |Proceeding |----------->|           |Proceeding |---------->|
                      |           | 2xx        |           |           | 2xx       |
                      +-----------+ 2xx to TU  |           +-----------+ 2xx to TU |
                                               |                                   |
                                               |                                   |
                                               |                                   |
                                               |                                   V
                                               |                            +-----------+
                                               |                            |           |
                                               |                            | Accepted  |
                                               |                        +---|           |
                                               |              2xx       |   +-----------+
                                               |              2xx to TU |     ^    |
                                               |                        |     |    |
                                               |                        +-----+    |
                                               |                                   |
                                               |                 +-----------------+
                                               |                 | Timer M fires
                                               |                 | -
                                               |                 V
                      +-----------+            |           +-----------+
                      |           |            |           |           |
                      | Terminated|<-----------+           | Terminated|
                      |           |                        |           |
                      +-----------+                        +-----------+


                */

                if(this.Method == SIP_Methods.INVITE){
                    #region Calling

                    if(this.State == SIP_TransactionState.Calling){
                        // Store response.
                        AddResponse(response);

                        // Stop timer A,B
                        if(m_pTimerA != null){
                            m_pTimerA.Dispose();
                            m_pTimerA = null;

                            // Log
                            if(this.Stack.Logger != null){
                                this.Stack.Logger.AddText(this.ID,"Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=false] timer A(INVITE request retransmission) stopped.");
                            }
                        }
                        if(m_pTimerB != null){
                            m_pTimerB.Dispose();
                            m_pTimerB = null;

                            // Log
                            if(this.Stack.Logger != null){
                                this.Stack.Logger.AddText(this.ID,"Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=false] timer B(INVITE calling state timeout) stopped.");
                            }
                        }

                        // 1xx response.
                        if(response.StatusCodeType == SIP_StatusCodeType.Provisional){
                            OnResponseReceived(response);
                            SetState(SIP_TransactionState.Proceeding);
                        }
                        // 2xx response.
                        else if(response.StatusCodeType == SIP_StatusCodeType.Success){
                            OnResponseReceived(response);
                            SetState(SIP_TransactionState.Accpeted);

                            /* RFC 6025 7.1.
                                When the "Accepted" state is entered, timer L MUST be set to fire in 64*T1.
                            */
                            m_pTimerM = new TimerEx(64 * SIP_TimerConstants.T1);
                            m_pTimerM.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimerM_Elapsed);
                            m_pTimerM.Enabled = true;

                            // Log
                            if(this.Stack.Logger != null){
                                this.Stack.Logger.AddText(this.ID,"Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=true] timer M(2xx retransmission wait) started, will trigger after " + m_pTimerM.Interval + ".");
                            }
                        }
                        // 3xx - 6xx response.
                        else{
                            SendAck(response);
                            OnResponseReceived(response);
                            SetState(SIP_TransactionState.Completed);

                            /* RFC 3261 17.1.1.2. 
                                The client transaction SHOULD start timer D when it enters the "Completed" state, 
                                with a value of at least 32 seconds for unreliable transports, and a value of zero 
                                seconds for reliable transports.
                            */
                            m_pTimerD = new TimerEx(this.Flow.IsReliable ? 0 : 32000,false);
                            m_pTimerD.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimerD_Elapsed);
                            // Log
                            if(this.Stack.Logger != null){
                                this.Stack.Logger.AddText(this.ID,"Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=false] timer D(INVITE 3xx - 6xx response retransmission wait) started, will trigger after " + m_pTimerD.Interval + ".");
                            }
                            m_pTimerD.Enabled = true;
                        }
                    }

                    #endregion

                    #region Proceeding

                    else if(this.State == SIP_TransactionState.Proceeding){
                        // Store response.
                        AddResponse(response);

                        // 1xx response.
                        if(response.StatusCodeType == SIP_StatusCodeType.Provisional){
                            OnResponseReceived(response);
                        }
                        // 2xx response.
                        else if(response.StatusCodeType == SIP_StatusCodeType.Success){
                            OnResponseReceived(response);
                            SetState(SIP_TransactionState.Accpeted);

                            /* RFC 6025 7.1.
                                When the "Accepted" state is entered, timer L MUST be set to fire in 64*T1.
                            */
                            m_pTimerM = new TimerEx(64 * SIP_TimerConstants.T1);
                            m_pTimerM.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimerM_Elapsed);
                            m_pTimerM.Enabled = true;

                            // Log
                            if(this.Stack.Logger != null){
                                this.Stack.Logger.AddText(this.ID,"Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=true] timer M(2xx retransmission wait) started, will trigger after " + m_pTimerM.Interval + ".");
                            }
                        }
                        // 3xx - 6xx response.
                        else{
                            SendAck(response);
                            OnResponseReceived(response);
                            SetState(SIP_TransactionState.Completed);

                            /* RFC 3261 17.1.1.2. 
                                The client transaction SHOULD start timer D when it enters the "Completed" state, 
                                with a value of at least 32 seconds for unreliable transports, and a value of zero 
                                seconds for reliable transports.
                            */
                            m_pTimerD = new TimerEx(this.Flow.IsReliable ? 0 : 32000,false);
                            m_pTimerD.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimerD_Elapsed);
                            // Log
                            if(this.Stack.Logger != null){
                                this.Stack.Logger.AddText(this.ID,"Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=false] timer D(INVITE 3xx - 6xx response retransmission wait) started, will trigger after " + m_pTimerD.Interval + ".");
                            }
                            m_pTimerD.Enabled = true;
                        }
                    }

                    #endregion

                    #region Accepted

                    else if(this.State == SIP_TransactionState.Accpeted){
                        if(response.StatusCodeType == SIP_StatusCodeType.Success){
                            OnResponseReceived(response);
                        }
                    }

                    #endregion

                    #region Completed

                    else if(this.State == SIP_TransactionState.Completed){
                        // 3xx - 6xx
                        if(response.StatusCode >= 300){
                            SendAck(response);
                        }
                    }

                    #endregion

                    #region Terminated

                    else if(this.State == SIP_TransactionState.Terminated){
                        // We should never reach here, but if so, do nothing.
                    }

                    #endregion
                }

                #endregion

                #region Non-INVITE

                /* RFC 3251 17.1.2.2
                                               |Request from TU
                                               |send request
                           Timer E             V
                           send request  +-----------+
                               +---------|           |-------------------+
                               |         |  Trying   |  Timer F          |
                               +-------->|           |  or Transport Err.|
                                         +-----------+  inform TU        |
                            200-699         |  |                         |
                            resp. to TU     |  |1xx                      |
                            +---------------+  |resp. to TU              |
                            |                  |                         |
                            |   Timer E        V       Timer F           |
                            |   send req +-----------+ or Transport Err. |
                            |  +---------|           | inform TU         |
                            |  |         |Proceeding |------------------>|
                            |  +-------->|           |-----+             |
                            |            +-----------+     |1xx          |
                            |              |      ^        |resp to TU   |
                            | 200-699      |      +--------+             |
                            | resp. to TU  |                             |
                            |              |                             |
                            |              V                             |
                            |            +-----------+                   |
                            |            |           |                   |
                            |            | Completed |                   |
                            |            |           |                   |
                            |            +-----------+                   |
                            |              ^   |                         |
                            |              |   | Timer K                 |
                            +--------------+   | -                       |
                                               |                         |
                                               V                         |
                         NOTE:           +-----------+                   |
                                         |           |                   |
                     transitions         | Terminated|<------------------+
                     labeled with        |           |
                     the event           +-----------+
                     over the action
                     to take
                */

                else{
                    #region Trying

                    if(this.State == SIP_TransactionState.Trying){
                        // Store response.
                        AddResponse(response);

                        // Stop timer E
                        if(m_pTimerE != null){
                            m_pTimerE.Dispose();
                            m_pTimerE = null;

                            // Log
                            if(this.Stack.Logger != null){
                                this.Stack.Logger.AddText(this.ID,"Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=false] timer E(Non-INVITE request retransmission) stopped.");
                            }
                        }

                        // 1xx response.
                        if(response.StatusCodeType == SIP_StatusCodeType.Provisional){
                            OnResponseReceived(response);
                            SetState(SIP_TransactionState.Proceeding);
                        }
                        // 2xx - 6xx response.
                        else{
                            // Stop timer F
                            if(m_pTimerF != null){
                                m_pTimerF.Dispose();
                                m_pTimerF = null;

                                // Log
                                if(this.Stack.Logger != null){
                                    this.Stack.Logger.AddText(this.ID,"Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=false] timer F(Non-INVITE trying,proceeding state timeout) stopped.");
                                }
                            }

                            OnResponseReceived(response);
                            SetState(SIP_TransactionState.Completed);

                            /* RFC 3261 17.1.2.2. 
                                The client transaction enters the "Completed" state, it MUST set
                                Timer K to fire in T4 seconds for unreliable transports, and zero
                                seconds for reliable transports.
                            */
                            m_pTimerK = new TimerEx(this.Flow.IsReliable ? 1 : SIP_TimerConstants.T4,false);
                            m_pTimerK.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimerK_Elapsed);
                            // Log
                            if(this.Stack.Logger != null){
                                this.Stack.Logger.AddText(this.ID,"Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=false] timer K(Non-INVITE 3xx - 6xx response retransmission wait) started, will trigger after " + m_pTimerK.Interval + ".");
                            }
                            m_pTimerK.Enabled = true;
                        }
                    }

                    #endregion

                    #region Proceeding

                    else if(this.State == SIP_TransactionState.Proceeding){
                        // Store response.
                        AddResponse(response);

                        // 1xx response.
                        if(response.StatusCodeType == SIP_StatusCodeType.Provisional){
                            OnResponseReceived(response);
                        }                        
                        // 2xx - 6xx response.
                        else{
                            // Stop timer F
                            if(m_pTimerF != null){
                                m_pTimerF.Dispose();
                                m_pTimerF = null;

                                // Log
                                if(this.Stack.Logger != null){
                                    this.Stack.Logger.AddText(this.ID,"Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=false] timer F(Non-INVITE trying,proceeding state timeout) stopped.");
                                }
                            }

                            OnResponseReceived(response);
                            SetState(SIP_TransactionState.Completed);

                            /* RFC 3261 17.1.2.2. 
                                The client transaction enters the "Completed" state, it MUST set
                                Timer K to fire in T4 seconds for unreliable transports, and zero
                                seconds for reliable transports.
                            */
                            m_pTimerK = new TimerEx(this.Flow.IsReliable ? 0 : SIP_TimerConstants.T4,false);
                            m_pTimerK.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimerK_Elapsed);
                            // Log
                            if(this.Stack.Logger != null){
                                this.Stack.Logger.AddText(this.ID,"Transaction [branch='" + this.ID + "';method='" + this.Method + "';IsServer=false] timer K(Non-INVITE 3xx - 6xx response retransmission wait) started, will trigger after " + m_pTimerK.Interval + ".");
                            }
                            m_pTimerK.Enabled = true;
                        }
                    }

                    #endregion

                    #region Completed

                    else if(this.State == SIP_TransactionState.Completed){
                        // Eat retransmited response.
                    }

                    #endregion

                    #region Terminated

                    else if(this.State == SIP_TransactionState.Terminated){
                        // We should never reach here, but if so, do nothing.
                    }

                    #endregion
                }

                #endregion
            }
        }
        /// <summary>
        /// Is raised when INVITE 100 (Trying) response must be sent if no response sent by transaction user.
        /// </summary>
        /// <param name="sender">Sender.</param>
        /// <param name="e">Event data.</param>
        private void m_pTimer100_Elapsed(object sender,System.Timers.ElapsedEventArgs e)
        {
            lock(this.SyncRoot){
                // RFC 3261 17.2.1. TU didn't generate response in 200 ms, send '100 Trying' to stop request retransmission.
                if(this.State == SIP_TransactionState.Proceeding && this.Responses.Length == 0){
                    /* RFC 3261 17.2.1.
                        The 100 (Trying) response is constructed according to the procedures in Section 8.2.6, except that the
                        insertion of tags in the To header field of the response (when none was present in the request) 
                        is downgraded from MAY to SHOULD NOT.
                     * 
                       RFC 3261 8.2.6.
                        When a 100 (Trying) response is generated, any Timestamp header field present in the request MUST 
                        be copied into this 100 (Trying) response. If there is a delay in generating the response, the UAS
                        SHOULD add a delay value into the Timestamp value in the response. This value MUST contain the difference 
                        between the time of sending of the response and receipt of the request, measured in seconds.
                    */

                    SIP_Response tryingResponse = this.Stack.CreateResponse(SIP_ResponseCodes.x100_Trying,this.Request);
                    if(this.Request.Timestamp != null){
                        tryingResponse.Timestamp = new SIP_t_Timestamp(this.Request.Timestamp.Time,(DateTime.Now - this.CreateTime).Seconds);
                    }

                    try{
                        this.Stack.TransportLayer.SendResponse(this,tryingResponse);
                    }
                    catch(Exception x){
                        OnTransportError(x);
                        SetState(SIP_TransactionState.Terminated);
                        return;
                    }
                }

                if(m_pTimer100 != null){
                    m_pTimer100.Dispose();
                    m_pTimer100 = null;
                }
            }
        }
Esempio n. 52
0
 /// <summary>
 /// Default constructor.
 /// </summary>
 public TCP_Client()
 {
     m_pTimer_IdleTimeout = new TimerEx(30000, true);
     m_pTimer_IdleTimeout.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimer_IdleTimeout_Elapsed);
 }
Esempio n. 53
0
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="session">Owner RTP multimedia session.</param>
        /// <param name="localEP">Local RTP end point.</param>
        /// <param name="clock">RTP media clock.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>localEP</b>, <b>localEP</b> or <b>clock</b> is null reference.</exception>
        internal RTP_Session(RTP_MultimediaSession session, RTP_Address localEP, RTP_Clock clock)
        {
            if (session == null)
            {
                throw new ArgumentNullException("session");
            }
            if (localEP == null)
            {
                throw new ArgumentNullException("localEP");
            }
            if (clock == null)
            {
                throw new ArgumentNullException("clock");
            }

            m_pSession = session;
            m_pLocalEP = localEP;
            m_pRtpClock = clock;

            m_pRtpReceiveBuffer = new byte[Workaround.Definitions.MaxStreamLineLength];
            m_pRtcpReceiveBuffer = new byte[Workaround.Definitions.MaxStreamLineLength];

            m_pLocalSources = new List<RTP_Source_Local>();
            m_pTargets = new List<RTP_Address>();
            m_pMembers = new Dictionary<uint, RTP_Source>();
            m_pSenders = new Dictionary<uint, RTP_Source>();
            m_pConflictingEPs = new Dictionary<string, DateTime>();

            m_pRtpSocket = new Socket(localEP.IP.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
            m_pRtpSocket.Bind(localEP.RtpEP);
            m_pRtcpSocket = new Socket(localEP.IP.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
            m_pRtcpSocket.Bind(localEP.RtcpEP);

            m_pRtcpTimer = new TimerEx();
            m_pRtcpTimer.Elapsed += delegate { SendRtcp(); };
            m_pRtcpTimer.AutoReset = false;
        }
Esempio n. 54
0
            /// <summary>
            /// Starts data connection processing.
            /// </summary>
            /// <exception cref="ObjectDisposedException">Is raised when this is disposed and this method is accessed.</exception>
            public void Start()
            {
                if(m_IsDisposed){
                    throw new ObjectDisposedException(this.GetType().Name);
                }

                // Passive mode, start waiting client connection.
                if(m_pSession.PassiveMode){
                    WriteLine("150 Waiting data connection on port '" + ((IPEndPoint)m_pSession.m_pPassiveSocket.LocalEndPoint).Port + "'.");
                                                            
                    // Start connection wait timeout timer.
                    TimerEx timer = new TimerEx(10000,false);
                    timer.Elapsed += delegate(object sender,System.Timers.ElapsedEventArgs e){
                        WriteLine("550 Data connection wait timeout.");
                        Dispose();
                    };
                    timer.Enabled = true;

                    m_pSession.m_pPassiveSocket.BeginAccept(
                        delegate(IAsyncResult ar){
                            try{
                                timer.Dispose();

                                m_pSocket = m_pSession.m_pPassiveSocket.EndAccept(ar);

                                // Log
                                m_pSession.LogAddText("Data connection opened.");

                                StartDataTransfer();
                            }
                            catch{
                                WriteLine("425 Opening data connection failed.");
                                Dispose();
                            }
                        },
                        null
                    );
                }
                // Active mode, connect to client data port.
                else{
                    WriteLine("150 Opening data connection to '" + m_pSession.m_pDataConEndPoint.ToString() + "'.");
                    
					m_pSocket = new Socket(m_pSession.LocalEndPoint.AddressFamily,SocketType.Stream,ProtocolType.Tcp);
                    m_pSocket.BeginConnect(
                        m_pSession.m_pDataConEndPoint,
                        delegate(IAsyncResult ar){
                            try{
                                m_pSocket.EndConnect(ar);

                                // Log
                                m_pSession.LogAddText("Data connection opened.");

                                StartDataTransfer();
                            }
                            catch{
                                WriteLine("425 Opening data connection to '" + m_pSession.m_pDataConEndPoint.ToString() + "' failed.");
                                Dispose();
                            }
                        },
                        null
                    );
                }
            }
            /// <summary>
            /// Default constructor.
            /// </summary>
            /// <param name="dialog">Owner INVITE dialog.</param>
            /// <param name="response">INVITE 2xx response.</param>
            /// <exception cref="ArgumentNullException">Is raised when <b>dialog</b> or <b>response</b> is null reference.</exception>
            public UasInvite2xxRetransmit(SIP_Dialog_Invite dialog, SIP_Response response)
            {
                if (dialog == null)
                {
                    throw new ArgumentNullException("dialog");
                }
                if (response == null)
                {
                    throw new ArgumentNullException("response");
                }

                m_pDialog = dialog;
                m_pResponse = response;

                /* RFC 3261 13.3.1.4.
                    Once the response has been constructed, it is passed to the INVITE
                    server transaction.  Note, however, that the INVITE server
                    transaction will be destroyed as soon as it receives this final
                    response and passes it to the transport.  Therefore, it is necessary
                    to periodically pass the response directly to the transport until the
                    ACK arrives.  The 2xx response is passed to the transport with an
                    interval that starts at T1 seconds and doubles for each
                    retransmission until it reaches T2 seconds (T1 and T2 are defined in
                    Section 17).  Response retransmissions cease when an ACK request for
                    the response is received.  This is independent of whatever transport
                    protocols are used to send the response.
                 
                        Since 2xx is retransmitted end-to-end, there may be hops between
                        UAS and UAC that are UDP.  To ensure reliable delivery across
                        these hops, the response is retransmitted periodically even if the
                        transport at the UAS is reliable.                    
                */

                m_pTimer = new TimerEx(SIP_TimerConstants.T1, false);
                m_pTimer.Elapsed += m_pTimer_Elapsed;
                m_pTimer.Enabled = true;
            }
Esempio n. 56
0
        /// <summary>
        /// Cleans up any resources being used.
        /// </summary>
        public void Dispose()
        {
            if(m_IsDisposed){
                return;
            }
            m_IsDisposed = true;

            foreach(UDP_DataReceiver receiver in m_pUdpDataReceivers){
                receiver.Dispose();
            }
            m_pUdpDataReceivers = null;
            if(m_pRtcpTimer != null){
                m_pRtcpTimer.Dispose();
                m_pRtcpTimer = null;
            }
            m_pSession = null;
            m_pLocalEP = null;
            m_pTargets = null;
            foreach(RTP_Source_Local source in m_pLocalSources.ToArray()){
                source.Dispose();
            }
            m_pLocalSources = null;
            m_pRtcpSource = null;
            foreach(RTP_Source source in m_pMembers.Values){
                source.Dispose();
            }
            m_pMembers = null;
            m_pSenders = null;
            m_pConflictingEPs = null;
            m_pRtpSocket.Close();
            m_pRtpSocket = null;
            m_pRtcpSocket.Close();
            m_pRtcpSocket = null;
            m_pUdpDataReceivers = null;

            OnDisposed();

            this.Disposed = null;
            this.Closed = null;
            this.NewSendStream = null;
            this.NewReceiveStream = null;
        }
            /// <summary>
            /// Cleans up any resources being used.
            /// </summary>
            public void Dispose()
            {
                lock (m_pLock)
                {
                    if (m_IsDisposed)
                    {
                        return;
                    }
                    m_IsDisposed = true;

                    m_pDialog.m_pUacInvite2xxRetransmitWaits.Remove(this);

                    m_pDialog = null;
                    m_pInvite = null;
                    if (m_pTimer != null)
                    {
                        m_pTimer.Dispose();
                        m_pTimer = null;
                    }
                }
            }
Esempio n. 58
0
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="session">Owner RTP multimedia session.</param>
        /// <param name="localEP">Local RTP end point.</param>
        /// <param name="clock">RTP media clock.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>localEP</b>, <b>localEP</b> or <b>clock</b> is null reference.</exception>
        internal RTP_Session(RTP_MultimediaSession session,RTP_Address localEP,RTP_Clock clock)
        {
            if(session == null){
                throw new ArgumentNullException("session");
            }
            if(localEP == null){
                throw new ArgumentNullException("localEP");
            }
            if(clock == null){
                throw new ArgumentNullException("clock");
            }

            m_pSession  = session;
            m_pLocalEP  = localEP;
            m_pRtpClock = clock;

            m_pLocalSources = new List<RTP_Source_Local>();
            m_pTargets = new List<RTP_Address>();
            m_pMembers = new Dictionary<uint,RTP_Source>();
            m_pSenders = new Dictionary<uint,RTP_Source>();
            m_pConflictingEPs = new Dictionary<string,DateTime>();
            m_pPayloads = new KeyValueCollection<int,Codec>();
            
            m_pUdpDataReceivers = new List<UDP_DataReceiver>();
            m_pRtpSocket = new Socket(localEP.IP.AddressFamily,SocketType.Dgram,ProtocolType.Udp);
            m_pRtpSocket.Bind(localEP.RtpEP);
            m_pRtcpSocket = new Socket(localEP.IP.AddressFamily,SocketType.Dgram,ProtocolType.Udp);
            m_pRtcpSocket.Bind(localEP.RtcpEP);
                        
            m_pRtcpTimer = new TimerEx();
            m_pRtcpTimer.Elapsed += new System.Timers.ElapsedEventHandler(delegate(object sender,System.Timers.ElapsedEventArgs e){
                SendRtcp();
            });
            m_pRtcpTimer.AutoReset = false;
        }
Esempio n. 59
0
        /// <summary>
        /// Cleans up any resources being used.
        /// </summary>
        internal void Dispose()
        {
            m_pCache = null;

            m_pTimerTimeout.Dispose();
            m_pTimerTimeout = null;
        }
        /// <summary>
        /// Starts transaction processing.
        /// </summary>
        private void Start()
        {
            #region INVITE

            if(this.Method == SIP_Methods.INVITE){
                /* RFC 3261 17.2.1.
                    When a server transaction is constructed for a request, it enters the "Proceeding" state. The server 
                    transaction MUST generate a 100 (Trying) response unless it knows that the TU will generate a provisional 
                    or final response within 200 ms, in which case it MAY generate a 100 (Trying) response.
                */

                SetState(SIP_TransactionState.Proceeding);

                m_pTimer100 = new TimerEx(200,false);
                m_pTimer100.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimer100_Elapsed);
                m_pTimer100.Enabled = true;
            }

            #endregion

            #region Non-INVITE

            else{
                // RFC 3261 17.2.2. The state machine is initialized in the "Trying" state.
                SetState(SIP_TransactionState.Trying);
            }

            #endregion
        }