Пример #1
0
        /// <summary>
        /// エコーデータの読み込み
        /// </summary>
        /// <param name="connection"></param>
        /// <param name="payload"></param>
        /// <param name="payload_len"></param>
        private static void ReadEcho(MrsConnection connection, IntPtr payload, UInt32 payload_len)
        {
            mrs.Time read_tm = new mrs.Time();
            read_tm.Set();

            byte[] read_data = new byte[payload_len];
            Marshal.Copy(payload, read_data, 0, (int)payload_len);

            mrs.Buffer buffer = new mrs.Buffer();
            buffer.Write(read_data);
            while (buffer.GetDataLen() > 0)
            {
                mrs.Time write_tm = buffer.ReadTime();
                MRS_LOG_DEBUG("ReadEcho data={0} data_len={1} diff_time={2}({3} - {4})",
                              ToString(buffer.GetData()), m_nWriteDataLen, (read_tm - write_tm).ToString(), read_tm.ToString(), write_tm.ToString());
                if (!buffer.Read(null, m_nWriteDataLen))
                {
                    MRS_LOG_ERR("Lost data. len={0} {1}", buffer.GetDataLen(), mrs.Utility.ToHex(buffer.GetData(), buffer.GetDataLen()));
                    m_bLoop = false;
                    break;
                }

                ++m_nReadCount;
                if (m_nWriteCount * m_nConnections <= m_nReadCount)
                {
                    MRS_LOG_DEBUG("Since all records have been received, it is finished.");
                    m_bLoop = false;
                }
            }
        }
Пример #2
0
        /// <summary>
        /// TCPソケット切断時に呼ばれる
        /// </summary>
        /// <param name="connection"></param>
        /// <param name="connection_data"></param>
        private static void OnDisconnect(MrsConnection connection, IntPtr connection_data)
        {
            some1disconnected = true;

            for (int i = 0; i < m_MaxPlayer; i++)
            {
                if (connection == m_nowConnect[i])
                {
                    MRS_LOG_DEBUG("OnDisconnect {0} : {1} local_mrs_version=0x{2:X} remote_mrs_version=0x{3:X}",
                                  ConnectionTypeToString(connection), m_nowConnect[i].ToInt32(), mrs_get_version(MRS_VERSION_KEY), mrs_connection_get_remote_version(connection, MRS_VERSION_KEY));
                    m_gameProc.eraseProfileData(i);
                    m_nowConnect[i] = IntPtr.Zero;
                }
                if (m_nowConnect[i].ToInt32() == 0)
                {
                    for (int j = i + 1; j < m_MaxPlayer; j++)
                    {
                        if (m_nowConnect[j].ToInt32() != 0)
                        {
                            m_nowConnect[i] = m_nowConnect[j];
                            m_nowConnect[j] = IntPtr.Zero;
                            break;
                        }
                    }
                }
                //MRS_LOG_DEBUG("now Connect No.{0} : {1}", i, m_nowConnect[i].ToInt32());
            }
            nowplayers = mrs_get_connection_num();

            if (nowplayers <= 2)
            {
                g_gameon = false; m_gameProc.CloseGame();
            }
        }
Пример #3
0
        /// <summary>
        /// TCPソケット接続時に呼ばれる
        /// </summary>
        /// <param name="connection"></param>
        private static void OnConnect(MrsConnection connection)
        {
            if (g_isPlay || nowplayers >= m_MaxPlayer)
            {
                mrs_close(connection); return;
            }
            g_isRoom = true;
            for (int i = 0; i < m_MaxPlayer; i++)
            {
                if (m_nowConnect[i].ToInt32() == 0)
                {
                    m_nowConnect[i] = connection;
                    MRS_LOG_DEBUG("OnConnect {0} : {1} local_mrs_version=0x{2:X} remote_mrs_version=0x{3:X}",
                                  ConnectionTypeToString(connection), m_nowConnect[i].ToInt32(), mrs_get_version(MRS_VERSION_KEY), mrs_connection_get_remote_version(connection, MRS_VERSION_KEY));
                    nowplayers = mrs_get_connection_num();
                    MRS_LOG_DEBUG("now Connect No.{0} : {1}", i, m_nowConnect[i].ToInt32());
                    break;
                }
                MRS_LOG_DEBUG("now Connect No.{0} : {1}", i, m_nowConnect[i].ToInt32());
            }
            bool connectAll = true;

            for (int j = 0; j < m_MaxPlayer; j++)
            {
                if (m_nowConnect[j].ToInt32() == 0)
                {
                    connectAll = false;  break;
                }
            }
            if (connectAll)
            {
            }
            mrs_set_cipher(connection, mrs_cipher_create(MrsCipherType.ECDH));
        }
Пример #4
0
        /// <summary>
        /// TCPソケットが新しい接続を生成した時に呼ばれる
        /// </summary>
        /// <param name="server"></param>
        /// <param name="server_data"></param>
        /// <param name="client"></param>
        private static void OnNewConnection(MrsServer server, IntPtr server_data, MrsConnection client)
        {
            MRS_LOG_DEBUG("OnNewConnection {0} : {1}", ConnectionTypeToString(client), client.ToString());

            mrs_set_disconnect_callback(client, m_OnDisconnect);
            mrs_set_error_callback(client, m_OnError);
            mrs_set_read_record_callback(client, m_OnReadRecord);
            OnConnect(client);
        }
Пример #5
0
        /// <summary>
        /// エコーデータを書き込み数分書き込む
        /// </summary>
        /// <param name="connection"></param>
        private static void WriteEchoAll(MrsConnection connection)
        {
            StringBuilder sb = new StringBuilder();

            switch (g_Connect.GetRequest().ConnectionType)
            {
            case MrsConnectionType.TCP:
                sb.Append("TCP ");
                break;

            case MrsConnectionType.UDP:
                sb.Append("UDP ");
                break;

            case MrsConnectionType.WS:
                sb.Append("WS ");
                break;

            case MrsConnectionType.WSS:
                sb.Append("WSS ");
                break;

            case MrsConnectionType.TCP_SSL:
                sb.Append("TCP_SSL");
                break;

            case MrsConnectionType.MRU:
                sb.Append("MRU");
                break;

            default:
                sb.Append("INVALID");
                break;
            }

            if (m_canKeyExchange && m_canEncryptRecords)
            {
                sb.Append("  CRYPT");
            }
            else
            {
                sb.Append("NOCRYPT");
            }

            byte[] data = new byte[m_nWriteDataLen];
            for (uint i = 0; i < m_nWriteCount; ++i)
            {
                string str  = String.Format("{0} {1}: {2}", sb.ToString(), connection, i + 1);
                byte[] conv = System.Text.Encoding.UTF8.GetBytes(str);
                System.Buffer.BlockCopy(conv, 0, data, 0, conv.Length);
                WriteEcho(connection, data, m_nWriteDataLen);
            }
        }
Пример #6
0
        /// <summary>
        /// レコードのパース
        /// </summary>
        /// <param name="connection"></param>
        /// <param name="connection_data"></param>
        /// <param name="seqnum"></param>
        /// <param name="options"></param>
        /// <param name="payload_type"></param>
        /// <param name="_payload"></param>
        /// <param name="payload_len"></param>
        private static void ParseRecord(MrsConnection connection, IntPtr connection_data, UInt32 seqnum, UInt16 options, UInt16 payload_type, IntPtr _payload, UInt32 payload_len)
        {
            Mrs.MRS_LOG_DEBUG("ParseRecord seqnum=0x{0} options=0x{1:X2} payload={2:X}/{3}", seqnum, options, payload_type, payload_len);
            // MRS_PAYLOAD_TYPE_BEGIN - MRS_PAYLOAD_TYPE_ENDの範囲内で任意のIDを定義し、対応するアプリケーションコードを記述する
            switch (payload_type)
            {
            case 0x01:
                ReadEcho(connection, _payload, payload_len);
                break;

            default:
                break;
            }
        }
Пример #7
0
        /// <summary>
        /// コネクションタイプを表す文字列を返す
        /// </summary>
        private static string ConnectionTypeToString(MrsConnection connection)
        {
            MrsConnectionType type = mrs_connection_get_type(connection);

            switch (type)
            {
            case MrsConnectionType.NONE: { return("NONE"); }

            case MrsConnectionType.TCP: { return("TCP"); }

            case MrsConnectionType.UDP: { return("UDP"); }
            }
            return("INVALID");
        }
Пример #8
0
        /// <summary>
        /// ソケット接続時に呼ばれる
        /// </summary>
        /// <param name="connection"></param>
        /// <param name="connection_data"></param>
        private static void OnConnect(MrsConnection connection, IntPtr connection_data)
        {
            MRS_LOG_DEBUG("OnConnect local_mrs_version=0x{0} remote_mrs_version=0x{1}",
                          mrs_get_version(MRS_VERSION_KEY), mrs_connection_get_remote_version(connection, MRS_VERSION_KEY));

            if (m_canKeyExchange)
            {
                mrs_set_cipher(connection, mrs_cipher_create(MrsCipherType.ECDH));
                mrs_key_exchange(connection, m_OnKeyExchange);
            }
            else
            {
                WriteEchoAll(connection);
            }
        }
Пример #9
0
        /// <summary>
        /// エコーデータの書き込み
        /// </summary>
        /// <param name="connection"></param>
        /// <param name="data"></param>
        private static void WriteEcho(MrsConnection connection, byte[] data, uint data_len)
        {
            mrs.Time write_tm = new mrs.Time();
            write_tm.Set();
            mrs.Buffer buffer = new mrs.Buffer();
            buffer.WriteTime(write_tm);
            buffer.Write(data, data_len);

            if (m_canValidRecord)
            {
                mrs_write_record(connection, m_nRecordOptions, 0x01, buffer.GetData(), buffer.GetDataLen());
            }
            else
            {
                mrs_write(connection, buffer.GetData(), buffer.GetDataLen());
            }
        }
Пример #10
0
        /// <summary>
        /// 実行
        /// </summary>
        public void Run()
        {
            try
            {
                mrs_initialize();
                using (ExitSignal sig = new ExitSignal())
                {
                    sig.SetSignal((obj, e) =>
                    {
                        m_bLoop = false;
                        Thread.Sleep(10);
                    });

                    uint connections = 0;
                    for (uint i = 0; i < m_nConnections; ++i)
                    {
                        MrsConnection client = g_Connect.FallbackConnect();
                        if (client == IntPtr.Zero)
                        {
                            MRS_LOG_ERR("mrs_connect[{0}]: {1}", i, mrs_get_error_string(mrs_get_last_error()));
                            break;
                        }
                        ++connections;
                    }
                    if (connections != m_nConnections)
                    {
                        return;
                    }

                    while (m_bLoop)
                    {
                        mrs_update();
                        mrs_sleep(m_SleepMsec);
                    }
                }
            }
            catch (Exception e)
            {
                MRS_LOG_ERR(e.Message);
            }
            finally
            {
                mrs_finalize();
            }
        }
Пример #11
0
        /// <summary>
        /// フォールバック接続時に呼ばれる
        /// </summary>
        /// <param name="connection"></param>
        /// <param name="request"></param>
        private static void OnFallbackConnectCallback(MrsConnection connection, mrs.Connect.Request request)
        {
            MRS_LOG_DEBUG("OnFallbackConnectCallback connection_type={0} addr={1} port={2} timeout_msec={3}",
                          (int)request.ConnectionType, request.Addr, request.Port, request.TimeoutMsec);

            mrs_set_connect_callback(connection, m_OnConnect);
            mrs_set_disconnect_callback(connection, m_OnDisconnect);
            mrs_set_error_callback(connection, m_OnError);
            if (m_canValidRecord)
            {
                mrs_set_read_record_callback(connection, m_OnReadRecord);
            }
            else
            {
                mrs_set_read_callback(connection, m_OnRead);
            }
            mrs_connection_set_path(connection, m_ConnectionPath);
        }
Пример #12
0
        /// <summary>
        /// ソケットにエラーが発生した時に呼ばれる
        /// </summary>
        /// <param name="connection"></param>
        /// <param name="connection_data"></param>
        /// <param name="status"></param>
        private static void OnError(MrsConnection connection, IntPtr connection_data, MrsConnectionError status)
        {
            switch (status)
            {
            case MrsConnectionError.CONNECT_ERROR:
            case MrsConnectionError.CONNECT_TIMEOUT:
            {
                MrsConnection client = g_Connect.FallbackConnect(connection);
                if (client != IntPtr.Zero)
                {
                    return;
                }
            }
            break;

            default:
                break;
            }

            MRS_LOG_DEBUG("OnError local_mrs_version=0x{0} remote_mrs_version=0x{1} status={2}",
                          mrs_get_version(MRS_VERSION_KEY), mrs_connection_get_remote_version(connection, MRS_VERSION_KEY), mrs_get_connection_error_string(status));
        }
Пример #13
0
 /// <summary>
 /// エラー時に呼ばれる
 /// </summary>
 /// <param name="connection"></param>
 /// <param name="connection_data"></param>
 /// <param name="status"></param>
 private static void OnError(MrsConnection connection, IntPtr connection_data, MrsConnectionError status)
 {
     MRS_LOG_DEBUG("OnError {0} local_mrs_version=0x{1:X} remote_mrs_version=0x{2:X} status={3}",
                   ConnectionTypeToString(connection), mrs_get_version(MRS_VERSION_KEY), mrs_connection_get_remote_version(connection, MRS_VERSION_KEY), mrs_get_connection_error_string(status));
 }
Пример #14
0
        /// <summary>
        /// レコードのパース
        /// </summary>
        /// <param name="connection"></param>
        /// <param name="connection_data"></param>
        /// <param name="seqnum"></param>
        /// <param name="options"></param>
        /// <param name="payload_type"></param>
        /// <param name="_payload"></param>
        /// <param name="payload_len"></param>
        private static void ParseRecord(MrsConnection connection, IntPtr connection_data, UInt32 seqnum, UInt16 options, UInt16 payload_type, IntPtr _payload, UInt32 payload_len)
        {
            //MRS_LOG_DEBUG("ParseRecord seqnum=0x{0:X} options=0x{1:X} payload type={2:X} payload len={3}", seqnum, options, payload_type, payload_len);
            switch (payload_type)
            {
            // MRS_PAYLOAD_TYPE_BEGIN - MRS_PAYLOAD_TYPE_ENDの範囲内で任意のIDを定義し、対応するアプリケーションコードを記述する
            case 0x01:
            {
                g_payloadType = 0x02;
                int i = 0;

                for (; i < m_MaxPlayer; i++)
                {
                    if (connection == m_nowConnect[i])
                    {
                        for (int j = 0; j < nowplayers; j++)
                        {
                            if (i != j)
                            {
                                IntPtr p_Send = m_gameProc.getProfileData(j);
                                mrs_write_record(m_nowConnect[i], options, g_payloadType, p_Send, (uint)m_gameProc.getProfileSize(j));
                                MRS_LOG_DEBUG("SENT No.{0} Player to No.{1} Player's Data", i, j);
                            }
                        }
                        break;
                    }
                }
                IntPtr p_data = m_gameProc.setProfile(_payload, i);

                g_payloadType = 0x01;
                for (int j = 0; j < nowplayers; j++)
                {
                    if (j == i)
                    {
                        g_payloadType = 0x01;
                        mrs_write_record(m_nowConnect[j], options, g_payloadType, p_data, (uint)Marshal.SizeOf(m_gameProc.getProfile(i)));
                    }
                    if (j != i && m_nowConnect[j] != (IntPtr)0)
                    {
                        g_payloadType = 0x02;
                        mrs_write_record(m_nowConnect[j], options, g_payloadType, p_data, (uint)m_gameProc.getProfileSize(i));
                    }
                }
            }
            break;

            // 0x03 ゲームスタート準備
            case 0x03:
            {
                g_isPlay      = true;
                nowplayers    = mrs_get_connection_num();
                g_payloadType = 0x03;
                MRS_LOG_DEBUG("received 0x03 data");
                // ゲーム処理初期化
                m_gameProc.Initialize();
                readybit = 0;

                g_isRoom = false;

                // ゲームスタートに必要なデータの作成・送信
                IntPtr sendptr = m_gameProc.getStartData((int)nowplayers);

                for (int i = 0; i < nowplayers; i++)
                {
                    mrs_write_record(m_nowConnect[i], options, g_payloadType, sendptr, (uint)m_gameProc.getStartDataSize());
                }
                MRS_LOG_DEBUG("sent start data");
                Marshal.FreeHGlobal(sendptr);
            }
            break;

            // 0x04 クライアント達の初期位置設定待ち
            case 0x04:
            {
                int i = 0;
                for (; i < m_MaxPlayer; i++)
                {
                    if (connection == m_nowConnect[i])
                    {
                        break;
                    }
                }
                MRS_LOG_DEBUG("received 0x04 data from Player no.{0}", i);

                m_gameProc.setPlayerData(i, _payload);


                readybit += 1 << i;

                MRS_LOG_DEBUG("READY BIT : {0}", Convert.ToString(readybit, 2));

                int correctBit = 0;
                for (int j = 0; j < mrs_get_connection_num(); j++)
                {
                    correctBit += 1 << j;
                }
                if (readybit == correctBit)
                {
                    g_payloadType = 0x04;
                    SendDataEveryone();
                    MRS_LOG_DEBUG("EVERYONE READY!");

                    g_gameon = true;
                }
            }
            break;

            // 0x05 カウントダウン開始の告知
            case 0x05:
            {
                for (int i = 0; i < nowplayers; i++)
                {
                    if (m_nowConnect[i].ToInt32() != 0)
                    {
                        mrs_write_record(m_nowConnect[i], options, payload_type, _payload, payload_len);
                    }
                }
            }
            break;

            // 0x06 カウントダウン時間の送受信
            case 0x06:
            {
                for (int i = 0; i < nowplayers; i++)
                {
                    if (m_nowConnect[i].ToInt32() != 0)
                    {
                        mrs_write_record(m_nowConnect[i], options, payload_type, _payload, payload_len);
                    }
                }
            }
            break;

            // 0x07 ステージ番号の送受信
            case 0x07:
                unsafe {
                    int stageid = *(int *)_payload;
                    m_gameProc.setStageId(stageid);

                    for (int i = 0; i < nowplayers; i++)
                    {
                        if (m_nowConnect[i].ToInt32() != 0)
                        {
                            mrs_write_record(m_nowConnect[i], options, payload_type, _payload, payload_len);
                        }
                    }
                }
                break;

            // プレイヤーデータ送受信用PayloadType
            case 0x12:
            {
                if (g_gameon)
                {
                    int i = 0;
                    for (; i < m_MaxPlayer; i++)
                    {
                        if (connection == m_nowConnect[i])
                        {
                            break;
                        }
                    }

                    m_gameProc.setPlayerData(i, _payload);

                    for (int j = 0; j < mrs_get_connection_num(); j++)
                    {
                        if (j != i)
                        {
                            if (m_nowConnect[j].ToInt32() != 0)
                            {
                                mrs_write_record(m_nowConnect[j], options, payload_type, _payload, payload_len);
                            }
                        }
                    }
                }
            }
            break;

            // ショットデータ送受信用Type
            case 0x13:
            {
                if (g_gameon)
                {
                    IntPtr send = m_gameProc.setShotData(_payload);

                    for (int j = 0; j < nowplayers; j++)
                    {
                        if (m_nowConnect[j].ToInt32() != 0)
                        {
                            mrs_write_record(m_nowConnect[j], options, payload_type, send, payload_len);
                        }
                    }
                }
            }
            break;

            // 床の落下の合図、全員に合図を送信
            case 0x15:
            {
                MRS_LOG_DEBUG("RECIEVE 0x15  FALL FLOOR !!");
                for (int i = 0; i < nowplayers; i++)
                {
                    if (m_nowConnect[i].ToInt32() != 0)
                    {
                        mrs_write_record(m_nowConnect[i], options, payload_type, _payload, payload_len);
                    }
                }
            } break;

            // 弾の反射情報
            case 0x16:
            {
                MRS_LOG_DEBUG("RECIEVE 0x16  REFLEXION SHOT !!");
                for (int i = 0; i < nowplayers; i++)
                {
                    if (m_nowConnect[i].ToInt32() != 0)
                    {
                        mrs_write_record(m_nowConnect[i], options, payload_type, _payload, payload_len);
                    }
                }
            }
            break;

            //------------------------------------ 死亡判定系 0x2#

            // 落下死
            case 0x21:
            {
                MRS_LOG_DEBUG("RECIEVE SOMEONE FALLING !!");
                for (int i = 0; i < nowplayers; i++)
                {
                    if (m_nowConnect[i].ToInt32() != 0)
                    {
                        mrs_write_record(m_nowConnect[i], options, payload_type, _payload, payload_len);
                    }
                }
            }
            break;

            // 被弾死
            case 0x22:
            {
                MRS_LOG_DEBUG("RECIEVE SOMEONE TAKING SHOT !!");

                IntPtr sendHit = m_gameProc.SomeoneDeadHit(_payload);
                for (int i = 0; i < nowplayers; i++)
                {
                    if (m_nowConnect[i].ToInt32() != 0)
                    {
                        mrs_write_record(m_nowConnect[i], options, payload_type, sendHit, payload_len);
                    }
                }
            }
            break;

            //------------------------------------ シーン切り替え 0x3#
            // リザルト表示中
            case 0x31:
            {
                MRS_LOG_DEBUG("ON_RESULT");
                g_gameon = false;
                m_gameProc.setStageId(1);
            }
            break;

            // ルームに戻る選択を受信
            case 0x32:
            {
                MRS_LOG_DEBUG("BACK_ROOM");
                for (int i = 0; i < nowplayers; i++)
                {
                    if (m_nowConnect[i].ToInt32() != 0)
                    {
                        mrs_write_record(m_nowConnect[i], options, 0x32, null, 0);
                    }
                }
                g_isRoom = true;
                g_isPlay = false;
            }
            break;

            // タイトルに戻る選択を受信
            case 0x33: {
                MRS_LOG_DEBUG("BACK_TITLE");
                for (int i = 0; i < nowplayers; i++)
                {
                    if (m_nowConnect[i].ToInt32() != 0)
                    {
                        mrs_write_record(m_nowConnect[i], options, 0x33, null, 0);
                    }
                }
                g_isPlay = false;
            }
            break;
            }
        }
Пример #15
0
 /// <summary>
 /// バイナリデータ受信時に呼ばれる
 /// </summary>
 /// <param name="connection"></param>
 /// <param name="connection_data"></param>
 /// <param name="_data"></param>
 /// <param name="data_len"></param>
 private static void OnRead(MrsConnection connection, IntPtr connection_data, IntPtr _data, UInt32 data_len)
 {
     ReadEcho(connection, _data, data_len);
 }
Пример #16
0
 /// <summary>
 /// レコード受信時に呼ばれる
 /// </summary>
 /// <param name="connection"></param>
 /// <param name="connection_data"></param>
 /// <param name="seqnum"></param>
 /// <param name="options"></param>
 /// <param name="payload_type"></param>
 /// <param name="_payload"></param>
 /// <param name="payload_len"></param>
 private static void OnReadRecord(MrsConnection connection, IntPtr connection_data, UInt32 seqnum, UInt16 options, UInt16 payload_type, IntPtr _payload, UInt32 payload_len)
 {
     ParseRecord(connection, connection_data, seqnum, options, payload_type, _payload, payload_len);
 }
Пример #17
0
 /// <summary>
 /// ソケット切断時に呼ばれる
 /// </summary>
 /// <param name="connection"></param>
 /// <param name="connection_data"></param>
 private static void OnDisconnect(MrsConnection connection, IntPtr connection_data)
 {
     MRS_LOG_DEBUG("OnDisconnect local_mrs_version=0x{0} remote_mrs_version=0x{1}",
                   mrs_get_version(MRS_VERSION_KEY), mrs_connection_get_remote_version(connection, MRS_VERSION_KEY));
 }
Пример #18
0
 /// <summary>
 /// 鍵交換した時に呼ばれる
 /// </summary>
 /// <param name="connection"></param>
 /// <param name="connection_data"></param>
 private static void OnKeyExchange(MrsConnection connection, IntPtr connection_data)
 {
     MRS_LOG_DEBUG("OnKeyExchange");
     WriteEchoAll(connection);
 }