Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - Newt

Pages: [1]
1
General / SMF Themes
« on: August 16, 2013, 02:32:16 am »
could we get the option to use different themes for the site?

2
Intermud / Problem with Tim's LPC IMC2 client
« on: March 03, 2010, 11:26:15 am »
I can't figure out why this isn't working.  No errors or anything...just never get callbacks.  Spoke with Davion and he confirmed that it does connect...but then times out and is closed.


Code: [Select]
// Tim Johnson
// Started on May 1, 2004.
// Use this however you want.
#include <socket.h>
#include <network.h>
#include <security.h>
#include <save.h>
#include <config.h>
#include <daemons.h>
#include <std.h>

inherit DAEMON;

//#include <save.h> //need to add: #define SAVE_IMC2 DIR_SECURE_DAEMONS_SAVE "/imc2"

// File to save data to, .o will be added automatically to the end.
// This will have private stuff in it, don't put this in a directory where your wizards can read it.
#define SAVE_FILE "/adm/save/daemons/imc2" //SAVE_IMC2

//#define NO_AUTO 1

// Connection data...
#define HOSTNAME "server01.mudbytes.net"
#define HOSTPORT 5000
// HostIP overrides HOSTNAME, in case the mud doesn't want to resolve addresses.
#define HOSTIP "74.207.247.83"

// What name the network knows your mud as...
#define MUDNAME replace_string(mud_name(), " ", "")

// Passwords...
#define CLIENT_PW <password removed for posting>
#define SERVER_PW CLIENT_PW

// COMMAND_NAME is the command that people type to use this network.
#define COMMAND_NAME "imc2"

// NETWORK_ID is what your mud calls this network.
// This is the prefix that comes up on all messages to identify the IMC2 network.
// Tells for example look like:
// NETWORK_ID- Tim@TimMUD tells you: hi
// Make it similar to the command name, so players will understand.
#define NETWORK_ID "IMC2"

// DATA_LOG is where packets are logged to.
// Turn this off when not working on the system, as it invades privacy.
// Comment this out to turn it off.
#define DATA_LOG "imc2/general"

// UNKNOWN_DATA_LOG is where unrecognized packets are logged to.
// I wrote handlers for all packets I know of, so this should only pick
// up tests and possibly if anyone is creating new packets.
#define UNKNOWN_DATA_LOG "imc2/IMC2_UNKNOWN"

// Your MUD's URL is shared with other muds when building the mud list.
// This you could also put this in your who reply.
#define URL "http://shadowmudii.genesismuds.com/"

// ANNOUNCE_LOG is where network announcements get logged to.
// I suggest you keep this turned on.
// These announcements seem to be about channels being created and
// deleted, but may possibly have more.
#define ANNOUNCE_LOG "imc2/IMC2_ANNOUNCEMENTS"

// How many lines you want the backlog to be.
#define BACKLOG_SIZE 20

// Minimum permission number for channel to be viewable on the web.
#define BACKLOG_WEB_LEVEL 0

// If you use the web page with the mud list and channels and stuff,
// this'll be the URL for it, up to the point where the arguments
// are passed.
#define HTML_LOCATION URL //this is most likely borked


// WHO_STR is the code that you want a who request to display.
#define WHO_STR "/cmds/mortal/_who.c;who_list;80"

#ifndef VERSION
#define VERSION "Tim's LPC IMC2 client - Jan 30, 2005"
#endif

string tmpstr;

// Mode decides what kind of packet is expected
#define MODE_CONNECTED 1
#define MODE_WAITING_ACCEPT 2
#define MODE_CONNECT_ERROR 3 // Not used yet, I need to see what the hub sends.
#define MODE_HUB_DOWN 4 // Not used yet either.

#ifndef STREAM
#define STREAM 1
#endif
#ifndef EESUCCESS
#define EESUCCESS         1     /* Call was successful */
#endif
#ifndef THIS_PLAYER
#define THIS_PLAYER this_player()
#endif
#ifndef FIND_PLAYER
#define FIND_PLAYER(x) find_player(x)
#endif
#ifndef GET_CAP_NAME
#define GET_CAP_NAME(x) x->query_cap_name()
#endif
#ifndef GET_NAME
#define GET_NAME(x) x->query_name()
#endif
#ifndef IMC2_MSG
#define IMC2_MSG(x,y) foreach(tmpstr in explode(x,"\n")){ message("IMC2",tmpstr,y); }
#endif
#ifndef GET_GENDER
#define GET_GENDER(x) x->query_gender()
#endif
#ifndef ADMIN
#define ADMIN(x) creatorp(x)
#endif

// Other things that could be #define'd...
// INVIS(x) !visible(x)
// TELL_BOT "/u/t/timbot/imc2_invalidtells.c"
// TELL_BOTS ([ "timbot" : "/u/t/timbot/imc2_tellbot.c" ])
// CHAN_BOT "/u/t/timbot/imc2_chans.c"
// CHAN_BOTS ([ "ichat" : "/u/t/timbot/imc2_ichat.c" ])
// USER_EXISTS(x) user_exists(x)

// Debugging
#define DEB_IN  1
#define DEB_OUT 2
#define DEB_PAK 3
#define DEB_OTHER 0

nosave int socket_num;
int mode;
mapping ping_requests; // Keeps track of who sent a ping request.
// Ping requests aren't labelled with names, so replies are destined to this MUD
// with no idea why, unless we keep track.
string buf=""; // Buffer for incoming packets (aren't always sent 1 at a time)
 
// Variables
string hub_name, network_name;
string server_pass, server_version;
mapping chaninfo;
mapping localchaninfo; // (["chan": ([ "perm":1, "name":"something", "users":({ }) ]) ])
mapping mudinfo;
mapping genders;
mapping tells;
int sequence;

// Prototypes :)
void create();
void remove();
string pinkfish_to_imc2(string str);
string imc2_to_pinkfish(string str);
string escape(string str);
string unescape(string str);
mapping string_to_mapping(string str);
string main_help();

private void send_packet(string sender, string packet_type, string target, string destination, string data);
private void send_text(string text);
private void got_packet(string info);
private void start_logon();
private varargs void send_is_alive(string origin);
private void channel_in(string fromname, string frommud, mapping data);
private void tell_in(string sender, string origin, string target, mapping data);
private void beep_in(string sender, string origin, string target, mapping data);
private void who_reply_in(string origin, string target, mapping data);
private void whois_in(string fromname, string frommud, string targ, mapping data);
private void whois_reply_in(string targ,string fromname,string frommud,mapping data);
private void ping_reply_in(string sender,string origin,string target,mapping data);
private void chanwho_reply_in(string origin, string target, mapping data);
private void send_keepalive_request();
private int chan_perm_allowed(object user, string chan);
private string localize_channel(string str);
private void chan_who_in(string fromname, string frommud, mapping data);
private void send_ice_refresh();
private void resolve_callback(string address, string resolved, int key);

private varargs void debug(mixed msg, int x){
    seteuid(UID_LOG);
    log_file(DATA_LOG, "DEBUG: "+msg+" "+x+"\n");
    seteuid(UID_SOCKET);
// Add stuff in here if you want to see messages.
}

// Functions for users to change.
int can_use(object user){ return 1; } // Is this person allowed to use IMC2 at all?  This function determines if tells can be sent to the person and such.
int level(object ob){
        // Outgoing packets are marked with the user's level.
        // This function figures it out.
        // If you have different ways of ranking, make this function convert them to what IMC2 uses.
        // IMC2 uses: Admin=5, Imp=4, Imm=3, Mort=2, or None=1
        if(ADMIN(ob)) return 5; // Admin
        //TMI-2: if(wizardp(ob)) return 3;
        //TMI-2: if(userp(ob)) return 2;
//Discworld: if(ob->query_creator()) return 3;
if(this_player()) return 2;
        return 1; // None
}

string chan_perm_desc(int i){
        // Given the permission level assigned locally to a channel, return a short
        // string describing what the number means.  The number means nothing
// outside of this MUD.  Also, they are independant of each other, and
// so you can do groups without having to always do subgroups of higher
// ones or anything like 'levels'.  BACKLOG_WEB_LEVEL is the only one of
// significance, as it's the only one that the web backlog thing works on.
        switch(i){
                case 2: return "admin";
                case 1: return "wizards";
                case 0: return "public";
        }
        return "invalid";
}

int chan_perm_allowed(object user, string chan){
        // Using the permission level assigned locally to a channel,
        // return 1 if user is allowed to use the channel, 0 if not.
        switch(localchaninfo[chan]["perm"]){
                case 2: if(ADMIN(user)) return 1; return 0;
case 1:
                // TMI-2: case 1: if(wizardp(user)) return 1; return 0;
                case 0: return 1;
        }
}


// Shouldn't have to change anything beyond this point.

private int read_callback(int socket, mixed info){
// string str, *strs;
string a,b; int done=0;

debug("Begin read_cb", socket_num);

if(!sizeof(info)) return 0;
debug(save_variable(info),DEB_IN);
#ifdef DATA_LOG
    seteuid(UID_LOG);
    log_file(DATA_LOG,"SERVER: "+save_variable(info)+"\n");
    seteuid(UID_SOCKET);
#endif
buf += info;
// The hub groups packets, unfortunately.
switch(mode){
case MODE_WAITING_ACCEPT: // waiting for Hub to send autosetup
if(sscanf(info, "autosetup %s accept %s\n\r",
hub_name, network_name)==2){
debug("Connected, hub is "+hub_name+", network is "+network_name);
mode = MODE_CONNECTED;
send_is_alive("*");
send_keepalive_request();
send_ice_refresh();
}
else if(sscanf(info, "PW %s %s version=%d %s\n",
hub_name, server_pass, server_version, network_name)==4){
mode = MODE_CONNECTED;
send_is_alive("*");
send_keepalive_request();
send_ice_refresh();
}
else{ // Failed login sends plaintext error message.
debug("Failed to connect... "+info);
}
buf=""; // clear buffer
break;
case MODE_CONNECTED:
while(!done){
if(sscanf(buf,"%s\n\r%s",a,b)==2){ // found a break...
got_packet(a);
buf=b;
}
else{ // no break...
done = 1;
}
}
/*
strs = explode(info,"\n\r");
foreach(str in strs){
got_packet(str);
}
buf="";
*/
break;
}
return 1;
}

private void got_packet(string info){
string str;
string a,b;
int i;
string sender, origin, route, packet_type, target, destination, strdata;
int sequence;
mapping data;
object who;
if(!sizeof(info)) return;
debug(save_variable(info),DEB_PAK);

str = info;
// messages end with " \n\r" or "\n" or sometimes just a space
sscanf(str, "%s\n^", str);
sscanf(str, "%s\r^", str);
sscanf(str, "%s ^", str);
sscanf(str, "%s ^", str);
if(sscanf(str, "%s %d %s %s %s %s",
a, sequence, route, packet_type,
b, strdata)==6){ // matches
if(sscanf(b,"%s@%s",target,destination)!=2){
// Could be MUD instead of Name@MUD or *@MUD
target="*"; destination=b;
}
if(sscanf(a,"%s@%s",sender,origin)!=2){
sender="*"; origin=a;
}
data = string_to_mapping(strdata);
// debug("sender="+sender);
// debug("origin="+origin);
// debug("sequence="+sequence);
// debug("route="+route);
// debug("packet_type="+packet_type);
// debug("data="+save_variable(data));
if(!mudinfo[origin]) mudinfo[origin] = ([ ]);

switch(packet_type){
case "is-alive": // For making a MUD list.
if(!mudinfo[origin]) mudinfo[origin] = ([ ]);
// example of info:
// versionid=\"IMC2 AntiFreeze CL-2 SWR 1.0\" url=none md5=1
//mudinfo[origin]["version"]="blah";
mudinfo[origin]+=data;
mudinfo[origin]["online"]=1;
debug("handled is-alive for mud "+origin);
break;
case "close-notify": // Someone disconnected.
if(!mudinfo[data["host"]]) mudinfo[data["host"]] = ([]);
mudinfo[data["host"]]["online"]=0;
break;
case "keepalive-request": // Request for is-alive.
send_is_alive(origin);
break;
case "ice-msg-b": // Broadcast channel message.
channel_in(sender, origin, data);
break;
case "tell": // Tells or emotes.
tell_in(sender, origin, target, data);
break;
case "who-reply":
who_reply_in(origin,target,data);
break;
case "whois": // Like I3's locate
whois_in(sender,origin,target,data);
break;
case "whois-reply":
whois_reply_in(target,sender,origin,data);
break;
case "beep":
beep_in(sender, origin, target, data);
break;
case "ice-update": // Reply from ice-refresh.
chaninfo[data["channel"]]=data;
break;
case "wHo": // Drop-through
case "who":
send_packet("*","who-reply",sender,origin,
"text="+escape(pinkfish_to_imc2(WHO_STR)));
break;
case "ice-destroy": // Deleting channel.
map_delete(chaninfo,data["channel"]);
break;
case "user-cache": // User info, like I3's ucache service.
if(!genders[origin]) genders[origin]=([ ]);
genders[origin][sender]=data["gender"];
break;
case "user-cache-reply": // Reply with user info
if(!genders[origin]) genders[origin]=([ ]);
genders[origin][data["user"]]=data["gender"];
break;
case "user-cache-request": // Request for user info
sscanf(data["user"],"%s@%*s",str);
who = FIND_PLAYER(lower_case(str));
if(who
#ifdef INVIS
&& !INVIS(who)
#endif
){
switch(GET_GENDER(who)){
case "male" : i=0; break;
case "female" : i=1; break;
default : i=2; break;
}
send_packet("*","user-cache-reply",sender,
origin,sprintf("gender=%d",i));
}
break;
case "ping":
send_packet("*","ping-reply",sender,origin,
sprintf("path=\"%s\"",route));
break;
case "ping-reply":
ping_reply_in(sender,origin,target,data);
break;
case "ice-msg-r": // Relayed channel message.
channel_in(sender, origin, data);
break;
case "ice-chan-whoreply": // Tell who's listening to a channel.
chanwho_reply_in(origin,target,data);
break;
case "emote": // Channel creation/destruction message... anything else?
IMC2_MSG(NETWORK_ID+" announces: "+data["text"]+"\n",
filter_array(users(), (: ADMIN($1) :)));
#ifdef ANNOUNCE_LOG
                    seteuid(UID_LOG);
log_file(ANNOUNCE_LOG,ctime(time())+": "+data["text"]+"\n");
seteuid(UID_SOCKET);
#endif
break;
case "ice-chan-who": // Check who's listening to a channel.
chan_who_in(sender,origin,data);
break;
case "channel-notify":
// Don't care about this.  Useful only if you care when
// people on other MUDs start/stop listening to a channel.
// example: Someone@SomeMUD 1087076772 SomeMUD channel-notify *@*  channel=Hub01:ichat status=0
break;
// The following packets shouldn't be incoming.
case "ice-cmd": // Remote channel administration
case "remote-admin": // For controlling the hub
case "ice-refresh": // Request data about channels
case "ice-msg-p": // Private channel message
debug("This packet isn't supposed to be incoming: "+packet_type);
break;
default:
#ifdef UNKNOWN_DATA_LOG
                seteuid(UID_LOG);
                log_file(UNKNOWN_DATA_LOG,"Unknown packet: "+escape(info)+"\n\n");
                seteuid(UID_SOCKET);
#endif
debug("Unlisted packet type: "+packet_type);
break;
}
}
else{
buf += info;
debug("Doesn't match incoming pattern, so putting on buffer: "+str);
#ifdef BAD_PACKET
            seteuid(UID_LOG);
log_file(BAD_PACKET,"Doesn't match incoming pattern: "+str+"\n");
seteuid(UID_SOCKET);
#endif
}
}
 
private int close_callback(int socket){
// Connection was closed.
#ifdef DATA_LOG
    seteuid(UID_LOG);
log_file(DATA_LOG,"DISCONNECTED\n");
seteuid(UID_SOCKET);
#endif
socket_close(socket_num);
// socket->remove();
create();
return 1;
}

private void send_text(string text){
// Send a literal string.
// Almost everything should use the send_packet function instead of this.
#ifdef DATA_LOG
    seteuid(UID_LOG);
log_file(DATA_LOG,"CLIENT: "+save_variable(text)+"\n");
seteuid(UID_SOCKET);
#endif
debug(save_variable(text), DEB_OUT);
// debug("writing to socket: "+socket_num);
socket_write(socket_num,text);
// imc2_socket->send(text);
return;
}

void create(){
#ifdef DATA_LOG
    seteuid(UID_LOG);
log_file(DATA_LOG,"-------------------------\nStarting IMC2...\n");
seteuid(UID_SOCKET);
#endif
    if(sizeof(get_dir(SAVE_FILE+".o"))) restore_object(SAVE_FILE);
if(!mudinfo) mudinfo = ([ ]);
if(!chaninfo) chaninfo = ([ ]);
if(!localchaninfo) localchaninfo = ([ ]);
if(!genders) genders = ([ ]);
if(!tells) tells=([ ]);
ping_requests=([ ]);
mode = MODE_WAITING_ACCEPT;
#ifdef HOSTIP
    // We already know the IP, go straight to the connecting, just do callback as if it found the IP.
    resolve_callback(HOSTIP,HOSTIP,1);
#else
    if(!resolve(HOSTNAME, "resolve_callback")){
        //Debug("Addr_server is not running, resolve failed.");
#ifdef DATA_LOG
        log_file(DATA_LOG,"Addr_server is not running, resolve failed.\n");
#endif
        remove();
        return;
    }
#endif
debug("Finished creating IMC2 object");
}

void remove(){
// This object is getting destructed.
if(!socket_num) socket_close(socket_num);
debug("In remove()", socket_num);
seteuid(UID_LOG);
log_file(DATA_LOG,"IMC2 OBJECT REMOVED\n");
seteuid(UID_SOCKET);

save_object(SAVE_FILE);
destruct(this_object());

}

private void resolve_callback( string address, string resolved, int key ) {
// Figured out what the IP is for the address.
int error;
debug("Resolved to: "+resolved, socket_num);

//seteuid(UID_SOCKET);
socket_num = socket_create(STREAM, "read_callback", "close_callback");
//seteuid(getuid());
if (socket_num < 0) {
#ifdef DATA_LOG
        seteuid(UID_LOG);
log_file(DATA_LOG,"socket_create: " + socket_error(socket_num) + "\n");
seteuid(UID_SOCKET);
#endif
debug("socket_create: " + socket_error(socket_num) + "\n");
return;
}
debug("Created socket descriptor ", socket_num);

error = socket_bind(socket_num, 0);
if (error != EESUCCESS) {
#ifdef DATA_LOG
        seteuid(UID_LOG);
log_file(DATA_LOG,"socket_bind error: " + socket_error(error) + "\n");
seteuid(UID_SOCKET);
#endif
socket_close(socket_num);
return;
}

error = socket_connect(socket_num, resolved+" "+HOSTPORT, "read_callback", "write_callback");
if (error != EESUCCESS) {
#ifdef DATA_LOG
        seteuid(UID_LOG);
log_file(DATA_LOG,"socket_connect error: " + socket_error(error) + "\n");
seteuid(UID_SOCKET);
#endif
socket_close(socket_num);
return;
}
}

private void write_callback(int socket){
start_logon();
}

private void start_logon(){
debug("Gonna try logging in, sending the PW thing...");
#if NOT_AUTO
send_text(sprintf("PW %s %s version=%d\n",
#else
send_text(sprintf("PW %s %s version=%d autosetup %s\n",
#endif
MUDNAME,
CLIENT_PW, 2
#ifndef NOT_AUTO
, SERVER_PW
#endif
));
buf="";
/* For invitation-only networks.
send_text(sprintf("PW %s %s version=%d %s\n",
MUDNAME,
CLIENT_PW, 2, "hub03"
));
*/
sequence=time();
}

At one point I changed things assuming the socket was ready and called start_logon()  it sent the autosetup stuff and the status page for the IMC2 server said I was online...the socket stayed open at this point but still just sat there on my end.

Any help will be greatly appreciated,
Newt

Pages: [1]