bool Server::configureSocket(int fd) const { if (!makeNonBlocking(fd)) { return false; } const int yesPlease = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yesPlease, sizeof(yesPlease)) == -1) { LS_ERROR(_logger, "Unable to set reuse socket option: " << getLastError()); return false; } if (_maxKeepAliveDrops > 0) { if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &yesPlease, sizeof(yesPlease)) == -1) { LS_ERROR(_logger, "Unable to enable keepalive: " << getLastError()); return false; } const int oneSecond = 1; if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &oneSecond, sizeof(oneSecond)) == -1) { LS_ERROR(_logger, "Unable to set idle probe: " << getLastError()); return false; } if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &oneSecond, sizeof(oneSecond)) == -1) { LS_ERROR(_logger, "Unable to set idle interval: " << getLastError()); return false; } if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &_maxKeepAliveDrops, sizeof(_maxKeepAliveDrops)) == -1) { LS_ERROR(_logger, "Unable to set keep alive count: " << getLastError()); return false; } } return true; }
int createAndBind( char const * port ) { addrinfo ai; // http://baike.baidu.com/view/6757218.htm memset( &ai, 0, sizeof(addrinfo) ); // 初始化 ai.ai_family = AF_UNSPEC; // 不限 ipv4/6 ai.ai_socktype = SOCK_STREAM; // tcp ai.ai_flags = AI_PASSIVE; // 被动,用于 bind addrinfo *pai; // getaddrinfo 的结果容器 int rtv = getaddrinfo( nullptr, port, &ai, &pai ); if( rtv ) { std::cout << "getaddrinfo error:" << gai_strerror( rtv ) << "\n"; return -1; } FreeHelper fh_pai( [&](){ freeaddrinfo( pai ); } ); // 确保出函数时 pai 得以回收 int sfd; for( addrinfo *p = pai; p != nullptr; p = p->ai_next ) { sfd = socket( p->ai_family, p->ai_socktype, p->ai_protocol ); if( sfd == -1 ) { continue; // socket 创建失败,进入下一个循环 } rtv = bind( sfd, p->ai_addr, p->ai_addrlen ); if( rtv == 0 ) { goto LabSuccess; // 成功 bind, 跳到后续执行点 } else { close( sfd ); // 失败立即关闭,进入下一个循环 } } std::cout << "bind error.\n"; return -1; LabSuccess: FreeHelper fh_sfd( [&](){ close( sfd ); } ); // 确保出函数时 sfd 得以回收 int opt = SO_REUSEADDR; rtv = setsockopt( sfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt) ); if( rtv == -1 ) { std::cout << "setsockopt error.\n"; return -1; } if( !makeNonBlocking( sfd ) ) { return -1; } fh_sfd.cancel(); // 取消保护, 要返回, 不需回收 return sfd; }
int Exiv2::http(dict_t& request,dict_t& response,std::string& errors) { if ( !request.count("verb") ) request["verb" ] = "GET"; if ( !request.count("header") ) request["header" ] = "" ; if ( !request.count("version")) request["version"] = "1.0"; if ( !request.count("port") ) request["port" ] = "" ; std::string file; errors = ""; int result = 0; //////////////////////////////////// // Windows specific code #ifdef WIN32 WSADATA wsaData; WSAStartup(MAKEWORD(2,2), &wsaData); #endif const char* servername = request["server" ].c_str(); const char* page = request["page" ].c_str(); const char* verb = request["verb" ].c_str(); const char* header = request["header" ].c_str(); const char* version = request["version"].c_str(); const char* port = request["port" ].c_str(); const char* servername_p = servername; const char* port_p = port ; std::string url = std::string("http://") + request["server"] + request["page"]; // parse and change server if using a proxy const char* PROXI = "HTTP_PROXY"; const char* proxi = "http_proxy"; const char* PROXY = getenv(PROXI); const char* proxy = getenv(proxi); bool bProx = PROXY || proxy; const char* prox = bProx ? (proxy?proxy:PROXY):""; Exiv2::Uri Proxy = Exiv2::Uri::Parse(prox); // find the dictionary of no_proxy servers const char* NO_PROXI = "NO_PROXY"; const char* no_proxi = "no_proxy"; const char* NO_PROXY = getenv(NO_PROXI); const char* no_proxy = getenv(no_proxi); bool bNoProxy = NO_PROXY||no_proxy; std::string no_prox = std::string(bNoProxy?(no_proxy?no_proxy:NO_PROXY):""); Exiv2::dict_t noProxy= stringToDict(no_prox + ",localhost,127.0.0.1"); // if the server is on the no_proxy list ... ignore the proxy! if ( noProxy.count(servername) ) bProx = false; if ( bProx ) { servername_p = Proxy.Host.c_str(); port_p = Proxy.Port.c_str(); page = url.c_str(); std::string p(proxy?proxi:PROXI); // std::cerr << p << '=' << prox << " page = " << page << std::endl; } if ( !port [0] ) port = "80"; if ( !port_p[0] ) port_p = "80"; //////////////////////////////////// // open the socket int sockfd = (int) socket(AF_INET , SOCK_STREAM,IPPROTO_TCP) ; if ( sockfd < 0 ) return error("unable to create socket\n",NULL,NULL,0) ; // connect the socket to the server int server = -1 ; // fill in the address struct sockaddr_in serv_addr ; int serv_len = sizeof(serv_addr); memset((char *)&serv_addr,0,serv_len); serv_addr.sin_addr.s_addr = inet_addr(servername_p); serv_addr.sin_family = AF_INET ; serv_addr.sin_port = htons(atoi(port_p)); // convert unknown servername into IP address // http://publib.boulder.ibm.com/infocenter/iseries/v5r3/index.jsp?topic=/rzab6/rzab6uafinet.htm if (serv_addr.sin_addr.s_addr == (unsigned long)INADDR_NONE) { struct hostent* host = gethostbyname(servername_p); if ( !host ) return error("no such host",servername_p,NULL,0); memcpy(&serv_addr.sin_addr,host->h_addr,sizeof(serv_addr.sin_addr)); } makeNonBlocking(sockfd) ; //////////////////////////////////// // and connect server = connect(sockfd, (const struct sockaddr *) &serv_addr, serv_len) ; if ( server == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK ) return error(errors,"error - unable to connect to server = %s port = %s wsa_error = %d",servername_p,port_p,WSAGetLastError()); char buffer[32*1024+1]; size_t buff_l= sizeof buffer - 1 ; //////////////////////////////////// // format the request #ifdef MSDEV_2003 int n = sprintf(buffer,httpTemplate,verb,page,version,servername,header) ; #else int n = snprintf(buffer,buff_l,httpTemplate,verb,page,version,servername,header) ; #endif buffer[n] = 0 ; response["requestheaders"]=std::string(buffer,n); //////////////////////////////////// // send the header (we'll have to wait for the connection by the non-blocking socket) while ( sleep_ >= 0 && send(sockfd,buffer,n,0) == SOCKET_ERROR /* && WSAGetLastError() == WSAENOTCONN */ ) { Sleep(snooze) ; sleep_ -= snooze ; } if ( sleep_ < 0 ) return error(errors,"error - timeout connecting to server = %s port = %s wsa_error = %d",servername,port,WSAGetLastError()); int end = 0 ; // write position in buffer bool bSearching = true ; // looking for headers in the response int status= 200 ; // assume happiness //////////////////////////////////// // read and process the response int err ; n=forgive(recv(sockfd,buffer,(int)buff_l,0),err) ; while ( n >= 0 && OK(status) ) { if ( n ) { end += n ; buffer[end] = 0 ; size_t body = 0 ; // start of body if ( bSearching ) { // search for the body for ( size_t b = 0 ; bSearching && b < lengthof(blankLines) ; b++ ) { if ( strstr(buffer,blankLines[b]) ) { bSearching = false ; body = (int) ( strstr(buffer,blankLines[b]) - buffer ) + strlen(blankLines[b]) ; status = atoi(strchr(buffer,' ')) ; } } // parse response headers char* h = buffer; char C = ':' ; char N = '\n'; int i = 0 ; // initial byte in buffer while(buffer[i] == N ) i++; h = strchr(h+i,N)+1; response[""]=std::string(buffer+i).substr(0,h-buffer-2); result = atoi(strchr(buffer,' ')); char* c = strchr(h,C); char* n = strchr(h,N); while ( c && n && c < n && h < buffer+body ) { std::string key(h); std::string value(c+1); key = key.substr(0,c-h); value = value.substr(0,n-c-1); response[key]=value; h = n+1; c = strchr(h,C); n = strchr(h,N); } } // if the bufffer's full and we're still searching - give up! // this handles the possibility that there are no headers if ( bSearching && buff_l-end < 10 ) { bSearching = false ; body = 0 ; } if ( !bSearching && OK(status) ) { flushBuffer(buffer,body,end,file); } } n=forgive(recv(sockfd,buffer+end,(int)(buff_l-end),0),err) ; if ( !n ) { Sleep(snooze) ; sleep_ -= snooze ; if ( sleep_ < 0 ) n = FINISH ; } } if ( n != FINISH || !OK(status) ) { #ifdef MSDEV_2003 sprintf(buffer,"wsa_error = %d,n = %d,sleep_ = %d status = %d" , WSAGetLastError() , n , sleep_ , status ) ; #else snprintf(buffer,sizeof buffer,"wsa_error = %d,n = %d,sleep_ = %d status = %d" , WSAGetLastError() , n , sleep_ , status ) ; #endif error(errors,buffer,NULL,NULL,0) ; } else if ( bSearching && OK(status) ) { if ( end ) { // we finished OK without finding headers, flush the buffer flushBuffer(buffer,0,end,file) ; } else { return error(errors,"error - no response from server = %s port = %s wsa_error = %d",servername,port,WSAGetLastError()); } } //////////////////////////////////// // close sockets closesocket(server) ; closesocket(sockfd) ; response["body"]=file; return result; }
int test1() { int sfd = createAndBind( "12345" ); if( sfd == -1 ) { return -1; } FreeHelper fh_sfd( [&](){ close( sfd ); } ); // 确保回收 sfd int rtv = listen( sfd, SOMAXCONN ); // 系统设置的 /proc/sys/net/core/somaxconn 也是一层限制, 有文章建议设为 1024 if( rtv == -1 ) // http://www.hackbase.com/tech/2008-06-18/41054.html { std::cout << "listen error.\n"; return -1; } int efd = epoll_create( _maxEvents ); if( efd == -1 ) { std::cout << "epoll_create1 error.\n"; return -1; } FreeHelper fh_efd( [&](){ close( efd ); } ); // 确保回收 efd epoll_event e; e.data.fd = sfd; e.events = EPOLLIN | EPOLLET; rtv = epoll_ctl( efd, EPOLL_CTL_ADD, sfd, &e ); if( rtv == -1 ) { std::cout << "epoll_ctl error.\n"; return -1; } auto es = (epoll_event*)calloc( _maxEvents, sizeof(e) ); FreeHelper fh_es( [&](){ free( es ); } ); Dict<int, Binary*> tokens; FreeHelper fh_tokens( [&]() { for( int i = 0; i < tokens._nodes._len; ++i ) { close( tokens._nodes[ i ]->_key ); delete tokens._nodes[ i ]->_value; } } ); while( true ) { int n = epoll_wait( efd, es, _maxEvents, 0 ); // -1 if( n == -1 ) { std::cout << "epoll_wait error.\n"; // if( errno == EINTR ) // 当前不确定这个错误要不要无视 return -1; } for( int i = 0; i < n; ++i ) { auto &ce = es[ i ]; if( ( ce.events & EPOLLERR ) || ( ce.events & EPOLLHUP ) || !( ce.events & EPOLLIN ) ) { std::cout << "epoll error.\n"; continue; } else if( sfd == ce.data.fd ) { while( true ) { sockaddr sa; auto salen = (socklen_t)sizeof(sa); int ifd = accept( sfd, &sa, &salen ); if( ifd == -1 ) { if( ( errno == EAGAIN ) || ( errno == EWOULDBLOCK ) ) { break; // 执行到这里的时候已经处理完所有连接请求,跳出 } else { std::cout << "accept error.\n"; } break; } char hbuf[ NI_MAXHOST ], sbuf[ NI_MAXSERV ]; // 这段代码是取创建的连接的客户端地址信息 rtv = getnameinfo( &sa, salen, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV ); if( rtv == 0 ) { std::cout << "accepted. in_fd = " << ifd << ", host = " << hbuf << ", port = " << sbuf << "\n"; } rtv = makeNonBlocking( ifd ); if( rtv == -1 ) { close( ifd ); return -1; } e.data.fd = ifd; e.events = EPOLLIN | EPOLLET; rtv = epoll_ctl( efd, EPOLL_CTL_ADD, ifd, &e ); if( rtv == -1 ) { std::cout << "epoll_ctl error.\n"; close( ifd ); return -1; } std::cout << "tokens.add( ifd : " << ifd << " ).\n"; tokens.add( ifd, new Binary() ); } continue; } else { auto ifd = ce.data.fd; Binary* bin; if( !tokens.tryGet( ifd, bin ) ) { std::cout << "cannot get ifd: " << ifd << " from tokens.\n"; continue; } bool done = false; // 有数据未读,必须读光( edge triggered mode ) do { bin->ensure( 4096 ); rtv = recv( ifd, bin->_buf + bin->_len, 4096, 0 ); if( rtv == -1 ) { if( errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK ) { break; } std::cout << "read error.\n"; done = true; break; } else if( rtv == 0 ) // 0 长度表示连接已断开 { done = true; break; } bin->_len += rtv; } while( rtv == 4096 ); // 按某文章的说法,读到的字节数小于 buf 长,就表明已经读完了 if( !done ) // 顺利读完数据到此 { LabBegin: // 这里使用 readIdx 来存上一次的扫描点 for( ; bin->_readIdx < bin->_len; ++bin->_readIdx ) { if( bin->_buf[ bin->_readIdx ] == '\n' ) { ++bin->_readIdx; // 跳过空格 if( bin->_buf[ 0 ] == '`' ) // 退出 { return 0; } else if( bin->_buf[ 0 ] == ' ' ) // 广播 { for( int i = 0; i < tokens._nodes._len; ++i ) { auto cifd = tokens._nodes[ i ]->_key; if( cifd == ifd ) continue; rtv = write( cifd, bin->_buf, bin->_readIdx ); if( rtv == -1 ) { close( cifd ); Binary* bin; if( !tokens.tryRemove( cifd, bin ) ) { std::cout << "cannot remove cifd: " << cifd << " from tokens.\n"; } else { delete bin; } } } } rtv = send( ifd, bin->_buf, bin->_readIdx, 0 ); // 回发收到的数据 \n 截止 if( rtv == -1 ) { std::cout << "write error.\n"; done = true; break; } memmove( bin->_buf, bin->_buf + bin->_readIdx, bin->_len - bin->_readIdx ); bin->_len = bin->_len - bin->_readIdx; bin->_readIdx = 0; if( bin->_len ) goto LabBegin; break; } } } if( done ) // 出问题需要关闭 ifd { std::cout << "closed. ce.data.fd = " << ifd << "\n"; close( ifd ); Binary* bin; if( !tokens.tryRemove( ifd, bin ) ) { std::cout << "cannot remove ifd: " << ifd << " from tokens.\n"; } else { delete bin; } } } } // todo: logic code here usleep( 1 ); } return 0; }
int main(int argc, char* argv[]){ pthread_mutex_init(&lock, NULL); /* Attach Signal handlers */ signal(SIGINT,killClientProgramHandler); signal(SIGCHLD,xtermReaperHandler); bool newUser; char *username = NULL; char *portNumber = NULL; char *ipAddress = NULL; char *filePtr; int c; char message[1024]; //check flags in command line while ((c = getopt(argc, argv, "hcva:")) != -1){ switch(c){ case 'h': USAGE("./client"); exit(EXIT_SUCCESS); case 'c': newUser = true; break; case 'v': verbose = true; break; case 'a': if (optarg != NULL){ filePtr = optarg; break; } else case '?': default: USAGE("./client"); exit(EXIT_FAILURE); } } //get username, ip, and address from command line if (optind < argc && (argc - optind) == 3){ username = argv[optind++]; ipAddress = argv[optind++]; portNumber = argv[optind++]; } else{ USAGE("./client"); exit(EXIT_FAILURE); } //initialize audit file FILE* auditFile = NULL; int auditFd = 0; auditFile = initAudit(filePtr); auditFd = fileno(auditFile); //fclose(auditFile); char ipPort[1024]; memset(&ipPort, 0, 1024); ipPortString(ipAddress, portNumber, ipPort); char auditEvent[1024]; // TRY CONNECTING TO SOCKET if ((clientFd = createAndConnect(portNumber, clientFd,ipAddress)) < 0){ sfwrite(&lock, stderr, "Error creating and connecting socket\n"); //createAuditEvent(username, "ERR, ", "ERR # message", NULL, NULL, auditEvent); //printf("%s\n", auditEvent); exit(0); } char loginMSG[1024]; memset(&loginMSG, 0, 1024); /*********** NOTIFY SERVER OF CONNECTION *****/ if (performLoginProcedure(clientFd, username, newUser, loginMSG) == 0){ close(clientFd); createAuditEvent(username, "LOGIN", ipPort, "fail", loginMSG, auditEvent); lockWriteUnlock(auditEvent, auditFd); exit(0); } createAuditEvent(username, "LOGIN", ipPort, "success", loginMSG, auditEvent); lockWriteUnlock(auditEvent, auditFd); /******************************************/ /* IMPLEMENT POLL */ /****************************************/ /* Initialize Polls Interface*/ memset(clientPollFds, 0 , sizeof(clientPollFds)); int pollStatus; clientPollNum=3; // CREATE GLOBAL SOCKET PAIR int globalSocketPair[2]={0,0}; createSocketPair(globalSocketPair,2); globalSocket= globalSocketPair[0]; // assign to global var /* Set poll for clientFd */ clientPollFds[0].fd = clientFd; clientPollFds[0].events = POLLIN; if (makeNonBlocking(clientFd)<0){ sfwrite(&lock, stderr,"Error making socket nonblocking.\n"); //fprintf(stderr, "Error making socket nonblocking.\n"); } /* Set poll for stdin */ clientPollFds[1].fd = 0; clientPollFds[1].events = POLLIN; if (makeNonBlocking(0)<0){ sfwrite(&lock, stderr,"Error making stdin nonblocking.\n"); //fprintf(stderr, "Error making stdin nonblocking.\n"); } //UNBLOCK THE GLOBAL SOCKET/READ AND ADD THE GLOBAL READ SOCKET ON POLL WATCH if(makeNonBlocking(globalSocketPair[0])<0){ sfwrite(&lock, stderr,"Error making global socket 1 nonblocking.\n"); //fprintf(stderr, "Error making global socket 1 nonblocking.\n"); } if(makeNonBlocking(globalSocketPair[1])<0){ sfwrite(&lock, stderr,"Error making global socket 2 nonblocking.\n"); //fprintf(stderr, "Error making global socket 2 nonblocking.\n"); } clientPollFds[2].fd = globalSocketPair[1]; // hold onto the read pipe for the global var. clientPollFds[2].events = POLLIN; /************************/ /* ETERNAL POLL */ /***********************/ while(1){ pollStatus = poll(clientPollFds, clientPollNum, -1); if(pollStatus<0){ sfwrite(&lock, stderr,"poll(): %s\n", strerror(errno)); //fprintf(stderr,"poll(): %s\n",strerror(errno)); continue; } int i; for(i=0;i<clientPollNum;i++){ if(clientPollFds[i].revents==0){ continue; } if(clientPollFds[i].revents!=POLLIN){ sfwrite(&lock, stderr,"poll.revents:%s\n",strerror(errno)); // fprintf(stderr,"poll.revents:%s\n",strerror(errno)); break; } /***********************************/ /* POLLIN FROM CLIENTFD */ /*********************************/ if(clientPollFds[i].fd == clientFd){ int serverBytes =0; while( (serverBytes = recv(clientFd, message, 1024, 0))>0){ if (verbose){ sfwrite(&lock, stdout, VERBOSE "%s", message); sfwrite(&lock, stdout, DEFAULT ""); //printf(VERBOSE "%s" DEFAULT, message); } if (checkVerb(PROTOCOL_EMIT, message)){ char sessionLength[1024]; memset(&sessionLength, 0, 1024); if (extractArgAndTest(message, sessionLength)){ displayClientConnectedTime(sessionLength); } } else if (checkVerb(PROTOCOL_UTSIL, message)){ char listOfUsers[1024]; memset(&listOfUsers, 0, 1024); if (extractArgsAndTest(message, listOfUsers)){ sfwrite(&lock, stdout, "%s\n", listOfUsers); //printf("%s\n", listOfUsers); } else{ sfwrite(&lock, stderr, "Error with UTSIL response\n"); //fprintf(stderr, "Error with UTSIL response\n"); } } else if (checkVerb(PROTOCOL_BYE, message)){ createAuditEvent(username, "LOGOUT", "error", NULL, NULL, auditEvent); lockWriteUnlock(auditEvent, auditFd); fclose(auditFile); close(clientFd); exit(EXIT_SUCCESS); } else if (checkVerb(PROTOCOL_UOFF, message)){ } /***********************************/ /* RECEIVED MSG BACK FROM SERVER */ /*********************************/ else if (extractArgAndTestMSG(message,NULL,NULL,NULL) ){ char toUser[1024]; char fromUser[1024]; char messageFromUser[1024]; //CLEAR BUFFERS BEFORE FILLING MESSAGE CONTACT INFO memset(&toUser,0,strnlen(toUser,1024)); memset(&fromUser,0,strnlen(fromUser,1024)); memset(&messageFromUser,0,1024); // EXTRACT THE ARGS AND SEE IF IT'S VALID if(extractArgAndTestMSG(message,toUser,fromUser,messageFromUser)){ //IF NO OPEN CHAT FROM PREVIOUS CONTACT, AND MESSAGE ADDRESSED TO THIS CLIENT if(getXtermByUsername(fromUser)==NULL && strcmp(toUser,username)==0){ //CREATE CHAT BOX int child = createXterm(fromUser,username, auditFd); send(child,messageFromUser,strnlen(messageFromUser,1023),0); char *messagePtr = (void *)messageFromUser + strlen(messageFromUser); *messagePtr = '\0'; createAuditEvent(username, "MSG", "from", fromUser, messageFromUser, auditEvent); lockWriteUnlock(auditEvent, auditFd); /*//CONTINUE TO SEND CHAT Xterm* xterm = getXtermByUsername(fromUser); if(xterm!=NULL){ send(xterm->chatFd,messageFromUser,strnlen(messageFromUser,1023),0); }else{ fprintf(stderr,"createXterm() in poll: not initialized \n"); }*/ } //IF CHAT EXISTS FROM PREVIOUS CONTACT, AND MESSAGE ADDRESSED TO THIS CLIENT else if(getXtermByUsername(fromUser)!=NULL && strcmp(toUser,username)==0){ Xterm* xterm = getXtermByUsername(fromUser); //SAFE SEND if(xterm!=NULL){ send(xterm->chatFd,messageFromUser,strnlen(messageFromUser,1023),0); char *messagePtr = (void *)messageFromUser + strlen(messageFromUser) - 1; *messagePtr = '\0'; createAuditEvent(username, "MSG", "from", fromUser, messageFromUser, auditEvent); lockWriteUnlock(auditEvent, auditFd); }else{ sfwrite(&lock, stderr, "poll() loop: receiving MSG from server from pre-existing chat user, but no chatbox found\n"); //fprintf(stderr,"poll() loop: receiving MSG from server from pre-existing chat user, but no chatbox found\n"); } } //IF CHATBOX DOESN'T EXIST FROM PREVIOUS CONTACT, BUT THIS CLIENT IS THE SENDER else if(getXtermByUsername(toUser)==NULL && strcmp(fromUser,username)==0){ //CREATE CHAT BOX int child = createXterm(toUser,username, auditFd); send(child,messageFromUser,strnlen(messageFromUser,1023),0); char *messagePtr = (void *)messageFromUser + strlen(messageFromUser); *messagePtr = '\0'; createAuditEvent(username, "MSG", "to", toUser, messageFromUser, auditEvent); lockWriteUnlock(auditEvent, auditFd); /*//SAFE-SEND CHAT Xterm* xterm = getXtermByUsername(toUser); if(xterm!=NULL){ send(xterm->chatFd,messageFromUser,strnlen(messageFromUser,1023),0); }else{ fprintf(stderr,"poll() loop: receiving MSG from server from pre-existing chat user, but no chatbox found\n"); }*/ } } } memset(&message,0,1024); } if((serverBytes=read(clientFd,message,1))==0){ close(clientFd); exit(0); } } /***********************************/ /* POLLIN FROM STDIN */ /*********************************/ else if(clientPollFds[i].fd == 0){ int bytes=0; char stdinBuffer[1024]; memset(&stdinBuffer,0,1024); while( (bytes=read(0,&stdinBuffer,1024))>0){ stdinBuffer[strlen(stdinBuffer)-1] = 0; /*send time verb to server*/ if(strcmp(stdinBuffer,"/time")==0){ protocolMethod(clientFd, TIME, NULL, NULL, NULL, verbose, &lock); createAuditEvent(username, "CMD", stdinBuffer, "success", "client", auditEvent); lockWriteUnlock(auditEvent, auditFd); } else if(strcmp(stdinBuffer,"/listu")==0){ protocolMethod(clientFd, LISTU, NULL, NULL, NULL, verbose, &lock); createAuditEvent(username, "CMD", stdinBuffer, "success", "client", auditEvent); lockWriteUnlock(auditEvent, auditFd); } else if(strcmp(stdinBuffer,"/logout")==0){ protocolMethod(clientFd, BYE, NULL, NULL, NULL, verbose, &lock); waitForByeAndClose(clientFd); createAuditEvent(username, "LOGOUT", "intentional", NULL, NULL, auditEvent); lockWriteUnlock(auditEvent, auditFd); fclose(auditFile); exit(EXIT_SUCCESS); } else if(strstr(stdinBuffer,"/chat")!=NULL){ // CONTAINS "/chat" if (processChatCommand(clientFd,stdinBuffer,username, verbose, &lock) == 0) createAuditEvent(username, "CMD", "/chat", "failure", "client", auditEvent); else createAuditEvent(username, "CMD", "/chat", "success", "client", auditEvent); lockWriteUnlock(auditEvent, auditFd); } else if(strcmp(stdinBuffer,"/help")==0){ displayHelpMenu(clientHelpMenuStrings); createAuditEvent(username, "CMD", stdinBuffer, "success", "client", auditEvent); lockWriteUnlock(auditEvent, auditFd); } else if(strcmp(stdinBuffer,"/audit")==0){ processAudit(auditFd); createAuditEvent(username, "CMD", stdinBuffer, "success", "client", auditEvent); lockWriteUnlock(auditEvent, auditFd); } else{ createAuditEvent(username, "CMD", stdinBuffer, "failure", "client", auditEvent); lockWriteUnlock(auditEvent, auditFd); } } } /*******************************/ /* Catch Global Socket Write */ /*****************************/ else if(clientPollFds[i].fd == clientPollFds[2].fd){ char byte; read(clientPollFds[2].fd,&byte,1); } else{ /****************************************/ /* USER TYPED INTO CHAT XTERM */ /**************************************/ //READ BYTES FROM CHAT BOX CHILD PROCESS char chatBuffer[1024]; memset(chatBuffer,0,1024); int chatBytes =-1; chatBytes = read(clientPollFds[i].fd,chatBuffer,1024); //IF CHILD XTERM DIED if(chatBytes==0){ cleanUpXterm(getXtermByChatFd(clientPollFds[i].fd)); }else{ //BUILD MESSAGE PROTOCOL TO SEND TO SERVER/ TO BE RELAYED TO PERSON Xterm* xterm = getXtermByChatFd(clientPollFds[i].fd); if(xterm==NULL){ sfwrite(&lock, stderr, "error in poll loop: getXtermByChatFd() returned NULL\n"); //fprintf(stderr,"error in poll loop: getXtermByChatFd() returned NULL\n"); continue;//continue searching the rest of for loop for events } char userMsgBuffer[1024]; memset(&userMsgBuffer, 0, 1024); char relayMessage[1024]; memset(&relayMessage,0,1024); if(buildMSGProtocol(relayMessage ,xterm->toUser, username, chatBuffer)==false){ sfwrite(&lock, stderr, "error in poll loop: buildMSGProtocol() unable to build relay message to server\n"); //fprintf(stderr,"error in poll loop: buildMSGProtocol() unable to build relay message to server\n"); continue; //continue searching the rest of for loop for events } chatBytes = send(clientFd,relayMessage,strnlen(relayMessage,1023),0); chatBuffer[strlen(chatBuffer) - 1] = 0; createAuditEvent(username, "MSG", "to", xterm->toUser, chatBuffer, auditEvent); lockWriteUnlock(auditEvent, auditFd); } } }/* MOVE ON TO NEXT POLL FD */ }/* FOREVER RUNNING LOOP */ return 0; }