WebSocketBroker クラスは、mpchat_server で WebSocketMessageHandler を利用している部分である。 定義は次のようになっている:
class WebSocketBroker: public nine::WebSocketMessageHandler
{
public:
bool initialize(ChatService*);
virtual void turn();
virtual bool handleMessage(nine::Message*);
virtual void onSessionOpen(int sid, nine::WebSocketChannel* pChannel);
virtual void onSessionClose(int sid);
private:
void notifyLog(int cid);
ChatService* m_pService;
struct Comm {
inline Comm() { }
bool connected;
int lastIndex;
};
std::vector< Comm > m_comms;
};
WebSocketBroker は WebSocketMessageHandler であり、WebSocketHandler である。 WebSocketHandler は、HttpServer の authorizeWebSocket() 関数の戻り値としてフレームワークに渡すことで利用されるようになる。
bool Server::initialize(const ServerConfig* pCfg)
{
...
if (! m_wsBroker.initialize(&m_service)) {
return false;
}
m_httpServer.setHandler("/ws", &m_wsBroker);
m_httpServer は PathHttpServer である。
setHandler() により、WebSocketBroker は "/ws" のリクエストパスに対応するよう設定される。
bool WebSocketBroker::initialize(ChatService* pService)
{
{
typedef nine::WebSocketMessageHandler super;
nine::WebSocketMessageHandlerConfig cfg;
cfg.nSessions = 10;
cfg.sessionTimeoutSec = 0;
if (! super::initialize(&cfg)) {
return false;
}
}
m_comms.resize(10);
for (int i=0; i<m_comms.size(); ++i) {
m_comms[i].connected = false;
}
m_pService = pService;
return true;
}
notifyLog() は private 関数であり、このクラスの他の関数から呼ばれる。 処理内容は、ChatService からログを取得し、LogNotify メッセージに入れて post することである。
void WebSocketBroker::notifyLog(int cid)
{
LogNotify msg;
m_pService->get(m_comms[cid].lastIndex, &msg);
int n = msg.get_chat_length();
if (n == 0) {
return;
}
if (! post(cid, &msg)) {
return;
}
m_comms[cid].lastIndex = msg.get_chat(n-1).get_index();
}
ChatService::get() では、受け取るログの最初の番号を指定できる。 WebSocketBroker はこの番号を lastIndex に記憶しておき、get() に渡している。
WebSocket は常時接続されているが、送信バッファがいっぱいの場合などで post() は失敗する。 post() 成功時に、最後に送信したメッセージ番号を更新するようにしている。
handleMessage() は、要求に含まれていたメッセージを処理するハンドラである。
bool WebSocketBroker::handleMessage(nine::Message* pMsg)
{
int cid = pMsg->getCommunicatorId();
int msgid = pMsg->getMessageId();
if (msgid == ChatRequest::MESSAGE_ID) {
ChatRequest* p = static_cast< ChatRequest* >(pMsg);
m_pService->add(p->get_chat());
notifyLog(cid);
return true;
} else if (msgid == LogRequest::MESSAGE_ID) {
return true;
}
return false;
}
ChatRequest は、クライアントが新規発言をした際に送られるメッセージである。 ChatRequest は同時に発言ログの要求も行う。
if (msgid == ChatRequest::_MESSAGE_ID) {
ChatRequest* p = static_cast< ChatRequest* >(pMsg);
m_pService->add(p->get_chat());
notifyLog(cid);
return true;
WebSocketBroker は最後に送信したログを記憶しているので、ChatRequest のログ番号指示は無視している。