bool ServerSocketInterface::initSession()
{
    Event_ServerIdentification identEvent;
    identEvent.set_server_name(servatrice->getServerName().toStdString());
    identEvent.set_server_version(VERSION_STRING);
    identEvent.set_protocol_version(protocolVersion);
    SessionEvent *identSe = prepareSessionEvent(identEvent);
    sendProtocolItem(*identSe);
    delete identSe;
    
    int maxUsers = servatrice->getMaxUsersPerAddress();

    //allow unlimited number of connections from the trusted sources
    QString trustedSources = settingsCache->value("server/trusted_sources","127.0.0.1,::1").toString();
    if (trustedSources.contains(socket->peerAddress().toString(),Qt::CaseInsensitive))
        return true;
    
    if ((maxUsers > 0) && (servatrice->getUsersWithAddress(socket->peerAddress()) >= maxUsers)) {
        Event_ConnectionClosed event;
        event.set_reason(Event_ConnectionClosed::TOO_MANY_CONNECTIONS);
        SessionEvent *se = prepareSessionEvent(event);
        sendProtocolItem(*se);
        delete se;

        return false;
    }

    return true;
}
void Server_AbstractUserInterface::sendProtocolItemByType(ServerMessage::MessageType type, const ::google::protobuf::Message &item)
{
    switch (type) {
        case ServerMessage::RESPONSE: sendProtocolItem(static_cast<const Response &>(item)); break;
        case ServerMessage::SESSION_EVENT: sendProtocolItem(static_cast<const SessionEvent &>(item)); break;
        case ServerMessage::GAME_EVENT_CONTAINER: sendProtocolItem(static_cast<const GameEventContainer &>(item)); break;
        case ServerMessage::ROOM_EVENT: sendProtocolItem(static_cast<const RoomEvent &>(item)); break;
    }
}
void Server_ProtocolHandler::processCommandContainer(CommandContainer *cont)
{
	const QList<Command *> &cmdList = cont->getCommandList();
	ResponseCode finalResponseCode = RespOk;
	for (int i = 0; i < cmdList.size(); ++i) {
		ResponseCode resp = processCommandHelper(cmdList[i], cont);
		if ((resp != RespOk) && (resp != RespNothing))
			finalResponseCode = resp;
	}
	
	ProtocolResponse *pr = cont->getResponse();
	if (!pr)
		pr = new ProtocolResponse(cont->getCmdId(), finalResponseCode);

	GameEventContainer *gQPublic = cont->getGameEventQueuePublic();
	if (gQPublic) {
		Server_Game *game = games.value(gQPublic->getGameId()).first;
		Server_Player *player = games.value(gQPublic->getGameId()).second;
		GameEventContainer *gQPrivate = cont->getGameEventQueuePrivate();
		GameEventContainer *gQOmniscient = cont->getGameEventQueueOmniscient();
		if (gQPrivate) {
			int privatePlayerId = cont->getPrivatePlayerId();
			Server_Player *privatePlayer;
			if (privatePlayerId == -1)
				privatePlayer = player;
			else
				privatePlayer = game->getPlayer(privatePlayerId);
			if (gQOmniscient) {
				game->sendGameEventContainer(gQPublic, privatePlayer, true);
				game->sendGameEventContainerOmniscient(gQOmniscient, privatePlayer);
			} else
				game->sendGameEventContainer(gQPublic, privatePlayer);
			privatePlayer->sendProtocolItem(gQPrivate);
		} else
			game->sendGameEventContainer(gQPublic);
	}
	
	const QList<ProtocolItem *> &iQ = cont->getItemQueue();
	for (int i = 0; i < iQ.size(); ++i)
		sendProtocolItem(iQ[i]);
	
	sendProtocolItem(pr);
	
	while (!itemQueue.isEmpty())
		sendProtocolItem(itemQueue.takeFirst());

	if (cont->getReceiverMayDelete())
		delete cont;
}
void ServerSocketInterface::processProtocolItem(ProtocolItem *item)
{
	CommandContainer *cont = qobject_cast<CommandContainer *>(item);
	if (!cont)
		sendProtocolItem(new ProtocolResponse(cont->getCmdId(), RespInvalidCommand));
	else
		processCommandContainer(cont);
}
bool ServerSocketInterface::initSession()
{
    Event_ServerIdentification identEvent;
    identEvent.set_server_name(servatrice->getServerName().toStdString());
    identEvent.set_server_version(VERSION_STRING);
    identEvent.set_protocol_version(protocolVersion);
    SessionEvent *identSe = prepareSessionEvent(identEvent);
    sendProtocolItem(*identSe);
    delete identSe;

	//limit the number of total users based on configuration settings
	bool enforceUserLimit = settingsCache->value("security/enable_max_user_limit", false).toBool();
	if (enforceUserLimit){
		int userLimit = settingsCache->value("security/max_users_total", 500).toInt();
		int playerCount = (databaseInterface->getActiveUserCount() + 1);
		if (playerCount > userLimit){
			std::cerr << "Max Users Total Limit Reached, please increase the max_users_total setting." << std::endl;
			logger->logMessage(QString("Max Users Total Limit Reached, please increase the max_users_total setting."), this);
			Event_ConnectionClosed event;
			event.set_reason(Event_ConnectionClosed::USER_LIMIT_REACHED);
			SessionEvent *se = prepareSessionEvent(event);
			sendProtocolItem(*se);
			delete se;
			return false;
		}
	}

    //allow unlimited number of connections from the trusted sources
    QString trustedSources = settingsCache->value("security/trusted_sources","127.0.0.1,::1").toString();
    if (trustedSources.contains(socket->peerAddress().toString(),Qt::CaseInsensitive))
        return true;
    
	int maxUsers = servatrice->getMaxUsersPerAddress();
    if ((maxUsers > 0) && (servatrice->getUsersWithAddress(socket->peerAddress()) >= maxUsers)) {
        Event_ConnectionClosed event;
        event.set_reason(Event_ConnectionClosed::TOO_MANY_CONNECTIONS);
        SessionEvent *se = prepareSessionEvent(event);
        sendProtocolItem(*se);
        delete se;

        return false;
    }

    return true;
}
void Server_ProtocolHandler::pingClockTimeout()
{

    int cmdcountinterval = server->getCommandCountingInterval();
    int msgcountinterval = server->getMessageCountingInterval();
    int pingclockinterval = server->getClientKeepAlive();

    int interval = server->getMessageCountingInterval();
    if (interval > 0) {
        if(pingclockinterval > 0) {
            messageSizeOverTime.prepend(0);
            if (messageSizeOverTime.size() > (msgcountinterval / pingclockinterval))
                messageSizeOverTime.removeLast();
            messageCountOverTime.prepend(0);
            if (messageCountOverTime.size() > (msgcountinterval / pingclockinterval))
                messageCountOverTime.removeLast();
        }
    }

    interval = server->getCommandCountingInterval();
    if (interval > 0) {
        if (pingclockinterval > 0) {
            commandCountOverTime.prepend(0);
            if (commandCountOverTime.size() > (cmdcountinterval / pingclockinterval))
                commandCountOverTime.removeLast();
        }
    }

    if (timeRunning - lastDataReceived > server->getMaxPlayerInactivityTime())
        prepareDestroy();

    if (!userInfo || QString::fromStdString(userInfo->privlevel()).toLower() == "none") {
        if ((server->getIdleClientTimeout() > 0) && (idleClientWarningSent)) {
            if (timeRunning - lastActionReceived > server->getIdleClientTimeout()) {
                prepareDestroy();
            }
        }

        if (((timeRunning - lastActionReceived) >= ceil(server->getIdleClientTimeout() *.9)) && (!idleClientWarningSent) && (server->getIdleClientTimeout() > 0)) {
            Event_NotifyUser event;
            event.set_type(Event_NotifyUser::IDLEWARNING);
            SessionEvent *se = prepareSessionEvent(event);
            sendProtocolItem(*se);
            delete se;
            idleClientWarningSent = true;
        }
    }

    ++timeRunning;
}
ServerSocketInterface::ServerSocketInterface(Servatrice *_server, QTcpSocket *_socket, QObject *parent)
	: Server_ProtocolHandler(_server, parent), servatrice(_server), socket(_socket), topLevelItem(0)
{
	xmlWriter = new QXmlStreamWriter;
	xmlWriter->setDevice(socket);
	
	xmlReader = new QXmlStreamReader;
	
	connect(socket, SIGNAL(readyRead()), this, SLOT(readClient()));
	connect(socket, SIGNAL(disconnected()), this, SLOT(deleteLater()));
	connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(catchSocketError(QAbstractSocket::SocketError)));
	
	xmlWriter->writeStartDocument();
	xmlWriter->writeStartElement("cockatrice_server_stream");
	xmlWriter->writeAttribute("version", QString::number(ProtocolItem::protocolVersion));
	
	sendProtocolItem(new Event_ServerMessage(Servatrice::versionString));
}
void Server_AbstractUserInterface::sendResponseContainer(const ResponseContainer &responseContainer, Response::ResponseCode responseCode)
{
    const QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *> > &preResponseQueue = responseContainer.getPreResponseQueue();
    for (int i = 0; i < preResponseQueue.size(); ++i)
        sendProtocolItemByType(preResponseQueue[i].first, *preResponseQueue[i].second);
    
    if (responseCode != Response::RespNothing) {
        Response response;
        response.set_cmd_id(responseContainer.getCmdId());
        response.set_response_code(responseCode);
        ::google::protobuf::Message *responseExtension = responseContainer.getResponseExtension();
        if (responseExtension)
            response.GetReflection()->MutableMessage(&response, responseExtension->GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(*responseExtension);
        sendProtocolItem(response);
    }
    
    const QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *> > &postResponseQueue = responseContainer.getPostResponseQueue();
    for (int i = 0; i < postResponseQueue.size(); ++i)
        sendProtocolItemByType(postResponseQueue[i].first, *postResponseQueue[i].second);
}