/* S1.C // Server */ #include "mysocket.h" int ns; int NS; int SD; int Pid; struct FQ { int sd; int ns; char fName[ 32 ]; struct FQ *Next; }; struct FQ *FileQ; struct FQ *fqptr; struct FQ *fqtmp; #define MSGQMAX 31 struct MyMessage MsgQ[ MSGQMAX+1 ]; int mqhead; int mqtail; struct MyMessage MSG_IN; struct MyMessage MSG_OUT; struct sockaddr sockname; int MSize; /*** FUNCTIONS () *********************************/ int ShutDown() { close( SD ); unlink( "sb0000" ); /* CLOSE AND UNLINK ANY OPEN CHANNEL FILES */ while( FileQ ) { strcpy( MSG_OUT.Text, "-" ); strcat( MSG_OUT.Text, " ShutDown Channel " ); strcat( MSG_OUT.Text, FileQ->fName ); MSG_OUT.Msg1 = IDM_SHUTDOWN; MSG_OUT.Msg2 = IDM_CLOSE; write( FileQ->ns, &MSG_OUT, MSize ); close( FileQ->sd ); unlink( FileQ->fName ); fqptr = FileQ; FileQ = FileQ->Next; free( fqptr ); } printf("\r\t SERVER SHUTDOWN ! (v.1a) Pid = %d \n\n", Pid ); exit( 0 ); } /* ShutDown() */ void SpoolMsg() { /* CIRCLUAR ARRAY OF MYMESSAGE TYPE */ memcpy( &MsgQ[ mqtail ], &MSG_IN, MSize ); mqtail++; /* INCRMENT THE TAIL POINTER, CHECK IF ITS OVER THE MAX */ if( mqtail > MSGQMAX ) mqtail = 0; } /* SpoolMsg() */ void ProcessMsgQ() { int found; /* IF THERE ARE NEW MESSAGES TO PROCESS */ if( mqhead != mqtail ) { switch( MsgQ[ mqhead ].Msg1 ) { case IDM_OPEN: /* OPEN A CHANNEL FOR COMMUCATING */ fqptr = FileQ; found = 0; /* FIND THE CORRECT CHANNEL FILE, IF IT EXIST */ while( fqptr && !found ) { if( strcmp(fqptr->fName, MsgQ[ mqhead ].fName) == 0 ) found = 1; else fqptr = fqptr->Next; } if( !found ) { /* IF NOT FOUND IN QUEUE CREATE NEW NODE FOR LIST */ if( ( fqtmp = (struct FQ *) malloc( sizeof(struct FQ))) == NULL ) { perror( "\n Malloc Error FQ OPEN ! \n " ); exit( 98 ); } strcpy( fqtmp->fName, MsgQ[ mqhead ].fName ); fqtmp->Next = (struct FQ *) NULL; /* IF EMPTY FILE QUEUE */ if( FileQ == (struct FQ *) NULL ) { FileQ = fqtmp; fqptr = FileQ; } else { /* FIND THE CORRECT CHANNEL */ fqptr = FileQ; while( fqptr->Next ) fqptr = fqptr->Next; fqptr->Next = fqtmp; fqptr = fqptr->Next; } } /* IF CHANNEL IS ALREADY IN FILE QUEUE */ if( found ) { strcpy( MSG_OUT.Text, "+ " ); MSG_OUT.Msg2 = FOUND; } else { strcpy( MSG_OUT.Text, "- " ); MSG_OUT.Msg2 = NOTFOUND; fqptr->sd=socket( AF_UNIX,SOCK_STREAM, 0 ); sockname.sa_family = AF_UNIX; strcpy( sockname.sa_data, fqptr->fName ); /* SET UP SOCKET AS A CHANNEL */ if( bind( fqptr->sd, &sockname, SIZEOFSOCKNAME ) == -1 ) { perror( "\n Binding Error, Server OPEN ! \n " ); exit( 89 ); } listen( fqptr->sd, 1 ); /* NON_BLOCK ON CHANNEL FILE */ fcntl( fqptr->sd, F_SETFL, O_NONBLOCK ); strcpy( MSG_OUT.fName, fqptr->fName ); } strcat( MSG_OUT.Text, "OK to Transmit on channel " ); strcat( MSG_OUT.Text, fqptr->fName ); MSG_OUT.Msg1 = IDM_OK; write( NS, &MSG_OUT, MSize ); close( NS ); break; case IDM_CLOSE: /* CLOSE A CHANNEL IN THE FILE QUEUE */ strcpy( MSG_OUT.Text, "Closed Channel" ); strcat( MSG_OUT.Text, fqptr->fName ); MSG_OUT.Msg1 = IDM_OK; MSG_OUT.Msg2 = IDM_CLOSE; fqptr = FileQ; /* IF THE CHANNEL IS THE HEAD OF THE QUEUE */ if( strcmp( MSG_IN.fName, fqptr->fName ) == 0 ) { write( fqptr->ns, &MSG_OUT, MSize ); FileQ = FileQ->Next; close( fqptr->sd ); unlink( fqptr->fName ); free( fqptr ); } else { /* ELSE FIND AND REMOVE THE CHANNEL FROM THE FILE QUEUE */ while( strcmp( fqptr->Next->fName, MsgQ[ mqhead ].fName ) != 0 ) fqptr = fqptr->Next; write( fqptr->ns, &MSG_OUT, MSize ); fqtmp = fqptr->Next; fqptr = fqtmp->Next; close( fqtmp->sd ); unlink( fqtmp->fName ); free( fqtmp ); } break; case IDM_INFO: /* CLIENT REQUEST FOR SHARED DATA */ MSG_OUT.Msg1 = IDM_INFO; MSG_OUT.Msg2 = IDM_OK; strcpy( MSG_OUT.Text, "Data: Information" ); fqptr = FileQ; while( strcmp( fqptr->fName, MsgQ[ mqhead ].fName ) != 0 ) fqptr = fqptr->Next; write( fqptr->ns, &MSG_OUT, MSize ); break; case IDM_BUY: /* BUY SOMETHING FROM SHARED DATA */ switch( MSG_IN.Msg2 ) { case BEER: if( ! MSG_OUT.Beers ) { MSG_OUT.Msg1 = IDM_NOSALE; MSG_OUT.Msg2 = ERR_SOLDOUT; strcpy( MSG_OUT.Text, "SOLD OUT OF BEER !" ); } else if( MSG_IN.Money >= MSG_OUT.CostBeer ) { MSG_OUT.Msg1 = IDM_SALE; MSG_OUT.Msg2 = IDM_OK; strcpy( MSG_OUT.Text, "YOU BOUGHT A BEER !" ); MSG_OUT.Money = MSG_IN.Money - MSG_OUT.CostBeer; MSG_OUT.Beers--; } else { MSG_OUT.Msg1 = IDM_NOSALE; MSG_OUT.Msg2 = ERR_LOWMONEY; strcpy( MSG_OUT.Text, "YOU DO NOT HAVE ENOUGH MONEY FOR BEER !" ); } break; case CANDY: if( ! MSG_OUT.Candybars ) { MSG_OUT.Msg1 = IDM_NOSALE; MSG_OUT.Msg2 = ERR_SOLDOUT; strcpy( MSG_OUT.Text, "SOLD OUT OF CANDY !" ); } else if( MSG_IN.Money >= MSG_OUT.CostCandy ) { MSG_OUT.Msg1 = IDM_SALE; MSG_OUT.Msg2 = IDM_OK; strcpy( MSG_OUT.Text, "YOU BOUGHT A CANDY BAR !" ); MSG_OUT.Money = MSG_IN.Money - MSG_OUT.CostCandy; MSG_OUT.Candybars--; } else { MSG_OUT.Msg1 = IDM_NOSALE; MSG_OUT.Msg2 = ERR_LOWMONEY; strcpy( MSG_OUT.Text, "YOU DO NOT HAVE ENOUGH MONEY FOR CANDY !" ); } break; case POP: if( ! MSG_OUT.Pops ) { MSG_OUT.Msg1 = IDM_NOSALE; MSG_OUT.Msg2 = ERR_SOLDOUT; strcpy( MSG_OUT.Text, "SOLD OUT OF POP !" ); } else if( MSG_IN.Money >= MSG_OUT.CostPop ) { MSG_OUT.Msg1 = IDM_SALE; MSG_OUT.Msg2 = IDM_OK; strcpy( MSG_OUT.Text, "YOU BOUGHT A POP !" ); MSG_OUT.Money = MSG_IN.Money - MSG_OUT.CostPop; MSG_OUT.Pops--; } else { MSG_OUT.Msg1 = IDM_NOSALE; MSG_OUT.Msg2 = ERR_LOWMONEY; strcpy( MSG_OUT.Text, "YOU DO NOT HAVE ENOUGH MONEY FOR POP !" ); } break; } /* WRITE A RETURN MESSAGE TO THE CORRECT CLIENT */ fqptr = FileQ; while( strcmp( fqptr->fName, MsgQ[ mqhead ].fName ) != 0 ) fqptr = fqptr->Next; write( fqptr->ns, &MSG_OUT, MSize ); break; case IDM_SHUTDOWN: /* A FUNTION CALL TO SHUTDOWN SERVER, USED FOR STUDENT TO LEARN MORE ABOUT PROGRAM */ MSG_OUT.Msg1 = IDM_OK; MSG_OUT.Msg2 = IDM_SHUTDOWN; strcpy( MSG_OUT.Text, " Server is ShutDown !!! " ); fqptr = FileQ; while( strcmp( fqptr->fName, MsgQ[ mqhead ].fName ) != 0 ) fqptr = fqptr->Next; write( fqptr->ns, &MSG_OUT, MSize ); ShutDown(); break; case IDM_WAIT: /* A FUNTION CALL USED FOR STUDENT TO LEARN MORE ABOUT PROGRAM */ MSG_OUT.Msg1 = IDM_OK; MSG_OUT.Msg2 = IDM_WAIT; strcpy( MSG_OUT.Text, " Sleeping ( 10 ) " ); write( ns, &MSG_OUT, MSize ); sleep( 10 ); MSG_OUT.Msg1 = IDM_DONE; MSG_OUT.Msg2 = IDM_OK; strcpy( MSG_OUT.Text, " DONE " ); fqptr = FileQ; while( strcmp( fqptr->fName, MsgQ[ mqhead ].fName ) != 0 ) fqptr = fqptr->Next; write( fqptr->ns, &MSG_OUT, MSize ); break; default: MSG_OUT.Msg1 = ERROR; MSG_OUT.Msg2 = MsgQ[ mqhead ].Msg1; strcpy( MSG_OUT.Text, "Unimplemented Server Function ! (v.1a)" ); fqptr = FileQ; /* WRITE A RETURN MESSAGE TO THE CORRECT CLIENT */ while( strcmp( fqptr->fName, MsgQ[ mqhead ].fName ) != 0 ) fqptr = fqptr->Next; write( fqptr->ns, &MSG_OUT, MSize ); break; } /* switch( MsgQ[ mqhead ].Msg1 ) */ close( fqptr->ns ); /* INCERMENT THE HEAD OF THE MESSAGE QUEUE BY ONE MESSAGE */ mqhead++; } /* if( MsgQ ) */ } /* ProcessMsg() */ /*** MAIN *********************************/ void main() { int i; int fromlen; /* DEFAULTS */ MSize = sizeof( struct MyMessage ); FileQ = (struct FQ *) NULL; mqhead = 0; mqtail = 0; Pid = getpid(); MSG_OUT.Pid = Pid; MSG_OUT.CostBeer = 1.00; MSG_OUT.Beers = 100; MSG_OUT.CostCandy = 0.75; MSG_OUT.Candybars = 3; MSG_OUT.CostPop = 0.50; MSG_OUT.Pops = 200; /* OPEN THE MAIN CHANNEL "sb0000" */ SD=socket( AF_UNIX,SOCK_STREAM, 0 ); sockname.sa_family = AF_UNIX; strcpy( sockname.sa_data, "sb0000" ); if( bind( SD, &sockname, SIZEOFSOCKNAME ) == -1 ) { perror( "\n Binding Error, Server Start ! \n " ); exit( 99 ); } listen( SD, 1 ); /* NON_BLOCK ON SB0000 */ fcntl( SD, F_SETFL, O_NONBLOCK ); /* TRAP CONTROL C */ signal( SIGINT, ShutDown ); printf("\n VENDING MACHINE SERVER STARTED. (v.1a) Pid = %d by Louis Guzik \n\n ", Pid ); for(;;) /* LOOP; READ, SPOOL, PROCESS MESSAGES */ { /* READ FROM MAIN CHANNEL SB000 */ NS = accept( SD, &sockname, &fromlen ); i = read( NS, &MSG_IN, MSize ); if( i > 0 ) { printf( "\r\n\t Server Received Text -->%s<-- From Client Pid [%d] \n ", MSG_IN.Text, MSG_IN.Pid ); SpoolMsg(); } /* READ FROM FILE QUEUE CHANNELS */ fqptr = FileQ; while( fqptr ) { fqptr->ns = accept( fqptr->sd, &sockname, &fromlen ); i = read( fqptr->ns, &MSG_IN, MSize ); if( i > 0 ) { printf( "\r\t Server Received Text -->%s<-- From Client Pid [%d] \n\n ", MSG_IN.Text, MSG_IN.Pid ); SpoolMsg(); } /* CHECK THE NEXT CHANNEL FILE */ fqptr = fqptr->Next; } /* PROCESS ONE NEW MESSAGE */ ProcessMsgQ(); } /* for(;;) */ } /* main() */