Facebook
From Tinct Dolphin, 6 Years ago, written in Plain Text.
Embed
Download Paste or View Raw
Hits: 233
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <sstream>
  5. #include <unistd.h>
  6. #include <sys/types.h>
  7. #include <sys/socket.h>
  8. #include <netinet/in.h>
  9. #include <arpa/inet.h>
  10. #include <iostream>
  11. #include <vector>
  12. #include <set>
  13.  
  14. using namespace std;
  15.  
  16. class Room {
  17. public:
  18.     string name;
  19.     int desc;
  20.  
  21.     Room(int d, string n) {
  22.         desc = d;
  23.         name = n;
  24.     }
  25. };
  26.  
  27. class Client {
  28. public:
  29.     int desc;
  30.     string Name;
  31.     vector<Room> rooms;
  32.  
  33.     Client(int d, string n) {
  34.         desc = d;
  35.         Name = n;
  36.  
  37.     }
  38.  
  39.     Client() {}
  40. };
  41.  
  42. vector<string> messagess = { "/join", "/disconnect" };
  43. set<string> rooms;
  44. vector<Client*> clients;
  45. set<int> meta;
  46. set<int> list;
  47. int metadata = -2;
  48.  
  49. int parseCommand(string message) {
  50.     int result = -1;
  51.     for (auto e : messagess) {
  52.         if (message.find(e) == 0) {
  53.             for (unsigned int i = 0; i < messagess.size(); i++) {
  54.                 if (messagess[i] == e)
  55.                     result = i;
  56.             }
  57.         }
  58.     }
  59.     return result;
  60. }
  61.  
  62. void sendMessage(int m,string avamys) {
  63.     int sent = 0;
  64.     unsigned int got = 0;
  65.     do {
  66.         sent = send(m, avamys.c_str() + got, avamys.size() - got, MSG_CONFIRM);
  67.         got += sent;
  68.     } while (got < avamys.size());
  69. }
  70.  
  71. void sendMetadata(){
  72.     for (int m: meta){
  73.         if (m != metadata){
  74.             for (Client *c : clients){
  75.                 for (Room r : c->rooms){
  76.                     string avamys = to_string(r.desc) + ":" + r.name + ":" + c->Name;
  77.                     avamys.append("\n");
  78.                     sendMessage(m,avamys);
  79.                 }
  80.             }
  81.             string avamys = "@@DONE\n";
  82.             sendMessage(m,avamys);
  83.         }
  84.     }
  85. }
  86.  
  87.  
  88. void split(const string& s, char delim, vector<string>& elems) {
  89.     stringstream ss;
  90.     ss.str(s);
  91.     string item;
  92.     while (getline(ss, item, delim)) {
  93.         elems.push_back(item);
  94.     }
  95. }
  96.  
  97. vector<string> split(const string& s, char delim) {
  98.     vector<string> elems;
  99.     split(s, delim, elems);
  100.     return elems;
  101. }
  102.  
  103. int main(int argc, char* argv[]) {
  104.  
  105.     if (argc < 2) {
  106.         cout << "Nie podano portu!" << endl;
  107.         return -1;
  108.     }
  109.     rooms.insert(argv[0]);
  110.     fd_set master;
  111.     fd_set read_fds;
  112.     fd_set write_fds;
  113.     struct sockaddr_in serveraddr;
  114.     struct sockaddr_in serveraddr_meta;
  115.     struct sockaddr_in clientaddr;
  116.     int fdmax = -1; //najwiekszy deskryptor
  117.     int listener; //nasluchujacy dekspytor
  118.     int newfd; //najnowszy zaakceptowany
  119.     int nbytes;
  120.     int guest = 0;
  121.     int yes = 1;
  122.     int port = stoi(argv[1]);
  123.     socklen_t addrlen;
  124.     int i, j;
  125.     string tt = argv[0];
  126.     int t = tt.find("select");
  127.  
  128.     FD_ZERO(&master);
  129.     FD_ZERO(&read_fds);
  130.  
  131.     if ((listener = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  132.     {
  133.         perror("Server-socket()-listener error");
  134.         exit(1);
  135.     }
  136.     printf("Server-socket()-listener is OK...\n");
  137.  
  138.     if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
  139.     {
  140.         perror("Server-setsockopt()-listener error");
  141.         exit(1);
  142.     }
  143.     printf("Server-setsockopt()-listener is OK...\n");
  144.  
  145.     serveraddr.sin_family = AF_INET;
  146.     serveraddr.sin_addr.s_addr = INADDR_ANY;
  147.     serveraddr.sin_port = htons(stoi(argv[1]));
  148.  
  149.     if (bind(listener, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) == -1)
  150.     {
  151.         perror("Server-bind()-listener error");
  152.         exit(1);
  153.     }
  154.     printf("Server-bind()-listener is OK...\n");
  155.  
  156.     if (listen(listener, 5) == -1)   //kolejka
  157.     {
  158.         perror("Server-listen()-listener error");
  159.         exit(1);
  160.     }
  161.     printf("Server-listen()-listener is OK...\n");
  162.  
  163.     ///////////METADATA//////////////////
  164.     if (t >= 0)   //czy Main room?
  165.     {
  166.         if ((metadata = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  167.         {
  168.             perror("Server-socket()-metadata error");
  169.             exit(1);
  170.         }
  171.         printf("Server-socket()-metadata is OK...\n");
  172.         if (setsockopt(metadata, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
  173.         {
  174.             perror("Server-setsockopt()-metadata error");
  175.             exit(1);
  176.         }
  177.         printf("Server-setsockopt()-metadata is OK...\n");
  178.  
  179.         serveraddr_meta.sin_family = AF_INET;
  180.         serveraddr_meta.sin_addr.s_addr = INADDR_ANY;
  181.         serveraddr_meta.sin_port = htons(stoi(argv[1]) - 1);
  182.  
  183.         if (bind(metadata, (struct sockaddr*)&serveraddr_meta, sizeof(serveraddr_meta)) == -1)
  184.         {
  185.             perror("Server-bind()-meta error");
  186.             exit(1);
  187.         }
  188.         printf("Server-bind()-meta is OK...\n");
  189.         if (listen(metadata, 5) == -1)   //kolejka
  190.         {
  191.             perror("Server-listen()-metadata error");
  192.             exit(1);
  193.         }
  194.         printf("Server-listen()-metadata is OK...\n");
  195.     }
  196.  
  197.     /* listener do mastera */
  198.     FD_SET(listener, &master);
  199.     FD_SET(metadata, &master);
  200.     if (listener > fdmax) fdmax = listener;
  201.     if (metadata > fdmax) fdmax = metadata;
  202.     meta.insert(metadata);
  203.     list.insert(listener);
  204.     for (;;){
  205.         read_fds = master;
  206.         if (select(fdmax + 1, &read_fds, NULL, NULL, NULL) == -1) {
  207.             perror("Server-select() error");
  208.             exit(1);
  209.         }
  210.         printf("Server-select() is OK...\n");
  211.         /*szuka po deskryptorach czy cos do czytania*/
  212.         for (i = 0; i <= fdmax; i++) {
  213.             if (FD_ISSET(i, &read_fds)) {
  214.                 if (i == listener) {
  215.                     /* nowe polaczenia */
  216.                     addrlen = sizeof(clientaddr);
  217.                     if ((newfd = accept(listener, (struct sockaddr*)&clientaddr, &addrlen)) == -1) {
  218.                         perror("Server-accept()-listener error");
  219.                     }
  220.                     else {
  221.                         printf("Server-accept()-listener is OK...\n");
  222.                         FD_SET(newfd, &master); /* add to master set */
  223.                         list.insert(newfd);
  224.                         Client *temp = new Client(newfd, "Guest"+to_string(guest));
  225.                         Room ro(stoi(argv[1]), "Main");
  226.                         temp->rooms.push_back(ro);
  227.                         clients.push_back(temp);
  228.                         guest++;
  229.                         if (newfd > fdmax) fdmax = newfd;
  230.                         printf("%s: New connection from %s on socket %d\n", argv[0], inet_ntoa(clientaddr.sin_addr), newfd);
  231.                     }
  232.                 }
  233.                 else if (i == metadata) {
  234.                     /* nowe polaczenia do odczytu metadanych*/
  235.                     addrlen = sizeof(clientaddr);
  236.                     if ((newfd = accept(metadata, (struct sockaddr*)&clientaddr, &addrlen)) == -1) {
  237.                         perror("Server-accept()-metadata error");
  238.                     }
  239.                     else {
  240.                         printf("Server-accept()-metadata is OK...\n");
  241.                         meta.insert(newfd);
  242.                     }
  243.                     if (newfd > fdmax) fdmax = newfd;
  244.                     printf("%s: New connection from %s on socket %d\n", argv[0], inet_ntoa(clientaddr.sin_addr), newfd);
  245.                 }
  246.                 else
  247.                 {
  248.                     int iterator = 0;
  249.                     int unexpected_error = 0;
  250.                     int command;
  251.                     string message = "";
  252.                     char* buf = new char[1024];
  253.                     /* czytamy wiadomość */
  254.                     do {
  255.                         if ((nbytes = recv(i, buf, sizeof(buf), 0)) <= 0) {  //zamkniete lub error
  256.                             if (nbytes == 0)
  257.                                 printf("%s: socket %d hung up\n", argv[0], i); //zamkniete
  258.                             else
  259.                                 perror("recv() error(odbieranie)");
  260.                             close(i); //zamykamy i usuwamy z seta
  261.                             FD_CLR(i, &master);
  262.                             list.erase(i);
  263.                             unexpected_error = 1;
  264.                             break;
  265.                         }
  266.                         message.append(buf, 0, nbytes);
  267.                         iterator += nbytes;
  268.                     } while (message[iterator - 1] != '\n');
  269.                     if (unexpected_error == 1) continue; // jeśli błąd konczymy obslugę tego klienta w tej iteracji selecta
  270.  
  271.                     vector<string> msg_split = split(message, ':');
  272.                     /* aktualizujemy nazwę użytkownika, która była nieznana podczas accepta */
  273.                     for (Client *c : clients) {
  274.                         if (c->desc == i && c->Name.find("Guest") >= 0) {
  275.                             c->Name = msg_split[0];
  276.                             if (fork()==0) {
  277.                                 sendMetadata();
  278.                                 exit(0);
  279.                             }
  280.                         }
  281.                     }
  282.                     /* sprawdzamy czy wiadomość zawiera komendę */
  283.                     command = parseCommand(msg_split[1]);
  284.                     switch (command) {
  285.                     case 0: // join
  286.                         port++;
  287.                         vector<string> words_in_message = split(msg_split[1], ' ');
  288.                         if (words_in_message.size() < 2) {
  289.                             cout << "Nie podano nazwy pokoju!" << endl;
  290.                             break;
  291.                         }
  292.                         if (t < 0) {
  293.                             cout << "Nie mozna tworzyc pokoju!" << endl;
  294.                             break;
  295.                         }
  296.                         string room_name = words_in_message[1];
  297.                         room_name = room_name.substr(0,room_name.size()-2);
  298.                         if (fork() == 0) {
  299.                             execl("./select.o", room_name.c_str(), (char*)to_string(port).c_str(), nullptr);
  300.                             perror("RIP");
  301.                             exit(1);
  302.                         }
  303.                         else {
  304.                             /* dodaj pokój do pokoi klienta */
  305.                             Room ro(port, room_name);
  306.                             for (Client *c: clients) if (c->desc == i) c->rooms.push_back(ro);
  307.  
  308.                             if (fork()==0){
  309.                                 sendMetadata();
  310.                                 exit(0);
  311.                             }
  312.                             break;
  313.                         }
  314.                     }
  315.                     cout << "Zaczynam wysylac: " << message << endl;
  316.                     /* mamy dane, trzeba je rozeslac*/
  317.                     for (j = 0; j <= fdmax; j++) {
  318.                         if (FD_ISSET(j, &master) && list.find(j) != list.end()) {
  319.                             if (j != listener) sendMessage(j,message);
  320.                         } //if
  321.                     } //for
  322.                 } //else
  323.             } //if (inset)
  324.         } //for (descs)
  325.     } //for (;;)
  326.     return 1;
  327. } //main
  328.  
  329.