Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <unistd.h>
- #include <sys/stat.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/ipc.h>
- #include <sys/shm.h>
- #include <sys/msg.h>
- #include <signal.h>
- #include <stdint.h>
- #include <proc/procps.h>
- #include "chat.h"
- struct user {
- uid_t uid;
- char nick[10];
- struct user *next;
- };
- struct user *head;
- struct user *tail;
- int main( int argc, char **argv ){
- deamonize();
- initialize_user_list();
- create_shared_memory();
- create_message_queue();
- poll();
- return 0;
- }
- void deamonize(){
- pid_t pid = fork();
- if( pid > 0 ) /* parent */
- exit( 0 );
- if( pid < 0 ){ /* fork error */
- fprintf( stderr, "Fork error\n" );
- exit( 1 );
- }
- /* child */
- setsid();
- umask( 0 );
- chdir( "/" );
- }
- void initialize_user_list(){
- head = (struct user *) malloc( sizeof( struct user ) );
- tail = head; /* List is accessed from tail */
- }
- void create_shared_memory(){
- key_t key = ftok( "/dev/zero", 64 );
- shm_id = shmget( key, SHM_SIZE, 0 );
- shm_addr = shmat( shm_id, 0, 0 );
- cur_addr = shm_addr;
- }
- void create_message_queue(){
- key_t key = ftok( "/dev/zero", 65 );
- msg_id = msgget( key, 0 );
- }
- void poll(){
- struct message *msg;
- for(;;){
- msgrcv( msg_id, msg, 4096, 0, IPC_NOWAIT );
- }
- server_process( msg );
- }
- void server_process( struct message *msg ){
- char *opcode = strtok( msg->mtext, " \t\n" );
- if( !strcmp( opcode, "JOIN" ) ){
- adduser( msg->mtype );
- }
- if( !strcmp( opcode, "BYE" ) ){
- deluser( msg->mtype );
- }
- else if( !strcmp( opcode, "SAY" ) ){
- say( msg );
- }
- }
- void broadcast( char *str ){
- struct message *msg;
- strncpy( msg->mtext, str, strlen( str ) );
- struct user *rider = tail;
- while( rider = rider->next ){
- msg->mtype = SERVER_MESSAGE_TYPE + rider->uid;
- msgsnd( msg_id, msg, 4096, 0 );
- kill( rider->uid, SIGPOLL );
- }
- }
- void echo( char *str, long uid ){
- struct message *echomessage;
- echomessage->mtext = strcat( "WRITE ", str );
- echomessage->mtype = SERVER_MESSAGE_TYPE + uid;
- msgsnd( msg_id, echomessage, 4096, 0 );
- }
- void adduser( long uid ){
- struct message *input;
- echo( "Choose a handle (9 characters or fewer): ", uid );
- msgrcv( msg_id, input, 4096, uid, 0 );
- struct user *new = (struct user *) malloc( sizeof( struct user ) );
- strncpy( new->nick, input->mtext, 9 );
- new->nick[10] = '\0';
- echo( "Welcome to the server!\n" );
- /*
- * Note: The new user MUST be added to the user list
- * AFTER all this information is processed, otherwise
- * these messages may be mixed up with the broadcast
- * messages addressed to that process. This will
- * not happen in the program's present state, but
- * it will become an issue should the server ever
- * incorporate multithreading.
- */
- head->next = new;
- head = new;
- }
- void deluser( long uid ){
- struct user *rider = tail;
- while( rider->next->uid != uid ) rider = rider->next;
- struct user *temp = rider->next;
- rider->next = rider->next->next;
- free( temp );
- echo( "See ya!\n", uid );
- }
- void say( struct message *msg ){
- write_memory( msg );
- broadcast( "READ\n" );
- sprintf( msg->mtext, "UPDATE_PTR %d\n", cur_addr - shm_addr );
- broadcast( msg->mtext );
- }
- void write_memory( struct message *msg ){
- int len;
- struct user *rider = tail;
- while( rider != head && rider->uid != msg->mtype )
- rider = rider->next;
- if( rider->uid != msg->mtype ) goto error;
- len = strlen( rider->nick );
- memwrite( rider->nick );
- memwrite( ": " );
- memwrite( msg->mtext );
- error:
- echo( "Internal server error. Operation aborted.\n", msg->mtype );
- }
- void memwrite( char *str ){
- /* Next line calculates distance of cur_addr from end of region: */
- intmax_t d = SHM_SIZE - cur_addr + shm_addr;
- int len = strlen( str );
- if( likely( len < d ) ){
- strncpy( cur_addr, str, len );
- cur_addr += len;
- }
- else if( unlikely( len == d ) ){
- strncpy( cur_addr, str, len );
- cur_addr = shm_addr;
- }
- else{
- strncpy( cur_addr, str, d );
- cur_addr = shm_addr;
- strncpy( cur_addr, str+d, len-d );
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement