void imc_delete_info(imc_info *i) { imc_connect *c; imc_info *last; for (c=imc_connect_list; c; c=c->next) if (c->info==i) do_close(c); if (i==imc_info_list) imc_info_list=i->next; else { for (last=imc_info_list; last && last->next!=i; last=last->next) ; if (!last) imc_logerror("imc_delete_info: not in list"); else last->next=i->next; } if (i->name) imc_strfree(i->name); if (i->host) imc_strfree(i->host); if (i->clientpw) imc_strfree(i->clientpw); if (i->serverpw) imc_strfree(i->serverpw); imc_cancel_event(NULL, i); imc_free(i, sizeof(*i)); }
void imc_cancel_info(imc_info *i) { imc_info *last; if (i==imc_info_list) imc_info_list=i->next; else { for (last=imc_info_list; last && last->next!=i; last=last->next) ; if (!last) imc_logerror("imc_delete_info: not in list"); else last->next=i->next; } if (i->name) imc_strfree(i->name); if (i->host) imc_strfree(i->host); if (i->clientpw) imc_strfree(i->clientpw); if (i->serverpw) imc_strfree(i->serverpw); imc_free(i, sizeof(*i)); }
void icec_recv_destroy(const char *from, const char *channel) { ice_channel *c; const char *mud; mud = imc_mudof(from); if(!strchr(channel, ':') || strcasecmp(mud, ice_mudof(channel))) { return; } c = icec_findchannel(channel); if(!c) { return; } if(c == icec_channel_list) { icec_channel_list = c->next; } else { ice_channel *p; for(p = icec_channel_list; p; p = p->next) if(p->next == c) { break; } if(p) { p->next = c->next; } } icec_localfree(c); imc_strfree(c->name); imc_strfree(c->owner); imc_strfree(c->operators); imc_strfree(c->invited); imc_strfree(c->excluded); }
void icec_localfree(ice_channel *c) { if (c->local) { imc_strfree(c->local->name); imc_strfree(c->local->format1); imc_strfree(c->local->format2); imc_free(c->local, sizeof(icec_lchannel)); c->local=NULL; } }
void icec_recv_update(const char *from, const char *chan, const char *owner, const char *operators, const char *policy, const char *invited, const char *excluded) { ice_channel *c; const char *mud; mud = imc_mudof(from); /* forged? */ if(!strchr(chan, ':') || strcasecmp(mud, ice_mudof(chan))) { return; } c = icec_findchannel(chan); if(!c) { c = imc_malloc(sizeof(*c)); c->name = imc_strdup(chan); c->owner = imc_strdup(owner); c->operators = imc_strdup(operators); c->invited = imc_strdup(invited); c->excluded = imc_strdup(excluded); c->local = NULL; c->active = NULL; c->next = icec_channel_list; icec_channel_list = c; } else { imc_strfree(c->owner); imc_strfree(c->operators); imc_strfree(c->invited); imc_strfree(c->excluded); c->name = imc_strdup(chan); c->owner = imc_strdup(owner); c->operators = imc_strdup(operators); c->invited = imc_strdup(invited); c->excluded = imc_strdup(excluded); } if(!strcasecmp(policy, "open")) { c->policy = ICE_OPEN; } else if(!strcasecmp(policy, "closed")) { c->policy = ICE_CLOSED; } else { c->policy = ICE_PRIVATE; } if(c->local && !ice_audible(c, imc_name)) { icec_localfree(c); } icec_notify_update(c); imc_cancel_event(ev_icec_timeout, c); imc_add_event(ICEC_TIMEOUT, ev_icec_timeout, c, 0); }
void imc_whoreply_end(void) { imc_send_whoreply(wr_to, wr_buf, -(wr_sequence+1)); imc_strfree(wr_to); wr_buf[0]=0; imc_shrinksbuf(wr_buf); }
/* called when a keepalive has been received */ void imc_recv_keepalive(const char *from, const char *version, const char *flags) { imc_reminfo *p; if (!strcasecmp(from, imc_name)) return; /* this should never fail, imc.c should create an * entry if one doesn't exist (in the path update * code) */ p=imc_find_reminfo(from, 0); if (!p) /* boggle */ return; if(!time_of_last_ralive) { time_of_last_ralive=time(NULL); } else { time_since_last_ralive = time(NULL) - time_of_last_ralive; time_of_last_ralive =time(NULL); } if (imc_hasname(flags, "hide")) p->hide=1; else p->hide=0; /* lower-level code has already updated p->alive */ if (strcasecmp(version, p->version)) /* remote version has changed? */ { imc_strfree(p->version); /* if so, update it */ p->version=imc_strdup(version); } /* Only routers should ping - and even then, only directly connected muds */ /* and only if there is an open connection - shogar */ if (imc_is_router && imc_getinfo(from) && imc_getinfo(from)->connection && imc_getinfo(from)->connection->state==IMC_CONNECTED) { struct timeval tv; gettimeofday(&tv, NULL); imc_send_ping(from, tv.tv_sec, tv.tv_usec); } /* or muds acting as a hub to another mud - shogar */ if (!imc_is_router && imc_getinfo(from) && imc_getinfo(from)->connection && !(imc_getinfo(from)->flags & IMC_HUB) && mud_has_hub) { struct timeval tv; gettimeofday(&tv, NULL); imc_send_ping(from, tv.tv_sec, tv.tv_usec); } }
void icec_save_channels(void) { ice_channel *c; FILE *fp; char name[MAX_STRING_LENGTH]; strcpy(name, imc_prefix); strcat(name, "icec"); fp=fopen(name, "w"); if (!fp) { imc_logerror("Can't write to %s", name); return; } for (c=saved_channel_list; c; c=c->next) { /* update */ ice_channel *current=icec_findlchannel(c->local->name); if (current) { imc_strfree(c->name); imc_strfree(c->local->format1); imc_strfree(c->local->format2); c->name=imc_strdup(current->name); c->local->format1=imc_strdup(current->local->format1); c->local->format2=imc_strdup(current->local->format2); c->local->level=current->local->level; } /* save */ fprintf(fp, "%s %s %d\n" "%s\n" "%s\n", c->name, c->local->name, c->local->level, c->local->format1, c->local->format2); } fclose(fp); }
void ev_icec_timeout(void *data) { ice_channel *c = data; if(c == icec_channel_list) { icec_channel_list = c->next; } else { ice_channel *p; for(p = icec_channel_list; p; p = p->next) if(p->next == c) { break; } if(p) { p->next = c->next; } } icec_localfree(c); imc_strfree(c->name); imc_strfree(c->owner); imc_strfree(c->operators); imc_strfree(c->invited); imc_strfree(c->excluded); }
/* close down imc */ void imc_shutdown(void) { imc_ignore_data *ign, *ign_next; imc_info *info, *info_next; if (imc_active==IA_NONE) { imc_logerror("imc_shutdown: called with imc_active==0"); return; } if (imc_active>=IA_UP) imc_shutdown_network(); for (ign=imc_ignore_list; ign; ign=ign_next) { ign_next=ign->next; imc_freeignore(ign); } imc_ignore_list=NULL; for (info=imc_info_list; info; info=info_next) { info_next=info->next; imc_delete_info(info); } imc_info_list=NULL; if (imc_active >= IA_UP) imc_shutdown_network(); imc_strfree(imc_prefix); imc_prefix=NULL; if (imc_active >= IA_CONFIG2) imc_strfree(imc_name); imc_name=NULL; imc_active=IA_NONE; }
/* free_mail: free a mail structure */ static void free_mail(imc_mail *p) { if (!p) { imc_logerror("BUG: free_mail: freeing NULL pointer"); return; } if (p->usage) { imc_logerror("BUG: free_mail: freeing mail at %p with usage=%d", p, p->usage); return; } if (p->from) imc_strfree(p->from); if (p->to) imc_strfree(p->to); if (p->id) imc_strfree(p->id); if (p->text) imc_strfree(p->text); if (p->subject) imc_strfree(p->subject); if (p->date) imc_strfree(p->date); imc_cancel_event(NULL, p); imc_free(p, sizeof(*p)); }
/* update our routing table based on a packet received with path "path" */ static void updateroutes(const char *path) { imc_reminfo *p; const char *sender, *last; const char *temp; /* loop through each item in the path, and update routes to there */ last = imc_lastinpath(path); temp = path; while (temp && temp[0]) { sender=imc_firstinpath(temp); if (strcasecmp(sender, imc_name)) { /* not from us */ /* check if its in the list already */ p = imc_find_reminfo(sender, 1); if (!p) /* not in list yet, create a new entry */ { p=imc_new_reminfo(); p->name = imc_strdup(sender); p->ping = 0; p->alive = imc_now; p->route = imc_strdup(last); p->version = imc_strdup("unknown"); p->type = IMC_REMINFO_NORMAL; } else { /* already in list, update the entry */ if (strcasecmp(last, p->route)) { imc_strfree(p->route); p->route=imc_strdup(last); } p->alive=imc_now; p->type = IMC_REMINFO_NORMAL; } } /* get the next item in the path */ temp=strchr(temp, '!'); if (temp) temp++; /* skip to just after the next '!' */ } }
/* free_mailid: free a mailid */ static void free_mailid(imc_mailid *p) { if (!p) { imc_logerror("BUG: free_mailid: freeing NULL pointer"); return; } if (p->id) imc_strfree(p->id); imc_cancel_event(NULL, p); imc_free(p, sizeof(*p)); }
/* free_qnode: free a qnode */ static void free_qnode(imc_qnode *q) { if (!q) { imc_logerror("BUG: free_qnode: freeing NULL pointer"); return; } if (q->tomud) imc_strfree(q->tomud); if (q->data && !--q->data->usage) delete_ml(q->data); imc_cancel_event(NULL, q); imc_free(q, sizeof(*q)); }
/* checkrepeat: check for repeats in the memory table */ static int checkrepeat(const char *mud, unsigned long seq) { int i; for (i=0; i<IMC_MEMORY; i++) if (imc_memory[i].from && !strcasecmp(mud, imc_memory[i].from) && seq == imc_memory[i].sequence) return 1; /* not a repeat, so log it */ if (imc_memory[memory_head].from) imc_strfree(imc_memory[memory_head].from); imc_memory[memory_head].from = imc_strdup(mud); imc_memory[memory_head].sequence = seq; memory_head++; if (memory_head==IMC_MEMORY) memory_head=0; return 0; }
/* handle a packet destined for us, or a broadcast */ void imc_recv(const imc_packet *p) { imc_char_data d; int bcast; imc_reminfo *i; bcast=!strcmp(imc_mudof(p->i.to), "*") ? 1 : 0; getdata(p, &d); if(!imc_is_router) { i=imc_find_reminfo(imc_mudof(p->from),0); if(i) { if(i->path) imc_strfree(i->path); i->path=imc_strdup(p->i.path); i->ping=0; i->type=0; } } /* chat: message to a channel (broadcast) */ if (!strcasecmp(p->type, "chat") && !imc_isignored(p->from)) imc_recv_chat(&d, imc_getkeyi(&p->data, "channel", 0), imc_getkey(&p->data, "text", "")); /* emote: emote to a channel (broadcast) */ else if (!strcasecmp(p->type, "emote") && !imc_isignored(p->from)) imc_recv_emote(&d, imc_getkeyi(&p->data, "channel", 0), imc_getkey(&p->data, "text", "")); /* tell: tell a player here something */ else if (!strcasecmp(p->type, "tell")) { if (imc_isignored(p->from)) { imc_sendignore(p->from); } else { imc_recv_tell(&d, p->to, imc_getkey(&p->data, "text", ""), imc_getkeyi(&p->data, "isreply", 0)); } } /* who-reply: receive a who response */ else if (!strcasecmp(p->type, "who-reply")) imc_recv_whoreply(p->to, imc_getkey(&p->data, "text", ""), imc_getkeyi(&p->data, "sequence", -1)); /* who: receive a who request */ else if (!strcasecmp(p->type, "who")) { if (imc_isignored(p->from)) { imc_sendignore(p->from); } else { imc_recv_who(&d, imc_getkey(&p->data, "type", "who")); } } /* whois-reply: receive a whois response */ else if (!strcasecmp(p->type, "whois-reply")) imc_recv_whoisreply(p->to, imc_getkey(&p->data, "text", "")); /* whois: receive a whois request */ else if (!strcasecmp(p->type, "whois")) imc_recv_whois(&d, p->to); /* beep: beep a player */ else if (!strcasecmp(p->type, "beep")) { if (imc_isignored(p->from)) { imc_sendignore(p->from); } else { imc_recv_beep(&d, p->to); } } /* is-alive: receive a keepalive (broadcast) */ else if (!strcasecmp(p->type, "is-alive")) imc_recv_keepalive(imc_mudof(p->from), imc_getkey(&p->data, "versionid", "unknown"), imc_getkey(&p->data, "flags", "")); /* ping: receive a ping request */ else if (!strcasecmp(p->type, "ping")) imc_recv_ping(imc_mudof(p->from), imc_getkeyi(&p->data, "time-s", 0), imc_getkeyi(&p->data, "time-us", 0), p->i.path); /* ping-reply: receive a ping reply */ else if (!strcasecmp(p->type, "ping-reply")) imc_recv_pingreply(imc_mudof(p->from), imc_getkeyi(&p->data, "time-s", 0), imc_getkeyi(&p->data, "time-us", 0), imc_getkey(&p->data, "path", NULL), p->i.path); /* mail: mail something to a local player */ else if (!strcasecmp(p->type, "mail")) imc_recv_mail(imc_getkey(&p->data, "from", "error@hell"), imc_getkey(&p->data, "to", "error@hell"), imc_getkey(&p->data, "date", "(IMC error: bad date)"), imc_getkey(&p->data, "subject", "no subject"), imc_getkey(&p->data, "id", "bad_id"), imc_getkey(&p->data, "text", "")); /* mail-ok: remote confirmed that they got the mail ok */ else if (!strcasecmp(p->type, "mail-ok")) imc_recv_mailok(p->from, imc_getkey(&p->data, "id", "bad_id")); /* mail-reject: remote rejected our mail, bounce it */ else if (!strcasecmp(p->type, "mail-reject")) imc_recv_mailrej(p->from, imc_getkey(&p->data, "id", "bad_id"), imc_getkey(&p->data, "reason", "(IMC error: no reason supplied")); /* handle keepalive requests - shogar */ else if (!strcasecmp(p->type, "keepalive-request")) { if(imc_is_router) imc_logstring("Recieved keepalive request from %s", p->from); imc_send_keepalive(); } /* expire closed hubs - shogar */ else if (!strcasecmp(p->type, "close-notify")) { imc_reminfo *r; char fake[90]; struct timeval tv; if(imc_is_router) imc_logstring("%s reports %s closed.", p->from, imc_getkey(&p->data, "host","unknown")); if(imc_is_router) return; r = imc_find_reminfo(imc_getkey(&p->data,"host","unknown"),0); if(r) { r->type = IMC_REMINFO_EXPIRED; for(r=imc_reminfo_list;r;r=r->next) { char *sf; sprintf(fake,"!%s",imc_getkey(&p->data,"host","___unknown")); if(r->name && r->path && (sf=strstr(r->path,fake)) && sf && (*(sf+strlen(fake))=='!' || *(sf+strlen(fake)) == 0) ) { // imc_logstring("Expiring %s",r->path); r->type = IMC_REMINFO_EXPIRED; gettimeofday(&tv, NULL); imc_send_ping(r->name, tv.tv_sec, tv.tv_usec); } } } } /* These 4 added by me for the auto-hub-swap -- Scion 1/9/99 */ else if (!strcasecmp(p->type, "inforequest")) /* Request connection info from all 1.00a hubs -- Scion */ imc_recv_inforequest(p->from); /* Had to use inforequest because 0.10 responds to info-request :) */ else if (!strcasecmp(p->type, "info-reply")) /* receive the reply from the inforequest :) -- Scion */ imc_recv_info_reply(p->from, imc_getkey(&p->data, "hub", "no"), imc_getkeyi(&p->data, "direct", -1)); else if (!strcasecmp(p->type, "switch-reply")) /* hub confirmed that it added a connection to us. -- Scion */ imc_autoconnect_reply_accept( /* Add a connection back to the hub */ p->from, imc_getkey(&p->data, "host", "!!!"), imc_getkeyi(&p->data, "port", -1), imc_getkey(&p->data, "clientpw", "password"), imc_getkey(&p->data, "serverpw", "password"), imc_getkeyi(&p->data, "rcvstamp", 0), imc_getkeyi(&p->data, "noforward", 0), imc_getkey(&p->data, "flags", "none"), imc_getkey(&p->data, "localname", "!!!"), imc_getkey(&p->data, "confirm", "not accepted") ); else if (!strcasecmp(p->type, "imc-switch")) /* hub receives request to add a connection -- Scion */ imc_recv_autoconnect( p->from, imc_getkey(&p->data, "host", "!!!"), imc_getkeyi(&p->data, "port", -1), imc_getkey(&p->data, "clientpw", "password"), imc_getkey(&p->data, "serverpw", "password"), imc_getkeyi(&p->data, "rcvstamp", 0), imc_getkeyi(&p->data, "noforward", 0), imc_getkey(&p->data, "flags", "none"), imc_getkey(&p->data, "localname", "!!!") ); /* call catch-all fn if present */ else { imc_packet out; if (imc_recv_hook) if ((*imc_recv_hook)(p, bcast)) return; if (bcast || !strcasecmp(p->type, "reject")) return; /* reject packet */ if (!imc_is_router) { strcpy(out.type, "reject"); strcpy(out.to, p->from); strcpy(out.from, p->to); imc_clonedata(&p->data, &out.data); imc_addkey(&out.data, "old-type", p->type); imc_send(&out); imc_freedata(&out.data); } } }
void imc_shutdown_network(void) { imc_event *ev, *ev_next; imc_connect *c, *c_next; imc_reminfo *p, *pnext; if (imc_active < IA_UP) { imc_logerror("imc_shutdown_network: called with imc_active==%d", imc_active); return; } if (imc_lock) { imc_logerror("imc_shutdown_network: called from within imc_idle_select"); return; } imc_logstring("shutting down network"); if (imc_active == IA_LISTENING) imc_shutdown_port(); imc_logstring("rx %ld packets, %ld bytes (%ld/second)", imc_stats.rx_pkts, imc_stats.rx_bytes, (imc_now == imc_stats.start) ? 0 : imc_stats.rx_bytes / (imc_now - imc_stats.start)); imc_logstring("tx %ld packets, %ld bytes (%ld/second)", imc_stats.tx_pkts, imc_stats.tx_bytes, (imc_now == imc_stats.start) ? 0 : imc_stats.tx_bytes / (imc_now - imc_stats.start)); imc_logstring("largest packet %d bytes", imc_stats.max_pkt); imc_logstring("dropped %d packets by sequence number", imc_stats.sequence_drops); imc_mail_shutdown(); for (c=imc_connect_list; c; c=c_next) { c_next=c->next; do_close(c); imc_extract_connect(c); } imc_connect_list=NULL; if(!imc_is_router) icec_shutdown(); for (p=imc_reminfo_list; p; p=pnext) { pnext=p->next; imc_strfree(p->version); imc_strfree(p->name); if(p->path) imc_strfree(p->path); imc_free(p, sizeof(imc_reminfo)); } imc_reminfo_list=NULL; for (ev=imc_event_list; ev; ev=ev_next) { ev_next=ev->next; imc_free(ev, sizeof(imc_event)); } for (ev=imc_event_free; ev; ev=ev_next) { ev_next=ev->next; imc_free(ev, sizeof(imc_event)); } imc_event_list=imc_event_free=NULL; unlock_prefix(); imc_active=IA_CONFIG2; }