bool CServer::OnClientInit(CServerClient* pClient) { if(pClient == NULL) return false; long lIndexID = pClient->GetIndexID(); //绑定套接字到完成端口 if( !AssociateSocketWithCP(pClient->m_hSocket,lIndexID) ) { pClient->Close(); FreeClient(pClient); PutErrorString(NET_MODULE,"%-15s %s",__FUNCTION__,"在函数CServer::OnConClientInitial(...)中,AssociateSocketWithCP(...)操作失败."); return false; } if( pClient->StartReadData() == false) { pClient->Close(); FreeClient(pClient); return false; } if( pClient->IsAccept() ) AddNewAcceptSocket(lIndexID); //判断接受数据是否超时,超时则关闭改套接字 DoNewAcceptSocket(); return true; }
//当关闭的时候 void CServer::OnClose(PER_IO_OPERATION_DATA *pPerIOData,long lIndexID) { if(NULL == pPerIOData) return; if(pPerIOData->OperationType == SOT_Send) { CBaseMessage* pMsg = (CBaseMessage*)pPerIOData->pParam; if(pMsg->RemoveRefCount() == 0) CBaseMessage::FreeMsg(pMsg); } else if(pPerIOData->OperationType == SOT_Receive) { m_pDBAllocator->FreeDB((CDataBlock*)pPerIOData->pParam); } CServerClient *pClient = FindClient(lIndexID); if(pClient) { //取消超时监视 if(pClient->IsAccept()) RemoveNewAcceptSocket(pClient->GetIndexID()); pClient->OnClose(); FreeClient(pClient); } FreeIoOper(pPerIOData); }
// error的时候调用 void CServer::OnError(PER_IO_OPERATION_DATA *pPerIOData,long lIndexID,int errorCode) { if(NULL == pPerIOData) return; char str[200]; if(pPerIOData->OperationType == SOT_Send) { sprintf(str, "完成端口线程产生一次失败的发送IO操作(ErrorID:%d)。",errorCode); CBaseMessage* pMsg = (CBaseMessage*)pPerIOData->pParam; if(pMsg->RemoveRefCount() == 0) CBaseMessage::FreeMsg(pMsg); } else if(pPerIOData->OperationType == SOT_Receive) { sprintf(str, "完成端口线程产生一次失败的接受IO操作(ErrorID:%d)。",errorCode); m_pDBAllocator->FreeDB((CDataBlock*)pPerIOData->pParam); } CServerClient *pClient = FindClient(lIndexID); if(pClient) { //取消超时监视 if(pClient->IsAccept()) RemoveNewAcceptSocket(pClient->GetIndexID()); pClient->OnClose(); FreeClient(pClient); } FreeIoOper(pPerIOData); if(errorCode != 64) { PutTraceString(NET_MODULE,str); } }
void CloseAfterSent(proxy_client*c) { /*add------------_*/ int len; if(BufferListGetData(c->blist,&len)==NULL){ FreeClient(c); }else{ c->flags|=CLIENT_CLOSE_AFTER_SENT; } /*add------------_*/ }
void CServerSocket::Close() { Lock(); CCustomClientSocket * ClientSocket; SetActive(false); for(int i =0 ;i< (int)m_ActiveClientSocketList.size();i++) { ClientSocket = m_ActiveClientSocketList[i]; if(ClientSocket !=NULL) { FreeClient(ClientSocket); } } Unlock(); m_FreeClientPool.FreeTimeOutClient(MAX_FREE_TIMEOUT); }
void Proxy_AcceptTcpHandler(aeEventLoop*el,int fd,void*privdata,int mask) { int cport,cfd; char cip[128]; cfd=anetTcpAccept(anet_error,fd,cip,&cport); if(cfd==AE_ERR){ LogError("accept client connection failed:%s",anet_error); return; } LogInfo("Accept client from:%s:%d\n",cip,cport); proxy_client*c=AllocClient(cfd); if(c==NULL||aeCreateFileEvent(el,cfd,AE_READABLE,ReadIncome,c)==AE_ERR){ LogError("Create event failed"); FreeClient(c); } }
void CServer::OnReceive(PER_IO_OPERATION_DATA *pPerIOData,long lIndexID,long lReadNum) { CServerClient* pClient = FindClient(lIndexID); if( pClient ) { if(pClient->IsAccept()) RemoveNewAcceptSocket(lIndexID); CDataBlock *pReadDB = (CDataBlock*)pPerIOData->pParam; //添加读数据的大小 pClient->AddRecvSize(lReadNum); //设置读取数据的大小 pReadDB->SetCurSize(lReadNum); //添加完成的读数据 pClient->AddReceiveData(pPerIOData->m_nSequenceNumber,pReadDB); //重新开始读取数据 if(pClient->ReadFromCompletionPort(pPerIOData,NULL) ) { pClient->OnReceive(); //如果平均每秒接受的大小超过限制值,发出错误信息.断开 if(pClient->GetCurRecvSizePerSecond() > pClient->GetMaxRecvSizePerSecond() ) { Log4c::Warn(NET_MODULE,"erro,(SocketID:%d) the current rcv data size per-second(%d) greater the max value(%d),shutdown the socket!", lIndexID,pClient->GetCurRecvSizePerSecond(),pClient->GetMaxRecvSizePerSecond()); //关闭 pClient->Close();; } } else { //处理错误情况 FreeIoOper(pPerIOData); pClient->OnClose(); FreeClient(pClient); } } else { //处理错误情况 FreeIoOper(pPerIOData); } return; }
void SendOutcome(aeEventLoop*el,int fd,void*privdata,int mask) { LogDebug("sendoutcome"); proxy_client*c=(proxy_client*)privdata; int len,nwritten=0,totwritten=0; char*buf; buf=BufferListGetData(c->blist,&len); if(buf==NULL){ LogDebug("delete write event ,cause no data could sendout"); aeDeleteFileEvent(el,fd,AE_WRITABLE);//why delete writeable event?? } while(1){ buf=BufferListGetData(c->blist,&len); if(buf==NULL){ //no data to send if(c->flags&CLIENT_CLOSE_AFTER_SENT){ FreeClient(c); return; } break; } nwritten=send(fd,buf,len,MSG_DONTWAIT); if(nwritten<=0) break; totwritten+=nwritten; LogDebug("Write and pop data %p %d",c->blist,nwritten); BufferListPop(c->blist,nwritten); if(totwritten>MAX_WRITE_PER_EVENT) break; } LogDebug("totwritten %d",totwritten); if(nwritten==-1){ if(errno==EAGAIN){ nwritten=0; }else{ LogDebug("Write error %s",strerror(errno)); c->OnError(c); return; } } }
//主动连接服务器,返回该连接的ID //返回-1,表示失败 long CServer::Connect(LPCTSTR lpszHostAddress, UINT nHostPort,long lFlag,ulong dwTimeOut) { if(!(m_bMode&1)) return -1; CServerClient* pConClient = AllocClient(false); if(pConClient == NULL) return -1; if( !pConClient->CreateEx(0,NULL,SOCK_STREAM) ) { PutErrorString(NET_MODULE,"%-15s Create socket bound to %s:%u FAILED, ERR_ID: %d.",__FUNCTION__, lpszHostAddress, nHostPort, GetLastError()); return -1; } pConClient->SetFlag(lFlag); //设置编号 pConClient->SetSendRevBuf(); //设置套接字选项 pConClient->SetSocketOpt(); long lID = pConClient->GetIndexID(); pConClient->SetClose(false); pConClient->SetShutDown(false); pConClient->SetParam(false,0xFFFFFFF,m_lConMaxBlockSendMsgNum, m_lConPendingWrBufNum,m_lConPendingRdBufNum, m_lConMaxSendSizePerSecond,m_lConMaxRecvSizePerSecond,lFlag); if( !Connect(pConClient,lpszHostAddress,nHostPort,dwTimeOut) ) { pConClient->Close(); FreeClient(pConClient); return -1; } tagSocketOper* pSocketOpera = AllocSockOper(); pSocketOpera->Init(SCOT_Init,lID,pConClient,0); m_SocketOperaCommands.Push_Back(pSocketOpera); return lID; }
void Client::ClientEventCallback(evutil_socket_t sockfd, short event, void *userdata) { Client *client = (Client*)userdata; if (event & EV_READ) { int cap = client->m_intemp.capacity(); int ret = read(sockfd, &client->m_intemp[0], cap); if (ret == -1) { if (errno != EAGAIN && errno != EINTR) { FreeClient(client); return; } } else if (ret == 0) { FreeClient(client); //client wants to leave, //so let it leave whether or not there's still any data waiting to send to it. return; } else { client->m_inbuf.append(client->m_intemp.c_str(), ret); } } if (event & EV_WRITE) { int ret = write(sockfd, client->m_outbuf.c_str(), client->m_outbuf.size()); if (ret == -1) { if (errno != EAGAIN && errno != EINTR) { if (client->m_status != ON_RESPONSE) { FreeClient(client); return; } } } else { client->m_outbuf.erase(client->m_outbuf.begin(), client->m_outbuf.begin() + ret); //if client really want to keep write event, we can't unregister write event, even though there's nothing to send. if (client->m_outbuf.size() == 0 && !client->m_want_write) { client->UnsetWriteEvent(); } } } // core logic, just call status machine to handle the whole thing, it's so easy :) if (!client->StatusMachine()) { FreeClient(client); //some error has happend, kick out the client. } }
// 删除一个客户端 bool CServer::FreeClient(long lSocketID) { CServerClient* pClient = FindClient(lSocketID); FreeClient(pClient); return true; }
static Status RegisterClientProc(SmsConn smsConn, SmPointer managerData, char *previousId) { ClientRec *client = (ClientRec *) managerData; char *id; List *cl; int send_save; if (verbose) { printf ( "On IceConn fd = %d, received REGISTER CLIENT [Previous Id = %s]\n", IceConnectionNumber (client->ice_conn), previousId ? previousId : "NULL"); printf ("\n"); } if (!previousId) { id = SmsGenerateClientID (smsConn); send_save = 1; } else { int found_match = 0; send_save = 1; for (cl = ListFirst (PendingList); cl; cl = ListNext (cl)) { PendingClient *pendClient = (PendingClient *) cl->thing; if (!strcmp (pendClient->clientId, previousId)) { SetInitialProperties (client, pendClient->props); XtFree (pendClient->clientId); XtFree (pendClient->clientHostname); XtFree ((char *) pendClient); ListFreeOne (cl); found_match = 1; send_save = 0; break; } } if (!found_match) { for (cl = ListFirst (RestartAnywayList); cl; cl = ListNext (cl)) { ClientRec *rClient = (ClientRec *) cl->thing; if (!strcmp (rClient->clientId, previousId)) { SetInitialProperties (client, rClient->props); FreeClient (rClient, False /* don't free props */); ListFreeOne (cl); found_match = 1; send_save = 0; break; } } } if (!found_match) { for (cl = ListFirst (RestartImmedList); cl; cl = ListNext (cl)) { ClientRec *rClient = (ClientRec *) cl->thing; if (!strcmp (rClient->clientId, previousId)) { SetInitialProperties (client, rClient->props); FreeClient (rClient, False /* don't free props */); ListFreeOne (cl); found_match = 1; send_save = 0; break; } } } if (!found_match) { /* * previous-id was bogus: return bad status and the client * should re-register with a NULL previous-id */ free (previousId); return (0); } else { id = previousId; } } SmsRegisterClientReply (smsConn, id); if (verbose) { printf ( "On IceConn fd = %d, sent REGISTER CLIENT REPLY [Client Id = %s]\n", IceConnectionNumber (client->ice_conn), id); printf ("\n"); } client->clientId = id; client->clientHostname = SmsClientHostName (smsConn); client->restarted = (previousId != NULL); if (send_save) { SmsSaveYourself (smsConn, SmSaveLocal, False, SmInteractStyleNone, False); ListAddLast (InitialSaveList, (char *) client); } else if (client_info_visible) { /* We already have all required client info */ UpdateClientList (); XawListHighlight (clientListWidget, current_client_selected); } return (1); }
void CloseDownClient(ClientRec *client) { int index_deleted = 0; if (verbose) { printf ("ICE Connection closed, IceConn fd = %d\n", IceConnectionNumber (client->ice_conn)); printf ("\n"); } SmsCleanUp (client->smsConn); IceSetShutdownNegotiation (client->ice_conn, False); IceCloseConnection (client->ice_conn); client->ice_conn = NULL; client->smsConn = NULL; if (!shutdownInProgress && client_info_visible) { for (index_deleted = 0; index_deleted < numClientListNames; index_deleted++) { if (clientListRecs[index_deleted] == client) break; } } ListSearchAndFreeOne (RunningList, (char *) client); if (saveInProgress) { Status delStatus = ListSearchAndFreeOne ( WaitForSaveDoneList, (char *) client); if (delStatus) { ListAddLast (FailedSaveList, (char *) client); client->freeAfterBadSavePopup = True; } ListSearchAndFreeOne (WaitForInteractList, (char *) client); ListSearchAndFreeOne (WaitForPhase2List, (char *) client); if (delStatus && ListCount (WaitForSaveDoneList) == 0) { if (ListCount (FailedSaveList) > 0 && !checkpoint_from_signal) PopupBadSave (); else FinishUpSave (); } else if (ListCount (WaitForInteractList) > 0 && OkToEnterInteractPhase ()) { LetClientInteract (ListFirst (WaitForInteractList)); } else if (!phase2InProgress && ListCount (WaitForPhase2List) > 0 && OkToEnterPhase2 ()) { StartPhase2 (); } } if (client->restartHint == SmRestartImmediately && !shutdownInProgress) { Clone (client, True /* use saved state */); ListAddLast (RestartImmedList, (char *) client); } else if (client->restartHint == SmRestartAnyway) { ListAddLast (RestartAnywayList, (char *) client); } else if (!client->freeAfterBadSavePopup) { FreeClient (client, True /* free props */); } if (shutdownInProgress) { if (ListCount (RunningList) == 0) EndSession (0); } else if (client_info_visible) { UpdateClientList (); if (current_client_selected == index_deleted) { if (current_client_selected == numClientListNames) current_client_selected--; if (current_client_selected >= 0) { XawListHighlight (clientListWidget, current_client_selected); ShowHint (clientListRecs[current_client_selected]); if (client_prop_visible) { DisplayProps (clientListRecs[current_client_selected]); } } } else { if (index_deleted < current_client_selected) current_client_selected--; XawListHighlight (clientListWidget, current_client_selected); } } }
/* ** ParseConfig -- parse the config file into linked list of clients. ** ** Parameters: ** None. ** ** Returns: ** 1 on success, 0 otherwise. ** ** Side Effects: ** - Linked list of clients will be (re)allocated. ** ** Warnings: ** - GetBootFiles() must be called before this routine ** to create a linked list of default boot files. */ int ParseConfig(void) { FILE *fp; CLIENT *client; u_int8_t *addr; char line[C_LINELEN]; char *cp, *bcp; int i, j; int omask, linecnt = 0; if (BootAny) /* ignore config file */ return(1); FreeClients(); /* delete old list of clients */ if ((fp = fopen(ConfigFile, "r")) == NULL) { syslog(LOG_ERR, "ParseConfig: can't open config file (%s)", ConfigFile); return(0); } /* * We've got to block SIGHUP to prevent reconfiguration while * dealing with the linked list of Clients. This can be done * when actually linking the new client into the list, but * this could have unexpected results if the server was HUP'd * whilst reconfiguring. Hence, it is done here. */ omask = sigblock(sigmask(SIGHUP)); /* * GETSTR positions `bcp' at the start of the current token, * and null terminates it. `cp' is positioned at the start * of the next token. spaces & commas are separators. */ #define GETSTR while (isspace(*cp) || *cp == ',') cp++; \ bcp = cp; \ while (*cp && *cp!=',' && !isspace(*cp)) cp++; \ if (*cp) *cp++ = '\0' /* * For each line, parse it into a new CLIENT struct. */ while (fgets(line, C_LINELEN, fp) != NULL) { linecnt++; /* line counter */ if (*line == '\0' || *line == '#') /* ignore comment */ continue; if ((cp = strchr(line,'#')) != NULL) /* trash comments */ *cp = '\0'; cp = line; /* init `cp' */ GETSTR; /* get RMP addr */ if (bcp == cp) /* all delimiters */ continue; /* * Get an RMP address from a string. Abort on failure. */ if ((addr = ParseAddr(bcp)) == NULL) { syslog(LOG_ERR, "ParseConfig: line %d: can't parse <%s>", linecnt, bcp); continue; } if ((client = NewClient(addr)) == NULL) /* alloc new client */ continue; GETSTR; /* get first file */ /* * If no boot files are spec'd, use the default list. * Otherwise, validate each file (`bcp') against the * list of boot-able files. */ i = 0; if (bcp == cp) /* no files spec'd */ for (; i < C_MAXFILE && BootFiles[i] != NULL; i++) client->files[i] = BootFiles[i]; else { do { /* * For each boot file spec'd, make sure it's * in our list. If so, include a pointer to * it in the CLIENT's list of boot files. */ for (j = 0; ; j++) { if (j==C_MAXFILE||BootFiles[j]==NULL) { syslog(LOG_ERR, "ParseConfig: line %d: no boot file (%s)", linecnt, bcp); break; } if (STREQN(BootFiles[j], bcp)) { if (i < C_MAXFILE) client->files[i++] = BootFiles[j]; else syslog(LOG_ERR, "ParseConfig: line %d: too many boot files (%s)", linecnt, bcp); break; } } GETSTR; /* get next file */ } while (bcp != cp); /* * Restricted list of boot files were spec'd, * however, none of them were found. Since we * apparently can't let them boot "just anything", * the entire record is invalidated. */ if (i == 0) { FreeClient(client); continue; } } /* * Link this client into the linked list of clients. * SIGHUP has already been blocked. */ if (Clients) client->next = Clients; Clients = client; } (void) fclose(fp); /* close config file */ (void) sigsetmask(omask); /* reset signal mask */ return(1); /* return success */ }