void ARXFlatBufferMgrImpl::freeBuffers() { registerClient(NULL); for (unsigned int i = 0; i < IBufferMgr::MAX_BUFFERS; i++) { mBuffers[i].clear(); } }
// TODO: allow more than one device I2C::I2C( const char *device, int address ) { if( (dev = open( device, O_RDWR ) ) < 0) throw std::invalid_argument( std::string( "I2C: Unable to open device: " ) + strerror( errno ) ); registerClient( address ); }
bool EntriesManager::modifyClient(RequestContext::ClientId clientId, uint16_t bufferSize) { auto clientIt = m_clients.find(clientId); if (clientIt == m_clients.end()) { LOGE("Unknow client [" << clientId << "]"); return false; } clientIt->second.bufferSize = bufferSize; registerClient(clientId, clientIt); return true; }
void DisplayRefreshMonitorManager::windowScreenDidChange(PlatformDisplayID displayID, DisplayRefreshMonitorClient& client) { if (client.hasDisplayID() && client.displayID() == displayID) return; unregisterClient(client); client.setDisplayID(displayID); registerClient(client); if (client.isScheduled()) scheduleAnimation(client); }
//------------------------------------------------------------------------------ void ServerFiber::main() { server_->config_->parse(); stdErr.setDebugLevels(server_->config_->value("debug_levels","+0,+1,+2,+3")); union { uint8_t cmd; uint8_t ui8; }; auth(); while( !terminated_ ){ *this >> cmd; switch( cmd ){ case cmQuit : putCode(eOK); terminate(); break; case cmGetProcessStartTime : *this << getProcessStartTime(); break; case cmSelectServerType : *this >> ui8; putCode(ui8 < stCount ? eOK : eInvalidServerType); serverType_ = ServerType(ui8); break; case cmRegisterClient : registerClient(); break; case cmRegisterDB : registerDB(); break; case cmGetDB : getDB(); break; case cmSendMail : sendMail(); break; case cmRecvMail : recvMail(); break; case cmRemoveMail : removeMail(); break; case cmSelectProtocol : *this >> ui8; putCode(ui8 < 2 ? eOK : eInvalidProtocol); protocol_ = ui8; break; default : // unrecognized or unsupported command, terminate putCode(eInvalidCommand); terminate(); } } }
/** * @brief Performs intial operations. * Initializes filter, queue, controller config with default values. * @param void * @return S_OK if the open driver call successfull otherwise S_FALSE */ HRESULT CDIL_CAN_VSCOM::performInitOperations(void) { DWORD dwClientID; memset(&sg_VSCanCfg, 0, sizeof(sg_VSCanCfg)); /* Create critical section for ensuring thread safeness of read message function */ InitializeCriticalSection(&sg_DIL_CriticalSection); /* Register Monitor client */ dwClientID = 0; registerClient(TRUE, dwClientID, CAN_MONITOR_NODE); return(S_OK); }
Wgt::Wgt( QWidget * parent ) : QWidget( parent ) { ui.setupUi( this ); connect( ui.connect, SIGNAL(clicked()), this, SLOT(connectHost()) ); connect( ui.registerClient, SIGNAL(clicked()), this, SLOT(registerClient()) ); connect( ui.send, SIGNAL(clicked()), this, SLOT(send()) ); connect( ui.sendFile, SIGNAL(clicked()), this, SLOT(sendFile()) ); connect( ui.status, SIGNAL(clicked()), this, SLOT(status()) ); connect( ui.clear, SIGNAL(clicked()), this, SLOT(clear()) ); connect( this, SIGNAL(sigLog(const QString &)), this, SLOT(slotLog(const QString &)), Qt::QueuedConnection ); xmpp.setMessageHandler( boost::bind( &Wgt::messageHandler, this, _1, _2 ) ); xmpp.setLogHandler( boost::bind( &Wgt::logHandler, this, _1 ) ); }
bool EntriesManager::addClient(RequestContext::ClientId clientId, uint16_t bufferSize) { if (clientId == RequestContext::InvalidClientId) { LOGE("Invalid client id"); return false; } if (m_clients.find(clientId) != m_clients.end()) { LOGE("Client [" << clientId << "] already exists, use modify instead"); return false; } /* * For the first time client is registered for future entry, after this its state is kept, * so client can fetch entries continuously */ EntriesQueue::EntryId startPoint = m_container.getBackEntryId(); auto itInfo = m_clients.emplace(clientId, ClientInfo(clientId, startPoint, bufferSize)); addEntryCount(startPoint, itInfo.first); registerClient(clientId, itInfo.first); return true; }
bool TextClientManager::processDeregisterCommand(const std::string &command, const Poco::Net::SocketAddress &address) { char buf[16] = { 0 }; if (sscanf(command.c_str(), "register %s", buf) != 1) { return false; } buf[sizeof(buf)-1] = 0; Poco::Net::DatagramSocket *socket = NULL; if (strcmp("all", buf) == 0) { socket = registerDefault(address); } else { socket = registerClient(atoi(buf), address); } if (socket) { const char *response = "registered"; socket->sendBytes(response, strlen(response)); } return true; }
void wait4Register(cli *client, blist messages, bstring incompleteMessage){ incompleteMessage = incompleteMessage ? incompleteMessage : safe_BfromCstr(""); /*recv messages until you receive a nick and user msg*/ bstring raw; int i = handleRegisterMessages(messages, client); while (!(client->nick && client->user)){ raw = safeRecv(client); messages = extractMessages(raw, &incompleteMessage); i = handleRegisterMessages(messages, client); } /*trim message list to be the list of messages recv'd*/ /*after the client completed registration*/ blistDeleteRange(messages, 0, i); /*complete client registration*/ registerClient(client, messages, incompleteMessage); }
void serveClient(ClientDesc client) { SSL* ssl; ssl = client.ssl; Message req; req = receive(ssl); switch (req.getType()) { case Message::REGISTER_REQ : { registerClient(req, client); break; } case Message::TEXT_MSG : { forwardMessage(req, client); break; } case Message::BROADCAST_MSG : { broadcastTextMessageToAll(req, client); break; } case Message::CLIENT_QUIT_IND : { forgetAboutClient(client); broadcastInfoAboutQuitClient(client); break; } default: { break; } } }
//-------------------------------------------------------------- void ofApp::update(){ int time = ofGetElapsedTimeMillis(); if (time - lastPulseTime > PULSE_INTERVAL) { lastPulseTime = time; sendPulse(); } while(oscReceiver.hasWaitingMessages()){ // get the next message ofxOscMessage m; oscReceiver.getNextMessage(&m); // handle heartbeat if(m.getAddress() == "/call/home"){ registerClient(&m); } } }
//////////////////////////////////////////////////////////////////////////////// // Funciton to connect and register and all that nonsense void connectPlease( Folder *dir, int sock ) { int nbytes; // Number of bytes char buffer[ MAXBUFSIZE ]; // Buffer nbytes = write( sock, "CONNECT", MAXBUFSIZE ); ERROR( nbytes < 0 ); bzero( buffer, MAXBUFSIZE ); nbytes = read( sock, buffer, MAXBUFSIZE ); ERROR ( nbytes < 0 ); switch ( parseCmd( buffer ) ) { case CONNECT: { printf( "$ Connection Established\n" ); switch ( registerClient( dir, sock ) ) { case FAILURE: { printf( "$ There is already a user with the name '%s' on the server.\n", dir->name ); close( sock ); exit( EXIT_SUCCESS ); } case SUCCESS: { printf( "$ You have been connected as %s\n", dir->name ); sendList( dir, sock ); break; } } break; } default: { printf( "$ Error in registering\n" ); } } } // connectionPlease( )
bool Client::init(int*argc,char ** argv,BaseModel *model) { glutInit(argc,argv); glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_ALPHA ); glutInitWindowPosition( 100, 100 ); glutInitWindowSize(1024, 768 ); glutCreateWindow("glut-opengl"); if(glewInit()!=GLEW_OK) { fprintf(stderr,"Fail to initialize GLEW \n"); return false; } s_client=this; /** init GL **/ glClearColor(0.2f,0.2f,0.4f,0.0f); glEnable(GL_TEXTURE_2D); /** register glut method **/ registerClient(); /** test method **/ m_model=model; m_model->load(); #ifdef KEE_SHADER m_programID=Shader::loadShaders("vertex.txt", "fragment.txt"); m_matrixID=glGetUniformLocation(m_programID,"MVP"); projectViewModel(); #endif angle_x=0.0f; angle_y=0.0f; return true; }
void DataBus::Server::processPackets(Client *client) { // Check client if (client == 0) { // Error, null pointer return; } // Find client in the list int index = m_clients.indexOf(client); if (index < 0) { // Error, client was not found return; } // Process all packets while (client->packetsAvailable()) { // Process packet Packet packet = client->takePacket(); switch (packet.getPacketType()) { case PacketType_RegisterClientRequest: { // Try to register the client quint8 returnStatus = registerClient(client, packet); // Send Register Client Response Packet responsePacket; if (RegisterClientResponsePacket::create(packet.getSource(), packet.getPacketId(), returnStatus, &responsePacket) == false) { // Error, failed to create packet break; } client->sendPacket(responsePacket); break; } case PacketType_GetClientListRequest: { // Create response Packet responsePacket; QList<quint8> clientIdList = getRegisteredClientIdList(); if (GetClientListResponsePacket::create(packet.getSource(), packet.getPacketId(), clientIdList, &responsePacket) == false) { // Error, failed to create packet break; } // Send Get Client List Response client->sendPacket(responsePacket); break; } case PacketType_GetClientStatusRequest: { // Parse packet quint8 clientId; if (DataBus::GetClientStatusRequestPacket::parse(packet, &clientId) == false) { // Error, failed to parse packet break; } // Create response ClientStatus clientStatus = getRegisteredClientStatus(clientId); Packet responsePacket; if (GetClientStatusResponsePacket::create(packet.getSource(), packet.getPacketId(), clientId, clientStatus, &responsePacket) == false) { // Error, failed to create packet break; } // Send Get Client Status Response client->sendPacket(responsePacket); break; } default: { // Forward packet to a client forwardPacket(packet); break; } } } }
/* * Main routine of our mini time server */ int main(int argc, char* argv[]) { establishRedirection("mtimesrv.log", REDIR_OUT_APPEND, STDOUT_FILENO | STDERR_FILENO); printf("\nMicro Time Server\nVersion: %s\n\n", MTIMESRV_VERSION); init(); daemonize(); /* main server loop */ while(1) { ipc_packet_data.sem_id = status.sem_id; ipc_packet_data.reqresp = &request; if(receiveRequest(&ipc_packet_data) < 0) { ipcerror("mtimesrv::main():receiveRequest() - failed"); exit(1); } /* Dispatch requests */ switch(request.command) { case IDLE: printf("Idle\n"); fflush(stdout); break; case TIME: sendTime(); break; case OPEN: registerClient(); break; case VERSION: sendVersion(); break; case TERMINATE: terminate(); break; case PING: processPing(); break; default: printf("Unsupported command (%d) from a client (PID=%d)... Ignored.\n", request.command, request.client_pid); fflush(stdout); break; } /* Reset the request buffer */ memset(&request, 0, sizeof(request_t)); } return 0; }
IOReturn AppleGPIO::callPlatformFunction(const OSSymbol *functionName, bool waitForFunction, void *param1, void *param2, void *param3, void *param4 ) { DLOG("AppleGPIO::callPlatformFunction %s %s %08lx %08lx %08lx %08lx\n", functionName->getCStringNoCopy(), waitForFunction ? "TRUE" : "FALSE", (UInt32)param1, (UInt32)param2, (UInt32)param3, (UInt32)param4); if (fPlatformFuncArray) { UInt32 i; IOPlatformFunction *pfFunc; UInt32 count = fPlatformFuncArray->getCount(); for (i = 0; i < count; i++) { if (pfFunc = OSDynamicCast(IOPlatformFunction, fPlatformFuncArray->getObject(i))) { DLOG ("AppleGPIO::callPlatformFunction '%s' - got platformFunction object\n", functionName->getCStringNoCopy()); // If param4 is an OSSymbol reference, check for interrupt event registration // or enable/disable symbols if (pfFunc->platformFunctionMatch(functionName, kIOPFFlagIntGen, NULL)) { OSSymbol *subFunctionSym; DLOG ("AppleGPIO::callPlatformFunction '%s' - got platformFunction interrupt match\n", functionName->getCStringNoCopy()); if (param4 && (subFunctionSym = OSDynamicCast(OSSymbol, (const OSMetaClassBase *)param4))) { DLOG ("AppleGPIO::callPlatformFunction '%s', subFunction '%s'\n", functionName->getCStringNoCopy(), subFunctionSym->getCStringNoCopy()); if (subFunctionSym == fSymIntRegister) return (registerClient(param1, param2, param3) ? kIOReturnSuccess : kIOReturnBadArgument); if (subFunctionSym == fSymIntUnRegister) return (unregisterClient(param1, param2, param3) ? kIOReturnSuccess : kIOReturnBadArgument); if (subFunctionSym == fSymIntEnable) return (enableClient(param1, param2, param3) ? kIOReturnSuccess : kIOReturnBadArgument); if (subFunctionSym == fSymIntDisable) return (disableClient(param1, param2, param3) ? kIOReturnSuccess : kIOReturnBadArgument); return kIOReturnBadArgument; // Unknown function } else { DLOG ("AppleGPIO::callPlatformFunction '%s', param4 not a OSSymbol\n", functionName->getCStringNoCopy()); } } // Check for on-demand case if (pfFunc->platformFunctionMatch (functionName, kIOPFFlagOnDemand, NULL)) { DLOG ("AppleGPIO::callPlatformFunction '%s', calling demand function\n", functionName->getCStringNoCopy()); return (performFunction (pfFunc, param1, param2, param3, param4) ? kIOReturnSuccess : kIOReturnBadArgument); } DLOG ("AppleGPIO::callPlatformFunction '%s' - got no match\n", functionName->getCStringNoCopy()); } } #ifdef OLD_STYLE_COMPAT // Need to catch old-style register-, unregister-, enable-, disable- commands DLOG ("AppleGPIO::callPlatformFunction '%s' - handling old style\n", functionName->getCStringNoCopy()); // Is it an interrupt notification registration request? if (fRegisterStrings && fRegisterStrings->containsObject(functionName)) { return (registerClient(param1, param2, param3) ? kIOReturnSuccess : kIOReturnBadArgument); } // unregister? else if (fUnregisterStrings && fUnregisterStrings->containsObject(functionName)) { return (unregisterClient(param1, param2, param3) ? kIOReturnSuccess : kIOReturnBadArgument); } else if (fEnableStrings && fEnableStrings->containsObject(functionName)) { return (enableClient(param1, param2, param3) ? kIOReturnSuccess : kIOReturnBadArgument); } else if (fDisableStrings && fDisableStrings->containsObject(functionName)) { return (disableClient(param1, param2, param3) ? kIOReturnSuccess : kIOReturnBadArgument); } #endif } DLOG("AppleGPIO::callPlatformFunction unrecognized function\n"); return super::callPlatformFunction(functionName, waitForFunction, param1, param2, param3, param4); }
void *accept_thread(void *accept_sock) { //socket descriptor for each client int acptsock; //Retrieve the socket that passed from pthread_create acptsock= (intptr_t)accept_sock; //Buffer to send&receive data// char buf[256]; //Received bytes int bytes; //Declare the structure of the sending message in order //the filemanager to communicate with the client and vice versa FILEHEADER *msg = (FILEHEADER *)malloc(sizeof(FILEHEADER)); //While the client is connect to the system you have to keep the connection while(1) { //If connection is established then start communicating // //Initialize buffer with zeros // bzero(buf, sizeof(buf)); //Waiting...to receive data from the client// if (recv(acptsock, buf, sizeof(buf), 0) < 0) { perror("Received() failed!"); close(acptsock); pthread_exit((void *) 0); } //Check if direc received a message if(strlen(buf) != 0) { //Show the message that received// printf("----------------------------------\n"); printf("accept_thread received: %s\n", buf); } else if (strlen(buf) == 0) { //printf("Unable to received messsage!\n"); close(acptsock); pthread_exit((void *) 0); } //Decode the message that receive from the client //in order to identify the type of the message// decode(buf,msg); if( strcmp(msg->type , "REQCLIENTID" )== 0) { bzero(buf,sizeof(buf)); //encode the clientID sprintf(buf,"REQCLIENTID,%ld,%ld" , registerClient(msg->username ), msg->MSGID ); if (send(acptsock, buf, sizeof(buf) , 0) < 0 ) { perror("Send:Unable to send clientID"); } //Deallocations free(msg->username); } else if( strcmp(msg->type , "REQCREATE" )== 0 ) { printf("Received Create: %s , owner:%ld\n", msg->filename, msg->owner); //Store fileid unsigned long fileid = lookUpFileID(msg->filename , msg->owner ); if(fileid == -1) { //Store the new file in the metadata //Also , retrieve the fileID for the file fileid = registerFile(msg->filename, msg->owner); } printf("REQCREATE Function return: %ld \n", fileid); bzero(buf, sizeof(buf)); //encode the clientID sprintf(buf, "REQCREATE,%ld,%ld", fileid, msg->MSGID); if (send(acptsock, buf, sizeof(buf), 0) < 0) { perror("Send:Unable to send clientID"); } //Deallocations free(msg->filename); } else if( strcmp(msg->type , "REQFILEID" )== 0 ) { printf("Received REQFILEID: %s , owner:%ld\n" , msg->filename ,msg->owner); //Store the new file in the metadata //Also , retrieve the fileID for the file unsigned long fileid = lookUpFileID(msg->filename , msg->owner ); if(fileid == -1) { //Store the new file in the metadata //Also , retrieve the fileID for the file fileid = registerFile(msg->filename, msg->owner); } printf("REQFILEID Function return: %ld \n" , fileid); bzero(buf,sizeof(buf)); //encode the clientID sprintf(buf,"REQFILEID,%ld,%ld" , fileid , msg->MSGID ); if (send(acptsock, buf, sizeof(buf) , 0) < 0 ) { perror("Send:Unable to send clientID"); } //Deallocations free(msg->filename); } else if( strcmp(msg->type , "REQFILESLIST" )== 0 ) { bzero(buf,sizeof(buf)); GString *list=NULL; list=getfilelist(list); printf("List\n"); if (send(acptsock, list->str, strlen(list->str) , 0) < 0 ) { perror("Send:Unable to send clientID"); } //Deallocate memory g_string_free(list,TRUE); } }//While }
// Loop the client thread here void *wallyClientThread(void *argPtr){ slog(DEBUG,DEBUG,"WallyClient Thread started. Waiting for plugins to get ready."); pthread_mutex_init(&commandMutex,0); while(ph->pluginLoaderDone == false){ usleep(100); } slog(DEBUG,FULLDEBUG,"WallyClient Thread started. Plugins ready."); commandMap = malloc(sizeof(hash_table)); ht_init(commandMap, HT_KEY_CONST | HT_VALUE_CONST, 0.05); tempMap = malloc(sizeof(hash_table)); ht_init(tempMap, HT_KEY_CONST | HT_VALUE_CONST, 0.05); int startDelay = 1; int ret=0; char *startDelayString = NULL; clientThreadRunning = true; while(clientThreadRunning == true) { switch(clientState) { case DISCOVERY: //ssdpDiscovery(1); // Both plugins (ssdp and cloudConnector) // set ph->location and return once they registered // Cloud connector needs additional handling after asprintf(&startDelayString,"%d",startDelay); if(ph->ssdp) { call("ssdp::discovery",&ret,startDelayString); } else if(ph->cloud) { call("cloud::connect",&ret,startDelayString); } free(startDelayString); if(ph->location) { if(run_callback){ slog(DEBUG,DEBUG,"Executing JS Callback for client discovery"); #ifndef WITH_SEADUK duv_push_ref(ctx, finishCallback); duk_push_string(ctx, ph->location); duk_call(ctx, 1); duk_to_int(ctx, -1); #endif } saveLocation(FLAGFILE); } startDelay = 1; slog(DEBUG,DEBUG,"Change state from discovery to register"); clientState = REGISTER; break; case REGISTER: if(ph->location){ if(registerClient(ph->location)){ slog(DEBUG,DEBUG,"Starting longpoll."); url_longpoll(commandURL,60,LONGPOLL_INIT,NULL); clientState = COMMAND; } else { slog(DEBUG,DEBUG,"Registration failed."); } } else { slog(LVL_INFO,WARN,"Register was called without a valid location"); } break; case COMMAND: slog(DEBUG,DEBUG,"Requesting next core command from %s",commandURL); int ret = getCommand(commandURL,60); if(ret == true && ht_get_simple(commandMap,"command")){ int commandValid = false; slog(DEBUG,DEBUG,"Command : %s",ht_get_simple(commandMap,"command")); // Handle the commands which are supported by the wallyd here if(ht_compare(commandMap,"command","config")){ commandValid = true; slog(DEBUG,DEBUG,"Preparing to persist config"); if(persistConfig(registerMap)){ sendSuccess(ht_get_simple(commandMap,"id")); } } if(ht_compare(commandMap,"command","reboot")){ commandValid = true; sendSuccess(ht_get_simple(commandMap,"id")); slog(DEBUG,DEBUG,"Preparing to reboot"); system(BIN_REBOOT); } if(ht_compare(commandMap,"command","firmwareUpdate")){ commandValid = true; sendSuccess(ht_get_simple(commandMap,"id")); slog(DEBUG,DEBUG,"Preparing to update firmware"); system(BIN_UPDATEFW); } if(ht_compare(commandMap,"command","getlog")){ commandValid = true; slog(DEBUG,DEBUG,"Preparing to send log to server"); //sendSuccess(ht_get_simple(commandMap,"id")); //persistConfig(registerMap); } if(commandValid == false){ slog(DEBUG,DEBUG,"Command %s not valid. Ingoring.",ht_get_simple(commandMap,"command")); sendFailed(ht_get_simple(commandMap,"id"),"unknown.command"); } } else { slog(LVL_INFO,WARN,"getCommand failed."); } pthread_mutex_unlock(&commandMutex); break; case QUIT: slog(DEBUG,DEBUG,"Thread is quiting."); break; } sleep(threadDelay); } return 0; }
/* Main */ int main(int argc, char ** argv) { struct sockaddr_in inaddr; socklen_t inaddrlen; struct timeval timeout; ssl_t *ssl; serverDtls_t *dtlsCtx; SOCKET sock; fd_set readfd; unsigned char *sslBuf, *recvfromBuf, *CAstream; #ifdef USE_DTLS_DEBUG_TRACE unsigned char *addrstr; #endif #if !defined(ID_PSK) && !defined(ID_DHE_PSK) unsigned char *keyValue, *certValue; int32 keyLen, certLen; #endif sslKeys_t *keys; int32 freeBufLen, rc, val, recvLen, err, CAstreamLen; int32 sslBufLen, rcr, rcs, sendLen, recvfromBufLen; sslSessOpts_t options; #ifdef WIN32 WSADATA wsaData; WSAStartup(MAKEWORD(1, 1), &wsaData); #endif rc = 0; ssl = NULL; dtlsCtx = NULL; sock = INVALID_SOCKET; /* parse input arguments */ if (0 != process_cmd_options(argc, argv)) { usage(); return 0; } if (sigsetup() < 0) { _psTrace("Init error creating signal handlers\n"); return DTLS_FATAL; } if (matrixSslOpen() < 0) { _psTrace("Init error opening MatrixDTLS library\n"); return DTLS_FATAL; } if (matrixSslNewKeys(&keys, NULL) < 0) { _psTrace("Init error allocating key structure\n"); matrixSslClose(); return DTLS_FATAL; } if ((rc = initClientList(MAX_CLIENTS)) < 0) { _psTrace("Init error opening client list\n"); goto MATRIX_EXIT; } recvfromBufLen = matrixDtlsGetPmtu(); if ((recvfromBuf = psMalloc(MATRIX_NO_POOL, recvfromBufLen)) == NULL) { rc = PS_MEM_FAIL; _psTrace("Init error allocating receive buffer\n"); goto CLIENT_EXIT; } #ifdef USE_HEADER_KEYS /* In-memory based keys Build the CA list first for potential client auth usage */ CAstreamLen = 0; #ifdef USE_RSA CAstreamLen += sizeof(RSACAS); #ifdef USE_ECC CAstreamLen += sizeof(ECDHRSACAS); #endif #endif #ifdef USE_ECC CAstreamLen += sizeof(ECCAS); #endif CAstream = psMalloc(NULL, CAstreamLen); CAstreamLen = 0; #ifdef USE_RSA memcpy(CAstream, RSACAS, sizeof(RSACAS)); CAstreamLen += sizeof(RSACAS); #ifdef USE_ECC memcpy(CAstream + CAstreamLen, ECDHRSACAS, sizeof(ECDHRSACAS)); CAstreamLen += sizeof(ECDHRSACAS); #endif #endif #ifdef USE_ECC memcpy(CAstream + CAstreamLen, ECCAS, sizeof(ECCAS)); CAstreamLen += sizeof(ECCAS); #endif #ifdef EXAMPLE_RSA_KEYS switch (g_rsaKeySize) { case 1024: certValue = (unsigned char *)RSA1024; certLen = sizeof(RSA1024); keyValue = (unsigned char *)RSA1024KEY; keyLen = sizeof(RSA1024KEY); break; case 2048: certValue = (unsigned char *)RSA2048; certLen = sizeof(RSA2048); keyValue = (unsigned char *)RSA2048KEY; keyLen = sizeof(RSA2048KEY); break; case 3072: certValue = (unsigned char *)RSA3072; certLen = sizeof(RSA3072); keyValue = (unsigned char *)RSA3072KEY; keyLen = sizeof(RSA3072KEY); break; case 4096: certValue = (unsigned char *)RSA4096; certLen = sizeof(RSA4096); keyValue = (unsigned char *)RSA4096KEY; keyLen = sizeof(RSA4096KEY); break; default: _psTraceInt("Invalid RSA key length (%d)\n", g_rsaKeySize); return -1; } if ((rc = matrixSslLoadRsaKeysMem(keys, (const unsigned char *)certValue, certLen, (const unsigned char *)keyValue, keyLen, CAstream, CAstreamLen)) < 0) { _psTrace("No certificate material loaded. Exiting\n"); psFree(CAstream, NULL); matrixSslDeleteKeys(keys); matrixSslClose(); return rc; } #endif #ifdef EXAMPLE_ECDH_RSA_KEYS switch (g_ecdhKeySize) { case 256: certValue = (unsigned char *)ECDHRSA256; certLen = sizeof(ECDHRSA256); keyValue = (unsigned char *)ECDHRSA256KEY; keyLen = sizeof(ECDHRSA256KEY); break; case 521: certValue = (unsigned char *)ECDHRSA521; certLen = sizeof(ECDHRSA521); keyValue = (unsigned char *)ECDHRSA521KEY; keyLen = sizeof(ECDHRSA521KEY); break; default: _psTraceInt("Invalid ECDH_RSA key length (%d)\n", g_ecdhKeySize); return -1; } if ((rc = matrixSslLoadEcKeysMem(keys, (const unsigned char *)certValue, certLen, (const unsigned char *)keyValue, keyLen, CAstream, CAstreamLen)) < 0) { _psTrace("No certificate material loaded. Exiting\n"); psFree(CAstream, NULL); matrixSslDeleteKeys(keys); matrixSslClose(); return rc; } #endif #ifdef EXAMPLE_EC_KEYS switch (g_eccKeySize) { case 192: certValue = (unsigned char *)EC192; certLen = sizeof(EC192); keyValue = (unsigned char *)EC192KEY; keyLen = sizeof(EC192KEY); break; case 224: certValue = (unsigned char *)EC224; certLen = sizeof(EC224); keyValue = (unsigned char *)EC224KEY; keyLen = sizeof(EC224KEY); break; case 256: certValue = (unsigned char *)EC256; certLen = sizeof(EC256); keyValue = (unsigned char *)EC256KEY; keyLen = sizeof(EC256KEY); break; case 384: certValue = (unsigned char *)EC384; certLen = sizeof(EC384); keyValue = (unsigned char *)EC384KEY; keyLen = sizeof(EC384KEY); break; case 521: certValue = (unsigned char *)EC521; certLen = sizeof(EC521); keyValue = (unsigned char *)EC521KEY; keyLen = sizeof(EC521KEY); break; default: _psTraceInt("Invalid ECC key length (%d)\n", g_eccKeySize); return -1; } if ((rc = matrixSslLoadEcKeysMem(keys, certValue, certLen, keyValue, keyLen, CAstream, CAstreamLen)) < 0) { _psTrace("No certificate material loaded. Exiting\n"); psFree(CAstream, NULL); matrixSslDeleteKeys(keys); matrixSslClose(); return rc; } #endif #ifdef REQUIRE_DH_PARAMS if (matrixSslLoadDhParamsMem(keys, DHPARAM2048, DHPARAM2048_SIZE) < 0) { _psTrace("Unable to load DH parameters\n"); } #endif /* DH_PARAMS */ psFree(CAstream, NULL); #else /* USE_HEADER_KEYS */ /* File based keys Build the CA list first for potential client auth usage */ CAstreamLen = 0; #ifdef USE_RSA if (g_rsaKeySize == 3072) CAstreamLen += (int32)strlen(rsaCA3072File) + 1; else CAstreamLen += (int32)strlen(rsaCAFile) + 1; #ifdef USE_ECC CAstreamLen += (int32)strlen(ecdhRsaCAFile) + 1; #endif #endif #ifdef USE_ECC CAstreamLen += (int32)strlen(ecCAFile) + 1; #endif CAstream = psMalloc(NULL, CAstreamLen); memset(CAstream, 0x0, CAstreamLen); CAstreamLen = 0; #ifdef USE_RSA if (g_rsaKeySize == 3072) { memcpy(CAstream, rsaCA3072File, strlen(rsaCA3072File)); CAstreamLen += strlen(rsaCA3072File); } else { memcpy(CAstream, rsaCAFile, strlen(rsaCAFile)); CAstreamLen += strlen(rsaCAFile); } #ifdef USE_ECC memcpy(CAstream + CAstreamLen, ";", 1); CAstreamLen++; memcpy(CAstream + CAstreamLen, ecdhRsaCAFile, strlen(ecdhRsaCAFile)); CAstreamLen += strlen(ecdhRsaCAFile); #endif #endif #ifdef USE_ECC if (CAstreamLen > 0) { memcpy(CAstream + CAstreamLen, ";", 1); CAstreamLen++; } memcpy(CAstream + CAstreamLen, ecCAFile, strlen(ecCAFile)); #endif /* Load Identiy */ #ifdef EXAMPLE_RSA_KEYS if ((rc = matrixSslLoadRsaKeys(keys, rsaCertFile, rsaPrivkeyFile, NULL, (char*)CAstream)) < 0) { _psTrace("No certificate material loaded. Exiting\n"); psFree(CAstream); matrixSslDeleteKeys(keys); matrixSslClose(); return rc; } #endif #ifdef EXAMPLE_ECDH_RSA_KEYS if ((rc = matrixSslLoadEcKeys(keys, ecdhRsaCertFile, ecdhRsaPrivkeyFile, NULL, (char*)CAstream)) < 0) { _psTrace("No certificate material loaded. Exiting\n"); psFree(CAstream); matrixSslDeleteKeys(keys); matrixSslClose(); return rc; } #endif #ifdef EXAMPLE_EC_KEYS if ((rc = matrixSslLoadEcKeys(keys, ecCertFile, ecPrivkeyFile, NULL, (char*)CAstream)) < 0) { _psTrace("No certificate material loaded. Exiting\n"); psFree(CAstream); matrixSslDeleteKeys(keys); matrixSslClose(); return rc; } #endif #ifdef REQUIRE_DH_PARAMS if (matrixSslLoadDhParams(keys, dhParamFile) < 0) { _psTrace("Unable to load DH parameters\n"); } #endif psFree(CAstream); #endif /* USE_HEADER_KEYS */ #ifdef USE_PSK_CIPHER_SUITE /* The first ID is considered as null-terminiated string for compatibility with OpenSSL's s_client default client identity "Client_identity" */ matrixSslLoadPsk(keys, PSK_HEADER_TABLE[0].key, sizeof(PSK_HEADER_TABLE[0].key), PSK_HEADER_TABLE[0].id, strlen((const char *)PSK_HEADER_TABLE[0].id)); for (rc = 1; rc < PSK_HEADER_TABLE_COUNT; rc++) { matrixSslLoadPsk(keys, PSK_HEADER_TABLE[rc].key, sizeof(PSK_HEADER_TABLE[rc].key), PSK_HEADER_TABLE[rc].id, sizeof(PSK_HEADER_TABLE[rc].id)); } #endif /* PSK */ if ((sock = newUdpSocket(NULL, DTLS_PORT, &err)) == INVALID_SOCKET) { _psTrace("Error creating UDP socket\n"); goto DTLS_EXIT; } _psTraceInt("DTLS server running on port %d\n", DTLS_PORT); /* Server loop */ for (exitFlag = 0; exitFlag == 0;) { timeout.tv_sec = 1; timeout.tv_usec = 0; FD_ZERO(&readfd); FD_SET(sock, &readfd); /* Always just wait a second for any incoming data. The primary loop mechanism reads data from one source and replies with handshake data if needed (that reply may be a resend if reading a repeat message). Individual client timeouts are then handled */ val = select(sock+1, &readfd, NULL, NULL, &timeout); if (val > 0 && FD_ISSET(sock, &readfd)) { psTraceIntDtls("Select woke %d\n", val); /* recvfrom data must always go into generic buffer becuase we don't yet know who it is from */ inaddrlen = sizeof(struct sockaddr_in); if ((recvLen = (int32)recvfrom(sock, recvfromBuf, recvfromBufLen, 0, (struct sockaddr *)&inaddr, &inaddrlen)) < 0) { #ifdef WIN32 if (SOCKET_ERRNO != EWOULDBLOCK && SOCKET_ERRNO != WSAECONNRESET) { #else if (SOCKET_ERRNO != EWOULDBLOCK) { #endif _psTraceInt("recvfrom error %d. Exiting\n", SOCKET_ERRNO); goto DTLS_EXIT; } continue; } #ifdef USE_DTLS_DEBUG_TRACE /* nice for debugging */ { const char *addrstr; addrstr = getaddrstring((struct sockaddr *)&inaddr, 1); psTraceIntDtls("Read %d bytes ", recvLen); psTraceStrDtls("from %s\n", (char*)addrstr); psFree(addrstr, NULL); } #endif /* Locate the SSL context of this receive and create a new session if not found */ if ((dtlsCtx = findClient(inaddr)) == NULL) { memset(&options, 0x0, sizeof(sslSessOpts_t)); options.versionFlag = SSL_FLAGS_DTLS; options.truncHmac = -1; if (matrixSslNewServerSession(&ssl, keys, certValidator, &options) < 0) { rc = DTLS_FATAL; goto DTLS_EXIT; } if ((dtlsCtx = registerClient(inaddr, sock, ssl)) == NULL) { /* Client list is full. Just have to ignore */ matrixSslDeleteSession(ssl); continue; } } ssl = dtlsCtx->ssl; /* Move socket data into internal buffer */ freeBufLen = matrixSslGetReadbuf(ssl, &sslBuf); psAssert(freeBufLen >= recvLen); psAssert(freeBufLen == matrixDtlsGetPmtu()); memcpy(sslBuf, recvfromBuf, recvLen); /* Notify SSL state machine that we've received more data into the ssl buffer retreived with matrixSslGetReadbuf. */ if ((rcr = matrixSslReceivedData(ssl, recvLen, &sslBuf, (uint32*)&freeBufLen)) < 0) { clearClient(dtlsCtx); continue; /* Next connection */ } /* Update last activity time and reset timeout*/ psGetTime(&dtlsCtx->lastRecvTime, NULL); dtlsCtx->timeout = MIN_WAIT_SECS; PROCESS_MORE_FROM_BUFFER: /* Process any incoming plaintext application data */ switch (rcr) { case MATRIXSSL_HANDSHAKE_COMPLETE: /* This is a resumed handshake case which means we are the last to receive handshake flights and we know the handshake is complete. However, the internal workings will not flag us officially complete until we receive application data from the peer so we need a local flag to handle this case so we are not resending our final flight */ dtlsCtx->connStatus = RESUMED_HANDSHAKE_COMPLETE; psTraceDtls("Got HANDSHAKE_COMPLETE out of ReceivedData\n"); break; case MATRIXSSL_APP_DATA: /* Now safe to clear the connStatus flag that was keeping track of the state between receiving the final flight of a resumed handshake and receiving application data. The reciept of app data has now internally disabled flight resends */ dtlsCtx->connStatus = 0; _psTrace("Client connected. Received...\n"); _psTraceStr("%s\n", (char*)sslBuf); break; case MATRIXSSL_REQUEST_SEND: /* Still handshaking with this particular client */ while ((sslBufLen = matrixDtlsGetOutdata(ssl, &sslBuf)) > 0) { if ((sendLen = udpSend(dtlsCtx->fd, sslBuf, sslBufLen, (struct sockaddr*)&inaddr, sizeof(struct sockaddr_in), dtlsCtx->timeout, packet_loss_prob, NULL)) < 0) { psTraceDtls("udpSend error. Ignoring\n"); } /* Always indicate the entire datagram was sent as there is no way for DTLS to handle partial records. Resends and timeouts will handle any problems */ rcs = matrixDtlsSentData(ssl, sslBufLen); if (rcs == MATRIXSSL_REQUEST_CLOSE) { psTraceDtls("Got REQUEST_CLOSE out of SentData\n"); clearClient(dtlsCtx); break; } if (rcs == MATRIXSSL_HANDSHAKE_COMPLETE) { /* This is the standard handshake case */ _psTrace("Got HANDSHAKE_COMPLETE from SentData\n"); break; } /* SSL_REQUEST_SEND is handled by loop logic */ } break; case MATRIXSSL_REQUEST_RECV: psTraceDtls("Got REQUEST_RECV from ReceivedData\n"); break; case MATRIXSSL_RECEIVED_ALERT: /* The first byte of the buffer is the level */ /* The second byte is the description */ if (*sslBuf == SSL_ALERT_LEVEL_FATAL) { psTraceIntDtls("Fatal alert: %d, closing connection.\n", *(sslBuf + 1)); clearClient(dtlsCtx); continue; /* Next connection */ } /* Closure alert is normal (and best) way to close */ if (*(sslBuf + 1) == SSL_ALERT_CLOSE_NOTIFY) { clearClient(dtlsCtx); continue; /* Next connection */ } psTraceIntDtls("Warning alert: %d\n", *(sslBuf + 1)); if ((rcr = matrixSslProcessedData(ssl, &sslBuf, (uint32*)&freeBufLen)) == 0) { continue; } goto PROCESS_MORE_FROM_BUFFER; default: continue; /* Next connection */ } } else if (val < 0) { if (SOCKET_ERRNO != EINTR) { psTraceIntDtls("unhandled error %d from select", SOCKET_ERRNO); } } /* Have either timed out waiting for a read or have processed a single recv. Now check to see if any timeout resends are required */ rc = handleResends(sock); } /* Main Select Loop */ DTLS_EXIT: psFree(recvfromBuf, NULL); CLIENT_EXIT: closeClientList(); MATRIX_EXIT: matrixSslDeleteKeys(keys); matrixSslClose(); if (sock != INVALID_SOCKET) close(sock); return rc; } /******************************************************************************/ /* Work through client list and resend handshake flight if haven't heard from them in a while */ static int32 handleResends(SOCKET sock) { serverDtls_t *dtlsCtx; ssl_t *ssl; psTime_t now; unsigned char *sslBuf; int16 i; int32 sendLen, rc; uint32 timeout, sslBufLen, clientCount; clientCount = 0; /* return code is number of active clients or < 0 on error */ psGetTime(&now, NULL); for (i = 0; i < tableSize; i++) { dtlsCtx = &clientTable[i]; if (dtlsCtx->ssl != NULL) { clientCount++; timeout = psDiffMsecs(dtlsCtx->lastRecvTime, now, NULL) / 1000; /* Haven't heard from this client in a while. Might need resend */ if (timeout > dtlsCtx->timeout) { /* if timeout is too great. clear conn */ if (dtlsCtx->timeout >= MAX_WAIT_SECS) { clearClient(dtlsCtx); clientCount--; break; } /* Increase the timeout for next pass */ dtlsCtx->timeout *= 2; /* If we are in a RESUMED_HANDSHAKE_COMPLETE state that means we are positive the handshake is complete so we don't want to resend no matter what. This is an interim state before the internal mechaism sees an application data record and flags us as complete officially */ if (dtlsCtx->connStatus == RESUMED_HANDSHAKE_COMPLETE) { psTraceDtls("Connected but awaiting data\n"); continue; } ssl = dtlsCtx->ssl; while ((sslBufLen = matrixDtlsGetOutdata(ssl, &sslBuf)) > 0) { if ((sendLen = udpSend(dtlsCtx->fd, sslBuf, sslBufLen, (struct sockaddr*)&dtlsCtx->addr, sizeof(struct sockaddr_in), dtlsCtx->timeout / 2, packet_loss_prob, NULL)) < 0) { psTraceDtls("udpSend error. Ignoring\n"); } /* Always indicate the entire datagram was sent as there is no way for DTLS to handle partial records. Resends and timeouts will handle any problems */ if ((rc = matrixDtlsSentData(ssl, sslBufLen)) < 0) { psTraceDtls("internal error\n"); clearClient(dtlsCtx); clientCount--; break; } if (rc == MATRIXSSL_REQUEST_CLOSE) { psTraceDtls("Got REQUEST_CLOSE out of SentData\n"); clearClient(dtlsCtx); clientCount--; break; } if (rc == MATRIXSSL_HANDSHAKE_COMPLETE) { /* This is the standard handshake case */ psTraceDtls("Got HANDSHAKE_COMPLETE out of SentData\n"); break; } /* SSL_REQUEST_SEND is handled by loop logic */ } } } } return clientCount; }
int main ( int argc, char * argv[ ] ) { int sock, nuSock; // This will be our sockets int nbytes; // Number of bytes we receive in our message int code; // Error code for Select char buffer[ MAXBUFSIZE ]; // A buffer to store our received message char msg[ MAXBUFSIZE ]; // A Message to return Repository repo; // The registration list fd_set fds; struct timeval timeout; int count = 0; // // Make sure port is given on command line // if ( argc != 2 ) { printf( "USAGE: <port>\n" ); exit( EXIT_FAILURE ); } // // Initialize all the things! // repo.total = 0; maxPrint( &repo ); sock = createSocket( atoi( argv[1] ) ); timeout.tv_sec = 2; timeout.tv_usec = 0; FD_ZERO( &fds ); FD_SET( sock, &fds ); nuSock = acceptConnection( sock ); ERROR( nuSock < 0 ); FD_SET( nuSock, &fds ); // // Enter command loop // for ( ; ; ) { /* if ( ( code = select( sizeof( fds )*8, &fds, NULL, NULL, &timeout ) ) < 0 ) { ERROR( code < 0 ); } else if ( code == 0 ) { printf( "$ Timeout [%i]\r", count = ++count % 100 ); ERROR( count ); } else { count = 0; if ( FD_ISSET( sock, &fds ) ) { // Loop through all the conenctions Available while ( ( nuSock = acceptConnection( sock ) ) > 0 ); FD_SET( nuSock, &fds ); } */ ERROR( nuSock < 0 ); bzero( buffer, MAXBUFSIZE ); nbytes = read( nuSock, buffer, MAXBUFSIZE ); ERROR( nbytes < 0 ); printf( "[%s] %s\n", repo.cxn[whoisthis( &repo, nuSock )].name, buffer ); switch ( parseCmd ( buffer ) ) { case CONNECT: { nbytes = write( nuSock, buffer, MAXBUFSIZE ); ERROR( nbytes < 0 ); switch( registerClient( &repo, nuSock ) ) { case SUCCESS: getList ( &repo, nuSock ); printf( "> Success in registering '%s'\n", repo.cxn[repo.total-1].name ); break; case FAILURE: printf( "> Error in registration\n" ); break; } break; } case GET: sendMaster( &repo, nuSock ); break; case EXIT: { switch( removeClient( &repo, nuSock ) ) { case SUCCESS: printf( "> Client has been removed.\n" ); break; case FAILURE: printf( "> Error removing client.\n" ); break; } break; } default: sprintf( msg, "Invalid command: '%s'", buffer); nbytes = write( nuSock, msg, MAXBUFSIZE ); ERROR( nbytes < 0 ); break; } } close( nuSock ); close( sock ); return EXIT_SUCCESS; } // main( )
int main(int argc, char* argv[]){ printf("\n" BAR " Running Chat Client %s. " BAR "\n\n", argv[1]); if(argc != 2){ printf("ERROR: You must enter 1 name (no spaces) on the command line.\n"); return EXIT_FAILURE; } int cliPort = getPortFromName(argv[1]); //get the client's port based on name printf("Setting up client for UDP... \n"); int UDPsocket = getUDPSocket(); //obtain socket for UDP struct sockaddr_in cliAddr; setCliAddr(cliPort, UDPsocket, &cliAddr); //set up clients address with port struct sockaddr_in servAddr; //this is the server's address setServAddr(&servAddr); //set up the server addrss /************************* Contact UDP Server **********************/ char sendBuf[BUF_SIZE]; memset(&sendBuf, 0, BUF_SIZE); char recvBuf[BUF_SIZE]; memset(&recvBuf, 0, BUF_SIZE); int addrLen = sizeof(servAddr); char currChar; bool using = true; //when using the program while(using){ //register with UDP server registerClient(UDPsocket, argv[1], (struct sockaddr*) &servAddr, sendBuf); //now we expect to get a response which is a list of people //this linked list is the register of who is an isn't connected CC reg = (CC) malloc(sizeof(struct ConnectedClient)); //acts as head strcpy(reg->name, "CLIENT LIST"); reg->next = NULL; //obtain and display list of clients from UDP server getClientList(reg, UDPsocket, recvBuf); /********************** TRANSITION TO TCP *********************************/ printf("Would you like to wait for a connection or make a connection? (w/m): "); char waitOrMake = getc(stdin); //get a new socket of TCP type int sockTCP = socket(AF_INET, SOCK_STREAM, 0); if(sockTCP < 0){ //if < 0 we have an error deRegister(UDPsocket, argv[1], (struct sockaddr*) &servAddr, sendBuf); perror("We have an error"); return EXIT_FAILURE; } struct sockaddr_in tcpAddr = cliAddr; tcpAddr.sin_port = htons(ntohs(cliAddr.sin_port) + 1); //TCP port will be UDPport++; int nowSocket; //this will be the socket we use to communicate //may come from accepting a connection or starting a connection //we are now going to make a connection char* connectee = NULL; //the name of the person we connect to if(waitOrMake == 'm'){ //if the client wants to make a connection printf("Pick the numbered client you wish to talk to: "); int clientNum = 0; scanf("%d", &clientNum); //get address of other client struct sockaddr_in* cliOfInterest = getAddr(reg, clientNum); connectee = getName(reg, cliOfInterest); printf("Making connection to %s\n", connectee); //make connection to other client printf("Trying connection to socket %d\n", ntohs(cliOfInterest->sin_port)); if(connect(sockTCP, (struct sockaddr*) cliOfInterest, sizeof(*cliOfInterest)) < 0){ deRegister(UDPsocket, argv[1], (struct sockaddr*) &servAddr, sendBuf); perror("We have an error"); return EXIT_FAILURE; } nowSocket = sockTCP; printf("Connection made!\n"); //notify conectee that I connected sprintf(sendBuf, "%s%s%s %s%s", CONN_FANFAIR, "\t\t", argv[1], CONN_NOTICE, CONN_FANFAIR); send(nowSocket, sendBuf, strlen(sendBuf), 0); } else { int currCliSocket; //this will be the socket we recieve a connection on struct sockaddr_in cliOfInterest; int len = sizeof(cliOfInterest); //bind the TCP address (different port) to the TCP socket bind(sockTCP, (struct sockaddr*) &tcpAddr, sizeof(tcpAddr)); printf("Now listening on port %d.\n", ntohs(tcpAddr.sin_port)); listen(sockTCP, 1); //being listening for connections //if we get a connection we record the socket we are using and the address currCliSocket = accept(sockTCP, (struct sockaddr*) &cliOfInterest, &len); if(currCliSocket >= 0){ nowSocket = currCliSocket; printf("Connection being made by another client ...\n"); //name is send over TCP by client } else { deRegister(UDPsocket, argv[1], (struct sockaddr*) &servAddr, sendBuf); perror("Incomming connection failed"); return EXIT_FAILURE; } } //at this point we have a TCP connection with another client //we are now going to run two threads simultaneously //the child thread will be to send chat //the parent thread will be to listen and display //spawn a child process int pid = fork(); if(pid < 0){ //if failed to fork deRegister(UDPsocket, argv[1], (struct sockaddr*) &servAddr, sendBuf); perror("Failed to fork!\n"); return EXIT_FAILURE; } else if(pid != 0) { /*********************** PARENT *****************/ printf("You are now in a chat room.\n" "Type \"" END_CONN "\" to exit the chat room.\n\n"); bool sending = true; //client still wants to chat bool firstTime = true; //start off first time while(sending){ //we will be ready to send until END_CONN //printf("You [%s]: ", timeStr()); printf("%s", KCYN); //make home client cyan memset(&sendBuf, 0, BUF_SIZE); //clear buffer if(firstTime){ //if just come from selection firstTime = false; //next time will not be first time currChar = getc(stdin); //we do another getc() to clear ENTER_KEY } currChar = getc(stdin); //get message to send int i = 0; //while we done hit enter and less than max buff (-1 for '\0') while(((int)currChar != ENTER_KEY) && (i < (BUF_SIZE - 2))){ sendBuf[i] = currChar; i++; currChar = getc(stdin); } sendBuf[i] = '\0'; //if typed in command to end client, end client if(strcmp(sendBuf, END_CONN) == 0){ sending = false; //end the chat room //send message of leaving chatroom send(nowSocket, LEAVING_CHATROOM_MSG, sizeof(LEAVING_CHATROOM_MSG), 0); kill(pid, SIGKILL); //kill child process } else { //send message to server send(nowSocket, sendBuf, BUF_SIZE, 0); } } } else { /*********************************** CHILD **************************/ int nread; char bufbuf[120]; while(true){ //always ready to receive chat --------> until shared memory memset(recvBuf, 0, BUF_SIZE); //clear buffer nread = read(nowSocket, recvBuf, BUF_SIZE); //receive a message recvBuf[nread] = '\0'; //manually terminate string if(strcmp(recvBuf, ACK_MSG) == 0){ //if we received an ACK, we print ACK printf("*** received ***\n\n"); //symbolizes reception of message } else if(strcmp(recvBuf, LEAVING_CHATROOM_MSG) == 0){ //if other client left printf("*** *** *** You're friend left the chatroom. *** *** ***\n"); deRegister(UDPsocket, argv[1], (struct sockaddr*) &servAddr, sendBuf); printf("Press ENTER to exit...\n"); } else if(strstr(recvBuf, CONN_NOTICE) != NULL){ //if it is a connection notice, don't ACK printf("%s%s%s\n\n", KMAG, recvBuf, KCYN); } else { //if normal message send(nowSocket, ACK_MSG, sizeof(ACK_MSG), 0); //send ack of recieved and displayed printf("%s%s%s\n\n", KMAG, recvBuf, KCYN); //weirdly, we needed to do '\n' at the end... } } } close(nowSocket); //kill TCP connection //disconnet before ending deRegister(UDPsocket, argv[1], (struct sockaddr*) &servAddr, sendBuf); } return EXIT_SUCCESS; }