示例#1
0
void* ServerThread::run() {
	while (true) {
		//TODO main loop thread, process query by package
		try {
			char buff[512];
			memset(buff, 0, sizeof(buff));

			socket->receive(buff, sizeof(buff), MSG_PEEK);

			Package currentPackage = buff;

			/*char timeBuff[100];
			memset(timeBuff, 0, sizeof(timeBuff));
			time_t packageTime = currentPackage.getPackageTime();

			strftime(timeBuff, sizeof(timeBuff), "%T", gmtime(&packageTime));

			cout << "--- Received package stats --- " << endl
				 << "packageNum: " << currentPackage.getPackageType() << endl
				 << "packageTime: " << timeBuff << endl
				 << "--- End of package stats --- " << endl;*/
			if(currentPackage.getPackageType() == Protocol::userSignup) {
				/* Signup */
				/* Receive packet contains username password */
				// flush first
				memset(buff, 0, sizeof(buff));
				socket->receive(buff, sizeof(buff));

				UserInitPackage package = buff;

				string username = package.getUserName();
				string password = package.getUserPassword();

				if(Group::isGroupExists(username)) {
					//TODO signup fail, add signup fail message?
					SimpleMessagePackage reply(Protocol::userSignupFail);

					reply.setMessage("IT IS GROUP NAME");
					reply.send(*socket);
				} else {
					if (currentUser.newUser(username, password) == USER_SIGNUP_SUCCESS) {
						threadName = username;
						Package reply(Protocol::userSignupSuccess);

						// TODO: generate user id here
						reply.send(*socket);
					} else {
						//TODO signup fail, add signup fail message?
						SimpleMessagePackage reply(Protocol::userSignupFail);

						reply.send(*socket);
					}
				}
			} else if (currentPackage.getPackageType() == Protocol::userLogin) {
				cout << "logging in..." << endl;
				/* Login */
				/* Receive packet contains username password */
				memset(buff, 0, sizeof(buff));
				socket->receive(buff, sizeof(buff));

				UserInitPackage package = buff;

				string username = package.getUserName();
				string password = package.getUserPassword();

				if(currentUser.login(username, password) == USER_LOGIN_SUCCESS) {
					Package reply(Protocol::userLoginSuccess);
					reply.send(*socket);

					threadName = username;
					currentUser.loadMessages();
					checkNotification();
					Utils::writeServerLog(username + " has logged in");
				} else {
					//send login failed
					SimpleMessagePackage reply(Protocol::userLoginFail);

					reply.setMessage("Login failed");
					reply.send(*socket);

					cout << USER_LOGIN_INVALID << endl;
				}
			} else if (currentPackage.getPackageType() == Protocol::messageSend) {
				/* User sends message */
				/* if user is present (threadlist) then send to its queue,
				 * else call the currentUser.dumpMessageTo(targetUser)
				 */
				memset(buff, 0, sizeof(buff));
				socket->receive(buff, sizeof(buff));

				MessageSendPackage package = buff;

				string name = package.getReceiver();
				time_t msgTime = package.getPackageTime();
				string message = package.getMessage();
				string msg = currentUser.getUserName() + " : " + message;
				cout << msg << endl;
				bool isGroupName = Group::isGroupExists(name);
				if (isGroupName) {
					Group* temp = Group::getGroup(name);
					if(temp != NULL) {
						temp->broadcast(currentUser,msg);
						SimpleMessagePackage reply(Protocol::messageSendSuccess);
						reply.send(*socket);
					}
				} else { //to user
					if(User::isUserExists(name)) {
						Utils::writeServerLog(currentUser.getUserName() + " messages " + name);

						if(isUserOnline(name)) {
							threadPoolMutex.lock();
							for(unsigned int i = 0; i < threadPool.size(); i++) {
								if (threadPool.at(i)->threadName == name) {
									struct Message ms;
									ms.sender = currentUser.getUserName();
									ms.time = msgTime;
									ms.message = msg;
									threadPool[i]->acceptMessage(ms);
									SimpleMessagePackage reply(Protocol::messageSendSuccess);
									reply.send(*socket);
									break;
								}
							}
							threadPoolMutex.unlock();
						} else {
							currentUser.dumpMessageTo(name, msgTime, msg);
							SimpleMessagePackage reply(Protocol::messageSendSuccess);
							reply.send(*socket);
						}
					} else {
						//send it does not exist
						SimpleMessagePackage reply(Protocol::messageSendFailed);
						reply.setMessage("User " + name + " does not exist!");

						reply.send(*socket);
					}
				}
			} else if (currentPackage.getPackageType() == Protocol::groupCreate) {
				/* User create group */
				// flush
				socket->receive(buff, sizeof(buff));

				GroupCreatePackage package = buff;
				if(Group::createGroup(currentUser, package.getGroupName())) {
					UserIdPackage reply(Protocol::groupCreateSuccess, 0);
					// TODO: generate the group id here
					reply.send(*socket);
				} else {
					UserIdPackage reply(Protocol::groupCreateFail, 0);

					reply.send(*socket);
				}
			} else if (currentPackage.getPackageType() == Protocol::groupJoin) {
				/* User join group */
				// flush
				cout << "Masuk?" << endl;
				socket->receive(buff, sizeof(buff));
				//socket->receive(buff, sizeof(buff));

				GroupJoinPackage package = buff;

				string groupName = package.getGroupName();
				if(Group::isGroupExists(groupName)) {
					cout << "Group " << groupName << " exists!" << endl;

					Group* group = Group::getGroup(groupName);
					if(group->checkMembership(currentUser)) {
						cout << "already in group!" << endl;
						SimpleMessagePackage response(Protocol::groupJoinFail);

						response.setMessage("Already joined in group " + groupName);
						response.send(*socket);
					} else {
						cout << "Join success!" << endl;
						group->joinGroup(currentUser);

						Package response(Protocol::groupJoinSuccess);

						socket->send(response);
					}
				} else {
					cout << "Group " << groupName << " does not exist!" << endl;
					SimpleMessagePackage response(Protocol::groupJoinFail);

					response.setMessage("Group " + groupName + " does not exist");
					response.send(*socket);
				}
			} else if (currentPackage.getPackageType() == Protocol::groupLeave) {
				/* User join group */
				// flush
				socket->receive(buff, sizeof(buff));

				// abusing this package class
				SimpleMessagePackage package = buff;

				if(Group::isGroupExists(package.getMessage())) {
					Group* group = Group::getGroup(package.getMessage());
					if(group->checkMembership(currentUser)) {
						group->leaveGroup(currentUser);
						Package response(Protocol::groupLeaveSuccess);

						response.send(*socket);
					} else {
						SimpleMessagePackage response(Protocol::groupLeaveFail);

						response.setMessage("You are not a member of " + group->getGroupName());
						response.send(*socket);
					}
				} else {
					SimpleMessagePackage response(Protocol::groupLeaveFail);

					response.setMessage("Group " + package.getMessage() + " does not exist");
					response.send(*socket);
				}
			} else if(currentPackage.getPackageType() == Protocol::messageRecvRequest) {
				// flush
				socket->receive(buff, sizeof(buff));
				SimpleMessagePackage requestPackage(buff);

				if(!currentUser.unseenMessage.empty()) {
					while(!currentUser.unseenMessage.empty()) {
						struct Message ms;
						ms = currentUser.unseenMessage[0];

						if(requestPackage.getMessage() == ms.sender) {

							MessageSendPackage response(ms.sender, ms.message);
							response.resetTime();
							response.send(*socket);

							currentUser.unseenMessage.erase(currentUser.unseenMessage.begin());
						}
					}
					Package last(Protocol::messageRecvEnd);

					last.send(*socket);
				} else {
					// no new messages
					Package last(Protocol::messageRecvEnd);

					last.send(*socket);
				}

			} else if (currentPackage.getPackageType() == Protocol::userLogout) {
				/* Logout */
				Utils::writeServerLog(threadName + " logged out");
				break;
			} else {
				//flush
				socket->receive(buff, sizeof(buff));
			}
		} catch (SocketException& e) {
			cerr << "Caught SocketException: " << e.what() << endl;
			break;
		}
	}

	//cleanup codes
	threadPoolMutex.lock();
	for(unsigned int i = 0; i < threadPool.size();i++) {
		if (threadPool.at(i) == this) {
			threadPool.erase(threadPool.begin()+i);
			break;
		}
	}
	threadPoolMutex.unlock();

	return NULL;
}