/* /daemon/intermud.c * from the Dead Souls public domain LPC Library * daemon handling the InterMUD-3 Protocol * created by Descartes of Borg 950506 * Version: @(#) intermud.c 1.7@(#) * Last modified: 96/12/14 */ #ifndef __PACKAGE_SOCKETS__ #error You should not try and load /daemon/intermud.c with no sockets package. #else #include <std.h> #include <config.h> #include <config2.h> #include <daemons.h> #include <network.h> #include "include/intermud.h" #define SAVE_INTERMUD "/save/imud.o" #define SERVICES_D "/daemon/services" inherit CLIENT; private int Password; private class list MudList, ChannelList; private mapping Banned; private mixed *Nameservers; private static int Connected, Tries; static void create() { client::create(); Connected = 0; Password = 0; Tries = 0; Banned = ([]); Nameservers = ({ ({ "*yatmim", "149.152.218.102 23" }) }); MudList = new(class list); ChannelList = new(class list); MudList->ID = -1; MudList->List = ([]); ChannelList->ID = -1; ChannelList->List = ([]); if( file_size( SAVE_INTERMUD __SAVE_EXTENSION__ ) > 0 ) restore_object(SAVE_INTERMUD); //SetNoClean(1); //SetDestructOnClose(1); SetSocketType(MUD); call_out( (: Setup :), 2); } static void Setup() { string ip; int port; if( !Nameservers || !sizeof(Nameservers) ) return; sscanf(Nameservers[0][1], "%s %d", ip, port); if( eventCreateSocket(ip, port) < 0 ) return; eventWrite( ({ "startup-req-3", 5, mud_name(), 0, Nameservers[0][0], 0, Password, MudList->ID, ChannelList->ID, query_host_port(), PORT_OOB, PORT_UDP, mudlib() + "" , mudlib() + "" , driver(), "LP Mud", MUD_STATUS, ADMIN_EMAIL, (mapping)SERVICES_D->GetServices(), ([]) }) ); } static void eventRead(mixed *packet) { string *cles; mixed val; string ns, cle; int i, maxi; if( !packet || sizeof(packet) < 6 ) return; /* should send error */ if( Banned[packet[2]] ) { string reason = Banned[packet[2]]; eventWrite(({ "error", 5, mud_name(), 0, packet[2], packet[3], "unk-user", "Your mud is not allowed to send to this mud.", packet })); return; } switch(packet[0]) { case "startup-reply": if( sizeof(packet) != 8 ) return; /* should send error */ if( !sizeof(packet[6]) ) return; if( packet[6][0][0] == Nameservers[0][0] ) { Nameservers = packet[6]; Connected = Nameservers[0][0]; Password = packet[7]; save_object(SAVE_INTERMUD); } else { Nameservers = packet[6]; Setup(); } return; case "mudlist": if( sizeof(packet) != 8 ) return; if( packet[6] == MudList->ID ) return; if( packet[2] != Nameservers[0][0] ) return; MudList->ID = packet[6]; foreach(cle, val in packet[7]) { if( !val && MudList->List[cle] != 0 ) map_delete(MudList->List, cle); else if( val ) MudList->List[cle] = val; } save_object(SAVE_INTERMUD); return; case "channel-t": SERVICES_D->eventReceiveChannelTargettedEmote(packet); break; case "channel-e": SERVICES_D->eventReceiveChannelEmote(packet); break; case "channel-m": //tell_object(find_player("cratylus"),"hey\n"); SERVICES_D->eventReceiveChannelMessage(packet); break; case "chan-who-reply": SERVICES_D->eventReceiveChannelWhoReply(packet); break; case "chan-who-req": SERVICES_D->eventReceiveChannelWhoRequest(packet); break; case "chan-user-req": SERVICES_D->eventReceiveChannelUserRequest(packet); break; case "chanlist-reply": // if( packet[6] == ChannelList->ID ) return; if( packet[2] != Nameservers[0][0] ) return; ChannelList->ID = packet[6]; foreach(cle, val in packet[7]) { if( !val && ChannelList->List != 0 ) map_delete(ChannelList->List, cle); else if( val ) ChannelList->List[cle] = val; } save_object(SAVE_INTERMUD); SERVICES_D->eventRegisterChannels(packet[7]); return; case "emoteto": SERVICES_D->eventReceiveEmote(packet); break; case "finger-req": SERVICES_D->eventReceiveFingerRequest(packet); break; case "finger-reply": SERVICES_D->eventReceiveFingerReply(packet); break; case "locate-req": SERVICES_D->eventReceiveLocateRequest(packet); break; case "locate-reply": SERVICES_D->eventReceiveLocateReply(packet); break; case "tell": SERVICES_D->eventReceiveTell(packet); break; case "chan-user-reply": case "ucache-update": SERVICES_D->eventReceiveUcacheUpdate(packet); break; case "who-req": SERVICES_D->eventReceiveWhoRequest(packet); break; case "who-reply": SERVICES_D->eventReceiveWhoReply(packet); break; case "news": SERVICES_D->eventReceiveNews(packet); break; case "mail": SERVICES_D->eventReceiveMail(packet); break; case "mail-ok": SERVICES_D->eventReceiveMailOk(packet); break; case "file": break; case "error": SERVICES_D->eventReceiveError(packet); break; default: break; } } static void eventSocketClose() { int extra_wait; extra_wait = (Tries++) * 20; if( extra_wait > 600 ) extra_wait = 600; Connected = 0; call_out( (: Setup :), 20 + extra_wait); } static void eventConnectionFailure() { if( Connected ) return; error("Failed to find a useful name server.\n"); } int SetDestructOnClose(int x) { return 0; } int SetSocketType(int x) { return client::SetSocketType(MUD); } string GetMudName(string mud) { string *lc, *uc; int x; if( MudList->List[mud] ) return mud; lc = map(uc = keys(MudList->List), function(string str) { if( !str ) return ""; else return lower_case(str); }); x = member_array(lower_case(mud), lc); if( x < 0 ) return 0; else return uc[x]; } mapping GetMudList() { return copy(MudList->List); } string *GetMuds() { return keys(MudList->List); } mapping GetChannelList() { return copy(ChannelList->List); } string *GetChannels() { return keys(ChannelList->List); } string *GetMatch(string mud) { string *uc, *lc; mud = lower_case(mud); lc = map(uc = keys(MudList->List), (: lower_case :)); return map(filter(regexp(lc, "^"+mud, 1), (: intp :)), (: $(uc)[$1] :)); } string GetNameserver() { return Nameservers[0][0]; } int AddBanned(string mud, string reason) { if( !master()->valid_apply(({})) ) { return 0; } if( !(mud = GetMudName(mud)) ) { return 0; } Banned[mud] = reason; save_object(SAVE_INTERMUD); return 1; } #endif /* __PACKAGE_SOCKETS__ */