//sends a single user record to the file appending to the existing contents void USR_Manager::sendToFile(Util::User user) { std::ofstream output; output.open(Util::usersFilePath(), std::ofstream::out | std::ofstream::app); //check if saved user.highestscore is greater than the current highestscore score. if (checkIfUserExists(user)) { int highscore_from_file = findUserByUsername(user.username).highestScore; if (user.highestScore > highscore_from_file) output << user.username + " - " + std::to_string(user.highestScore) + "\n"; } else { output << user.username + " - " + std::to_string(user.highestScore) + "\n"; } output.close(); }
void* serverListener(void* parameters) //1st thread which communicates with the client { struct clientParams *p = (struct clientParams*) parameters; //login------------------------------------------------------------------------------------------------------ while(1) //login loop { p->recvError = recv(p->clientSocket, p->buf_login, 300, 0); //login information is recieved in one string if (p->recvError <= 0) //if there is an error in recieve, exit the thread { if (p->recvError < 0) perror("recv"); pthread_mutex_lock(&killLock); //killLock is locked until the pair thread dies threadToKill = p->threadId + 1; //if listernerThread exist, then the pair thread should exit too close(p->clientSocket); //and the related socket pthread_exit(p->threadId); } if (p->buf_login[strlen(p->buf_login) - 1] != '<') //check if the sysmbol is present after every message the client sends { //if not, the pair should exit pthread_mutex_lock(&killLock); threadToKill = p->threadId + 1; close(p->clientSocket); pthread_exit(p->threadId); } p->buf_login[strlen(p->buf_login) - 1]= '\0'; //to take away the symbol after checking decrypt((unsigned long*)p->buf_login); //after taking symbol away, login information is decrypted int i, reset = 0; int k = 0; for(i=0;i<100;i++) { p->buf_user[i] = '\0';} //the variables that will hold the name, password and login/reg choice are reset for(i=0;i<100;i++) { p->buf_pass[i] = '\0';} //so they can be used again if the user makes a mistake for(i=0;i<100;i++) { p->buf_answer[i] = '\0';} for(i = 0; i < strlen(p->buf_login); i++) { if ( p->buf_login[i] == ' ') {reset++; k = 0;} //we're looking for spaces to separate the words if (reset == 0) //we find the login/reg choice before the first space { p->buf_answer[k] = p->buf_login[i]; } if (reset == 1) //username after the first space { p->buf_user[k] = p->buf_login[i+1]; k++; } if (reset == 2) //password after the second space { p->buf_pass[k] = p->buf_login[i+1]; k++; } } p->buf_user[strlen(p->buf_user) - 1]= '\0'; //the space is removed from the username if( p->buf_answer[0] == '0') //registration of user { pthread_mutex_lock(&fileWriteLock); //new username and password written to file, hence locked if(!checkIfUserExists(p->buf_user)) //User present already? if no, create user, else print it exists { createUser(p->buf_user, p->buf_pass); pthread_mutex_unlock(&fileWriteLock); if (send(p->clientSocket, "User created!!", DATASIZE, 0) == -1) { pthread_mutex_lock(&killLock); threadToKill = p->threadId + 1; close(p->clientSocket); pthread_exit(p->threadId);} if (send(p->clientSocket, "youcanlogin", DATASIZE, 0) == -1) { pthread_mutex_lock(&killLock); threadToKill = p->threadId + 1; close(p->clientSocket); pthread_exit(p->threadId);} break; } else { pthread_mutex_unlock(&fileWriteLock); if (send(p->clientSocket, "User exists already", DATASIZE, 0) == -1) { pthread_mutex_lock(&killLock); threadToKill = p->threadId + 1; close(p->clientSocket); pthread_exit(p->threadId);} if (send(p->clientSocket, "nope", DATASIZE, 0) == -1) { pthread_mutex_lock(&killLock); threadToKill = p->threadId + 1; close(p->clientSocket); pthread_exit(p->threadId);} } } else if(p->buf_answer[0] == '1') //login of user { if(!controlPassword(p->buf_user, p->buf_pass)) //if the username and password doesnt match, kill the threads { if (send(p->clientSocket, "Wrong username or password.", DATASIZE, 0) == -1) { pthread_mutex_lock(&killLock); threadToKill = p->threadId + 1; close(p->clientSocket); pthread_exit(p->threadId);} if (send(p->clientSocket, "nope", DATASIZE, 0) == -1) { pthread_mutex_lock(&killLock); threadToKill = p->threadId + 1; close(p->clientSocket); pthread_exit(p->threadId);} } else //if matched, login. { if (send(p->clientSocket, "Succesful login. Welcome.", DATASIZE, 0) == -1) { pthread_mutex_lock(&killLock); threadToKill = p->threadId + 1; close(p->clientSocket); pthread_exit(p->threadId);} if (send(p->clientSocket, "youcanlogin", DATASIZE, 0) == -1) { pthread_mutex_lock(&killLock); threadToKill = p->threadId + 1; close(p->clientSocket); pthread_exit(p->threadId);} break; } } else { if (send(p->clientSocket, "Decrypting error. Try again.", DATASIZE, 0) == -1) { pthread_mutex_lock(&killLock); threadToKill = p->threadId + 1; close(p->clientSocket); pthread_exit(p->threadId);} if (send(p->clientSocket, "nope", DATASIZE, 0) == -1) { pthread_mutex_lock(&killLock); threadToKill = p->threadId + 1; close(p->clientSocket); pthread_exit(p->threadId);} } } //end login------------------------------------------------------------------------------------------------------ strcpy(userNames[p->threadId], p->buf_user); pthread_mutex_lock(&senderLock); //the message variable is locked, sender threads have time to send it before it changes strcpy(message, p->buf_user); //a message is sent to all clients with the name of this client strcat(message, " joined the chat."); usleep(300000); pthread_mutex_unlock(&senderLock); strcat(p->buf_user, ": "); while(1) //the main listening loop { if (threadToKill == p->threadId) //if the sender pair of this thread quit, so should listener quit too { pthread_mutex_unlock(&killLock); close(p->clientSocket); pthread_exit(p->threadId); } p->recvError = recv(p->clientSocket, p->uniqueText, DATASIZE, 0); //message is recieved if (p->recvError <= 0) { if (p->recvError < 0) perror("recv"); pthread_mutex_lock(&killLock); threadToKill = p->threadId + 1; close(p->clientSocket); if(queue[0] == p->threadId) //if this thread was in queue, remove it { queue[0] = -1; } pthread_exit(p->threadId); } if (p->uniqueText[strlen(p->uniqueText) - 1] != '<') { pthread_mutex_lock(&killLock); threadToKill = p->threadId + 1; close(p->clientSocket); if(queue[0] == p->threadId) { queue[0] = -1; } pthread_exit(p->threadId); } p->uniqueText[strlen(p->uniqueText) - 1]= '\0'; if(strcmp(p->uniqueText,"__Play__") == 0) //if the client says __Play__, put it in the queue { pthread_mutex_lock(&queueLock); //lock other threads to change the queue at the same time if(queue[0] == -1) //if the 1st position of queue is empty, thread ID is copied to it { //a message is sent to the client so it knows it's in the queue now queue[0] = p->threadId; strcpy(qName[0],p->buf_user); //the name of the user is also saved if (send(p->clientSocket, "queued", DATASIZE, 0) == -1) { pthread_mutex_lock(&killLock); threadToKill = p->threadId + 1; close(p->clientSocket); pthread_exit(p->threadId);} pthread_mutex_unlock(&queueLock); } else if(queue[1] == -1) //do the same for next position { pthread_mutex_unlock(&queueLock); if(strcmp(p->buf_user,qName[0])==0) //if the user trying to queue is the same as the one already in queue in position 0, decline it { //a message is sent to the client so it knows it was declined if(send(p->clientSocket, "notQueued", DATASIZE, 0) == -1) { pthread_mutex_lock(&killLock); threadToKill = p->threadId + 1; close(p->clientSocket); pthread_exit(p->threadId);} } else { pthread_mutex_lock(&queueLock); //lock the queue until the game is started if (send(p->clientSocket, "queued", DATASIZE, 0) == -1) { pthread_mutex_lock(&killLock); threadToKill = p->threadId + 1; close(p->clientSocket); pthread_exit(p->threadId);} queue[1] = p->threadId; strcpy(qName[1],p->buf_user); qReady = 1; //when 2nd position of queue is fille, qReady=1 } } } else if(strcmp(p->uniqueText,"__DontPlay__") == 0) //if the client sennds __DontPlay__ it is removed from the queue { if(queue[0] == p->threadId) //if this thread was in queue, remove it { queue[0] = -1; } } else { strcpy(p->tempText, p->buf_user); //buf_user: uniqueText strcat(p->tempText, p->uniqueText); pthread_mutex_lock(&senderLock); //the message variable is locked, sender threads have time to send it before it changes strcpy(message, p->tempText); usleep(300000); pthread_mutex_unlock(&senderLock); } } }