Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Copyright (C) 2011 - Raphael S.Carvalho (a.k.a Utroz)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details. You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
- */
- /* ECHO Server 0.11 - Developed by Utroz
- * Features: The server might send a message
- * for all connected clients.
- * A simple server in the internet domain using TCP
- * The port number is passed as an argument
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/shm.h>
- #include <sys/ipc.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #define BUFFER_SIZE 256
- #define SHM_FLG IPC_CREAT | 0666
- typedef struct buffer {
- char message[BUFFER_SIZE];
- int semaphore, last_sockfd;
- size_t size;
- } buffer_t;
- typedef struct node {
- int sockfd;
- struct node *next, *previous;
- } node_t;
- void error (const char *msg) { perror(msg); exit(EXIT_FAILURE); }
- /* Insert a new socket connection into linked lists */
- void insert (node_t *head, int sockfd)
- {
- node_t *new_node, *p;
- new_node = malloc(sizeof(node_t));
- if (new_node == NULL)
- error("memory can't be allocated");
- new_node->sockfd = sockfd;
- new_node->next = NULL;
- for (p = head; p->next != NULL; p = p->next)
- ;
- new_node->previous = p;
- p->next = new_node;
- }
- /* Try find a sockfd and remove it from the list */
- void delete (node_t *node, int sockfd)
- {
- node_t *p, *tmp_prev, *tmp_next;
- short find;
- find = 1; // 0 -> success
- for (p = node; (p->next != NULL) && find; ) {
- p = p->next;
- if(p->sockfd == sockfd)
- find = 0;
- }
- if (p->next == NULL && find == 0) {
- tmp_prev = p->previous;
- free(p);
- tmp_prev->next = NULL;
- } else if (find == 0){
- tmp_next = p->next;
- tmp_prev = p->previous;
- free(p);
- tmp_prev->next = tmp_next;
- }
- }
- void free_list (node_t *head)
- {
- node_t *tmp, *p;
- p = head;
- for (p = head; p->next != NULL; p = tmp) {
- p = p->next;
- tmp = p;
- free(p);
- }
- }
- void print_list (node_t *head)
- {
- node_t *p;
- for (p = head; p->next != NULL; ) {
- p = p->next;
- fprintf(stdout, "PID: %d | SockFD: %d | Address: %x | Next: %x | Previous: %x\n",
- getpid(), p->sockfd, p, p->next, p->previous);
- }
- }
- /* Send message to the clients. */
- void send_msg (buffer_t *shm_buffer, node_t *head)
- {
- node_t *p;
- int n;
- const current_fd = shm_buffer->last_sockfd;
- while (current_fd == shm_buffer->last_sockfd){
- if (shm_buffer->size > 0) {
- shm_buffer->semaphore = 1;
- for (p = head; p->next != NULL; ) {
- p = p->next;
- n = write(p->sockfd, shm_buffer->message, shm_buffer->size);
- if (n < 0)
- fprintf(stderr, "ERROR writing to socket fd: %d.\n", p->sockfd);
- }
- memset(shm_buffer->message, 0, BUFFER_SIZE);
- shm_buffer->semaphore = 0;
- shm_buffer->size = 0;
- }
- sleep(1);
- }
- exit(EXIT_SUCCESS);
- }
- /* New Socket Connection */
- void dostuff (int sockfd, buffer_t *shm_buffer)
- {
- int n;
- char buffer[BUFFER_SIZE];
- while (1) {
- memset(buffer, 0, BUFFER_SIZE);
- n = read(sockfd, buffer, BUFFER_SIZE - 1);
- if (n < 0);
- //error("ERROR reading from socket"); // Problem is here.
- if (buffer[0] == 0) {
- close(sockfd);
- error("ERROR reading from buffer");
- }
- fprintf(stdout, "Message received from SockFD %d: %s\n", sockfd, buffer);
- while (shm_buffer->semaphore) sleep(1);
- strcpy(shm_buffer->message, buffer);
- shm_buffer->size = n;
- }
- exit(EXIT_SUCCESS);
- }
- int main (int argc, char *argv[])
- {
- node_t *head;
- pid_t pid;
- /* Shared Memory */
- buffer_t *shm_buffer;
- int shmid;
- key_t key = getuid();
- /* Socket Data */
- int sockfd, newsockfd, portno;
- struct sockaddr_in serv_addr, cli_addr;
- socklen_t clilen;
- if (argc < 2)
- error("ERROR, no port provided");
- /* Allocate a dummy node */
- head = malloc(sizeof(node_t));
- if (head == NULL)
- error("memory can't be allocated");
- head->next = head->previous = NULL;
- /* Allocate a dummy buffer which will be the manager
- * for the interprocess communication */
- shmid = shmget(key, sizeof(buffer_t), SHM_FLG);
- if (shmid < 0)
- error("shmget");
- shm_buffer = shmat(shmid, (void *)0, 0);
- if (shm_buffer == (void *) -1)
- error("shmat");
- shm_buffer->semaphore = 0;
- /* Initializes a new socket from TCP protocol */
- sockfd = socket(AF_INET, SOCK_STREAM, 0);
- if (sockfd < 0)
- error("ERROR opening socket");
- memset((char *) &serv_addr, 0, sizeof(serv_addr));
- portno = atoi(argv[1]);
- serv_addr.sin_family = AF_INET;
- serv_addr.sin_addr.s_addr = INADDR_ANY;
- serv_addr.sin_port = htons(portno);
- if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
- error("ERROR on binding");
- listen(sockfd,5);
- clilen = sizeof(cli_addr);
- /* Begin message */
- fprintf(stdout, "SERVER ready (PID: %d): Waiting for new connections...\n\n", getpid());
- while (1) {
- newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
- if (newsockfd < 0)
- error("ERROR on accept");
- else {
- fprintf(stdout, "User x was connected!\n");
- shm_buffer->last_sockfd = newsockfd;
- insert(head, newsockfd);
- //delete(head, 5);
- print_list(head);
- pid = fork();
- if (pid < 0) {
- error("ERROR on fork");
- } else if (pid == 0) {
- send_msg (shm_buffer, head);
- }
- }
- pid = fork();
- if (pid < 0) {
- close(newsockfd);
- error("ERROR on fork");
- } else if (pid == 0) {
- close(sockfd);
- dostuff(newsockfd, shm_buffer);
- }
- }
- if(shmdt(shm_buffer) < 0)
- error("ERROR on detach");
- if(shmctl(shmid, IPC_RMID, NULL) < 0)
- error("ERROR on remove a shm");
- free_list(head);
- free(head);
- close(newsockfd);
- close(sockfd);
- return EXIT_SUCCESS;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement