部屋へ入る

handleEnterRoom

EnterRoomRequest を受け取ると、handleEnterRoom が呼ばれる。 ここで入室処理を記述する。

bool SampleRoomModule::handleEnterRoom(Room* _pRoom, EnterRoomRequest* pMsg, ResponseMessage* pRes, SessionHandle& hSession)
{
   if (! SampleEnterRoomRequest::Check(pMsg)) { return false; }
   SampleRoom *pRoom = static_cast< SampleRoom* >(_pRoom);

   char pw[20];
   memset(pw, 0, 20);
   SampleEnterRoomRequest::GetPassword(pMsg, pw);

   pRoom->lock();
   while (true) {
      if (! pRoom->enter(hSession, pw)) {
         pRes->setResult(ResponseMessage::ERR_INTERNAL);
         break;
      }
      if (pRoom->countMembers() == pRoom->getMemberSize()) {
         if (! pRoom->match()) {
            pRoom->leave(hSession);
            pRes->setResult(ResponseMessage::ERR_INTERNAL);
            break;
         }
      }
      break;
   }
   pRoom->unlock();

   if (pRes->isSucceed()) {
      EnterRoomNotify *p = new EnterRoomNotify();
      p->domainIndex = hSession.domain()->index();
      p->roomId = pRoom->id();
      hSession.session()->queueMessage(p);

      notifyRoom(pRoom);
   }

   return true;
}

SampleEnterRoomRequest

前半では EnterRoomRequest の拡張情報を処理している。

   if (! SampleEnterRoomRequest::Check(pMsg)) { return false; }
   SampleRoom *pRoom = static_cast< SampleRoom* >(_pRoom);

   char pw[20];
   memset(pw, 0, 20);
   SampleEnterRoomRequest::GetPassword(pMsg, pw);

拡張情報としてパスワードを格納しているので、それをローカル変数 pw に取り出している。

入室処理

続いて lock/unlock に挟まれて入室処理が書かれている。

   pRoom->lock();
   while (true) {
      if (! pRoom->enter(hSession, pw)) {
         pRes->setResult(ResponseMessage::ERR_INTERNAL);
         break;
      }
      if (pRoom->countMembers() == pRoom->getMemberSize()) {
         if (! pRoom->match()) {
            pRoom->leave(hSession);
            pRes->setResult(ResponseMessage::ERR_INTERNAL);
            break;
         }
      }
      break;
   }
   pRoom->unlock();

while を使っているのは break で脱出するためで、ループの意図は無い。

後半の if ブロックは、入室後に満員になった場合の処理である。これはマッチングチュートリアルで説明する。

さて、そうなると実際の入室処理は Room::enter を呼んでいるだけである。

SampleRoom::enter

enter は、メンバーの入室を行う。 同期化のコードのせいでやや見にくいので、簡単に書きなおしたものを示す:

bool SampleRoom::enter(const SessionHandle& hSession, const char password[20])
{
   const SampleRoomMatchInfo* p = getSampleMatchInfo();
   if (memcmp(p->password, password, 20) != 0) {
      return false;
   }

   if (! addMember(hSession)) {
     return false;
   }
   return true;
}

まずはパスワードのチェックをしている。 引数の password は EnterRoomRequest の拡張データに含まれていたもので、クライアントが送ってきた文字列である。 SampleRoomMatchInfo の password メンバ変数は、部屋を開く時に与えられたものである。

パスワードを確認したら、Room ベースクラスで定義されている addMember を呼ぶ。 ここでメンバー追加を行ってくれる。

EnterRoomNotify, RoomInfoNotify

RoomModule は入室を終えたらメッセージを投げる処理を記述する。

   if (pRes->isSucceed()) {
      EnterRoomNotify *p = new EnterRoomNotify();
      p->domainIndex = hSession.domain()->index();
      p->roomId = pRoom->id();
      hSession.session()->queueMessage(p);

      notifyRoom(pRoom);
   }
これも部屋を開く時の処理と同じで、
  • EnterRoomNotify を入室者に
  • RoomInfoNotify を入室者を含む部屋の全員に
送っている。