// Petrarch // Merentha Lib 1.0 // network.c #include <daemons.h> #include <socket.h> #include <std.h> inherit DAEMON; string convert_map_to_string3(mapping str); mapping __MUDS=([]); static string *__Services=({"rcre_request","rcre_reply","ping_request","ping_reply","rwho_request","rfinger_request","rtell_request","rwho_reply","rfinger_reply","rtell_reply"}); mapping query_mud_list() { return __MUDS; } mapping convert_string_to_map(string str) { mapping tmp=([]); string *parts=explode(str,"||M||"); string key, val; int i=sizeof(parts); while(i--) { sscanf(parts[i], "%s:||:||:%s", key, val); tmp[key]=val; } return tmp; } mapping convert_string_to_map2(string str) { mapping tmp=([]); string *parts=explode(str,"||MM||"); string key, val; int i=sizeof(parts); while(i--) { sscanf(parts[i], "%s::||::||::%s", key, val); tmp[key]=val; } return tmp; } mapping convert_string_to_map3(string str) { mapping tmp=([]); string *parts=explode(str,"||MMM||"); string key, val; int i=sizeof(parts); while(i--) { sscanf(parts[i], "%s:::||:::||:::%s", key, val); tmp[key]=val; } return tmp; } string convert_map_to_string(mapping str) { string *k=keys(str); string tmp=""; int i=sizeof(k); while(i--) { tmp+=k[i]+":||:||:"+str[k[i]]; if(i) tmp+="||M||"; } return tmp; } string convert_map_to_string2(mapping str) { string *k=keys(str); string tmp=""; int i=sizeof(k); while(i--) { tmp+=k[i]+"::||::||::"+convert_map_to_string3(str[k[i]]); if(i) tmp+="||MM||"; } return tmp; } string convert_map_to_string3(mapping str) { string *k=keys(str); string tmp=""; int i=sizeof(k); while(i--) { tmp+=k[i]+":::||:::||:::"+str[k[i]]; if(i) tmp+="||MMM||"; } return tmp; } void open_socket_to_send(string address, mapping message) { string *args; int s, error; if(!message || !address) return; if(message["args"] && stringp(message["args"])) { args=explode(message["args"], "\n"); if(sizeof(args)>6) { message["args"]=implode(args[0..5],"\n"); open_socket_to_send(address, message); message["args"]=implode(args[6..<0],"\n"); open_socket_to_send(address, message); return; } } s = socket_create(DATAGRAM, "close_callback"); if (s < 0) { log_file("network", "(osts) socket_create: "+socket_error(s)+"\n"); return; } log_file("network", "(osts) Created socket descriptor " + s + "\n"); error = socket_bind(s, 0); if (error != EESUCCESS) { log_file("network", "(osts) socket_bind: " + socket_error(error) + "\n"); socket_close(s); return; } socket_write(s,convert_map_to_string(message), address); socket_close(s); } varargs void read_callback(int s, mixed message, string host) { string args, junk; if(!message || !stringp(message)) { log_file("network", "(rcb) Received non-message from socket: "+s+"\n"); return; } message=convert_string_to_map(message); sscanf(socket_address(s), "%s %s", junk, args); if(junk=="0.0.0.0") sscanf(host, "%s %s", junk, args); if(mapp(message)) { if(!message["name"]) { return; } if(!message["service"] || member_array(message["service"],__Services)==-1) { return; } __MUDS[message["name"]]=([ "name":message["name"], "address":junk, "udp_port":message["udp_port"], "port":message["port"], "mudlib":message["mudlib"], "driver":message["driver"], "pings":0, ]); args=call_other(this_object(),({message["service"],message})); if(!args) { return; } if(strsrch(message["service"],"_request")!=-1) { open_socket_to_send(""+junk+" "+message["udp_port"], (["name":mud_name(), "port":query_host_port(), "udp_port":MERENTHA_INTERMUD, "mudlib":mudlib(), "driver":driver(), "remote_user":message["remote_user"], "args":args, "service":replace_string(message["service"],"_request","_reply"), ]) ); return; } } } void close_callback(int s) { log_file("network", "(ccb) Closed socket: "+s+"\n"); } void create_main_socket() { int s, error; s = socket_create(DATAGRAM, "read_callback"); if (s < 0) { log_file("network","(main) socket_create: "+socket_error(s)+"\n"); return; } log_file("network", "(main) Created socket descriptor " + s + "\n"); error = socket_bind(s, MERENTHA_INTERMUD); if (error != EESUCCESS) { log_file("network", "(main) socket_bind: " + socket_error(error) + "\n"); socket_close(s); return; } } void create() { restore_object("/save/daemons/network"); call_out("create_main_socket", 0); call_out("send_ping_request", 5); } void save_network() { save_object("/save/daemons/network"); } /************** SERVICES **************/ string rwho_reply(mapping message) { object player; if(player=find_player(message["remote_user"])) message("rwho", message["args"], player); return 0; } string rfinger_reply(mapping message) { object player; if(player=find_player(message["remote_user"])) message("rwho", message["args"], player); return 0; } string rtell_reply(mapping message) { object player; if(player=find_player(message["remote_user"])) message("rwho", message["args"], player); return 0; } string ping_reply(mapping message) { mapping remote_muds=convert_string_to_map2(message["args"]); string *new_names, *old_names; int i; if(!remote_muds || !mapp(remote_muds)) return 0; old_names=keys(__MUDS); i=sizeof(new_names=keys(remote_muds)); while(i--) { if(member_array(new_names[i], old_names)==-1 && lower_case(new_names[i])!=lower_case(mud_name()) && remote_muds["pings"]<MAX_PINGS) { __MUDS[new_names[i]]=convert_string_to_map3(remote_muds[new_names[i]]); old_names=keys(__MUDS); } } } string rwho_request(mapping message) { string *u=users()->query_cap_name(); int i=to_int(message["screen_width"]); if(!i) i=75; return "\n"+border("%^RED%^"+format_page(u, 4, i-4),"rwho : "+mud_name(), i); } string rfinger_request(mapping message) { int i=to_int(message["screen_width"]); if(!i) i=75; if(message["target"] && message["target"]!="0") return "\n"+FINGER_D->get_player_info(message["target"], i); else return "\n"+FINGER_D->get_player_list(i); } string rtell_request(mapping message) { object ob; if(!ob=find_player(message["target"])) { return ""+message["target"]+" could not be found in "+mud_name()+"."; } message("communication",capitalize(message["remote_user"])+"@"+message["name"]+" tells you: "+message["args"], ob); return ""+capitalize(message["target"])+" received your message."; } string rcre_request(mapping message) { CHAT_D->send_message(message["remote_user"],"intermer",message["args"]); return 0; } string ping_request(mapping message) { if(to_int(message["known_muds"])<sizeof(__MUDS)) return convert_map_to_string2(__MUDS); return 0; } string get_mud_address(string name) { if(!__MUDS) return "0"; if(!__MUDS[name]) return 0; return ""+__MUDS[name]["address"]+" "+__MUDS[name]["udp_port"]; } varargs int send_rwho_request(string mud, string player, int width) { string address=get_mud_address(mud); if(!address) return notify_fail("No such MUD.\n"); if(address=="0") return notify_fail("No MUDs.\n"); open_socket_to_send(address, (["name":mud_name(), "port":query_host_port(), "udp_port":MERENTHA_INTERMUD, "mudlib":mudlib(), "driver":driver(), "remote_user":player, "screen_width":(width?width:75), "service":"rwho_request", ]) ); return 1; } varargs int send_finger_request(string mud, string player, string target, int width) { string address=get_mud_address(mud); if(!address) return notify_fail("No such MUD.\n"); if(address=="0") return notify_fail("No MUDs.\n"); open_socket_to_send(address, (["name":mud_name(), "port":query_host_port(), "udp_port":MERENTHA_INTERMUD, "mudlib":mudlib(), "driver":driver(), "remote_user":player, "screen_width":(width?width:75), "service":"rfinger_request", "target":target, ]) ); return 1; } int send_rtell_request(string mud, string player, string target, string message) { string address=get_mud_address(replace_string(mud, ".", " ")); if(!address) return notify_fail("No such MUD.\n"); if(address=="0") return notify_fail("No MUDs.\n"); open_socket_to_send(address, (["name":mud_name(), "port":query_host_port(), "mudlib":mudlib(), "udp_port":MERENTHA_INTERMUD, "driver":driver(), "remote_user":player, "service":"rtell_request", "target":target, "args":message, ]) ); return 1; } int send_rcre_request(string player, string message) { string address, *names; int i=sizeof(names=keys(__MUDS)); while(i--) { address=get_mud_address(names[i]); if(!address) continue; if(address=="0") continue; open_socket_to_send(address, (["name":mud_name(), "port":query_host_port(), "udp_port":MERENTHA_INTERMUD, "mudlib":mudlib(), "driver":driver(), "remote_user":player+"@"+mud_name(), "service":"rcre_request", "args":message, ]) ); } return 1; } int send_ping_request() { string address, *names; int i=sizeof(names=keys(__MUDS)); while(i--) { __MUDS[names[i]]["pings"]=__MUDS[names[i]]["pings"]+1; if(to_int(__MUDS[names[i]]["pings"])>MAX_PINGS) map_delete(__MUDS,names[i]); address=get_mud_address(names[i]); if(!address) continue; if(address=="0") continue; open_socket_to_send(address, (["name":mud_name(), "port":query_host_port(), "udp_port":MERENTHA_INTERMUD, "mudlib":mudlib(), "driver":driver(), "service":"ping_request", "known_muds":sizeof(__MUDS), ]) ); } call_out("save_network", 90); call_out("send_ping_request", 900); return 1; }