/// \brief Handles heartbeat checking once a second. If a client is not heard /// from for at least 1 second, send it a heartbeat message which it /// should send back. If we haven't heard from it in 5s, shut down its /// logging. void LogServerThread::checkHeartBeats(void) { #ifndef NOLOGSERVER qlonglong epoch; // cout << "pre-lock 1" << endl; QMutexLocker lock(&logClientMapMutex); // cout << "pre-lock 2" << endl; QMutexLocker lock2(&logClientToDelMutex); loggingGetTimeStamp(&epoch, NULL); // cout << "msgcount " << msgsSinceHeartbeat << endl; msgsSinceHeartbeat = 0; ClientMap::iterator it = logClientMap.begin(); for( ; it != logClientMap.end(); ++it ) { QString clientId = it.key(); LoggerListItem *logItem = it.value(); qlonglong age = epoch - logItem->epoch; if (age > 5) { logClientToDel.append(clientId); } else { // cout << "age " << age << " " << clientId.toLocal8Bit().constData() << endl; pingClient(clientId); } } #endif }
void create(ClientMap& clientMap, char ID[], char plainPwd[], TABLE& id_table) { //clientMap.showMap(); if(clientMap.search(ID) != nullptr) { printf("ID %s exists, ", ID); // show 10 unused ID int count = 0; NextWordGenerator gen(ID); while(count != 10) { char *next = gen.getNext(); if(clientMap.search(next) == nullptr) // if the ID doesn't exist, show it { printf("%s%c", next, (count == 9) ? '\n' : ','); count++; } } return; } int pos = id_table.insert(ID); char encryptedPwd[110]; md5(encryptedPwd, plainPwd); clientMap.insert(ID, encryptedPwd, pos); printf("success\n"); return; }
void merge(ClientMap& clientMap, char ID[], char password[], char ID_2[], char password_2[], TABLE &id_table) { ClientData *clientData_1 = clientMap.search(ID); ClientData *clientData_2 = clientMap.search(ID_2); if (clientData_1 == nullptr){ printf("ID %s not found\n", ID); return; } if (clientData_2 == nullptr){ printf("ID %s not found\n", ID_2); return; } char encryptedPwd_1[110]; md5(encryptedPwd_1, password); if (strcmp(clientData_1->md5_password, encryptedPwd_1) != 0){ printf("wrong password1\n"); return; } char encryptedPwd_2[110]; md5(encryptedPwd_2, password_2); if (strcmp(clientData_2->md5_password, encryptedPwd_2) != 0){ printf("wrong password2\n"); return; } clientData_1->money += clientData_2->money; mergeHistory(clientData_1->history, clientData_2->history); char* tempID = id_table.eraser(clientData_2->IDpos, strlen(ID_2)); if (tempID != NULL){ ClientData *backID_clientData = clientMap.search(tempID); backID_clientData->IDpos = clientData_2->IDpos; } clientMap.erase(ID_2); printf("success, %s has %lld dollars\n", ID, clientData_1->money); return; }
void ChopClient (unsigned int clientID) //do not confuse with killClient, this is a harsh disconnect { ClientMap::iterator iter = clients.find(clientID); if (iter != clients.end()) { enet_peer_reset(iter->second); //disconnect now, regardless of what the client does clients.erase(iter); } }
void SendMessage ( unsigned int clientID, const Message& msg ) { ClientMap::iterator iter = clients.find(clientID); if (iter != clients.end()) { ENetPacket* packet = MessageEncoding::Encode(msg); enet_peer_send(iter->second, 0, packet); } }
void KillClient ( unsigned int clientID ) //this is the nice disconnect { ClientMap::iterator iter = clients.find(clientID); if (iter != clients.end()) { enet_peer_disconnect_later(iter->second, 0); clients.erase(iter); } }
void Server::disconnectAllClients() { ClientMap clients = mClientList.mClients; ClientMap::iterator it; for(it = clients.begin(); it != clients.end(); ++it) { Client* client = it->second; client->startDisconnect(); mClientList.removeClient(client); } }
bool ClientEngine::renderScene() { glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT); { static vec3f pos(0,-3,0); if(m_Window.keyState('W')) pos.z += 0.1; if(m_Window.keyState('S')) pos.z -= 0.1; if(m_Window.keyState('A')) pos.x += 0.1; if(m_Window.keyState('D')) pos.x -= 0.1; if(m_Window.keyState('Q')) pos.y += 0.1; if(m_Window.keyState('E')) pos.y -= 0.1; m_Camera.setPosition(pos); } m_Camera.update(); m_Camera.upload(); { glPushMatrix(); m_Shader.bind(); glScalef(1, 1, 1); m_ClientMap.draw(); glPopMatrix(); } CheckGl(); m_Window.swapBuffers(); return m_Window.isOpen(); }
void deposit(ClientMap& clientMap, char ID[], LLI money) { ClientData *clientData = clientMap.search(ID); clientData->money += money; printf("success, %lld dollars in current account\n", clientData->money); return; }
void search(ClientMap& clientMap, char ID[]){ //ClientData *clientData = clientMap.search(ID); //if (clientData == nullptr){ //cout << "ID " << ID <<" not found" << endl; // return; //} searchHistory(clientMap.search(lastID)->history, ID); }
void Shutdown () { if (serverHost) { clients.clear(); enet_host_destroy(serverHost); serverHost = NULL; } }
void remove(ClientMap& clientMap, char ID[], char plainPwd[], TABLE &id_table) { ClientData *clientData = clientMap.search(ID); if (clientData == nullptr){ printf("ID %s not found\n", ID); return; } char encryptedPwd[110]; md5(encryptedPwd, plainPwd); if (strcmp(clientData->md5_password, encryptedPwd) == 0){ char* tempID = id_table.eraser(clientData->IDpos, strlen(ID)); if (tempID != NULL){ ClientData *clientData_2 = clientMap.search(tempID); clientData_2->IDpos = clientData->IDpos; } clientMap.erase(ID); printf("success\n"); } else printf("wrong password\n"); }
void transfer(ClientMap& clientMap, char ID[], char transferID[], LLI money, TABLE& id_table) { ClientData *clientData = clientMap.search(ID); ClientData *transferData = clientMap.search(transferID); if (transferData == nullptr){ id_table.recommendID(transferID); return; } if (clientData->money < money){ printf("fail, %lld dollars only in current account\n", clientData->money); return; } clientData->money -= money; transferData->money += money; transferHistory(clientData->history, ID, transferData->history, transferID, timeStamp, money); timeStamp++; printf("success, %lld dollars left in current account\n", clientData->money); }
void withdraw(ClientMap& clientMap, char ID[], LLI money) { ClientData *clientData = clientMap.search(ID); if (clientData->money < money) printf("fail, %lld dollars only in current account\n", clientData->money); else{ clientData->money -= money; printf("success, %lld dollars left in current account\n", clientData->money); } return; }
/// \brief Expire any clients in the delete list void LogForwardThread::expireClients(void) { #ifndef NOLOGSERVER QMutexLocker lock(&logClientMapMutex); QMutexLocker lock2(&logRevClientMapMutex); QMutexLocker lock3(&logClientToDelMutex); while (!logClientToDel.isEmpty()) { QString clientId = logClientToDel.takeFirst(); logClientCount.deref(); LOG(VB_GENERAL, LOG_INFO, QString("Expiring client %1 (#%2)") .arg(clientId).arg(logClientCount.fetchAndAddOrdered(0))); LoggerListItem *item = logClientMap.take(clientId); if (!item) continue; LoggerList *list = item->list; delete item; while (!list->isEmpty()) { LoggerBase *logger = list->takeFirst(); ClientList *clientList = logRevClientMap.value(logger, NULL); if (!clientList || clientList->size() == 1) { if (clientList) { logRevClientMap.remove(logger); delete clientList; } delete logger; continue; } clientList->removeAll(clientId); } delete list; } // TODO FIXME: This is not thread-safe! // just this daemon left if (logClientCount.fetchAndAddOrdered(0) == 1 && m_shutdownTimer && !m_shutdownTimer->isActive()) { LOG(VB_GENERAL, LOG_INFO, "Starting 5min shutdown timer"); m_shutdownTimer->start(5*60*1000); } #endif }
void login(ClientMap& clientMap, char ID[], char plainPwd[]) { ClientData *clientData = clientMap.search(ID); if (clientData == nullptr){ printf("ID %s not found\n", ID); return; } char encryptedPwd[110]; md5(encryptedPwd, plainPwd); if (strcmp(clientData->md5_password, encryptedPwd) == 0) { strcpy(lastID, ID); //printf("lastID = %s\n", lastID); printf("success\n"); } else printf("wrong password\n"); return; }
namespace Server { ENetHost* serverHost = NULL; typedef std::map<unsigned int, ENetPeer*> ClientMap; ClientMap clients; static unsigned int nextClientID = 1; const uint32_t SERVER_BANDWIDTH_LIMIT = 1024 * 64; // 64 kB/s const int SERVER_MAX_CLIENTS = 8; // plucked this one out of my arse. unsigned int badMessage[SERVER_MAX_CLIENTS+1][5]; //[clientID][n] = time bad packet was sent unsigned int badMessageCount[SERVER_MAX_CLIENTS]; //number of bad packets sent std::map<int, BlowfishKey> sessionKey; std::map<int, BlowfishIV> sessionIV; void makeBlowKey(int clientID) { //ADAM sessionKey[clientID]; //ADAM sessionIV[clientID]; // add a random number generator for this } void Startup ( unsigned short port, const std::string& password ) { if (serverHost) { Shutdown(); } ENetAddress addr; addr.port = htons(port); addr.host = INADDR_ANY; serverHost = enet_host_create(&addr, SERVER_MAX_CLIENTS, SERVER_BANDWIDTH_LIMIT, SERVER_BANDWIDTH_LIMIT); } void Shutdown () { if (serverHost) { clients.clear(); enet_host_destroy(serverHost); serverHost = NULL; } } bool IsRunning () { return serverHost != NULL; } unsigned ClientCount () { return clients.size(); } void KillClient ( unsigned int clientID ) //this is the nice disconnect { ClientMap::iterator iter = clients.find(clientID); if (iter != clients.end()) { enet_peer_disconnect_later(iter->second, 0); clients.erase(iter); } } void ChopClient (unsigned int clientID) //do not confuse with killClient, this is a harsh disconnect { ClientMap::iterator iter = clients.find(clientID); if (iter != clients.end()) { enet_peer_reset(iter->second); //disconnect now, regardless of what the client does clients.erase(iter); } } void SendMessage ( unsigned int clientID, const Message& msg ) { ClientMap::iterator iter = clients.find(clientID); if (iter != clients.end()) { ENetPacket* packet = MessageEncoding::Encode(msg); enet_peer_send(iter->second, 0, packet); } } void BroadcastMessage ( const Message& msg ) { if (!serverHost) return; ENetPacket* packet = MessageEncoding::Encode(msg); enet_host_broadcast(serverHost, 0, packet); } bool IsConnected ( unsigned int clientID ) { return clients.find(clientID) != clients.end(); } static void BadClient(unsigned int clientID) //deal with a bad message { unsigned int currentTime = (unsigned int)GameTime(); if(badMessageCount[clientID] > 1) { if((currentTime - badMessage[clientID][badMessageCount[clientID]]) < 10) { // kick on 2nd in 10 seconds KillClient(clientID); return; } } badMessageCount[clientID]++; badMessage[clientID][badMessageCount[clientID]] = currentTime; } Message* GetMessage () { ENetEvent event; if (enet_host_service(serverHost, &event, 0)) { Message* msg = NULL; unsigned int clientID = 0; for (ClientMap::iterator iter = clients.begin(); iter != clients.end(); iter++) { if (iter->second == event.peer) { clientID = iter->first; } } switch (event.type) { case ENET_EVENT_TYPE_CONNECT: msg = new Message ( "CONNECT", NULL, 0 ); clientID = nextClientID++; msg->clientID = clientID; clients[clientID] = event.peer; badMessage[clientID][0] = 0; //clear bad-message entry so it can be used Message* keymsg; Message* ivmsg; //make and share encryption keys //ADAM makeBlowKey[clientID]; //ADAM keymsg = new Message( "BLOWKEY", sessionKey[clientID], 16 ); //make a message with the blowkey //ADAM SendMessage( clientID, keymsg ); //send the blowkey //ADAM ivmsg = new Message( "BLOWIV" , sessionIV[clientID], 8 ); //make a message with the blowIV //ADAM SendMessage( clientID, ivmsg ); //send the IV break; case ENET_EVENT_TYPE_DISCONNECT: { msg = new Message ( "DISCONNECT", NULL, 0 ); msg->clientID = clientID; ClientMap::iterator iter = clients.find(clientID); clients.erase(iter); } break; case ENET_EVENT_TYPE_RECEIVE: msg = MessageEncoding::Decode(event.packet); if(msg == NULL) { if (badMessageCount[clientID] >= 4) { KillClient(clientID); } else { BadClient(clientID); } } else { msg->clientID = clientID; /* if( Blowfish::do_decrypt(msg, sessionKey[clientID], sessionIV[clientID]) == false) // msg is passed by reference. Return 0 on error. { //do something with the bad message } else { //do something with the recieved message } */ //disabled until finished implementation } enet_packet_destroy(event.packet); break; } return msg; } return NULL; } }
void LogForwardThread::forwardMessage(LogMessage *msg) { #ifdef DUMP_PACKET QList<QByteArray>::const_iterator it = msg->begin(); int i = 0; for (; it != msg->end(); ++it, i++) { QByteArray buf = *it; cout << i << ":\t" << buf.size() << endl << "\t" << buf.toHex().constData() << endl << "\t" << buf.constData() << endl; } #endif msgsSinceHeartbeat.ref(); // First section is the client id QByteArray clientBa = msg->first(); QString clientId = QString(clientBa.toHex()); QByteArray json = msg->at(1); if (json.size() == 0) { // This is either a ping response or a first gasp logClientMapMutex.lock(); LoggerListItem *logItem = logClientMap.value(clientId, NULL); logClientMapMutex.unlock(); if (!logItem) { // Send an initial ping so the client knows we are in the house emit pingClient(clientId); } else { // cout << "pong " << clientId.toLocal8Bit().constData() << endl; loggingGetTimeStamp(&logItem->epoch, NULL); } return; } QMutexLocker lock(&logClientMapMutex); LoggerListItem *logItem = logClientMap.value(clientId, NULL); // cout << "msg " << clientId.toLocal8Bit().constData() << endl; if (logItem) { loggingGetTimeStamp(&logItem->epoch, NULL); } else { LoggingItem *item = LoggingItem::create(json); logClientCount.ref(); LOG(VB_FILE, LOG_DEBUG, QString("New Logging Client: ID: %1 (#%2)") .arg(clientId).arg(logClientCount.fetchAndAddOrdered(0))); #ifndef NOLOGSERVER // TODO FIXME This is not thread-safe! if (logClientCount.fetchAndAddOrdered(0) > 1 && m_shutdownTimer && m_shutdownTimer->isActive()) { LOG(VB_GENERAL, LOG_INFO, "Aborting shutdown timer"); m_shutdownTimer->stop(); } #endif QMutexLocker lock2(&loggerMapMutex); QMutexLocker lock3(&logRevClientMapMutex); // Need to find or create the loggers LoggerList *loggers = new LoggerList; LoggerBase *logger; // FileLogger from logFile QString logfile = item->logFile(); logfile.detach(); if (!logfile.isEmpty()) { logger = FileLogger::create(logfile, lock2.mutex()); ClientList *clients = logRevClientMap.value(logger); if (clients) clients->insert(0, clientId); if (logger && loggers) loggers->insert(0, logger); } #ifndef _WIN32 // SyslogLogger from facility int facility = item->facility(); #if CONFIG_SYSTEMD_JOURNAL if ((facility > 0) || (facility == SYSTEMD_JOURNAL_FACILITY)) { logger = SyslogLogger::create(lock2.mutex(), facility > 0); #else if (facility > 0) { logger = SyslogLogger::create(lock2.mutex()); #endif ClientList *clients = logRevClientMap.value(logger); if (clients) clients->insert(0, clientId); if (logger && loggers) loggers->insert(0, logger); } #endif // DatabaseLogger from table QString table = item->table(); if (!table.isEmpty()) { logger = DatabaseLogger::create(table, lock2.mutex()); ClientList *clients = logRevClientMap.value(logger); if (clients) clients->insert(0, clientId); if (logger && loggers) loggers->insert(0, logger); } logItem = new LoggerListItem; loggingGetTimeStamp(&logItem->epoch, NULL); logItem->list = loggers; logClientMap.insert(clientId, logItem); item->DecrRef(); } #ifndef NOLOGSERVER m_zmqPubSock->sendMessage(*msg); #else if (logItem && logItem->list && !logItem->list->isEmpty()) { LoggerList::iterator it = logItem->list->begin(); LoggingItem *item = LoggingItem::create(json); if (!item) return; for (; it != logItem->list->end(); ++it) { (*it)->logmsg(item); } item->DecrRef(); } #endif } /// \brief Stop the thread by setting the abort flag void LogForwardThread::stop(void) { m_aborted = true; }
unsigned ClientCount () { return clients.size(); }
bool ClientEngine::initialize() { // Setup Window m_Window.setName("void"); // Connect to server ENetAddress address; if(enet_address_set_host(&address, "localhost") != 0) return false; address.port = 1234; if(!m_Client.connect(&address)) return false; // Setup Resource Manager m_ResourceManager.registerResourceType<Texture2dFile>(RES_TEXTURE2D); // Setup OpenGL glClearDepth(1); glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); // Setup camera m_Camera.setNear(0.1); m_Camera.setFar(100); m_Camera.setRotation(Quaternion(vec3f(1,0,0), -tools4k::Pi*0.5)); m_Camera.setScreen(m_Window.size()); m_Camera.setFov(90); // Setup shader if(!m_Shader.load("Shader.vert", "Shader.frag")) return false; m_Shader.setUniform("DiffuseMap", 0); // Setup map { int myTileMap = m_ClientMap.createTileMap(); TileMap* tm = m_ClientMap.getTileMap(myTileMap); tm->diffuse = (Texture2dFile*)m_ResourceManager.loadResource(RES_TEXTURE2D, "tileset.png"); tm->tileSize = 32; tm->width = 128; int id = m_ClientMap.createVoxelType("Rock"); VoxelType* vt = m_ClientMap.getVoxelType(id); vt->collisionShape = VCSHAPE_CUBE; ClientVoxelType* cvt = m_ClientMap.getClientVoxelType(id); cvt->mesh = VCSHAPE_CUBE; cvt->renderMode = VRENDER_SOLID; cvt->tileMap = myTileMap; memset(cvt->faces, 0, sizeof(cvt->faces)); cvt->faces[VFACE_BACK] = 1; cvt->faces[VFACE_TOP] = 4; Voxel voxel; voxel.typeId = id; m_ClientMap.setVoxel(vec3i(0,0,0), voxel); m_ClientMap.setVoxel(vec3i(1,1,1), voxel); m_ClientMap.updateModel(aabb3i(vec3i(0,0,0), vec3i(10,10,10))); } if(!loadPackage("Base")) return false; return true; }
Message* GetMessage () { ENetEvent event; if (enet_host_service(serverHost, &event, 0)) { Message* msg = NULL; unsigned int clientID = 0; for (ClientMap::iterator iter = clients.begin(); iter != clients.end(); iter++) { if (iter->second == event.peer) { clientID = iter->first; } } switch (event.type) { case ENET_EVENT_TYPE_CONNECT: msg = new Message ( "CONNECT", NULL, 0 ); clientID = nextClientID++; msg->clientID = clientID; clients[clientID] = event.peer; badMessage[clientID][0] = 0; //clear bad-message entry so it can be used Message* keymsg; Message* ivmsg; //make and share encryption keys //ADAM makeBlowKey[clientID]; //ADAM keymsg = new Message( "BLOWKEY", sessionKey[clientID], 16 ); //make a message with the blowkey //ADAM SendMessage( clientID, keymsg ); //send the blowkey //ADAM ivmsg = new Message( "BLOWIV" , sessionIV[clientID], 8 ); //make a message with the blowIV //ADAM SendMessage( clientID, ivmsg ); //send the IV break; case ENET_EVENT_TYPE_DISCONNECT: { msg = new Message ( "DISCONNECT", NULL, 0 ); msg->clientID = clientID; ClientMap::iterator iter = clients.find(clientID); clients.erase(iter); } break; case ENET_EVENT_TYPE_RECEIVE: msg = MessageEncoding::Decode(event.packet); if(msg == NULL) { if (badMessageCount[clientID] >= 4) { KillClient(clientID); } else { BadClient(clientID); } } else { msg->clientID = clientID; /* if( Blowfish::do_decrypt(msg, sessionKey[clientID], sessionIV[clientID]) == false) // msg is passed by reference. Return 0 on error. { //do something with the bad message } else { //do something with the recieved message } */ //disabled until finished implementation } enet_packet_destroy(event.packet); break; } return msg; } return NULL; }
bool IsConnected ( unsigned int clientID ) { return clients.find(clientID) != clients.end(); }
//获取消息队列消息 void proc(void *arg) { HWND hMain = (HWND)arg; USE_JSONCODER_DOC(document); while(1) { Sleep(1); CAutoLock lock(&g_TGetLock); char *msg = NULL; try { msg = reinterpret_cast<char *>(msg_queue.Pop()); //msg = (&doublebuffer_queue)->Popup(); if(!msg) { continue; } } catch(...){ //Log("proc : msg_queue.Pop() fialed."); } #ifdef DEBUG_MODE std::cout << msg << std::endl; #endif //解码 LOAD_JSONCODER_STR(document, msg); JsonCoder jc_decoder; if(!jc_decoder.CheckPacket(document)) { //cout << "error packet" << endl; PostMessage(hMain, WM_ERRORPCK, 0, 0); continue; } //获取消息 uint32 cmd = jc_decoder.GetInt(JC_KEY::JC_MSGTYPE, document); //服务端发送过来的回应包 if(cmd == MESSAGE_TYPE::cmdLoginRep) { //返回的客户列表 std::string user_list = jc_decoder.GetString(JC_KEY::JC_USERLISTREP, document); //上线提示 std::string onlineUser = jc_decoder.GetString(JC_KEY::JC_ONLINEREP, document); //发送上线提醒消息 std::string *olUser = new std::string(onlineUser); PostMessage(hMain, WM_ONLINEWARN, (WPARAM)olUser, 0); #ifdef DEBUG_MODE cout << "user_list" << user_list << endl; #endif //发送列表消息 std::string *uList = new std::string(user_list); //上线的用户提示 std::string *warn = new std::string(onlineUser); PostMessage(hMain, WM_UPDATELIST, (WPARAM)uList, (LPARAM)warn); } else if(cmd == MESSAGE_TYPE::cmdLogoutRep) { //客户端离线提示 std::string logoutUser = jc_decoder.GetString(JC_KEY::JC_LOGOUTUSER, document); //列表删除 ClientMap::iterator ite = cmap.begin(); ite = cmap.find(logoutUser); if(ite != cmap.end()) { cmap.erase(ite); } std::string *ss = new std::string(logoutUser); PostMessage(hMain, WM_DELUSERLIST, (WPARAM)ss, 0); } else if(cmd == MESSAGE_TYPE::cmdPublicMsgRep) { //发送者id std::string user_identify = jc_decoder.GetString(JC_KEY::JC_IDENTIFY, document); //谁发送的 std::string sender = jc_decoder.GetString(JC_KEY::JC_SENDER, document); //发送了什么 std::string pubmsg = jc_decoder.GetString(JC_KEY::JC_PUBMSG, document); //发送时间 std::string pubtime = jc_decoder.GetString(JC_KEY::JC_PUBTIME, document); if(strcmp(user_identify.c_str(), g_Identify.c_str()) != 0) { std::wstring tmp = PublicTool::string2wstring(sender); tmp.append(STR_OTHER_SAY); tmp.append(PublicTool::string2wstring(pubmsg)); tmp.append(L"["); tmp.append(PublicTool::string2wstring(pubtime)); tmp.append(L"]"); std::wstring *ss = new std::wstring(tmp); PostMessage(hMain, WM_PUBMSG, (WPARAM)ss, 0); } } //内存归还到内存池 MsgPool.Release(msg); } }