bool lmcTraceInit( LmcTraceMode tMode, QString logdir, QString strLogFileName ) { g_traceMode = DoNotTrace; g_logFileName.clear(); if ( logdir.isEmpty() ) return false; if ( strLogFileName.isEmpty() ) return false; g_traceMode = tMode; // log directory QDir logDir( logdir ); if( ! logDir.exists() ) logDir.mkdir( logDir.absolutePath() ); // log file name g_logFileName = strLogFileName; lmctrace( "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n" \ " application log\n" \ "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-" ); return true; }
void lmcMessaging::prepareFile(MessageType type, qint64 msgId, bool retry, QString* lpszUserId, XmlMessage* pMessage) { Q_UNUSED(type); Q_UNUSED(msgId); Q_UNUSED(retry); int fileOp = indexOf( FileOpNames, FO_Max, pMessage->data(XN_FILEOP) ); int fileMode = indexOf( FileModeNames, FM_Max, pMessage->data(XN_MODE) ); User* user = getUser(lpszUserId); QString szMessage = pMessage->toString(); lmctrace("Sending file message type " + QString::number(fileOp) + " to user " + *lpszUserId + ", Mode: " + QString::number(fileMode)); switch(fileOp) { case FO_Request: pNetwork->initSendFile(&user->id, &user->address, &szMessage); break; case FO_Accept: pNetwork->initReceiveFile(&user->id, &user->address, &szMessage); break; case FO_Cancel: pNetwork->fileOperation((FileMode)fileMode, &user->id, &szMessage); break; } }
bool lmcMessaging::addUser(QString szUserId, QString szVersion, QString szAddress, QString szName, QString szStatus, QString szAvatar, QString szNote) { for(int index = 0; index < userList.count(); index++) if(userList[index].id.compare(szUserId) == 0) return false; lmctrace("Adding new user: "******", " + szVersion + ", " + szAddress); if(!userGroupMap.contains(szUserId) || !groupList.contains(Group(userGroupMap.value(szUserId)))) userGroupMap.insert(szUserId, GRP_DEFAULT_ID); int nAvatar = szAvatar.isNull() ? -1 : szAvatar.toInt(); userList.append(User(szUserId, szVersion, szAddress, szName, szStatus, userGroupMap[szUserId], nAvatar, szNote)); if(!szStatus.isNull()) { XmlMessage xmlMessage; xmlMessage.addHeader(XN_FROM, szUserId); xmlMessage.addData(XN_STATUS, szStatus); // send a status message to app layer, this is different from announce message emit messageReceived(MT_Status, &szUserId, &xmlMessage); int statusIndex = statusIndexFromCode(szStatus); if(statusType[statusIndex] == StatusTypeOffline) // offline status return false; // no need to send a new user message to app layer } emit messageReceived(MT_Announce, &szUserId, NULL); return true; }
void lmcMessaging::start(void) { lmctrace("Messaging started"); pNetwork->start(); sendBroadcast(MT_Depart, NULL); sendBroadcast(MT_Announce, NULL); }
void lmcMessaging::stop(void) { sendBroadcast(MT_Depart, NULL); pNetwork->stop(); pSettings->setValue(IDS_STATUS, localUser->status); pSettings->setValue(IDS_AVATAR, localUser->avatar); saveGroups(); lmctrace("Messaging stopped"); }
void lmcMessaging::update(void) { lmctrace("Refreshing contacts list..."); sendBroadcast(MT_Announce, NULL); for(int index = 0; index < userList.count(); index++) { sendMessage(MT_Ping, &userList[index].id, NULL); } }
void MsgStream::connected(void) { outData = localId.toLocal8Bit(); outData.insert(0, "MSG"); // insert indicator that this socket handles messages outDataLen = outData.length(); // send an id message and then wait for public key message // from receiver, which will trigger readyRead signal qint64 numBytesWritten = socket->write(outData); if(numBytesWritten < 0) lmctrace("Error: Socket write failed"); }
// A web message has been received void lmcMessaging::receiveWebMessage(QString *lpszData) { MessageHeader* pMsgHeader = NULL; XmlMessage* pMessage = NULL; if ( ! getHeader(lpszData, &pMsgHeader, &pMessage) ) { lmctrace("Warning: Web message header parse failed"); return; } processWebMessage(pMsgHeader, pMessage); }
// A message has been received void lmcMessaging::receiveMessage(DatagramHeader* pHeader, QString* lpszData) { MessageHeader* pMsgHeader = NULL; XmlMessage* pMessage = NULL; if ( ! getHeader(lpszData, &pMsgHeader, &pMessage) ) { lmctrace("Warning: Message header parse failed"); return; } pMsgHeader->address = pHeader->address; processMessage(pMsgHeader, pMessage); }
void MsgStream::sendMessage(QByteArray& data) { qint32 dataLen = sizeof(quint32) + data.length(); outDataLen += dataLen; outData.resize(dataLen); QDataStream stream(&outData, QIODevice::WriteOnly); stream << (quint32)data.length(); stream.writeRawData(data.data(), data.length()); qint64 numBytesWritten = socket->write(outData); if(numBytesWritten < 0) lmctrace("Error: Socket write failed"); }
void lmcMessaging::sendUserData(MessageType type, QueryOp op, QString* lpszUserId, QString* lpszAddress) { lmctrace("Sending local user details to user " + *lpszUserId + " at " + *lpszAddress); XmlMessage xmlMessage; xmlMessage.addData(XN_USERID, localUser->id); xmlMessage.addData(XN_NAME, localUser->name); xmlMessage.addData(XN_ADDRESS, localUser->address); xmlMessage.addData(XN_VERSION, localUser->version); xmlMessage.addData(XN_STATUS, localUser->status); xmlMessage.addData(XN_NOTE, localUser->note); xmlMessage.addData(XN_QUERYOP, QueryOpNames[op]); QString szMessage = addHeader(type, msgId, &localUser->id, lpszUserId, &xmlMessage); pNetwork->sendMessage(lpszUserId, lpszAddress, &szMessage); }
void lmcMessaging::processWebMessage(MessageHeader* pHeader, XmlMessage *pMessage) { lmctrace("Processing web message type " + QString::number(pHeader->type)); switch(pHeader->type) { case MT_Version: emit messageReceived(pHeader->type, NULL, pMessage); break; case MT_WebFailed: emit messageReceived(pHeader->type, NULL, pMessage); break; default: break; } }
// This method converts a Datagram from network layer to a Message that can be passed to ui layer void lmcMessaging::processBroadcast(MessageHeader* pHeader, XmlMessage* pMessage) { Q_UNUSED(pMessage); // do not process broadcasts from local user unless loopback is specified in command line if(!loopback && pHeader->userId.compare(localUser->id) == 0) return; lmctrace("Processing broadcast type " + QString::number(pHeader->type) + " from user " + pHeader->userId); switch(pHeader->type) { case MT_Announce: if(!getUser(&pHeader->userId)) pNetwork->addConnection(&pHeader->userId, &pHeader->address); break; case MT_Depart: removeUser(pHeader->userId); break; default: break; } lmctrace("Broadcast processing done"); }
void lmcMessaging::processFile(MessageHeader* pHeader, XmlMessage* pMessage) { int fileMode = indexOf( FileModeNames, FM_Max, pMessage->data(XN_MODE) ); int fileOp = indexOf( FileOpNames, FO_Max, pMessage->data(XN_FILEOP) ); QString szMessage = pMessage->toString(); lmctrace("Processing file message type " + QString::number(fileOp) + " from user " + pHeader->userId + ", Mode: " + QString::number(fileMode)); switch(fileOp) { case FO_Request: emit messageReceived(pHeader->type, &pHeader->userId, pMessage); break; case FO_Accept: pNetwork->fileOperation(FM_Send, &pHeader->userId, &szMessage); emit messageReceived(pHeader->type, &pHeader->userId, pMessage); break; case FO_Cancel: if(fileMode == FM_Send) { pNetwork->fileOperation(FM_Receive, &pHeader->userId, &szMessage); emit messageReceived(pHeader->type, &pHeader->userId, pMessage); } else { pNetwork->fileOperation(FM_Send, &pHeader->userId, &szMessage); emit messageReceived(pHeader->type, &pHeader->userId, pMessage); } break; case FO_Abort: if(fileMode == FM_Send) { pNetwork->fileOperation(FM_Receive, &pHeader->userId, &szMessage); emit messageReceived(pHeader->type, &pHeader->userId, pMessage); } else { pNetwork->fileOperation(FM_Send, &pHeader->userId, &szMessage); emit messageReceived(pHeader->type, &pHeader->userId, pMessage); } break; case FO_Decline: case FO_Progress: emit messageReceived(pHeader->type, &pHeader->userId, pMessage); break; default: break; } }
void lmcMessaging::sendWebMessage(MessageType type, XmlMessage *pMessage) { Q_UNUSED(pMessage); QString szUrl; lmctrace("Sending web message type " + QString::number(type)); switch(type) { case MT_Version: // szUrl = QString(IDA_DOMAIN"/webservice.php?q=version&p="IDA_PLATFORM); szUrl = QString( "http://lanmsngr.sourceforge.net/webservice.php?q=version&p=").append(IDA_PLATFORM); pNetwork->sendWebMessage(&szUrl, NULL); break; default: break; } }
void lmcMessaging::init(XmlMessage *pInitParams) { lmctrace("Messaging initialized"); pNetwork->init(pInitParams); QString logonName = getLogonName(); QString szAddress = pNetwork->physicalAddress(); QString userId = createUserId(&szAddress, &logonName); pNetwork->setLocalId(&userId); pSettings = new lmcSettings(); QString userStatus = pSettings->value(IDS_STATUS, IDS_STATUS_VAL).toString(); int sIndex = statusIndexFromCode(userStatus); // if status not recognized, default to available if(sIndex < 0) userStatus = statusCode[0]; QString userName = getUserName(); int nAvatar = pSettings->value(IDS_AVATAR, IDS_AVATAR_VAL).toInt(); QString userNote = pSettings->value(IDS_NOTE, IDS_NOTE_VAL).toString(); localUser = new User(userId, IDA_VERSION, pNetwork->ipAddress, userName, userStatus, QString::null, nAvatar, userNote); loadGroups(); nTimeout = pSettings->value(IDS_TIMEOUT, IDS_TIMEOUT_VAL).toInt() * 1000; nMaxRetry = pSettings->value(IDS_MAXRETRIES, IDS_MAXRETRIES_VAL).toInt(); pTimer = new QTimer(this); connect(pTimer, SIGNAL(timeout()), this, SLOT(timer_timeout())); pTimer->start(1000); msgId = 1; }
void lmcMessaging::processMessage(MessageHeader* pHeader, XmlMessage* pMessage) { QString msgId; QString data = QString::null; XmlMessage reply; lmctrace("Processing message type " + QString::number(pHeader->type) + " from user " + pHeader->userId); switch(pHeader->type) { case MT_UserData: if(pMessage->data(XN_QUERYOP) == QueryOpNames[QO_Get]) sendUserData(pHeader->type, QO_Result, &pHeader->userId, &pHeader->address); // add the user only after sending back user data, this way both parties will have added each other addUser(pMessage->data(XN_USERID), pMessage->data(XN_VERSION), pMessage->data(XN_ADDRESS), pMessage->data(XN_NAME), pMessage->data(XN_STATUS), QString::null, pMessage->data(XN_NOTE)); break; case MT_Broadcast: emit messageReceived(pHeader->type, &pHeader->userId, pMessage); break; case MT_Status: data = pMessage->data(XN_STATUS); updateUser(pHeader->type, pHeader->userId, data); break; case MT_UserName: data = pMessage->data(XN_NAME); updateUser(pHeader->type, pHeader->userId, data); break; case MT_Note: data = pMessage->data(XN_NOTE); updateUser(pHeader->type, pHeader->userId, data); break; case MT_Message: // add message to received message list if(addReceivedMsg(pHeader->id, pHeader->userId)) { emit messageReceived(pHeader->type, &pHeader->userId, pMessage); } // send an acknowledgement msgId = QString::number(pHeader->id); reply.addData(XN_MESSAGEID, msgId); sendMessage(MT_Acknowledge, &pHeader->userId, &reply); break; case MT_GroupMessage: emit messageReceived(pHeader->type, &pHeader->userId, pMessage); break; case MT_PublicMessage: emit messageReceived(pHeader->type, &pHeader->userId, pMessage); break; case MT_Ping: // send an acknowledgement msgId = QString::number(pHeader->id); reply.addData(XN_MESSAGEID, msgId); sendMessage(MT_Acknowledge, &pHeader->userId, &reply); break; case MT_Query: // send a reply cum acknowledgement if its a 'get' query if(pMessage->data(XN_QUERYOP) == QueryOpNames[QO_Get]) { msgId = QString::number(pHeader->id); reply.addData(XN_MESSAGEID, msgId); reply.addData(XN_QUERYOP, QueryOpNames[QO_Result]); sendMessage(pHeader->type, &pHeader->userId, &reply); } else if(pMessage->data(XN_QUERYOP) == QueryOpNames[QO_Result]) { msgId = pMessage->data(XN_MESSAGEID); removePendingMsg(msgId.toLongLong()); emit messageReceived(pHeader->type, &pHeader->userId, pMessage); } break; case MT_ChatState: emit messageReceived(pHeader->type, &pHeader->userId, pMessage); break; case MT_Acknowledge: // remove message from pending list msgId = pMessage->data(XN_MESSAGEID); removePendingMsg(msgId.toLongLong()); break; case MT_File: case MT_Avatar: processFile(pHeader, pMessage); break; default: break; } lmctrace("Message processing done"); }
// This method converts a Message from ui layer to a Datagram that can be passed to network layer void lmcMessaging::prepareMessage(MessageType type, qint64 msgId, bool retry, QString* lpszUserId, XmlMessage* pMessage) { if(!isConnected()) { lmctrace("Warning: Not connected. Message not sent"); return; } User* receiver = getUser(lpszUserId); switch(type) { case MT_Status: pMessage->addData(XN_STATUS, localUser->status); break; case MT_UserName: pMessage->addData(XN_NAME, localUser->name); break; case MT_Note: pMessage->addData(XN_NOTE, localUser->note); break; case MT_Ping: // add message to pending list if(!retry) addPendingMsg(msgId, MT_Ping, lpszUserId, pMessage); break; case MT_Message: if(!receiver) { emit messageReceived(MT_Failed, lpszUserId, pMessage); break; } // add message to pending list if(!retry) addPendingMsg(msgId, MT_Message, lpszUserId, pMessage); break; case MT_GroupMessage: break; case MT_PublicMessage: break; case MT_Broadcast: break; case MT_Acknowledge: break; case MT_Query: // if its a 'get' query add message to pending list if(pMessage->data(XN_QUERYOP) == QueryOpNames[QO_Get] && !retry) addPendingMsg(msgId, MT_Query, lpszUserId, pMessage); else if(pMessage->data(XN_QUERYOP) == QueryOpNames[QO_Result]) getUserInfo(pMessage); break; case MT_ChatState: break; case MT_File: case MT_Avatar: prepareFile(type, msgId, retry, lpszUserId, pMessage); break; default: break; } if(!receiver) { lmctrace("Warning: Recipient " + *lpszUserId + " not found. Message not sent"); return; } lmctrace("Sending message type " + QString::number(type) + " to user " + receiver->id + " at " + receiver->address); QString szMessage = addHeader(type, msgId, &localUser->id, lpszUserId, pMessage); pNetwork->sendMessage(&receiver->id, &receiver->address, &szMessage); lmctrace("Message sending done"); }
void lmcMessaging::prepareBroadcast(MessageType type, XmlMessage* pMessage) { lmctrace("Sending broadcast type " + QString::number(type)); QString szMessage = addHeader(type, msgId, &localUser->id, NULL, pMessage); pNetwork->sendBroadcast(&szMessage); lmctrace("Broadcast sending done"); }
void lmcMessaging::connectionLost(QString* lpszUserId) { lmctrace("Connection to user " + *lpszUserId + " lost"); removeUser(*lpszUserId); }
// Handshake procedure has been completed void lmcMessaging::newConnection(QString* lpszUserId, QString* lpszAddress) { lmctrace("Connection completed with user " + *lpszUserId + " at " + *lpszAddress); sendUserData(MT_UserData, QO_Get, lpszUserId, lpszAddress); }