예제 #1
0
 private void ResetErrorParams()
 {
     this._currentBackOffMode = BackOffMode.None;
     this._currentBackOffWaitCount = 0;
     this._hardErrorRetryCount = 0;
 }
예제 #2
0
 private void HandleException(Exception ex)
 {
     // log exception
     Log("EXCEPTION THROWN!");
     ex.ToString()
       .Split(new[] { "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries)
       .ForEach(this.Log);
     this.CleanupConnection();
     var tae = ex as TwitterApiException;
     if (tae != null)
     {
         Log("Twitter API Exception [error: " + (int)tae.StatusCode + " / code: " + tae.TwitterErrorCode + "]");
         _stateUpdater.UpdateState(_account.UnreliableScreenName + ": User Streamsが切断されました" +
                                   "(エラー: " + (int)tae.StatusCode + ", コード: " + tae.TwitterErrorCode + ")");
         switch (tae.StatusCode)
         {
             case HttpStatusCode.Unauthorized:
                 // ERR: Unauthorized, invalid OAuth request?
                 Log(">>> Authorization failed.");
                 if (this.CheckHardError())
                 {
                     Log(">>> Too many failure is detected. Abort.");
                     this.RaiseDisconnectedByError(
                         "ユーザー認証が行えません。",
                         "PCの時刻設定が正しいか確認してください。回復しない場合は、OAuth認証を再度行ってください。");
                     return;
                 }
                 break;
             case HttpStatusCode.Forbidden:
             case HttpStatusCode.NotFound:
                 Log(">>> Endpoint forbidden.");
                 if (this.CheckHardError())
                 {
                     Log(">>> Too many failure is detected. Abort.");
                     this.RaiseDisconnectedByError(
                         "ユーザーストリーム接続が一時的、または恒久的に利用できなくなっています。",
                         "エンドポイントへの接続時にアクセスが拒否されたか、またはエンドポイントが削除されています。");
                     return;
                 }
                 break;
             case HttpStatusCode.NotAcceptable:
             case HttpStatusCode.RequestEntityTooLarge:
                 Log(">>> Arguments could not be accepted.");
                 this.RaiseDisconnectedByError(
                     "トラックしているキーワードが長すぎるか、不正な可能性があります。",
                     "(トラック中のキーワード:" + this._trackKeywords.JoinString(", ") + ")");
                 return;
             case HttpStatusCode.RequestedRangeNotSatisfiable:
                 Log(">>> Permission denied or parameter error.");
                 this.RaiseDisconnectedByError(
                     "ユーザーストリームに接続できません。",
                     "(システム エラー: 416 Range Unacceptable. Elevated permission is required or paramter is out of range.)");
                 return;
             case (HttpStatusCode)420:
                 // ERR: Too many connections
                 // (other client is already connected?)
                 Log(">>> Rate limited.(too many connected)");
                 this.RaiseDisconnectedByError(
                     "ユーザーストリーム接続が制限されています。",
                     "Krileが多重起動していないか確認してください。短時間に何度も接続を試みていた場合は、しばらく待つと再接続できるようになります。");
                 return;
         }
         Log(">>> general protocol error.)");
         // else -> backoff
         if (this._currentBackOffMode == BackOffMode.ProtocolError)
         {
             // wait count is raised exponentially.
             this._currentBackOffWaitCount *= 2;
         }
         else
         {
             this._currentBackOffWaitCount = 5000;
             this._currentBackOffMode = BackOffMode.ProtocolError;
         }
         // max wait is 320 sec.
         if (this._currentBackOffWaitCount >= 320000)
         {
             Log(">>> Protocol backoff threshold exceeded.");
             this.RaiseDisconnectedByError(
                 "Twitterが不安定な状態になっています。",
                 "プロトコル エラーにより、ユーザーストリームに既定のリトライ回数内で接続できませんでした。");
             _stateUpdater.UpdateState(_account.UnreliableScreenName + ": User Streamsへ接続できませんでした(プロトコル エラー)");
             return;
         }
     }
     else
     {
         Log(">>> general network error.)");
         // network error
         // -> backoff
         if (this._currentBackOffMode == BackOffMode.NetworkError)
         {
             // wait count is raised linearly.
             this._currentBackOffMode += 250;
         }
         else
         {
             // wait starts 250ms
             this._currentBackOffWaitCount = 250;
             this._currentBackOffMode = BackOffMode.NetworkError;
         }
         // max wait is 16 sec.
         if (this._currentBackOffWaitCount >= 16000)
         {
             Log(">>> Network backoff threshold exceeded.");
             this.RaiseDisconnectedByError(
                 "Twitterが不安定な状態になっています。",
                 "ネットワーク エラーにより、ユーザーストリームに規定のリトライ回数内で接続できませんでした。");
             _stateUpdater.UpdateState(_account.UnreliableScreenName + ": User Streamsへ接続できませんでした(ネットワーク エラー)");
             return;
         }
     }
     Log(">>> wait for reconnection... (" + _currentBackOffWaitCount + " ms)");
     // parsing error, auto-reconnect
     _stateUpdater.UpdateState(_account.UnreliableScreenName + ": User Streamsへの再接続を試みています...(" + _currentBackOffWaitCount + " msec 待機しています)");
     this._currentConnection.Add(
         Observable.Timer(TimeSpan.FromMilliseconds(this._currentBackOffWaitCount))
                   .Subscribe(_ => this.Reconnect()));
 }
예제 #3
0
        private void HandleException(Exception ex)
        {
            // log exception
            Log("EXCEPTION THROWN!");
            ex.ToString()
            .Split(new[] { "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries)
            .ForEach(this.Log);
            this.CleanupConnection();
            var tae = ex as TwitterApiException;

            if (tae != null)
            {
                Log("Twitter API Exception [error: " + (int)tae.StatusCode + " / code: " + tae.TwitterErrorCode + "]");
                _stateUpdater.UpdateState(_account.UnreliableScreenName + ": User Streamsが切断されました" +
                                          "(エラー: " + (int)tae.StatusCode + ", コード: " + tae.TwitterErrorCode + ")");
                switch (tae.StatusCode)
                {
                case HttpStatusCode.Unauthorized:
                    // ERR: Unauthorized, invalid OAuth request?
                    Log(">>> Authorization failed.");
                    if (this.CheckHardError())
                    {
                        Log(">>> Too many failure is detected. Abort.");
                        this.RaiseDisconnectedByError(
                            "ユーザー認証が行えません。",
                            "PCの時刻設定が正しいか確認してください。回復しない場合は、OAuth認証を再度行ってください。");
                        return;
                    }
                    break;

                case HttpStatusCode.Forbidden:
                case HttpStatusCode.NotFound:
                    Log(">>> Endpoint forbidden.");
                    if (this.CheckHardError())
                    {
                        Log(">>> Too many failure is detected. Abort.");
                        this.RaiseDisconnectedByError(
                            "ユーザーストリーム接続が一時的、または恒久的に利用できなくなっています。",
                            "エンドポイントへの接続時にアクセスが拒否されたか、またはエンドポイントが削除されています。");
                        return;
                    }
                    break;

                case HttpStatusCode.NotAcceptable:
                case HttpStatusCode.RequestEntityTooLarge:
                    Log(">>> Arguments could not be accepted.");
                    this.RaiseDisconnectedByError(
                        "トラックしているキーワードが長すぎるか、不正な可能性があります。",
                        "(トラック中のキーワード:" + this._trackKeywords.JoinString(", ") + ")");
                    return;

                case HttpStatusCode.RequestedRangeNotSatisfiable:
                    Log(">>> Permission denied or parameter error.");
                    this.RaiseDisconnectedByError(
                        "ユーザーストリームに接続できません。",
                        "(システム エラー: 416 Range Unacceptable. Elevated permission is required or paramter is out of range.)");
                    return;

                case (HttpStatusCode)420:
                    // ERR: Too many connections
                    // (other client is already connected?)
                    Log(">>> Rate limited.(too many connected)");
                    this.RaiseDisconnectedByError(
                        "ユーザーストリーム接続が制限されています。",
                        "Krileが多重起動していないか確認してください。短時間に何度も接続を試みていた場合は、しばらく待つと再接続できるようになります。");
                    return;
                }
                Log(">>> general protocol error.)");
                // else -> backoff
                if (this._currentBackOffMode == BackOffMode.ProtocolError)
                {
                    // wait count is raised exponentially.
                    this._currentBackOffWaitCount *= 2;
                }
                else
                {
                    this._currentBackOffWaitCount = 5000;
                    this._currentBackOffMode      = BackOffMode.ProtocolError;
                }
                // max wait is 320 sec.
                if (this._currentBackOffWaitCount >= 320000)
                {
                    Log(">>> Protocol backoff threshold exceeded.");
                    this.RaiseDisconnectedByError(
                        "Twitterが不安定な状態になっています。",
                        "プロトコル エラーにより、ユーザーストリームに既定のリトライ回数内で接続できませんでした。");
                    _stateUpdater.UpdateState(_account.UnreliableScreenName + ": User Streamsへ接続できませんでした(プロトコル エラー)");
                    return;
                }
            }
            else
            {
                Log(">>> general network error.)");
                // network error
                // -> backoff
                if (this._currentBackOffMode == BackOffMode.NetworkError)
                {
                    // wait count is raised linearly.
                    this._currentBackOffMode += 250;
                }
                else
                {
                    // wait starts 250ms
                    this._currentBackOffWaitCount = 250;
                    this._currentBackOffMode      = BackOffMode.NetworkError;
                }
                // max wait is 16 sec.
                if (this._currentBackOffWaitCount >= 16000)
                {
                    Log(">>> Network backoff threshold exceeded.");
                    this.RaiseDisconnectedByError(
                        "Twitterが不安定な状態になっています。",
                        "ネットワーク エラーにより、ユーザーストリームに規定のリトライ回数内で接続できませんでした。");
                    _stateUpdater.UpdateState(_account.UnreliableScreenName + ": User Streamsへ接続できませんでした(ネットワーク エラー)");
                    return;
                }
            }
            Log(">>> wait for reconnection... (" + _currentBackOffWaitCount + " ms)");
            // parsing error, auto-reconnect
            _stateUpdater.UpdateState(_account.UnreliableScreenName + ": User Streamsへの再接続を試みています...(" + _currentBackOffWaitCount + " msec 待機しています)");
            this._currentConnection.Add(
                Observable.Timer(TimeSpan.FromMilliseconds(this._currentBackOffWaitCount))
                .Subscribe(_ => this.Reconnect()));
        }
예제 #4
0
 private void HandleException(Exception ex)
 {
     // log exception
     Log("EXCEPTION THROWN!");
     ex.ToString()
       .Split(new[] { "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries)
       .ForEach(this.Log);
     this.CleanupConnection();
     var tae = ex as TwitterApiException;
     if (tae != null)
     {
         Log("Twitter API Exception [error: " + (int)tae.StatusCode + " / code: " + tae.TwitterErrorCode + "]");
         _stateUpdater.UpdateState(_account.UnreliableScreenName +
                                   ReceivingResources.UserStreamDisconnectedFormat.SafeFormat(
                                       (int)tae.StatusCode, tae.TwitterErrorCode));
         switch (tae.StatusCode)
         {
             case HttpStatusCode.Unauthorized:
                 // ERR: Unauthorized, invalid OAuth request?
                 Log(">>> Authorization failed.");
                 if (this.CheckHardError())
                 {
                     Log(">>> Too many failure is detected. Abort.");
                     this.RaiseDisconnectedByError(ReceivingResources.DisconnectedAuthError);
                     return;
                 }
                 break;
             case HttpStatusCode.Forbidden:
             case HttpStatusCode.NotFound:
                 Log(">>> Endpoint forbidden.");
                 if (this.CheckHardError())
                 {
                     Log(">>> Too many failure is detected. Abort.");
                     this.RaiseDisconnectedByError(ReceivingResources.DisconnectedEndpointError);
                     return;
                 }
                 break;
             case HttpStatusCode.NotAcceptable:
             case HttpStatusCode.RequestEntityTooLarge:
                 Log(">>> Arguments could not be accepted.");
                 this.RaiseDisconnectedByError(
                     ReceivingResources.DisconnectedTrackErrorFormat.SafeFormat(
                         this._trackKeywords.JoinString(", ")));
                 return;
             case HttpStatusCode.RequestedRangeNotSatisfiable:
                 Log(">>> Permission denied or parameter error.");
                 this.RaiseDisconnectedByError(ReceivingResources.DisconnectedRangeError);
                 return;
             case (HttpStatusCode)420:
                 // ERR: Too many connections
                 // (other client is already connected?)
                 Log(">>> Rate limited.(too many connected)");
                 this.RaiseDisconnectedByError(ReceivingResources.DisconnectedLimitError);
                 return;
         }
         Log(">>> general protocol error.)");
         // else -> backoff
         if (this._currentBackOffMode == BackOffMode.ProtocolError)
         {
             // wait count is raised exponentially.
             this._currentBackOffWaitCount *= 2;
         }
         else
         {
             this._currentBackOffWaitCount = 5000;
             this._currentBackOffMode = BackOffMode.ProtocolError;
         }
         // max wait is 320 sec.
         if (this._currentBackOffWaitCount >= 320000)
         {
             Log(">>> Protocol backoff threshold exceeded.");
             this.RaiseDisconnectedByError(ReceivingResources.DisconnectedProtocolError);
             _stateUpdater.UpdateState(_account.UnreliableScreenName + ": " +
                                       ReceivingResources.ConnectFailedByProtocol);
             return;
         }
     }
     else
     {
         Log(">>> general network error.)");
         // network error
         // -> backoff
         if (this._currentBackOffMode == BackOffMode.NetworkError)
         {
             // wait count is raised linearly.
             this._currentBackOffMode += 250;
         }
         else
         {
             // wait starts 250ms
             this._currentBackOffWaitCount = 250;
             this._currentBackOffMode = BackOffMode.NetworkError;
         }
         // max wait is 16 sec.
         if (this._currentBackOffWaitCount >= 16000)
         {
             Log(">>> Network backoff threshold exceeded.");
             this.RaiseDisconnectedByError(ReceivingResources.DisconnectedNetworkError);
             _stateUpdater.UpdateState(_account.UnreliableScreenName + ": " +
                                       ReceivingResources.ConnectFailedByNetwork);
             return;
         }
     }
     Log(">>> wait for reconnection... (" + _currentBackOffWaitCount + " ms)");
     // parsing error, auto-reconnect
     _stateUpdater.UpdateState(_account.UnreliableScreenName + ": " +
                               ReceivingResources.ReconnectingFormat.SafeFormat(_currentBackOffWaitCount));
     this._currentConnection.Add(
         Observable.Timer(TimeSpan.FromMilliseconds(this._currentBackOffWaitCount))
                   .Subscribe(_ => this.Reconnect()));
 }
예제 #5
0
        private void HandleException(Exception ex)
        {
            // log exception
            Log("EXCEPTION THROWN!");
            ex.ToString()
            .Split(new[] { "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries)
            .ForEach(this.Log);
            this.CleanupConnection();
            var tae = ex as TwitterApiException;

            if (tae != null)
            {
                Log("Twitter API Exception [error: " + (int)tae.StatusCode + " / code: " + tae.TwitterErrorCode + "]");
                _stateUpdater.UpdateState(_account.UnreliableScreenName +
                                          ReceivingResources.UserStreamDisconnectedFormat.SafeFormat(
                                              (int)tae.StatusCode, tae.TwitterErrorCode));
                switch (tae.StatusCode)
                {
                case HttpStatusCode.Unauthorized:
                    // ERR: Unauthorized, invalid OAuth request?
                    Log(">>> Authorization failed.");
                    if (this.CheckHardError())
                    {
                        Log(">>> Too many failure is detected. Abort.");
                        this.RaiseDisconnectedByError(ReceivingResources.DisconnectedAuthError);
                        return;
                    }
                    break;

                case HttpStatusCode.Forbidden:
                case HttpStatusCode.NotFound:
                    Log(">>> Endpoint forbidden.");
                    if (this.CheckHardError())
                    {
                        Log(">>> Too many failure is detected. Abort.");
                        this.RaiseDisconnectedByError(ReceivingResources.DisconnectedEndpointError);
                        return;
                    }
                    break;

                case HttpStatusCode.NotAcceptable:
                case HttpStatusCode.RequestEntityTooLarge:
                    Log(">>> Arguments could not be accepted.");
                    this.RaiseDisconnectedByError(
                        ReceivingResources.DisconnectedTrackErrorFormat.SafeFormat(
                            this._trackKeywords.JoinString(", ")));
                    return;

                case HttpStatusCode.RequestedRangeNotSatisfiable:
                    Log(">>> Permission denied or parameter error.");
                    this.RaiseDisconnectedByError(ReceivingResources.DisconnectedRangeError);
                    return;

                case (HttpStatusCode)420:
                    // ERR: Too many connections
                    // (other client is already connected?)
                    Log(">>> Rate limited.(too many connected)");
                    this.RaiseDisconnectedByError(ReceivingResources.DisconnectedLimitError);
                    return;
                }
                Log(">>> general protocol error.)");
                // else -> backoff
                if (this._currentBackOffMode == BackOffMode.ProtocolError)
                {
                    // wait count is raised exponentially.
                    this._currentBackOffWaitCount *= 2;
                }
                else
                {
                    this._currentBackOffWaitCount = 5000;
                    this._currentBackOffMode      = BackOffMode.ProtocolError;
                }
                // max wait is 320 sec.
                if (this._currentBackOffWaitCount >= 320000)
                {
                    Log(">>> Protocol backoff threshold exceeded.");
                    this.RaiseDisconnectedByError(ReceivingResources.DisconnectedProtocolError);
                    _stateUpdater.UpdateState(_account.UnreliableScreenName + ": " +
                                              ReceivingResources.ConnectFailedByProtocol);
                    return;
                }
            }
            else
            {
                Log(">>> general network error.)");
                // network error
                // -> backoff
                if (this._currentBackOffMode == BackOffMode.NetworkError)
                {
                    // wait count is raised linearly.
                    this._currentBackOffMode += 250;
                }
                else
                {
                    // wait starts 250ms
                    this._currentBackOffWaitCount = 250;
                    this._currentBackOffMode      = BackOffMode.NetworkError;
                }
                // max wait is 16 sec.
                if (this._currentBackOffWaitCount >= 16000)
                {
                    Log(">>> Network backoff threshold exceeded.");
                    this.RaiseDisconnectedByError(ReceivingResources.DisconnectedNetworkError);
                    _stateUpdater.UpdateState(_account.UnreliableScreenName + ": " +
                                              ReceivingResources.ConnectFailedByNetwork);
                    return;
                }
            }
            Log(">>> wait for reconnection... (" + _currentBackOffWaitCount + " ms)");
            // parsing error, auto-reconnect
            _stateUpdater.UpdateState(_account.UnreliableScreenName + ": " +
                                      ReceivingResources.ReconnectingFormat.SafeFormat(_currentBackOffWaitCount));
            this._currentConnection.Add(
                Observable.Timer(TimeSpan.FromMilliseconds(this._currentBackOffWaitCount))
                .Subscribe(_ => this.Reconnect()));
        }
예제 #6
0
 private void ResetErrorParams()
 {
     this._currentBackOffMode      = BackOffMode.None;
     this._currentBackOffWaitCount = 0;
     this._hardErrorRetryCount     = 0;
 }
예제 #7
0
 private IDisposable ConnectCore()
 {
     this.CheckDisposed();
     this.ConnectionState = UserStreamsConnectionState.Connecting;
     var con = this.Account.ConnectUserStreams(this._trackKeywords, this.Account.IsReceiveRepliesAll)
                   .Do(_ =>
                   {
                       if (this.ConnectionState != UserStreamsConnectionState.Connecting) return;
                       this.ConnectionState = UserStreamsConnectionState.Connected;
                       this._currentBackOffMode = BackOffMode.None;
                   })
                   .SubscribeWithHandler(new HandleStreams(this),
                                         this.HandleException,
                                         this.Reconnect);
     return con;
 }
예제 #8
0
 private void HandleException(Exception ex)
 {
     this.CleanupConnection();
     var tae = ex as TwitterApiException;
     if (tae != null)
     {
         switch (tae.StatusCode)
         {
             case HttpStatusCode.Unauthorized:
                 // ERR: Unauthorized, invalid OAuth request?
                 if (this.CheckHardError())
                 {
                     this.RaiseDisconnectedByError(
                         "ユーザー認証が行えません。",
                         "PCの時刻設定が正しいか確認してください。回復しない場合は、OAuth認証を再度行ってください。");
                     return;
                 }
                 break;
             case HttpStatusCode.Forbidden:
             case HttpStatusCode.NotFound:
                 if (this.CheckHardError())
                 {
                     this.RaiseDisconnectedByError(
                         "ユーザーストリーム接続が一時的、または恒久的に利用できなくなっています。",
                         "エンドポイントへの接続時にアクセスが拒否されたか、またはエンドポイントが削除されています。");
                     return;
                 }
                 break;
             case HttpStatusCode.NotAcceptable:
             case HttpStatusCode.RequestEntityTooLarge:
                 this.RaiseDisconnectedByError(
                     "トラックしているキーワードが長すぎるか、不正な可能性があります。",
                     "(トラック中のキーワード:" + this._trackKeywords.JoinString(", ") + ")");
                 return;
             case HttpStatusCode.RequestedRangeNotSatisfiable:
                 this.RaiseDisconnectedByError(
                     "ユーザーストリームに接続できません。",
                     "(システム エラー: 416 Range Unacceptable. Elevated permission is required or paramter is out of range.)");
                 return;
             case (HttpStatusCode)420:
                 // ERR: Too many connections
                 // (other client is already connected?)
                 this.RaiseDisconnectedByError(
                     "ユーザーストリーム接続が制限されています。",
                     "Krileが多重起動していないか確認してください。短時間に何度も接続を試みていた場合は、しばらく待つと再接続できるようになります。");
                 return;
         }
         // else -> backoff
         if (this._currentBackOffMode == BackOffMode.ProtocolError)
             this._currentBackOffWaitCount += this._currentBackOffWaitCount;
         // wait count is raised exponentially.
         else
             this._currentBackOffWaitCount = 5000;
         if (this._currentBackOffWaitCount >= 320000) // max wait is 320 sec.
         {
             this.RaiseDisconnectedByError(
                 "Twitterが不安定な状態になっています。",
                 "プロトコル エラーにより、ユーザーストリームに既定のリトライ回数内で接続できませんでした。");
             return;
         }
     }
     else
     {
         // network error
         // -> backoff
         if (this._currentBackOffMode == BackOffMode.NetworkError)
             this._currentBackOffMode += 250; // wait count is raised linearly.
         else
             this._currentBackOffWaitCount = 250; // wait starts 250ms
         if (this._currentBackOffWaitCount >= 16000) // max wait is 16 sec.
         {
             this.RaiseDisconnectedByError(
                 "Twitterが不安定な状態になっています。",
                 "ネットワーク エラーにより、ユーザーストリームに規定のリトライ回数内で接続できませんでした。");
             return;
         }
     }
     Debug.WriteLine("*** USER STREAMS error ***" + Environment.NewLine + ex);
     Debug.WriteLine(" -> reconnect.");
     // parsing error, auto-reconnect
     this._currentConnection.Add(
         Observable.Timer(TimeSpan.FromMilliseconds(this._currentBackOffWaitCount))
                   .Subscribe(_ => this.Reconnect()));
 }
예제 #9
0
 private IDisposable ConnectCore()
 {
     this.CheckDisposed();
     this.ConnectionState = UserStreamsConnectionState.Connecting;
     Debug.WriteLine("*USERSTREAMS* " + _account.UnreliableScreenName + ": Starting connection...");
     var con = this.Account.ConnectUserStreams(this._trackKeywords, this.Account.ReceiveRepliesAll,
                                               this.Account.ReceiveFollowingsActivity)
                   .Do(_ =>
                   {
                       if (this.ConnectionState != UserStreamsConnectionState.Connecting) return;
                       this.ConnectionState = UserStreamsConnectionState.Connected;
                       this._currentBackOffMode = BackOffMode.None;
                   })
                   .SubscribeWithHandler(new HandleStreams(this),
                                         this.HandleException,
                                         this.Reconnect);
     return con;
 }
예제 #10
0
 /// <summary>
 /// Connect to user streams.<para />
 /// Or, update connected streams.
 /// </summary>
 public void Connect()
 {
     CheckDisposed();
     Disconnect();
     _connection = this.AuthInfo.ConnectToUserStreams(trackKeywords)
         .Do(_ => currentBackOffMode = BackOffMode.None) // initialize back-off
         .Subscribe(
         _ => Register(_),
         ex => HandleException(ex),
         () =>
         {
             if (_connection != null)
             {
                 // make reconnect.
                 Disconnect();
                 System.Diagnostics.Debug.WriteLine("***Auto reconnect***");
                 Connect();
             }
         });
     RaiseIsConnectedEvent(true);
 }
예제 #11
0
 private void HandleException(Exception ex)
 {
     Disconnect();
     var wex = ex as WebException;
     if (wex != null)
     {
         if (wex.Status == WebExceptionStatus.ProtocolError)
         {
             var res = wex.Response as HttpWebResponse;
             if (res != null)
             {
                 // protocol error
                 switch (res.StatusCode)
                 {
                     case HttpStatusCode.Unauthorized:
                         // ERR: Unauthorized, invalid OAuth request?
                         if (CheckHardError())
                         {
                             RaiseDisconnectedByError("ユーザー認証が行えません。",
                                 "PCの時刻設定が正しいか確認してください。回復しない場合は、OAuth認証を再度行ってください。");
                             return;
                         }
                         break;
                     case HttpStatusCode.Forbidden:
                     case HttpStatusCode.NotFound:
                         if (CheckHardError())
                         {
                             RaiseDisconnectedByError("ユーザーストリーム接続が一時的、または恒久的に利用できなくなっています。",
                                 "エンドポイントへの接続時にアクセスが拒否されたか、またはエンドポイントが削除されています。");
                             return;
                         }
                         break;
                     case HttpStatusCode.NotAcceptable:
                     case HttpStatusCode.RequestEntityTooLarge:
                         RaiseDisconnectedByError("トラックしているキーワードが長すぎるか、不正な可能性があります。",
                             "(トラック中のキーワード:" + trackKeywords.JoinString(", ") + ")");
                         return;
                     case HttpStatusCode.RequestedRangeNotSatisfiable:
                         RaiseDisconnectedByError("ユーザーストリームに接続できません。",
                             "(テクニカル エラー: 416 Range Unacceptable. Elevated permission is required or paramter is out of range.)");
                         return;
                     case (HttpStatusCode)420:
                         // ERR: Too many connections
                         // (other client is already connected?)
                         if (CheckHardError())
                         {
                             RaiseDisconnectedByError("ユーザーストリーム接続が制限されています。",
                                 "Krileが多重起動していないか確認してください。短時間に何度も接続を試みていた場合は、しばらく待つと再接続できるようになります。");
                             return;
                         }
                         break;
                 }
             }
             // else -> backoff
             if (currentBackOffMode == BackOffMode.Protocol)
                 currentBackOffWaitCount += currentBackOffWaitCount; // wait count is raised exponentially.
             else
                 currentBackOffWaitCount = 5000;
             if (currentBackOffWaitCount >= 320000) // max wait is 320 sec.
             {
                 RaiseDisconnectedByError("Twitterが不安定な状態になっています。",
                     "プロトコル エラーにより、ユーザーストリームに既定のリトライ回数内で接続できませんでした。");
                 return;
             }
         }
         else
         {
             // network error
             // -> backoff
             if (currentBackOffMode == BackOffMode.Network)
                 currentBackOffMode += 250; // wait count is raised linearly.
             else
                 currentBackOffWaitCount = 250; // wait starts 250ms
             if (currentBackOffWaitCount >= 16000) // max wait is 16 sec.
             {
                 RaiseDisconnectedByError("Twitterが不安定な状態になっています。",
                     "ネットワーク エラーにより、ユーザーストリームに規定のリトライ回数内で接続できませんでした。");
                 return;
             }
         }
     }
     else
     {
         currentBackOffMode = BackOffMode.None;
         if (currentBackOffWaitCount == 110)
         {
             RaiseDisconnectedByError("ユーザーストリーム接続が何らかのエラーの頻発で停止しました。",
                 "Twitterが不安定な状態になっているか、仕様が変更された可能性があります: " + ex.Message);
             return;
         }
         if (currentBackOffWaitCount >= 108 && currentBackOffWaitCount <= 109)
         {
             currentBackOffWaitCount++;
         }
         else
         {
             currentBackOffWaitCount = 108; // wait shortly
         }
     }
     System.Diagnostics.Debug.WriteLine("*** USER STREAMS error ***" + Environment.NewLine + ex);
     System.Diagnostics.Debug.WriteLine(" -> reconnect.");
     // parsing error, auto-reconnect
     Observable.Timer(TimeSpan.FromMilliseconds(currentBackOffWaitCount))
         .Subscribe(_ => Connect());
 }
예제 #12
0
 /// <summary>
 ///     Connect to user streams.
 ///     <para />
 ///     Or, update connected streams.
 /// </summary>
 public void Connect()
 {
     CheckDisposed();
     Disconnect();
     _connection = AuthInfo.ConnectToUserStreams(_trackKeywords)
                           .Do(_ => _currentBackOffMode = BackOffMode.None) // initialize back-off
                           .Subscribe(
                               Register,
                               HandleException,
                               () =>
                               {
                                   if (_connection != null)
                                   {
                                       // make reconnect.
                                       Disconnect();
                                       Debug.WriteLine("***Auto reconnect***");
                                       Connect();
                                   }
                               });
     RaiseIsConnectedEvent(true);
 }
예제 #13
0
 private IDisposable ConnectCore()
 {
     CheckDisposed();
     ConnectionState = UserStreamsConnectionState.Connecting;
     return AuthInfo.ConnectToUserStreams(_trackKeywords)
                    .Do(_ =>
                    {
                        ConnectionState = UserStreamsConnectionState.Connected;
                        _currentBackOffMode = BackOffMode.None;
                    })
                    .Subscribe(
                        Register,
                        HandleException,
                        Reconnect);
 }