「バトルスポットにおける切断対策について」 2013.6.3 ichiraku

バトルスポットでは、
切断対策として、P2P切断処理が入っております。

P2P切断処理とは・・・P2P切断が起きた際に、自分を強制勝ちとして結果を送信する。
                    (切断した側は負けになります。)


  

===================================================

■P2Pが切断になる流れ

-----------------------------
１．Session

    NEXのSessionが切断を検知する。
　　→10秒間応答がなければ切断とみなす様です。

-----------------------------
２．gflnet_P2pManager

    gflnet_P2pManager.cpp の 210行あたりで、１．の切断をチェックしています。
    切断を検知すると、gflnet_ErrManagerのSetSessionLeftをコールします。

-----------------------------
３．SetSessionLeft
    
    SetSessionLeftでは、リスナーのOnSessionLeftをコールする

    ※リスナーが登録されているのは、バトルスポットのみです。
      このリスナーは切断対策の為だけのリスナーです。
  　
-----------------------------
４．battle_match_net

    OnSessonLeftが実装されているのは、battle_match_net.cppです。
    処理としては、gflnet_ErrManagerのSetBattleMatchをコールするだけです。

-----------------------------
５．gflnet_ErrManager

    SetBattleMatchでは、
    「P2P切断フラグを立てる」
    「切断のエラーアプレットを表示するトリガを設定する」
    の２つしか行っておりません。


    ここで、IsSessionLeftがTRUEになるので、
    P2P切断が発生したことになります。

===================================================

■なぜP2P切断の発生を複雑な実装にしているのか

    最初に書きましたが、バトルスポットではP2P切断にする為の処理が、
    複雑になっています。

    これには理由がいくつかあります。

    ●P2P切断後に通信エラーが発生すると、P2P切断を通信エラーで上書いて欲しい為。

        gflnet_ErrManagerはエラー処理が排他制御になっています。
        通常のアプリは、P2P切断でアプリが終了になる為この仕組みでよいのですが、
        バトルスポットはP2P切断をエラーとしない特殊なアプリです。

        既存の仕組みでは、P2P切断後に通信エラーが発生すると、
        gflnet_ErrManagerの方で通信エラーを無視します。
        バトルスポットでは、この仕組みではバグになるので、
        （通信エラーが発生しているのに、アプリが継続しているバグ）
        P2P切断を通信エラーで上書く必要がありました。

        処理としては、gflnet_ErrManagerのbErrOriginalのフラグを立てない事で排他をやめています。


    ●切断のエラーアプレットが何度も起動するのを防ぐため

        上記でP2P切断エラーの排他制御をやめています。
        しかし、SetSessionLeftは切断するまで呼ばれる関数です。
        その為、SetBattleMatchが何度も呼ばれて、切断のエラーアプレットが起動し続けるバグがあります。

        このバグ解消の為、
        battle_match_net.cpp で 一度しかSetBattleMatchを呼ばないように対処しています。


===================================================
■切断対策

  gflnetNexP2pStationManager のソースが切断対策のソースです。

  概要：NEXのSessionが10秒で切断のタイムアウトを発行する。
        その切断がくる前に、自分がインターネットに接続しているかをチェックして、
        接続していなかった場合は強制で通信エラーにする。



  NexP2pStationManagerが相手のパケットを監視していて、
  7秒間応答がないと切断されている可能性があると判断します。

  battle_match_netでは、上記の場合にインターネットの疎通テストを行います。
  疎通テストは1秒間ゲームサーバと通信しているか確かめます。（たぶんPing）
  疎通テストが失敗すると、強制で通信エラーにします。


  この対策により、
  切断した側が、必ずP2P切断よりも早く通信エラーになります。


  懸念点
    電波状況が悪いところにいると、運悪く疎通テストが失敗する可能性があります。
    その場合は、切断していないのに切断と判断されてしまいます。

   （ 実際に検証してみたところ、発生はしなかったですが、可能性としては残っています。）
  

