//in Trans-Level, do nothing. int st_clientNode_baseTrans::deal_current_message_block() { //First, get uuid as soon as possible if (m_bUUIDRecieved==false) { if (bIsValidUserId( m_currentHeader.source_id) ) { m_bUUIDRecieved = true; m_uuid = m_currentHeader.source_id; //regisit client node to hash-table; m_pClientTable->regisitClientUUID(this); } else if (m_currentHeader.source_id==0xffffffff) { //New clients } else //Invalid { emit evt_Message(this,tr("Client ID is invalid! Close client immediatly.")); m_currentBlock = QByteArray(); emit evt_close_client(this->sock()); } } else { if (!( bIsValidUserId(m_currentHeader.source_id) || (m_currentHeader.source_id==0xffffffff) ) ) { emit evt_Message(this,tr("Client ID is invalid! Close client immediatly.")); m_currentBlock = QByteArray(); emit evt_close_client(this->sock()); } if (bIsValidUserId(m_currentHeader.source_id)==true && m_uuid != m_currentHeader.source_id) { emit evt_Message(this,tr("Client ID Changed in Runtime! Close client immediatly.")); m_currentBlock = QByteArray(); emit evt_close_client(this->sock()); } } return 0; }
/** * @brief Begin a listening socket at special address and port. The socket will be activated as soon as possible * The Wait-and-Accept approaches are all managed by Listening thread, instead of main-GUI thread. * @fn zp_net_Engine::AddListeningAddress * @param id The name of this listening address:port. You can later using RemoveListeningAddress(id) to close it. * @param address Listening address. IPV6 is now not tested. * @param nPort Listening Port. in Linux, this value should larger than 1024. * @param bSSLConn True means this address using OpenSSL . False means plain TCP */ void zp_net_Engine::AddListeningAddress(QString id,const QHostAddress & address , quint16 nPort,bool bSSLConn /*= true*/) { if (m_map_netListenThreads.find(id)==m_map_netListenThreads.end()) { //Start Thread QThread * pThread = new QThread(this); zp_netListenThread * pListenObj = new zp_netListenThread(id,address,nPort,bSSLConn); pThread->start(); //m_mutex_listen.lock(); m_map_netInternalListenThreads[id] = pThread; m_map_netListenThreads[id] = pListenObj; //m_mutex_listen.unlock(); //Bind Object to New thread connect(this,&zp_net_Engine::startListen,pListenObj,&zp_netListenThread::startListen,Qt::QueuedConnection); connect(this,&zp_net_Engine::stopListen,pListenObj,&zp_netListenThread::stopListen,Qt::QueuedConnection); connect(pListenObj,&zp_netListenThread::evt_Message,this,&zp_net_Engine::evt_Message,Qt::QueuedConnection); connect(pListenObj,&zp_netListenThread::evt_ListenClosed,this,&zp_net_Engine::on_ListenClosed,Qt::QueuedConnection); connect(pListenObj,&zp_netListenThread::evt_NewClientArrived,this,&zp_net_Engine::on_New_Arrived_Client,Qt::QueuedConnection); pListenObj->moveToThread(pThread); //Start Listen Immediately emit startListen(id); } else emit evt_Message(this,"Warning>"+QString(tr("This ID has been used."))); }
/** * @brief This slot recieved incomming client socketDescriptor from listening threads.In this function, zp_net_Engine * will make a balance control, choosing a trans-thread which currently holds least clients than others. * @fn zp_net_Engine::on_New_Arrived_Client * @param socketDescriptor the socket descriptor for incomming client. */ void zp_net_Engine::on_New_Arrived_Client(qintptr socketDescriptor) { zp_netListenThread * pSource = qobject_cast<zp_netListenThread *>(sender()); if (!pSource) { emit evt_Message(this,"Warning>"+QString(tr("Non-zp_netListenThread type detected."))); return; } //emit evt_Message(this,"Info>" + QString(tr("Incomming client arriverd."))); qDebug()<<tr("Incomming client arriverd."); int nsz = m_vec_NetTransThreads.size(); int nMinPay = 0x7fffffff; int nMinIdx = -1; for (int i=0;i<nsz && nMinPay!=0;i++) { if (m_vec_NetTransThreads[i]->isActive()==false || m_vec_NetTransThreads[i]->SSLConnection()!=pSource->bSSLConn() ) continue; int nPat = m_vec_NetTransThreads[i]->CurrentClients(); if (nPat<nMinPay) { nMinPay = nPat; nMinIdx = i; } //qDebug()<<i<<" "<<nPat<<" "<<nMinIdx; } //remove old threads for (int i=0;i<nsz;i++) if (m_vec_NetTransThreads[i]->isActive()==false ) TransThreadDel(m_vec_NetTransThreads[i]); if (nMinIdx>=0 && nMinIdx<nsz) emit evt_EstablishConnection(m_vec_NetTransThreads[nMinIdx],socketDescriptor); else { emit evt_Message(this,"Warning>"+QString(tr("Need Trans Thread Object for clients."))); qCritical()<<tr("Need Trans Thread Object for clients."); } }
void st_clientNode_baseTrans::CheckHeartBeating() { QDateTime dtm = QDateTime::currentDateTime(); qint64 usc = this->m_last_Report.secsTo(dtm); if (usc >=m_pClientTable->heartBeatingThrd()) { emit evt_Message(this,tr("Client ") + QString("%1").arg((unsigned int)((quint64)this)) + tr(" is dead, kick out.")); emit evt_close_client(this->sock()); } }
void zp_ClusterNode::CheckHeartBeating() { QDateTime dtm = QDateTime::currentDateTime(); qint64 usc = this->m_last_Report.secsTo(dtm); int nThredHold = m_pTerm->heartBeatingThrdHold(); if (usc >= nThredHold) { emit evt_Message(this,tr("Client ") + QString("%1").arg((unsigned int)((quint64)this)) + tr(" is dead, kick out.")); emit evt_close_client(this->sock()); } }
/** * @brief Positive connect to a server. * In p2p connection, when the other side opens a listening address, this object can directly connect to the remote side. * @fn zp_net_Engine::connectTo * @param address the address to connect to * @param nPort port to connect to * @param bSSLConn if true, SSL connections will be used * @param extraData Extra data for users to remember extra imformation for this connection.this message will be * given back when on_connect is called. * @return bool */ bool zp_net_Engine::connectTo (const QHostAddress & address , quint16 nPort,bool bSSLConn, quint64 extraData) { bool res= false; //m_mutex_trans.lock(); int nsz = m_vec_NetTransThreads.size(); int nMinPay = 0x7fffffff; int nMinIdx = -1; for (int i=0;i<nsz && nMinPay!=0;i++) { if (m_vec_NetTransThreads[i]->isActive()==false || m_vec_NetTransThreads[i]->SSLConnection()!=bSSLConn ) continue; int nPat = m_vec_NetTransThreads[i]->CurrentClients(); if (nPat<nMinPay) { nMinPay = nPat; nMinIdx = i; } //qDebug()<<i<<" "<<nPat<<" "<<nMinIdx; } //remove old threads for (int i=0;i<nsz;i++) if (m_vec_NetTransThreads[i]->isActive()==false ) TransThreadDel(m_vec_NetTransThreads[i]); if (nMinIdx>=0 && nMinIdx<nsz) { res = true; emit evt_FireConnection(m_vec_NetTransThreads[nMinIdx],address,nPort,extraData); } else { emit evt_Message(this,"Warning>"+QString(tr("Need Trans Thread Object for clients."))); } //m_mutex_trans.unlock(); return res; }
//in Trans-Level, do nothing. int zp_ClusterNode::deal_current_message_block() { qint32 bytesLeft = m_currentHeader.data_length + sizeof(CROSS_SVR_MSG::tag_header) -m_currentMessageSize ; const CROSS_SVR_MSG * pMsg =(const CROSS_SVR_MSG *) m_currentBlock.constData(); switch(m_currentHeader.messagetype) { case 0x00://Heart Beating if (bytesLeft==0) { m_nRemoteClientNums = pMsg->payload.heartBeating.nClients; } break; case 0x01://basicInfo, when connection established, this message should be used // UnComment code below, will generate debug output. // if (m_currentBlock.length()>=64) // emit evt_Message(this,"Debug:" + m_currentBlock.toHex().left(64) + "..." + m_currentBlock.toHex().right(64)); // else // emit evt_Message(this,"Debug:" + m_currentBlock.toHex()); if (bytesLeft==0) { QString strName ((const char *)pMsg->payload.basicInfo.name); if (strName != m_pTerm->name()) { this->m_strTermName = strName; m_nPortLAN = pMsg->payload.basicInfo.port_LAN; m_addrLAN = QHostAddress((const char *)pMsg->payload.basicInfo.Address_LAN); m_nPortPub = pMsg->payload.basicInfo.port_Pub; m_addrPub = QHostAddress((const char *)pMsg->payload.basicInfo.Address_Pub); if (false==m_pTerm->regisitNewServer(this)) { this->m_strTermName.clear(); emit evt_Message(this,tr("Info: New Svr already regisited. Ignored.")+strName); emit evt_close_client(this->sock()); } else { emit evt_NewSvrConnected(this->termName()); m_pTerm->BroadcastServers(); } } else { emit evt_Message(this,tr("Can not connect to it-self, Loopback connections is forbidden.")); emit evt_close_client(this->sock()); } } break; case 0x02: //Server - broadcast messages // UnComment code below, will generate debug output. // if (m_currentBlock.length()>=64) // emit evt_Message(this,"Debug:" + m_currentBlock.toHex().left(64) + "..." + m_currentBlock.toHex().right(64)); // else // emit evt_Message(this,"Debug:" + m_currentBlock.toHex()); if (bytesLeft==0) { int nSvrs = pMsg->hearder.data_length / sizeof(CROSS_SVR_MSG::uni_payload::tag_CSM_Broadcast); for (int i=0;i<nSvrs;i++) { QString strName ((const char *)pMsg->payload.broadcastMsg[i].name); if (strName != m_pTerm->name() && m_pTerm->SvrNodeFromName(strName)==NULL) { QHostAddress addrToConnectTo((const char *)pMsg->payload.broadcastMsg[i].Address_LAN); quint16 PortToConnectTo = pMsg->payload.broadcastMsg[i].port_LAN; //because cross-connection is not good, we just want the low Addr:port connect to max Addr:Port. //Connect to New Servers if (strName > m_pTerm->name()) emit evt_connect_to(addrToConnectTo,PortToConnectTo,false); else emit evt_Message(this,tr("Name %1 <= %2, omitted.").arg(strName).arg(m_pTerm->name())); } } } break; case 0x03: // UnComment code below, will generate debug output. // if (m_currentBlock.length()>=64) // emit evt_Message(this,"Debug:" + m_currentBlock.toHex().left(64) + "..." + m_currentBlock.toHex().right(64)); // else // emit evt_Message(this,"Debug:" + m_currentBlock.toHex()); if (m_currentMessageSize==m_currentBlock.size()) { QByteArray arraySend ((const char *)(pMsg) + sizeof(CROSS_SVR_MSG::tag_header), m_currentMessageSize - sizeof(CROSS_SVR_MSG::tag_header)); if (deal_user_data(arraySend)==true) m_currentBlock = QByteArray(); } else { if (deal_user_data(m_currentBlock)==true) m_currentBlock = QByteArray(); } break; default: emit evt_Message(this,tr("Info:Unknown Msg Type got.")); emit evt_close_client(this->sock()); break; }; return 0; }
//!deal one message, affect m_currentRedOffset,m_currentMessageSize,m_currentHeader //!return bytes Used. int zp_ClusterNode::filter_message(QByteArray block, int offset) { const int blocklen = block.length(); while (blocklen>offset) { const char * dataptr = block.constData(); //Recieve First 2 byte while (m_currentMessageSize<2 && blocklen>offset ) { m_currentBlock.push_back(dataptr[offset++]); m_currentMessageSize++; } if (m_currentMessageSize < 2) //First 2 byte not complete continue; if (m_currentMessageSize==2) { const char * headerptr = m_currentBlock.constData(); memcpy((void *)&m_currentHeader,headerptr,2); } if (m_currentHeader.Mark == 0x1234) //Valid Message { //while (m_currentMessageSize< sizeof(CROSS_SVR_MSG::tag_header) && blocklen>offset) if (m_currentMessageSize< sizeof(CROSS_SVR_MSG::tag_header) && blocklen>offset) { int nCpy = sizeof(CROSS_SVR_MSG::tag_header) - m_currentMessageSize; if (nCpy > blocklen - offset) nCpy = blocklen - offset; QByteArray arrCpy(dataptr+offset,nCpy); m_currentBlock.push_back(arrCpy); //m_currentBlock.push_back(dataptr[offset++]); //m_currentMessageSize++; offset += nCpy; m_currentMessageSize += nCpy; } if (m_currentMessageSize < sizeof(CROSS_SVR_MSG::tag_header)) //Header not completed. continue; else if (m_currentMessageSize == sizeof(CROSS_SVR_MSG::tag_header))//Header just completed. { const char * headerptr = m_currentBlock.constData(); memcpy((void *)&m_currentHeader,headerptr,sizeof(CROSS_SVR_MSG::tag_header)); //continue reading if there is data left behind if (block.length()>offset) { qint32 bitLeft = m_currentHeader.data_length + sizeof(CROSS_SVR_MSG::tag_header) -m_currentMessageSize ; //while (bitLeft>0 && blocklen>offset) if (bitLeft>0 && blocklen>offset) { int nCpy = bitLeft; if (nCpy > blocklen - offset) nCpy = blocklen - offset; QByteArray arrCpy(dataptr+offset,nCpy); m_currentBlock.push_back(arrCpy); offset += nCpy; m_currentMessageSize += nCpy; bitLeft -= nCpy; //m_currentBlock.push_back(dataptr[offset++]); //m_currentMessageSize++; //bitLeft--; } //deal block, may be send data as soon as possible; deal_current_message_block(); if (bitLeft>0) continue; //This Message is Over. Start a new one. m_currentMessageSize = 0; m_currentBlock = QByteArray(); continue; } } else { if (block.length()>offset) { qint32 bitLeft = m_currentHeader.data_length + sizeof(CROSS_SVR_MSG::tag_header) -m_currentMessageSize ; //while (bitLeft>0 && blocklen>offset) if (bitLeft>0 && blocklen>offset) { int nCpy = bitLeft; if (nCpy > blocklen - offset) nCpy = blocklen - offset; QByteArray arrCpy(dataptr+offset,nCpy); m_currentBlock.push_back(arrCpy); offset += nCpy; m_currentMessageSize += nCpy; bitLeft -= nCpy; //m_currentBlock.push_back(dataptr[offset++]); //m_currentMessageSize++; //bitLeft--; } //deal block, may be processed as soon as possible; deal_current_message_block(); if (bitLeft>0) continue; //This Message is Over. Start a new one. m_currentMessageSize = 0; m_currentBlock = QByteArray(); continue; } } // end if there is more bytes to append } //end deal trans message else { const char * ptrCurrData = m_currentBlock.constData(); emit evt_Message(this,tr("Client Send a unknown start Header %1 %2. Close client immediately.") .arg((int)(ptrCurrData[0])).arg((int)(ptrCurrData[1]))); m_currentMessageSize = 0; m_currentBlock = QByteArray(); offset = blocklen; emit evt_close_client(this->sock()); } } // end while block len > offset return offset; }
//!deal one message, affect m_currentRedOffset,m_currentMessageSize,m_currentHeader //!return bytes Used. int st_clientNode_baseTrans::filter_message(QByteArray block, int offset) { const int blocklen = block.length(); while (blocklen>offset) { const char * dataptr = block.constData(); //Recieve First 2 byte while (m_currentMessageSize<2 && blocklen>offset ) { m_currentBlock.push_back(dataptr[offset++]); m_currentMessageSize++; } if (m_currentMessageSize < 2) //First 2 byte not complete continue; if (m_currentMessageSize==2) { const char * headerptr = m_currentBlock.constData(); memcpy((void *)&m_currentHeader,headerptr,2); } //Heart Beating if (m_currentHeader.Mark == 0xBEBE) { if (m_currentMessageSize< sizeof(EXAMPLE_HEARTBEATING) && blocklen>offset ) { int nCpy = offset - blocklen; if (nCpy > sizeof(EXAMPLE_HEARTBEATING) - m_currentMessageSize) nCpy = sizeof(EXAMPLE_HEARTBEATING) - m_currentMessageSize; m_currentBlock.push_back(QByteArray(dataptr+offset,nCpy)); offset += nCpy; m_currentMessageSize+=nCpy; } if (m_currentMessageSize < sizeof(EXAMPLE_HEARTBEATING)) //Header not completed. continue; //Send back emit evt_SendDataToClient(this->sock(),m_currentBlock); //Try to Get UUID Immediately if (m_bUUIDRecieved==false) { EXAMPLE_HEARTBEATING * pHbMsg = (EXAMPLE_HEARTBEATING *)(m_currentBlock.constData()); if (bIsValidUserId(pHbMsg->source_id)) { m_bUUIDRecieved = true; m_uuid = pHbMsg->source_id; //regisit client node to hash-table; m_pClientTable->regisitClientUUID(this); } } //This Message is Over. Start a new one. m_currentMessageSize = 0; m_currentBlock = QByteArray(); continue; } else if (m_currentHeader.Mark == 0x55AA) //Trans Message { if (m_currentMessageSize< sizeof(EXAMPLE_TRANS_MSG)-1 && blocklen>offset) { int nCpy = blocklen - offset; if (nCpy > sizeof(EXAMPLE_TRANS_MSG)-1 - m_currentMessageSize) nCpy = sizeof(EXAMPLE_TRANS_MSG)-1 - m_currentMessageSize; m_currentBlock.push_back(QByteArray(dataptr+offset,nCpy)); offset += nCpy; m_currentMessageSize+=nCpy; } if (m_currentMessageSize < sizeof(EXAMPLE_TRANS_MSG)-1) //Header not completed. continue; else if (m_currentMessageSize == sizeof(EXAMPLE_TRANS_MSG)-1)//Header just completed. { const char * headerptr = m_currentBlock.constData(); memcpy((void *)&m_currentHeader,headerptr,sizeof(EXAMPLE_TRANS_MSG)-1); //continue reading if there is data left behind if (block.length()>offset) { qint32 bitLeft = m_currentHeader.data_length + sizeof(EXAMPLE_TRANS_MSG) - 1 -m_currentMessageSize ; if (bitLeft>0 && blocklen>offset) { int nCpy = blocklen - offset; if (nCpy > bitLeft) nCpy = bitLeft; m_currentBlock.push_back(QByteArray(dataptr+offset,nCpy)); offset += nCpy; m_currentMessageSize+=nCpy; bitLeft -= nCpy; } //deal block, may be send data as soon as possible; deal_current_message_block(); if (bitLeft>0) continue; //This Message is Over. Start a new one. m_currentMessageSize = 0; m_currentBlock = QByteArray(); continue; } } else { if (block.length()>offset) { qint32 bitLeft = m_currentHeader.data_length + sizeof(EXAMPLE_TRANS_MSG) - 1 -m_currentMessageSize ; if (bitLeft>0 && blocklen>offset) { int nCpy = blocklen - offset; if (nCpy > bitLeft) nCpy = bitLeft; m_currentBlock.push_back(QByteArray(dataptr+offset,nCpy)); offset += nCpy; m_currentMessageSize+=nCpy; bitLeft -= nCpy; } //deal block, may be processed as soon as possible; deal_current_message_block(); if (bitLeft>0) continue; //This Message is Over. Start a new one. m_currentMessageSize = 0; m_currentBlock = QByteArray(); continue; } } // end if there is more bytes to append } //end deal trans message else { const char * ptrCurrData = m_currentBlock.constData(); emit evt_Message(this,tr("Client Send a unknown start Header %1 %2. Close client immediately.") .arg((int)(ptrCurrData[0])).arg((int)(ptrCurrData[1]))); m_currentMessageSize = 0; m_currentBlock = QByteArray(); offset = blocklen; emit evt_close_client(this->sock()); } } // end while block len > offset return offset; }