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;
}
前半では 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 を呼んでいるだけである。
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 を呼ぶ。 ここでメンバー追加を行ってくれる。
RoomModule は入室を終えたらメッセージを投げる処理を記述する。
if (pRes->isSucceed()) {
EnterRoomNotify *p = new EnterRoomNotify();
p->domainIndex = hSession.domain()->index();
p->roomId = pRoom->id();
hSession.session()->queueMessage(p);
notifyRoom(pRoom);
}