From 1b81ea383985c0c679b26ae4fef36b701e3a2acd Mon Sep 17 00:00:00 2001 From: Saturneric Date: Tue, 26 Feb 2019 22:25:59 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=B8=8E=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/instruct.h | 4 +++ include/net.h | 1 + include/server.h | 10 ++++-- src/client.cpp | 2 ++ src/controller.cpp | 46 +++++++++++++++----------- src/model.cpp | 82 ++++++++++++++++++++++++++++++++++------------ src/server.cpp | 71 +++++++++++++++++++++++---------------- src/socket.cpp | 4 +++ 8 files changed, 148 insertions(+), 72 deletions(-) diff --git a/include/instruct.h b/include/instruct.h index 6bb44a5..f3ca59f 100644 --- a/include/instruct.h +++ b/include/instruct.h @@ -43,5 +43,9 @@ bool config_search(vector &configs,string tfg); void getSQEPublicKey(respond *pres,void *args); void registerSQECallback(respond *pres,void *args); void* connectionDeamon(void *args); +//客户端连接管理守护进程 +void *clientServiceDeamon(void *); +//实用函数 +void gets_s(char *buff, uint32_t size); #endif /* instruct_h */ diff --git a/include/net.h b/include/net.h index e070722..1de3196 100644 --- a/include/net.h +++ b/include/net.h @@ -164,6 +164,7 @@ public: void SetDataSFD(int tdata_sfd); void SetClientAddr(Addr &caddr); void CloseConnection(void); + void Close(void); // 接收简单字符串数据 ssize_t Recv(string &str); // 接受储存二进制串 diff --git a/include/server.h b/include/server.h index bde8796..1374329 100644 --- a/include/server.h +++ b/include/server.h @@ -68,8 +68,9 @@ struct encrypt_post{ // 内容长度 uint32_t buff_size = 0; Document edoc; - + StringBuffer sb; bool Parse(string json); + void SelfParse(void); void GetJSON(string &json); void SetBuff(Byte *buff, uint32_t size); @@ -228,8 +229,11 @@ struct connection_listener{ int data_sfd; Addr client_addr; aes_key256 key; - pthread_t pid; - void *father_buff; + pthread_t pid = 0; + void *father_buff = nullptr; + SocketTCPCServer *server_cnt = nullptr; + bool if_active = true; + bool *pif_atv = nullptr; }; //通用服务器类 diff --git a/src/client.cpp b/src/client.cpp index f95e68b..c97ad2e 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -11,6 +11,7 @@ pthread_mutex_t mutex_clt; +//客户端构造函数 Client::Client(int port, string send_ip,int send_port):socket(port),send_socket(send_ip,send_port){ socket.UDPSetFCNTL(); listen_port = port; @@ -26,6 +27,7 @@ Client::Client(int port, string send_ip,int send_port):socket(port),send_socket( sqlite3_finalize(psqlsmt); } +//客户端请求接收守护进程 void *clientRequestDeamon(void *pvclt){ clock_thread_info *pclt = (clock_thread_info *) pvclt; Client *pclient = (Client *) pclt->args; diff --git a/src/controller.cpp b/src/controller.cpp index e9aa145..3e7d02b 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -539,28 +539,30 @@ int client(string instruct, vector &configs, vector &lconfigs, v printf("SHMAT Failed.\n"); } + //创建客户端连接管理线程 + connection_listener *pncl = new connection_listener(); + pncl->client_addr = nclt.server_cnt->GetClientAddr(); + pncl->data_sfd = nclt.server_cnt->GetDataSFD(); + pncl->key = nclt.post_key; + pncl->father_buff = buff; + pncl->server_cnt = nclt.server_cnt; + + pthread_create(&pncl->pid, NULL, clientServiceDeamon, pncl); + + memset(buff, 0, sizeof(uint32_t)); while (1) { //检测父进程信号 if(!memcmp(buff, "Exit", sizeof(uint32_t))){ - error::printInfo("get killing signal."); + pncl->if_active = false; + + pthread_join(pncl->pid, NULL); + nclt.server_cnt->Close(); + delete pncl; + memcpy(buff, "SEXT", sizeof(uint32_t)); //断开共享内存连接 shmdt(buff); exit(0); } - - nclt.server_cnt->Accept(); - - connection_listener *pncl = new connection_listener(); - pncl->client_addr = nclt.server_cnt->GetClientAddr(); - pncl->data_sfd = nclt.server_cnt->GetDataSFD(); - pncl->key = nclt.post_key; - pncl->father_buff = buff; - - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_create(&pncl->pid, &attr, connectionDeamon, pncl); - pthread_attr_destroy(&attr); usleep(1000); } } @@ -577,14 +579,19 @@ int client(string instruct, vector &configs, vector &lconfigs, v usleep(1000); } error::printSuccess("\nShell For Client: "); + string cmdstr; + char cmd[1024]; while (1) { - char cmd[1024]; printf(">"); - fgets(cmd,1024,stdin); - string cmdstr = cmd; - + gets_s(cmd,1024); + cmdstr = cmd; if(cmdstr == "Exit"){ + error::printInfo("Start to stop service..."); memcpy(buff, "Exit", sizeof(uint32_t)); + while (memcmp(buff, "SEXT", sizeof(uint32_t))) { + sleep(10000); + } + error::printInfo("Service stopped."); } } @@ -593,6 +600,7 @@ int client(string instruct, vector &configs, vector &lconfigs, v } + return 0; } diff --git a/src/model.cpp b/src/model.cpp index 2eefc84..66614a0 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -72,6 +72,7 @@ void registerSQECallback(respond *pres,void *args){ } } +//客户端连接管理守护线程 void *connectionDeamon(void *args){ connection_listener * pcntl = (connection_listener *)args; string first_data; @@ -94,11 +95,9 @@ void *connectionDeamon(void *args){ Server::ProcessSignedRawMsg(buff, size, *pnrwd); if(!memcmp(&pnrwd->info, "LCNT", sizeof(uint32_t))){ if_sm = false; - printf("Long Connection From Server.\n"); } else if(!memcmp(&pnrwd->info, "SCNT", sizeof(uint32_t))){ if_sm = true; - printf("Short Connection From Server.\n"); ntcps.SendRespond(dget); } else if(!memcmp(&pnrwd->info, "CNTL", sizeof(uint32_t))){ @@ -111,7 +110,10 @@ void *connectionDeamon(void *args){ else{ //断开无效连接 printf("Connection Illegal.\n"); - delete pnrwd; + delete pnrwd; + close(pcntl->data_sfd); + delete pcntl; + pthread_exit(NULL); } @@ -124,40 +126,44 @@ void *connectionDeamon(void *args){ delete pnrwd; while (1) { + if (*pcntl->pif_atv == false) { + close(pcntl->data_sfd); + delete pcntl; + break; + } //区分长连接与短连接 if(if_sm) size = ntcps.RecvRAW(&buff, t_addr); else size = ntcps.RecvRAW_SM(&buff, t_addr); - raw_data *pnrwd = new raw_data(); - packet *nppkt = new packet(); - encrypt_post *pncryp = new encrypt_post(); + if(size > 0){ - printf("MSG: %s\n", buff); + raw_data *pnrwd = new raw_data(); + packet *nppkt = new packet(); + encrypt_post *pncryp = new encrypt_post(); if(Server::CheckRawMsg(buff, size)){ Server::ProcessSignedRawMsg(buff, size, *pnrwd); //获得端对端加密报文 if(!memcmp(&pnrwd->info, "ECYP", sizeof(uint32_t))){ - printf("Get Encrypt Post.\n"); Server::Rawdata2Packet(*nppkt, *pnrwd); SQEServer::Packet2Post(*nppkt, *pncryp, pcntl->key); //获得注册信息反馈报文 if(!memcmp(&pncryp->type, "JRES", sizeof(uint32_t))){ - string jres_str = string(pncryp->buff,pncryp->buff_size); - Document ndoc; - ndoc.Parse(jres_str.data()); - if(ndoc["status"].GetString() == string("ok")){ + //自我解析 + pncryp->SelfParse(); + if(pncryp->edoc["status"].GetString() == string("ok")){ error::printSuccess("Register Successful."); + //进入客户端管理终端 memcpy(pcntl->father_buff,"D_OK", sizeof(uint32_t)); } } + //管理指令连接 + else if (!memcmp(&pnrwd->info, "JCMD", sizeof(uint32_t))) { + //来自管理员的命令 + + } } //心跳连接 else if(!memcmp(&pnrwd->info, "BEAT", sizeof(uint32_t))){ //printf("Connection Beated.\n"); - } - //管理指令连接 - else if(!memcmp(&pnrwd->info, "SCMD", sizeof(uint32_t))){ -// 来自管理员的命令 - } Server::freeRawdataServer(*pnrwd); Server::freePcaketServer(*nppkt); @@ -171,12 +177,46 @@ void *connectionDeamon(void *args){ break; } free(buff); + delete pnrwd; + delete pncryp; + delete nppkt; } - delete pnrwd; - delete pncryp; - delete nppkt; - usleep(10000); + usleep(1000); } pthread_exit(NULL); } + + +void *clientServiceDeamon(void *arg) { + connection_listener *pclst = (connection_listener *)arg; + while (1) { + if (pclst->if_active == false) { + break; + } + pclst->server_cnt->Accept(); + //构造连接守护子进程 + connection_listener *pncl = new connection_listener(); + pncl->client_addr = pclst->client_addr; + pncl->data_sfd = pclst->server_cnt->GetDataSFD(); + pncl->key = pclst->key; + pncl->father_buff = pclst->father_buff; + pncl->pif_atv = &pclst->if_active; + + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_create(&pncl->pid, &attr, connectionDeamon, pncl); + pthread_attr_destroy(&attr); + usleep(1000); + } +} + +void gets_s(char *buff, uint32_t size) { + char ch; + uint32_t i = 0; + while ((ch = getchar()) != '\n' && i < (size - 1)) { + buff[i++] = ch; + } + buff[i] = '\0'; +} \ No newline at end of file diff --git a/src/server.cpp b/src/server.cpp index 4a47491..f3f598f 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1068,7 +1068,11 @@ void *clientChecker(void *args){ pthread_exit(NULL); } -//注册客户端通信维持线程 +void encrypt_post::SelfParse(void) { + edoc.Parse(string(buff, buff_size).data()); +} + +//注册客户端接收通信维持线程 void *clientListener(void *args){ client_listen *pcltl = (client_listen *)args; char *buff; @@ -1077,7 +1081,16 @@ void *clientListener(void *args){ // 如果连接断开 if(pcltl->if_connected == false) break; // 建立新的监听连接 - pcltl->ptcps->Reconnect(); + try { + pcltl->ptcps->Reconnect(); + } + catch (const char *errinfo) { + string errstr = errinfo; + if (errstr == "fail to connect") { + pcltl->if_connected = false; + break; + } + } // 说明连接类型 raw_data nsrwd; SQEServer::BuildSmallRawData(nsrwd, "CNTL"); @@ -1088,17 +1101,15 @@ void *clientListener(void *args){ if(Server::CheckRawMsg(buff, size)){ raw_data nrwd; Server::ProcessSignedRawMsg(buff, size, nrwd); + //如果二进制串中储存端对端加密报文 if(!memcmp(&nrwd.info,"ECYP",sizeof(uint32_t))){ - packet npkt; - encrypt_post necryp; - Server::Rawdata2Packet(npkt, nrwd); - SQEServer::Packet2Post(npkt, necryp, pcltl->pcltr->key); - Server::freePcaketServer(npkt); + encrypt_post necryp; + SQEServer::SignedRawData2Post(nrwd, necryp, pcltl->pcltr->key); + if(!memcmp(&necryp.type,"JIFO",sizeof(uint32_t))){ - Document ndoc; - ndoc.Parse(string(necryp.buff,necryp.buff_size).data()); + necryp.SelfParse(); printf("Client %s[%s] Send Encrypt Post(JSON).\n",pcltl->pcltr->name.data(),pcltl->pcltr->tag.data()); - uint64_t pwd = ndoc["pwdmd5"].GetInt64(); + uint64_t pwd = necryp.edoc["pwdmd5"].GetInt64(); if(pwd == pcltl->pcltr->passwd){ printf("Password Check Passed.\n"); } @@ -1151,7 +1162,7 @@ void SQEServer::SendConnectionInfo(SocketTCPClient *pcnt_sock, bool ifshort) { if(ifshort) SQEServer::BuildSmallRawData(nsrwd, "SCNT"); else SQEServer::BuildSmallRawData(nsrwd, "LCNT"); pcnt_sock->SendRAW(nsrwd.msg, nsrwd.msg_size); - Server::freeRawdataServer(nsrwd); + Server::freeRawdataServer(nsrwd); } void *clientWaitDeamon(void *pvclt){ @@ -1188,10 +1199,8 @@ void *clientWaitDeamon(void *pvclt){ for(int i = 0; i < 8; i++){ ncryp->edoc["passwd"].PushBack(ppidx[i], allocator); } - //初始化端对端加密报文 string send_data; ncryp->GetJSON(send_data); - ncryp->InitNew(pclr->client_id, pclr->t_addr, "JRES"); ncryp->SetBuff((Byte *)send_data.data(),(uint32_t)send_data.size()); @@ -1199,8 +1208,8 @@ void *clientWaitDeamon(void *pvclt){ SQEServer::Post2SignedRawData(*ncryp, pclr->key, *pnrwd); //发送连接属性信息 - SQEServer::SendConnectionInfo(pcnt_sock); - + SQEServer::SendConnectionInfo(pcnt_sock,true); + //等待反馈 if (resFromClient(pcnt_sock)) { pcnt_sock->SendRAW(pnrwd->msg, pnrwd->msg_size); pcnt_sock->Close(); @@ -1215,33 +1224,27 @@ void *clientWaitDeamon(void *pvclt){ pthread_exit(NULL); } - + //建立客户端连接管理信息提供结构 client_listen *pcltl = new client_listen(); pcltl->pcltr = pclr; pcltl->if_get = false; pcltl->pid = 0; + + //建立子线程 pthread_t bt,lt; pcltl->pcryp = nullptr; pcltl->ptcps = pcnt_sock; - + + //监听线程 pthread_create(<, NULL, clientListener, pcltl); + //连接状态监测线程 pthread_create(&bt, NULL, clientChecker, pcltl); while (1 && pclr->click-- > 0) { sleep(1); if(pcltl->if_connected == false){ - printf("Register lost, start to separate.\n"); + printf("Register lost %s[%s]\n",pclr->name.data(),pclr->tag.data()); break; } - try{ - //pcnt_sock->Reconnect(); - //pcnt_sock->Close(); - } - catch(const char *error){ - if(!strcmp(error, "fail to connect")){ - printf("Lose Register: %s[%s]\n",pclr->name.data(),pclr->tag.data()); - break; - } - } } delete pclr; @@ -1276,7 +1279,7 @@ const uint8_t * aes_key256::GetIV(void){ void SQEServer::BuildBeatsRawData(raw_data &rwd){ - rwd.setData("Beat"); + rwd.setData("B"); SignedRawdata(&rwd, "BEAT"); } @@ -1307,3 +1310,13 @@ void SQEServer::BuildSmallRawData(raw_data &rwd, const char *info){ rwd.setData(""); SignedRawdata(&rwd, info); } + +bool encrypt_post::Parse(string json) { + return edoc.Parse(json.data()).HasParseError(); +} + +void encrypt_post::GetJSON(string &json) { + Writer writer(sb); + edoc.Accept(writer); + json = sb.GetString(); +} \ No newline at end of file diff --git a/src/socket.cpp b/src/socket.cpp index 9648348..731ba16 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -177,6 +177,10 @@ void SocketTCPClient::Reconnect(void){ void SocketTCPCServer::CloseConnection(void){ close(data_sfd); } +void SocketTCPCServer::Close(void) { + close(server_sfd); +} + void SocketTCPClient::GetRespond(string &str){ ssize_t size = recv(client_sfd, buff, BUFSIZ, 0);