#include #include #include #include #include #include #include #include #include #include #include #include using namespace std; class Room { public: string name; int desc; Room(int d, string n) { desc = d; name = n; } }; class Client { public: int desc; string Name; vector rooms; Client(int d, string n) { desc = d; Name = n; } Client() {} }; vector messagess = { "/join", "/disconnect" }; set rooms; vector clients; set meta; set list; int metadata = -2; int parseCommand(string message) { int result = -1; for (auto e : messagess) { if (message.find(e) == 0) { for (unsigned int i = 0; i < messagess.size(); i++) { if (messagess[i] == e) result = i; } } } return result; } void sendMessage(int m,string avamys) { int sent = 0; unsigned int got = 0; do { sent = send(m, avamys.c_str() + got, avamys.size() - got, MSG_CONFIRM); got += sent; } while (got < avamys.size()); } void sendMetadata(){ for (int m: meta){ if (m != metadata){ for (Client *c : clients){ for (Room r : c->rooms){ string avamys = to_string(r.desc) + ":" + r.name + ":" + c->Name; avamys.append("\n"); sendMessage(m,avamys); } } string avamys = "@@DONE\n"; sendMessage(m,avamys); } } } void split(const string& s, char delim, vector& elems) { stringstream ss; ss.str(s); string item; while (getline(ss, item, delim)) { elems.push_back(item); } } vector split(const string& s, char delim) { vector elems; split(s, delim, elems); return elems; } int main(int argc, char* argv[]) { if (argc < 2) { cout << "Nie podano portu!" << endl; return -1; } rooms.insert(argv[0]); fd_set master; fd_set read_fds; fd_set write_fds; struct sockaddr_in serveraddr; struct sockaddr_in serveraddr_meta; struct sockaddr_in clientaddr; int fdmax = -1; //najwiekszy deskryptor int listener; //nasluchujacy dekspytor int newfd; //najnowszy zaakceptowany int nbytes; int guest = 0; int yes = 1; int port = stoi(argv[1]); socklen_t addrlen; int i, j; string tt = argv[0]; int t = tt.find("select"); FD_ZERO(&master); FD_ZERO(&read_fds); if ((listener = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("Server-socket()-listener error"); exit(1); } printf("Server-socket()-listener is OK...\n"); if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { perror("Server-setsockopt()-listener error"); exit(1); } printf("Server-setsockopt()-listener is OK...\n"); serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = INADDR_ANY; serveraddr.sin_port = htons(stoi(argv[1])); if (bind(listener, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) == -1) { perror("Server-bind()-listener error"); exit(1); } printf("Server-bind()-listener is OK...\n"); if (listen(listener, 5) == -1) //kolejka { perror("Server-listen()-listener error"); exit(1); } printf("Server-listen()-listener is OK...\n"); ///////////METADATA////////////////// if (t >= 0) //czy Main room? { if ((metadata = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("Server-socket()-metadata error"); exit(1); } printf("Server-socket()-metadata is OK...\n"); if (setsockopt(metadata, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { perror("Server-setsockopt()-metadata error"); exit(1); } printf("Server-setsockopt()-metadata is OK...\n"); serveraddr_meta.sin_family = AF_INET; serveraddr_meta.sin_addr.s_addr = INADDR_ANY; serveraddr_meta.sin_port = htons(stoi(argv[1]) - 1); if (bind(metadata, (struct sockaddr*)&serveraddr_meta, sizeof(serveraddr_meta)) == -1) { perror("Server-bind()-meta error"); exit(1); } printf("Server-bind()-meta is OK...\n"); if (listen(metadata, 5) == -1) //kolejka { perror("Server-listen()-metadata error"); exit(1); } printf("Server-listen()-metadata is OK...\n"); } /* listener do mastera */ FD_SET(listener, &master); FD_SET(metadata, &master); if (listener > fdmax) fdmax = listener; if (metadata > fdmax) fdmax = metadata; meta.insert(metadata); list.insert(listener); for (;;){ read_fds = master; if (select(fdmax + 1, &read_fds, NULL, NULL, NULL) == -1) { perror("Server-select() error"); exit(1); } printf("Server-select() is OK...\n"); /*szuka po deskryptorach czy cos do czytania*/ for (i = 0; i <= fdmax; i++) { if (FD_ISSET(i, &read_fds)) { if (i == listener) { /* nowe polaczenia */ addrlen = sizeof(clientaddr); if ((newfd = accept(listener, (struct sockaddr*)&clientaddr, &addrlen)) == -1) { perror("Server-accept()-listener error"); } else { printf("Server-accept()-listener is OK...\n"); FD_SET(newfd, &master); /* add to master set */ list.insert(newfd); Client *temp = new Client(newfd, "Guest"+to_string(guest)); Room ro(stoi(argv[1]), "Main"); temp->rooms.push_back(ro); clients.push_back(temp); guest++; if (newfd > fdmax) fdmax = newfd; printf("%s: New connection from %s on socket %d\n", argv[0], inet_ntoa(clientaddr.sin_addr), newfd); } } else if (i == metadata) { /* nowe polaczenia do odczytu metadanych*/ addrlen = sizeof(clientaddr); if ((newfd = accept(metadata, (struct sockaddr*)&clientaddr, &addrlen)) == -1) { perror("Server-accept()-metadata error"); } else { printf("Server-accept()-metadata is OK...\n"); meta.insert(newfd); } if (newfd > fdmax) fdmax = newfd; printf("%s: New connection from %s on socket %d\n", argv[0], inet_ntoa(clientaddr.sin_addr), newfd); } else { int iterator = 0; int unexpected_error = 0; int command; string message = ""; char* buf = new char[1024]; /* czytamy wiadomość */ do { if ((nbytes = recv(i, buf, sizeof(buf), 0)) <= 0) { //zamkniete lub error if (nbytes == 0) printf("%s: socket %d hung up\n", argv[0], i); //zamkniete else perror("recv() error(odbieranie)"); close(i); //zamykamy i usuwamy z seta FD_CLR(i, &master); list.erase(i); unexpected_error = 1; break; } message.append(buf, 0, nbytes); iterator += nbytes; } while (message[iterator - 1] != '\n'); if (unexpected_error == 1) continue; // jeśli błąd konczymy obslugę tego klienta w tej iteracji selecta vector msg_split = split(message, ':'); /* aktualizujemy nazwę użytkownika, która była nieznana podczas accepta */ for (Client *c : clients) { if (c->desc == i && c->Name.find("Guest") >= 0) { c->Name = msg_split[0]; if (fork()==0) { sendMetadata(); exit(0); } } } /* sprawdzamy czy wiadomość zawiera komendę */ command = parseCommand(msg_split[1]); switch (command) { case 0: // join port++; vector words_in_message = split(msg_split[1], ' '); if (words_in_message.size() < 2) { cout << "Nie podano nazwy pokoju!" << endl; break; } if (t < 0) { cout << "Nie mozna tworzyc pokoju!" << endl; break; } string room_name = words_in_message[1]; room_name = room_name.substr(0,room_name.size()-2); if (fork() == 0) { execl("./select.o", room_name.c_str(), (char*)to_string(port).c_str(), nullptr); perror("RIP"); exit(1); } else { /* dodaj pokój do pokoi klienta */ Room ro(port, room_name); for (Client *c: clients) if (c->desc == i) c->rooms.push_back(ro); if (fork()==0){ sendMetadata(); exit(0); } break; } } cout << "Zaczynam wysylac: " << message << endl; /* mamy dane, trzeba je rozeslac*/ for (j = 0; j <= fdmax; j++) { if (FD_ISSET(j, &master) && list.find(j) != list.end()) { if (j != listener) sendMessage(j,message); } //if } //for } //else } //if (inset) } //for (descs) } //for (;;) return 1; } //main