Advertisement
utroz

ECHO Server 0.11

Jan 1st, 2012
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.69 KB | None | 0 0
  1. /*
  2.  * Copyright (C) 2011 - Raphael S.Carvalho (a.k.a Utroz)
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify it
  5.  * under the terms of the GNU General Public License as published by the Free
  6.  * Software Foundation; either version 2 of the License, or (at your option)
  7.  * any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful, but WITHOUT
  10.  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11.  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  12.  * more details.  You should have received a copy of the GNU General Public
  13.  * License along with this program; if not, write to the Free Software
  14.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  15.  */
  16.  
  17. /* ECHO Server 0.11 - Developed by Utroz
  18.  * Features: The server might send a message
  19.  * for all connected clients.
  20.  * A simple server in the internet domain using TCP
  21.  * The port number is passed as an argument
  22.  */
  23.  
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <unistd.h>
  28.  
  29. #include <sys/shm.h>
  30. #include <sys/ipc.h>
  31. #include <sys/types.h>
  32. #include <sys/socket.h>
  33. #include <netinet/in.h>
  34.  
  35. #define BUFFER_SIZE 256
  36. #define SHM_FLG     IPC_CREAT | 0666         
  37.  
  38. typedef struct buffer {
  39.     char message[BUFFER_SIZE];
  40.     int semaphore, last_sockfd;
  41.     size_t size;
  42. } buffer_t;
  43.  
  44. typedef struct node {
  45.     int sockfd;
  46.     struct node *next, *previous;
  47. } node_t;
  48.  
  49. void error (const char *msg) { perror(msg); exit(EXIT_FAILURE); }
  50.  
  51. /* Insert a new socket connection into linked lists */
  52. void insert (node_t *head, int sockfd)
  53. {
  54.     node_t *new_node, *p;
  55.    
  56.     new_node = malloc(sizeof(node_t));
  57.     if (new_node == NULL)
  58.     error("memory can't be allocated");
  59.    
  60.     new_node->sockfd = sockfd;
  61.     new_node->next = NULL;
  62.    
  63.     for (p = head; p->next != NULL; p = p->next)
  64.     ;
  65.    
  66.     new_node->previous = p;
  67.     p->next = new_node;
  68. }
  69.  
  70. /* Try find a sockfd and remove it from the list */
  71. void delete (node_t *node, int sockfd)
  72. {
  73.     node_t *p, *tmp_prev, *tmp_next;
  74.     short find;
  75.  
  76.     find = 1; // 0 -> success
  77.    
  78.     for (p = node; (p->next != NULL) && find; ) {  
  79.     p = p->next;
  80.     if(p->sockfd == sockfd)
  81.         find = 0;
  82.     }
  83.    
  84.     if (p->next == NULL && find == 0) {
  85.     tmp_prev = p->previous;
  86.    
  87.     free(p);
  88.     tmp_prev->next = NULL;
  89.    
  90.     } else if (find == 0){
  91.     tmp_next = p->next;
  92.     tmp_prev = p->previous;
  93.    
  94.     free(p);
  95.     tmp_prev->next = tmp_next;
  96.     }
  97. }
  98.  
  99. void free_list (node_t *head)
  100. {
  101.     node_t *tmp, *p;
  102.     p = head;
  103.    
  104.     for (p = head; p->next != NULL; p = tmp) {
  105.     p = p->next;
  106.     tmp = p;
  107.    
  108.     free(p);
  109.     }
  110. }
  111.  
  112. void print_list (node_t *head)
  113. {
  114.     node_t *p;
  115.    
  116.     for (p = head; p->next != NULL; ) {
  117.     p = p->next;
  118.     fprintf(stdout, "PID: %d | SockFD: %d | Address: %x | Next: %x | Previous: %x\n",
  119.         getpid(), p->sockfd, p, p->next, p->previous);
  120.     }
  121. }
  122.  
  123. /* Send message to the clients. */
  124. void send_msg (buffer_t *shm_buffer, node_t *head)
  125. {
  126.     node_t *p;
  127.     int n;
  128.     const current_fd = shm_buffer->last_sockfd;
  129.    
  130.     while (current_fd == shm_buffer->last_sockfd){
  131.     if (shm_buffer->size > 0) {
  132.         shm_buffer->semaphore = 1;
  133.        
  134.         for (p = head; p->next != NULL; ) {
  135.         p = p->next;
  136.         n = write(p->sockfd, shm_buffer->message, shm_buffer->size);  
  137.        
  138.         if (n < 0)
  139.             fprintf(stderr, "ERROR writing to socket fd: %d.\n", p->sockfd);   
  140.         }
  141.        
  142.         memset(shm_buffer->message, 0, BUFFER_SIZE);   
  143.         shm_buffer->semaphore = 0;
  144.         shm_buffer->size = 0;
  145.     }
  146.     sleep(1);
  147.     }
  148.    
  149.     exit(EXIT_SUCCESS);
  150. }
  151.  
  152. /* New Socket Connection */
  153. void dostuff (int sockfd, buffer_t *shm_buffer)
  154. {
  155.     int n;
  156.     char buffer[BUFFER_SIZE];
  157.    
  158.     while (1) {
  159.     memset(buffer, 0, BUFFER_SIZE);
  160.     n = read(sockfd, buffer, BUFFER_SIZE - 1);
  161.    
  162.     if (n < 0);
  163.         //error("ERROR reading from socket");   // Problem is here.
  164.    
  165.     if (buffer[0] == 0)  {  
  166.         close(sockfd);
  167.         error("ERROR reading from buffer");
  168.     }
  169.    
  170.     fprintf(stdout, "Message received from SockFD %d: %s\n", sockfd, buffer);
  171.    
  172.     while (shm_buffer->semaphore) sleep(1);
  173.     strcpy(shm_buffer->message, buffer);
  174.     shm_buffer->size = n;
  175.     }    
  176.    
  177.     exit(EXIT_SUCCESS);
  178. }
  179.  
  180. int main (int argc, char *argv[])
  181. {
  182.     node_t *head;
  183.     pid_t pid;
  184.    
  185.     /* Shared Memory */
  186.     buffer_t *shm_buffer;
  187.     int shmid;
  188.     key_t key = getuid();
  189.    
  190.     /* Socket Data */
  191.     int sockfd, newsockfd, portno;
  192.     struct sockaddr_in serv_addr, cli_addr;
  193.     socklen_t clilen;
  194.    
  195.     if (argc < 2)
  196.     error("ERROR, no port provided");
  197.    
  198.     /* Allocate a dummy node */
  199.     head = malloc(sizeof(node_t));
  200.     if (head == NULL)
  201.     error("memory can't be allocated");
  202.     head->next = head->previous = NULL;
  203.    
  204.     /* Allocate a dummy buffer which will be the manager
  205.      * for the interprocess communication */
  206.     shmid = shmget(key, sizeof(buffer_t), SHM_FLG);
  207.     if (shmid < 0)
  208.     error("shmget");   
  209.    
  210.     shm_buffer = shmat(shmid, (void *)0, 0);
  211.     if (shm_buffer == (void *) -1)
  212.     error("shmat");        
  213.     shm_buffer->semaphore = 0;
  214.    
  215.     /* Initializes a new socket from TCP protocol */
  216.     sockfd = socket(AF_INET, SOCK_STREAM, 0);
  217.     if (sockfd < 0)
  218.     error("ERROR opening socket");    
  219.    
  220.     memset((char *) &serv_addr, 0, sizeof(serv_addr));
  221.     portno = atoi(argv[1]);
  222.    
  223.     serv_addr.sin_family = AF_INET;
  224.     serv_addr.sin_addr.s_addr = INADDR_ANY;
  225.     serv_addr.sin_port = htons(portno);
  226.    
  227.     if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
  228.     error("ERROR on binding");
  229.    
  230.     listen(sockfd,5);
  231.     clilen = sizeof(cli_addr); 
  232.    
  233.     /* Begin message */
  234.     fprintf(stdout, "SERVER ready (PID: %d): Waiting for new connections...\n\n", getpid());
  235.     while (1) {
  236.     newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
  237.     if (newsockfd < 0)
  238.         error("ERROR on accept");
  239.     else {
  240.         fprintf(stdout, "User x was connected!\n");
  241.         shm_buffer->last_sockfd = newsockfd;
  242.         insert(head, newsockfd);
  243.         //delete(head, 5);
  244.         print_list(head);
  245.        
  246.         pid = fork();
  247.         if (pid < 0) {
  248.         error("ERROR on fork");
  249.         } else if (pid == 0) {
  250.         send_msg (shm_buffer, head);
  251.         }    
  252.     }  
  253.    
  254.     pid = fork();
  255.     if (pid < 0) {
  256.         close(newsockfd);
  257.         error("ERROR on fork");
  258.     } else if (pid == 0) {
  259.         close(sockfd);
  260.         dostuff(newsockfd, shm_buffer);
  261.     }  
  262.     }
  263.    
  264.     if(shmdt(shm_buffer) < 0)
  265.     error("ERROR on detach");
  266.    
  267.     if(shmctl(shmid, IPC_RMID, NULL) < 0)
  268.     error("ERROR on remove a shm");
  269.    
  270.     free_list(head);
  271.     free(head);
  272.     close(newsockfd);
  273.     close(sockfd);
  274.    
  275.     return EXIT_SUCCESS;
  276. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement