Facebook
From Insensitive Camel, 6 Years ago, written in C++.
Embed
Download Paste or View Raw
Hits: 263
  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.     Room(int d, string n)
  21.     {
  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.     Client(int d, string n)
  33.     {
  34.         desc = d;
  35.         Name = n;
  36.     }
  37. };
  38.  
  39.  
  40. string join = "/join";
  41. set<string> rooms;
  42. vector<Client*> clients;
  43. set<int> meta;
  44. set<int> list;
  45. int metadata = -2;
  46. int port;
  47. int t; // Czy main room
  48. int i, j;
  49. int fdmax = -1; //najwiekszy deskryptor
  50. int listener; //nasluchujacy dekspytor
  51. int newfd; //najnowszy zaakceptowany
  52. int nbytes;
  53. int guest = 0;
  54. int yes = 1;
  55. fd_set master;
  56. fd_set read_fds;
  57. fd_set write_fds;
  58. struct sockaddr_in serveraddr;
  59. struct sockaddr_in serveraddr_meta;
  60. struct sockaddr_in clientaddr;
  61. socklen_t addrlen;
  62. const string delimeterMetaDate = "@@DONE\n";
  63. vector<string> msg_split;
  64. string tt;
  65.  
  66. int iterator = 0;
  67. int unexpected_error = 0;
  68. string message;
  69. char bufor[256];
  70. size_t fnd;
  71. int size;
  72.  
  73. void createSocket()
  74. {
  75.     if ((listener = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  76.     {
  77.         perror("Server-socket()-listener error");
  78.         exit(1);
  79.     }
  80.     printf("Server-socket()-listener is OK...\n");
  81. }
  82.  
  83. void createSetSockopt()
  84. {
  85.   if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
  86.     {
  87.         perror("Server-setsockopt()-listener error");
  88.         exit(1);
  89.     }
  90.     printf("Server-setsockopt()-listener is OK...\n");
  91. }
  92.  
  93. void SetListener()
  94. {
  95.     serveraddr.sin_family = AF_INET;
  96.     serveraddr.sin_addr.s_addr = INADDR_ANY;
  97.     serveraddr.sin_port = htons(port);
  98.  
  99.     if (bind(listener, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) == -1)
  100.     {
  101.         perror("Server-bind()-listener error");
  102.         exit(1);
  103.     }
  104.     printf("Server-bind()-listener is OK...\n");
  105.  
  106.     if (listen(listener, 5) == -1)   //kolejka
  107.     {
  108.         perror("Server-listen()-listener error");
  109.         exit(1);
  110.     }
  111.     printf("Server-listen()-listener is OK...\n");
  112. }
  113.  
  114. void CreateMetaData()
  115. {
  116.     if ((metadata = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  117.     {
  118.         perror("Server-socket()-metadata error");
  119.         exit(1);
  120.     }
  121.     printf("Server-socket()-metadata is OK...\n");
  122.     if (setsockopt(metadata, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
  123.     {
  124.         perror("Server-setsockopt()-metadata error");
  125.         exit(1);
  126.     }
  127.     printf("Server-setsockopt()-metadata is OK...\n");
  128.  
  129.     serveraddr_meta.sin_family = AF_INET;
  130.     serveraddr_meta.sin_addr.s_addr = INADDR_ANY;
  131.     serveraddr_meta.sin_port = htons(port - 1);
  132.  
  133.     if (bind(metadata, (struct sockaddr*)&serveraddr_meta, sizeof(serveraddr_meta)) == -1)
  134.     {
  135.         perror("Server-bind()-meta error");
  136.         exit(1);
  137.     }
  138.     printf("Server-bind()-meta is OK...\n");
  139.     if (listen(metadata, 5) == -1)   //kolejka
  140.     {
  141.         perror("Server-listen()-metadata error");
  142.         exit(1);
  143.     }
  144.     printf("Server-listen()-metadata is OK...\n");
  145. }
  146.  
  147. bool isMessageAddRoom(string message) {
  148.     return message.find(join) != std::string::npos;
  149. }
  150.  
  151. void sendMessage(int m,string avamys) {
  152.     int sent = 0;
  153.     unsigned int got = 0;
  154.     do {
  155.         sent = send(m, avamys.c_str() + got, avamys.size() - got, MSG_CONFIRM);
  156.         got += sent;
  157.     } while (got < avamys.size());
  158. }
  159.  
  160. void sendMetadata(){
  161.     for (int m: meta){
  162.         if (m != metadata){
  163.             for (Client *c : clients){
  164.                 for (Room r : c->rooms){
  165.                     string row = to_string(r.desc) + ":" + r.name + ":" + c->Name;
  166.                     row.append("\n");
  167.                     sendMessage(m,row);
  168.                 }
  169.             }
  170.             sendMessage(m,delimeterMetaDate);
  171.         }
  172.     }
  173. }
  174.  
  175. void split(const string& s, char delim, vector<string>& elems) {
  176.     stringstream ss;
  177.     ss.str(s);
  178.     string item;
  179.     while (getline(ss, item, delim)) {
  180.         elems.push_back(item);
  181.     }
  182. }
  183.  
  184. vector<string> split(const string& s, char delim) {
  185.     vector<string> elems;
  186.     split(s, delim, elems);
  187.     return elems;
  188. }
  189.  
  190. void CreateRoom(string text)
  191. {
  192.  
  193.         port++;
  194.         vector<string> words_in_message = split(text, ' ');
  195.         cout<<"nazwa pokoju" << words_in_message[1] << "|"<<endl;
  196.         if (words_in_message.size() < 2) {
  197.             cout << "Nie podano nazwy pokoju!" << endl;
  198.             return;
  199.         }
  200.         if (t < 0) {
  201.             cout << "Nie mozna tworzyc pokoju!" << endl;
  202.             return;
  203.         }
  204.         string room_name = words_in_message[1];
  205.         if (fork() == 0) {
  206.             execl("./select", room_name.c_str(), (char*)to_string(port).c_str(), nullptr);
  207.             perror("RIP");
  208.             exit(1);
  209.         }
  210.         else {
  211.             /* dodaj pokój do pokoi klienta */
  212.             Room ro(port, room_name);
  213.             for (Client *c: clients) if (c->desc == i) c->rooms.push_back(ro);
  214.             if (fork()==0){
  215.                 sendMetadata();
  216.                 exit(0);
  217.             }
  218.             return;
  219.         }
  220.  
  221. }
  222.  
  223. void ReadMessage()
  224. {
  225.     do{
  226.         if((size = read(i, &bufor, 256)) <=0){
  227.             if(size == 0){// Jeśli 0 to klient się rozłączył
  228.                  printf("%s: socket %d hung up\n", tt.c_str(), i); //zamkniete
  229.             }
  230.             else{// Jeśli 0 to klient się rozłączył
  231.                   perror("recv() error(odbieranie)");
  232.             }
  233.             close(i); //zamykamy i usuwamy z seta
  234.             FD_CLR(i, &master);
  235.                 list.erase(i);
  236.             unexpected_error = 1;
  237.             break;
  238.         }
  239.     //Jeśli znaleziono znak końca wiadomości to break i koniec czytania wiadomości
  240.         string wczytane(bufor);
  241.         fnd = wczytane.find_first_of("^");//fnd reprezentuje pozycję znaku w stringu
  242.         if(fnd != string::npos){// Jeśli nie znajdzie znaku w stringu przyjmuje wartość nops czyli wiadmość się nie skończyła
  243.             if (fnd == 0)
  244.                 break;
  245.             wczytane = wczytane.substr(0,fnd);
  246.             message.append(wczytane);
  247.             break;
  248.         }
  249.         message.append(wczytane);
  250.     }while(fnd == string::npos);// Czytaj dopóki nie wytąpi znak końca
  251. }
  252.  
  253. void GetMessage()
  254. {
  255.  
  256.     cout<< message<<endl;
  257.    msg_split = split(message, ':');
  258.    /* aktualizujemy nazwę użytkownika, która była nieznana podczas accepta */
  259.    cout<< "0-" << msg_split[0]<<endl;
  260.       cout<< "1-"<<msg_split[1]<<endl;
  261.    for (Client *c : clients) {
  262.        if (c->desc == i && c->Name.find("Guest") >= 0) {
  263.            c->Name = msg_split[0];
  264.            if (fork()==0) {
  265.                sendMetadata();
  266.                exit(0);
  267.            }
  268.        }
  269.    }
  270. }
  271.  
  272. void NewConnect()
  273. {
  274.     addrlen = sizeof(clientaddr);
  275.     if ((newfd = accept(listener, (struct sockaddr*)&clientaddr, &addrlen)) == -1)
  276.     {
  277.         perror("Server-accept()-listener error");
  278.     }
  279.     else
  280.     {
  281.         printf("Server-accept()-listener is OK...\n");
  282.         FD_SET(newfd, &master); /* add to master set */
  283.         list.insert(newfd);
  284.         Client *temp = new Client(newfd, "Guest"+to_string(guest));
  285.         Room ro(port, "Main");
  286.         temp->rooms.push_back(ro);
  287.         clients.push_back(temp);
  288.         guest++;
  289.         if (newfd > fdmax) fdmax = newfd;
  290.         printf("%s: New connection from %s on socket %d\n", tt.c_str() , inet_ntoa(clientaddr.sin_addr), newfd);
  291.     }
  292. }
  293.  
  294. void NewConnectMetaData()
  295. {
  296.     addrlen = sizeof(clientaddr);
  297.     if ((newfd = accept(metadata, (struct sockaddr*)&clientaddr, &addrlen)) == -1)
  298.     {
  299.         perror("Server-accept()-metadata error");
  300.     }
  301.     else
  302.     {
  303.         printf("Server-accept()-metadata is OK...\n");
  304.         meta.insert(newfd);
  305.     }
  306.     if (newfd > fdmax) fdmax = newfd;
  307.     printf("%s: New connection from %s on socket %d\n", tt.c_str(), inet_ntoa(clientaddr.sin_addr), newfd);
  308. }
  309.  
  310. int main(int argc, char* argv[]) {
  311.  
  312.     if (argc < 2) {
  313.         cout << "Nie podano portu!" << endl;
  314.         return -1;
  315.     }
  316.     tt = argv[0];
  317.  
  318.     port = stoi(argv[1]);
  319.  
  320.     rooms.insert(tt);
  321.     t  = tt.find("select");
  322.  
  323.     FD_ZERO(&master);
  324.     FD_ZERO(&read_fds);
  325.  
  326.     createSocket();
  327.  
  328.     createSetSockopt();
  329.  
  330.     //set server addr
  331.     SetListener();
  332.  
  333.     ///////////METADATA//////////////////
  334.     if (t >= 0)   //czy Main room?
  335.     {
  336.         CreateMetaData();
  337.     }
  338.  
  339.     /* listener do mastera */
  340.     FD_SET(listener, &master);
  341.     FD_SET(metadata, &master);
  342.     if (listener > fdmax) fdmax = listener;
  343.     if (metadata > fdmax) fdmax = metadata;
  344.     meta.insert(metadata);
  345.     list.insert(listener);
  346.     for (;;){
  347.         read_fds = master;
  348.         if (select(fdmax + 1, &read_fds, NULL, NULL, NULL) == -1) {
  349.             perror("Server-select() error");
  350.             exit(1);
  351.         }
  352.         printf("Server-select() is OK...\n");
  353.         /*szuka po deskryptorach czy cos do czytania*/
  354.         for (i = 0; i <= fdmax; i++) {
  355.             if (FD_ISSET(i, &read_fds)) {
  356.                 if (i == listener) {
  357.                     NewConnect();
  358.                 }
  359.                 else if (i == metadata) {
  360.                     NewConnectMetaData();
  361.                 }
  362.                 else
  363.                 {
  364.                     message = "";
  365.                     //czytanie
  366.  
  367.                     ReadMessage();
  368.                     //update
  369.                     GetMessage();
  370.  
  371.                     if(isMessageAddRoom(msg_split[1]))
  372.                     {
  373.  
  374.                         CreateRoom(msg_split[1]);
  375.                     }
  376.  
  377.                     cout << "Send message: " << message << endl;
  378.                     /*wysyłanie danych*/
  379.                     for (j = 0; j <= fdmax; j++) {
  380.                         if (FD_ISSET(j, &master) && list.find(j) != list.end()) {
  381.                             if (j != listener) sendMessage(j,message);
  382.                         } //if
  383.                     } //for
  384.                 } //else
  385.             } //if (inset)
  386.         } //for (descs)
  387.     } //for (;;)
  388.     return 1;
  389. } //main
  390.