Advertisement
AnonymousNamefag

server.c

Oct 10th, 2018
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.00 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <sys/stat.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <sys/ipc.h>
  7. #include <sys/shm.h>
  8. #include <sys/msg.h>
  9. #include <signal.h>
  10. #include <stdint.h>
  11. #include <proc/procps.h>
  12.  
  13. #include "chat.h"
  14.  
  15. struct user {
  16.     uid_t uid;
  17.     char nick[10];
  18.     struct user *next;
  19. };
  20.  
  21. struct user *head;
  22. struct user *tail;
  23.  
  24. int main( int argc, char **argv ){
  25.     deamonize();
  26.     initialize_user_list();
  27.     create_shared_memory();
  28.     create_message_queue();
  29.     poll();
  30.     return 0;
  31. }
  32.  
  33. void deamonize(){
  34.     pid_t pid = fork();
  35.     if( pid > 0 ) /* parent */
  36.         exit( 0 );
  37.     if( pid < 0 ){ /* fork error */
  38.         fprintf( stderr, "Fork error\n" );
  39.         exit( 1 );
  40.     }
  41.     /* child */
  42.     setsid();
  43.     umask( 0 );
  44.     chdir( "/" );
  45. }
  46.  
  47. void initialize_user_list(){
  48.     head = (struct user *) malloc( sizeof( struct user ) );
  49.     tail = head; /* List is accessed from tail */
  50. }
  51.  
  52. void create_shared_memory(){
  53.     key_t key = ftok( "/dev/zero", 64 );
  54.     shm_id = shmget( key, SHM_SIZE, 0 );
  55.     shm_addr = shmat( shm_id, 0, 0 );
  56.     cur_addr = shm_addr;
  57. }
  58.  
  59. void create_message_queue(){
  60.     key_t key = ftok( "/dev/zero", 65 );
  61.     msg_id = msgget( key, 0 );
  62. }
  63.  
  64. void poll(){
  65.     struct message *msg;
  66.     for(;;){
  67.         msgrcv( msg_id, msg, 4096, 0, IPC_NOWAIT );
  68.     }
  69.     server_process( msg );
  70. }
  71.  
  72. void server_process( struct message *msg ){
  73.     char *opcode = strtok( msg->mtext, " \t\n" );
  74.     if( !strcmp( opcode, "JOIN" ) ){
  75.         adduser( msg->mtype );
  76.     }
  77.     if( !strcmp( opcode, "BYE" ) ){
  78.         deluser( msg->mtype );
  79.     }
  80.     else  if( !strcmp( opcode, "SAY" ) ){
  81.         say( msg );
  82.     }
  83. }
  84.  
  85. void broadcast( char *str ){
  86.     struct message *msg;
  87.     strncpy( msg->mtext, str, strlen( str ) );
  88.     struct user *rider = tail;
  89.     while( rider = rider->next ){
  90.         msg->mtype = SERVER_MESSAGE_TYPE + rider->uid;
  91.         msgsnd( msg_id, msg, 4096, 0 );
  92.         kill( rider->uid, SIGPOLL );
  93.     }
  94. }
  95.  
  96. void echo( char *str, long uid ){
  97.     struct message *echomessage;
  98.     echomessage->mtext = strcat( "WRITE ", str );
  99.     echomessage->mtype = SERVER_MESSAGE_TYPE + uid;
  100.     msgsnd( msg_id, echomessage, 4096, 0 );
  101. }
  102.  
  103. void adduser( long uid ){
  104.     struct message *input;
  105.     echo( "Choose a handle (9 characters or fewer): ", uid );
  106.     msgrcv( msg_id, input, 4096, uid, 0 );
  107.     struct user *new = (struct user *) malloc( sizeof( struct user ) );
  108.     strncpy( new->nick, input->mtext, 9 );
  109.     new->nick[10] = '\0';
  110.     echo( "Welcome to the server!\n" );
  111.     /*
  112.      * Note: The new user MUST be added to the user list
  113.      * AFTER all this information is processed, otherwise
  114.      * these messages may be mixed up with the broadcast
  115.      * messages addressed to that process.  This will
  116.      * not happen in the program's present state, but
  117.      * it will become an issue should the server ever
  118.      * incorporate multithreading.
  119.      */
  120.     head->next = new;
  121.     head = new;
  122. }
  123.  
  124. void deluser( long uid ){
  125.     struct user *rider = tail;
  126.     while( rider->next->uid != uid ) rider = rider->next;
  127.     struct user *temp = rider->next;
  128.     rider->next = rider->next->next;
  129.     free( temp );
  130.     echo( "See ya!\n", uid );
  131. }
  132.  
  133. void say( struct message *msg ){
  134.     write_memory( msg );
  135.     broadcast( "READ\n" );
  136.     sprintf( msg->mtext, "UPDATE_PTR %d\n", cur_addr - shm_addr );
  137.     broadcast( msg->mtext );
  138. }
  139.  
  140. void write_memory( struct message *msg ){
  141.     int len;
  142.     struct user *rider = tail;
  143.     while( rider != head && rider->uid != msg->mtype )
  144.         rider = rider->next;
  145.     if( rider->uid != msg->mtype ) goto error;
  146.     len = strlen( rider->nick );
  147.     memwrite( rider->nick );
  148.     memwrite( ": " );
  149.     memwrite( msg->mtext );
  150. error:
  151.     echo( "Internal server error.  Operation aborted.\n", msg->mtype );
  152. }
  153.  
  154. void memwrite( char *str ){
  155.     /* Next line calculates distance of cur_addr from end of region: */
  156.     intmax_t d = SHM_SIZE - cur_addr + shm_addr;
  157.     int len = strlen( str );
  158.     if( likely( len < d ) ){
  159.         strncpy( cur_addr, str, len );
  160.         cur_addr += len;
  161.     }
  162.     else if( unlikely( len == d ) ){
  163.         strncpy( cur_addr, str, len );
  164.         cur_addr = shm_addr;
  165.     }
  166.     else{
  167.         strncpy( cur_addr, str, d );
  168.         cur_addr = shm_addr;
  169.         strncpy( cur_addr, str+d, len-d );
  170.     }
  171. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement