#include "session.h"
// This file is part of MRCI.
// MRCI is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// MRCI is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with MRCI under the LICENSE.md file. If not, see
// .
void Session::acctDeleted(const QByteArray &data)
{
if (flags & LOGGED_IN)
{
// format: [32bytes(user_id)]
if (memcmp(userId, data.data(), BLKSIZE_USER_ID) == 0)
{
logout("", true);
asyncToClient(ASYNC_SYS_MSG, toTEXT("\nsystem: your session was forced to logout because your account was deleted.\n"), TEXT);
asyncToClient(ASYNC_USER_DELETED, data, TEXT);
}
}
}
void Session::acctEdited(const QByteArray &data)
{
if (flags & LOGGED_IN)
{
// format: [32bytes(user_id)]
if (memcmp(userId, data.data(), BLKSIZE_USER_ID) == 0)
{
sendLocalInfo();
}
}
}
void Session::acctRenamed(const QByteArray &data)
{
if (flags & LOGGED_IN)
{
// format: [32bytes(user_id)][48bytes(new_user_name)]
if (memcmp(userId, data.data(), BLKSIZE_USER_ID) == 0)
{
memcpy(userName, data.data() + BLKSIZE_USER_ID, BLKSIZE_USER_NAME);
castPeerInfo(PEER_INFO);
sendLocalInfo();
}
}
}
void Session::acctDispChanged(const QByteArray &data)
{
if (flags & LOGGED_IN)
{
// format: [32bytes(user_id)][64bytes(new_disp_name)]
if (memcmp(userId, data.data(), BLKSIZE_USER_ID) == 0)
{
memcpy(displayName, data.data() + BLKSIZE_USER_ID, BLKSIZE_DISP_NAME);
castPeerInfo(PEER_INFO);
sendLocalInfo();
}
}
}
void Session::castCatch(const QByteArray &data)
{
// format: [54bytes(chIds)][1byte(typeId)][rest-of-bytes(payload)]
if (matchChs(openSubChs, data.data()))
{
int payloadOffs = (MAX_OPEN_SUB_CHANNELS * BLKSIZE_SUB_CHANNEL) + 1;
quint8 typeId = static_cast(data[payloadOffs - 1]);
quint32 len = static_cast(data.size() - payloadOffs);
const char *payload = data.data() + payloadOffs;
asyncToClient(ASYNC_CAST, rdFromBlock(payload, len), typeId);
}
}
void Session::directDataFromPeer(const QByteArray &data)
{
// format: [28bytes(sessionId)][1byte(typeId)][rest-of-bytes(payload)]
if (memcmp(sessionId, data.data(), BLKSIZE_SESSION_ID) == 0)
{
int payloadOffs = BLKSIZE_SESSION_ID + 1;
quint8 typeId = static_cast(data[payloadOffs - 1]);
quint32 len = static_cast(data.size() - payloadOffs);
const char *payload = data.data() + payloadOffs;
asyncToClient(ASYNC_TO_PEER, rdFromBlock(payload, len), typeId);
}
}
void Session::p2p(const QByteArray &data)
{
// format: [28bytes(dst_sessionId)][28bytes(src_sessionId)][1byte(typeId)][rest-of-bytes(payload)]
if (memcmp(sessionId, data.data(), BLKSIZE_SESSION_ID) == 0)
{
int payloadOffs = (BLKSIZE_SESSION_ID * 2) + 1;
const char *src = data.data() + BLKSIZE_SESSION_ID;
const char *payload = data.data() + payloadOffs;
quint32 len = static_cast(data.size() - payloadOffs);
quint8 typeId = static_cast(data[payloadOffs - 1]);
if (typeId == P2P_REQUEST)
{
if (posOfBlock(src, p2pAccepted, MAX_P2P_LINKS, BLKSIZE_SESSION_ID) == -1)
{
if (addBlockToBlockset(src, p2pPending, MAX_P2P_LINKS, BLKSIZE_SESSION_ID))
{
asyncToClient(ASYNC_P2P, rdFromBlock(payload, len), P2P_REQUEST);
}
}
}
else if (typeId == P2P_OPEN)
{
if (rmBlockFromBlockset(src, p2pPending, MAX_P2P_LINKS, BLKSIZE_SESSION_ID))
{
if (addBlockToBlockset(src, p2pAccepted, MAX_P2P_LINKS, BLKSIZE_SESSION_ID))
{
asyncToClient(ASYNC_P2P, rdFromBlock(payload, len), P2P_OPEN);
}
}
}
else if (typeId == P2P_CLOSE)
{
if (rmBlockFromBlockset(src, p2pPending, MAX_P2P_LINKS, BLKSIZE_SESSION_ID))
{
asyncToClient(ASYNC_P2P, rdFromBlock(payload, len), P2P_CLOSE);
}
else if (rmBlockFromBlockset(src, p2pAccepted, MAX_P2P_LINKS, BLKSIZE_SESSION_ID))
{
asyncToClient(ASYNC_P2P, rdFromBlock(payload, len), P2P_CLOSE);
}
}
else if (posOfBlock(src, p2pAccepted, MAX_P2P_LINKS, BLKSIZE_SESSION_ID) != -1)
{
asyncToClient(ASYNC_P2P, rdFromBlock(src, BLKSIZE_SESSION_ID) + rdFromBlock(payload, len), typeId);
}
}
}
void Session::closeP2P(const QByteArray &data)
{
// format: [28bytes(src_sessionId)]
if (rmBlockFromBlockset(data.data(), p2pAccepted, MAX_P2P_LINKS, BLKSIZE_SESSION_ID) ||
rmBlockFromBlockset(data.data(), p2pPending, MAX_P2P_LINKS, BLKSIZE_SESSION_ID))
{
asyncToClient(ASYNC_P2P, data, P2P_CLOSE);
}
}
void Session::limitedCastCatch(const QByteArray &data)
{
// format: [54bytes(chIds)][1byte(typeId)][rest-of-bytes(payload)]
if (rd8BitFromBlock(activeUpdate) && matchChs(openSubChs, data.data()))
{
int payloadOffs = (MAX_OPEN_SUB_CHANNELS * BLKSIZE_SUB_CHANNEL) + 1;
quint32 len = static_cast(data.size() - payloadOffs);
quint8 typeId = static_cast(data[payloadOffs - 1]);
const char *payload = data.data() + payloadOffs;
if (typeId == PING_PEERS)
{
// PING_PEERS is formatted exactly like PEER_INFO. it only tells this
// async command to also send PEER_INFO of this session to the session
// that requested the ping using ASYNC_TO_PEER.
QByteArray peerId = rdFromBlock(payload, BLKSIZE_SESSION_ID);
QByteArray typeId = wrInt(PEER_INFO, 8);
QByteArray info = createPeerInfoFrame();
emit asyncToPeers(ASYNC_TO_PEER, peerId + typeId + info);
asyncToClient(ASYNC_LIMITED_CAST, rdFromBlock(payload, len), PEER_INFO);
}
else
{
asyncToClient(ASYNC_LIMITED_CAST, rdFromBlock(payload, len), typeId);
}
}
}
void Session::updateRankViaUser(const QByteArray &data)
{
if (flags & LOGGED_IN)
{
// format: [32bytes(userId)][4bytes(newRank)]
if (memcmp(data.data(), userId, BLKSIZE_USER_ID) == 0)
{
wr32BitToBlock(rd32BitFromBlock(data.data() + BLKSIZE_USER_ID), hostRank);
sendLocalInfo();
loadCmds();
}
}
}
void Session::userAddedToChannel(quint16 cmdId, const QByteArray &data)
{
// format: [8bytes(chId)][32bytes(userId)]
if (memcmp(data.data() + BLKSIZE_CHANNEL_ID, userId, BLKSIZE_USER_ID) == 0)
{
if ((cmdId == ASYNC_NEW_CH_MEMBER) || (cmdId == ASYNC_INVITE_ACCEPTED))
{
addBlockToBlockset(data.data(), chList, MAX_CHANNELS_PER_USER, BLKSIZE_CHANNEL_ID);
}
asyncToClient(cmdId, data, CH_MEMBER_INFO);
}
else if (posOfBlock(data.data(), chList, MAX_CHANNELS_PER_USER, BLKSIZE_CHANNEL_ID) != -1)
{
asyncToClient(cmdId, data, CH_MEMBER_INFO);
}
}
void Session::userRemovedFromChannel(const QByteArray &data)
{
// format: [8bytes(chId)][32bytes(user_id)]
if (memcmp(data.data() + BLKSIZE_CHANNEL_ID, userId, BLKSIZE_USER_ID) == 0)
{
closeByChId(rdFromBlock(data.data(), BLKSIZE_CHANNEL_ID), true);
rmBlockFromBlockset(data.data(), chList, MAX_CHANNELS_PER_USER, BLKSIZE_CHANNEL_ID);
asyncToClient(ASYNC_RM_CH_MEMBER, data, BYTES);
}
else if (posOfBlock(data.data(), chList, MAX_CHANNELS_PER_USER, BLKSIZE_CHANNEL_ID) != -1)
{
asyncToClient(ASYNC_RM_CH_MEMBER, data, BYTES);
}
}
void Session::channelDeleted(const QByteArray &data)
{
// format: [8bytes(chId)]
if (rmBlockFromBlockset(data.data(), chList, MAX_CHANNELS_PER_USER, BLKSIZE_CHANNEL_ID))
{
closeByChId(data, false);
asyncToClient(ASYNC_DEL_CH, data, CH_ID);
}
else if (rmLikeBlkFromBlkset(data, openSubChs, MAX_OPEN_SUB_CHANNELS, BLKSIZE_SUB_CHANNEL))
{
rmLikeBlkFromBlkset(data, openWritableSubChs, MAX_OPEN_SUB_CHANNELS, BLKSIZE_SUB_CHANNEL);
asyncToClient(ASYNC_DEL_CH, data, CH_ID);
}
}
void Session::channelMemberLevelUpdated(const QByteArray &data)
{
// format: [8bytes(chId)][32bytes(user_id)]
if (memcmp(data.data() + BLKSIZE_CHANNEL_ID, userId, BLKSIZE_USER_ID) == 0)
{
closeByChId(rdFromBlock(data.data(), BLKSIZE_CHANNEL_ID), true);
asyncToClient(ASYNC_MEM_LEVEL_CHANGED, data, BYTES);
}
else if (posOfBlock(data.data(), chList, MAX_CHANNELS_PER_USER, BLKSIZE_CHANNEL_ID) != -1)
{
asyncToClient(ASYNC_MEM_LEVEL_CHANGED, data, BYTES);
}
}
void Session::channelRenamed(const QByteArray &data)
{
// format: [8bytes(chId)]
if (posOfBlock(data.data(), chList, MAX_CHANNELS_PER_USER, BLKSIZE_CHANNEL_ID) != -1)
{
asyncToClient(ASYNC_RENAME_CH, data, BYTES);
}
}
void Session::channelActiveFlagUpdated(const QByteArray &data)
{
// format: [9bytes(72bit_sub_id)]
if (posOfBlock(data.data(), openSubChs, MAX_OPEN_SUB_CHANNELS, BLKSIZE_SUB_CHANNEL) != -1)
{
containsActiveCh(openSubChs, activeUpdate);
}
}
void Session::subChannelAdded(quint16 cmdId, const QByteArray &data)
{
// format: [8bytes(64bit_ch_id)][1byte(8bit_sub_ch_id)]
if (posOfBlock(data.data(), chList, MAX_CHANNELS_PER_USER, BLKSIZE_CHANNEL_ID) != -1)
{
asyncToClient(cmdId, data, BYTES);
}
}
void Session::subChannelUpdated(quint16 cmdId, const QByteArray &data)
{
// format: [9bytes(72bit_sub_id)]
if (rmBlockFromBlockset(data.data(), openSubChs, MAX_OPEN_SUB_CHANNELS, BLKSIZE_SUB_CHANNEL))
{
rmBlockFromBlockset(data.data(), openWritableSubChs, MAX_OPEN_SUB_CHANNELS, BLKSIZE_SUB_CHANNEL);
asyncToClient(cmdId, data, BYTES);
}
else if (posOfBlock(data.data(), chList, MAX_CHANNELS_PER_USER, BLKSIZE_CHANNEL_ID) != -1)
{
asyncToClient(cmdId, data, BYTES);
}
}
void Session::addModule(const QByteArray &data)
{
QString modApp = fromTEXT(data);
if (!modCmdNames.contains(modApp))
{
startModProc(modApp);
}
}
void Session::rmModule(const QByteArray &data)
{
QString modApp = fromTEXT(data);
if (modCmdNames.contains(modApp) && (modApp != QCoreApplication::applicationFilePath()))
{
for (auto&& cmdName : modCmdNames[modApp])
{
quint16 cmdId16 = cmdRealNames.key(cmdName);
emit killCmd16(cmdId16);
cmdRealNames.remove(cmdId16);
cmdUniqueNames.remove(cmdId16);
cmdAppById.remove(cmdId16);
cmdIds.removeOne(cmdId16);
}
modCmdNames.remove(modApp);
}
}
void Session::closeSubChannel(const QByteArray &data)
{
QByteArray oldSubChs = QByteArray(openSubChs, MAX_OPEN_SUB_CHANNELS * BLKSIZE_SUB_CHANNEL);
if (rmBlockFromBlockset(data.data(), openSubChs, MAX_OPEN_SUB_CHANNELS, BLKSIZE_SUB_CHANNEL))
{
rmBlockFromBlockset(data.data(), openWritableSubChs, MAX_OPEN_SUB_CHANNELS, BLKSIZE_SUB_CHANNEL);
if (rd8BitFromBlock(activeUpdate))
{
castPeerStat(oldSubChs, false);
containsActiveCh(openSubChs, activeUpdate);
}
}
}
void Session::openSubChannel(const QByteArray &data)
{
if (addBlockToBlockset(data.data(), openSubChs, MAX_OPEN_SUB_CHANNELS, BLKSIZE_SUB_CHANNEL))
{
containsActiveCh(openSubChs, activeUpdate);
rd8BitFromBlock(activeUpdate);
}
}