/****************************************************************************\ * * * C R E A T O R O F L E G E N D S * * (AberMud Version 5) * * * * The Creator Of Legends System is (C) Copyright 1989 Alan Cox, All Rights * * Reserved. * * * \****************************************************************************/ /* * Daemon Communications Server Routines * * Strange this but the theory behind the user being in a state * and of having a set of state changing vectors actually came * from the original pre-abermud basic experiments on a sirius! */ #include "System.h" /* System includes and options */ #include "User.h" Module "Communication Server"; Version "1.28"; Author "----*(A)"; /* * 1.21 AGC General Version With SUPERCEDE * 1.22 AGC Added acknowledged clear to avoid crashes * 1.23 AGC Fixed TPacket sent as NPacket bug in Handle_Login * 1.24 AGC Changes to fit in nicely with new IPC * 1.25 AGC Tweaks to FixLineFaults() * 1.26 AGC Moved motd code * 1.27 AGC BSX Aware * 1.28 AGC ANSIfication cleanup */ PORT *Master_Port=NULL; /* Our Port */ USER UserList[MAXUSER]; /* Information about each user */ short LineFault[MAXUSER]; /* 1 = user has timeout problem */ void FixLineFaults(void) { int ct=0; while(ct<MAXUSER) { if(UserList[ct].us_Port!=NULL) { SiloFlush(UserList[ct].us_Port); if(LineFault[ct]||UserList[ct].us_Port->po_Flags&FL_FAULT) { /* Fighting.. no getouts allowed */ if(UserList[ct].us_Item && GetUserFlag(UserList[ct].us_Item,2)!=0) { ct++; continue; } RemoveUser(ct); UserList[ct].us_State=AWAIT_LOGIN; } } LineFault[ct]=0; ct++; } } int Current_UserList; /* Number of the current user */ /* * Post a block of data to a PLAY process. */ int SendBlock(PORT *us, COMTEXT *block, int size) { int er; if((er=WriteMPort(us,block,size))<0) { if(er!=-20) { Log("Error: Port write fail - %d\n",er); exit(10); } return(-20); /* Queue Filled */ } return(1); } /* * Post a text block to a PLAY process */ int SendTPacket(PORT *us, short class, char *data) { COMTEXT a; a.pa_Type=class; a.pa_Sender=-1; strcpy(a.pa_Data,data); return(SendBlock(us,&a,strlen(data)+2*(sizeof(short))+1)); } /* * Post a numeric block to a PLAY process */ int SendNPacket(PORT *us, short class, short p1, short p2, short p3, short p4) { COMDATA a; a.pa_Type=class; a.pa_Sender=-1; a.pa_Data[0]=p1; a.pa_Data[1]=p2; a.pa_Data[2]=p3; a.pa_Data[3]=p4; return(SendBlock(us,(COMTEXT *)&a,sizeof(COMDATA))); } /* * Get a message sent to us from the Master_Port */ int GetPacket(PORT *port, COMTEXT *packet) { int er; BlockOff(port); if((er=ReadMPort(port, packet))<0) { if(er==-3||er==-2) /* Interruted call */ return(-2); /* Port empty */ exit(11); } if(packet->pa_Type==PACKET_BONG) return(-2); /* Fake a timer event */ return(0); } /* * This function starts the process of logging a new user into the * game environment. */ void Handle_Login(char *msg) { PORT *port; long v; char *a; int ct=0; char ubf[MAXUSERID+64]; char mbuf[256]; FILE *motd; extern PORT *Bind_Port(); /* * Look for a free slot */ while(ct<MAXUSER) { if(UserList[ct].us_Name[0]==0) break; ct++; } /* * See if there was room to login */ if(ct==MAXUSER-1||ct>=MaxSlot()) { while(*msg!='$') msg++; *msg++=0; if(sscanf(msg,"%ld$%s",&v,ubf)==0) { Log("Error: Corrupt Login Attempt"); return; } port=(PORT *)Bind_Port(ct,v); if(port==NULL) { UserList[ct].us_Port=NULL; return; } if(port->po_fd&256) { if(ct<MAXUSER-1) goto oops; } /* New IPC needs a user associating with the channel before we do work on it */ UserList[ct].us_Port=port; SendTPacket(port,PACKET_CLEAR, "Sorry..... the game is currently full.\n"); CloseMPort(port); UserList[ct].us_Port=NULL; } else /* * Accept the new login and enter it into the userlist */ { oops: a=msg; while(*msg!='$') msg++; *msg++=0; if(!sscanf(msg,"%ld$%s",&v,ubf)) { Log("Error: Corrupt Login"); return; } port=Bind_Port(ct,v); if(port==NULL) { Log("Error: Port Open Failed"); return; } strcpy(UserList[ct].us_UserName,a); strcpy(UserList[ct].us_Name,"<login>"); UserList[ct].us_State=AWAIT_NAME; UserList[ct].us_Flags=0; UserList[ct].us_Port=port; time(&(UserList[ct].us_Login)); if(*ubf!='*') sprintf(UserList[ct].us_UserName,"Internet:%s",ubf); /* * Game Login Code Here */ if(!IsBSX(ct) || (motd=fopen("motd.bsx","r"))==NULL) motd=fopen("motd","r"); if(motd) { while(fgets(mbuf,255,motd)!=NULL) { SendUser(ct,mbuf); } fclose(motd); } SendNPacket(port,PACKET_LOGINACCEPT,0,ct,0,0); /* login ok */ SendNPacket(port,PACKET_ECHO,0,0,0,0); /* Echo On */ SendTPacket(port,PACKET_SETPROMPT,"What be thy name ? "); SendNPacket(port,PACKET_INPUT,1,0,0,0); /* Go ahead and type */ } return; } /* * Decide what to do with a packet recieved from a PLAY */ void InterpretPacket(COMTEXT *x) { Current_UserList=x->pa_Sender; switch(x->pa_Type) { case PACKET_SUPERCEDE: /* Sent when new SERVER takes over */ SupercedeFlag=1; break; case PACKET_ABORT: /* Sent to cause termination */ Broadcast("Remote Abort Requested: Terminating Abruptly.\n",0); exit(0); case PACKET_CLEAR: /* Client gone pop! */ if(Current_UserList!=-1) { printf("Time Out From %d\n",Current_UserList); TimeOut(Current_UserList); } break; case PACKET_CLEARED: /* Sent to confirm a CLEAR request */ if(Current_UserList!=-1) UserList[Current_UserList].us_State=AWAIT_LOGIN; break; case PACKET_LOOPECHO: /* Loopback for testing */ if(Current_UserList!=-1) SendNPacket(UserList[Current_UserList].us_Port, PACKET_ECHOBACK,0,0,0,0); break; /* Honour echoback protocols */ case PACKET_COMMAND: /* Input from a player */ Handle_Command(Current_UserList,x->pa_Data); break; case PACKET_LOGINREQUEST: /* A new login */ Handle_Login(x->pa_Data); break; case PACKET_OUTPUT: Handle_Output(x->pa_Data); /* Console Out */ break; case PACKET_COMMFORCE: /* Command off menu bar */ Handle_CommForce(Current_UserList,x->pa_Data); break; /* State AWAIT_COMMAND command */ case PACKET_BSXSCENE: /* Incoming BSX Request */ Handle_BSXPacket(Current_UserList,x->pa_Data); break; default: Log("Invalid Packet: Type %d.\n", x->pa_Type); } } /* * Handle all of the pending input from the Master_Port */ void ProcessPackets(void) { int er; COMTEXT p; while(1) { er=GetPacket(Master_Port,&p); if(er==-2) break; InterpretPacket(&p); } } int Handle_Output(char *x) { printf("%s",x); /* For Now */ return(0); } /* * Sort out what must be done when a user does a command */ int Handle_Command(int ch, char *x) { if(ch==-1) return(-1); Command_Driver(ch,UserList[ch].us_State,x); return(0); } int Handle_CommForce(int ch, char *x) { if(ch==-1) return(-1); if(UserList[ch].us_State==AWAIT_COMMAND) Command_Driver(ch,AWAIT_COMMAND,x); return(0); }