bool_t write_to_descriptor(DESCRIPTOR_DATA *d, char *txt, int length) {
if (length <= 0)
length = strlen(txt);
if (d->mccp)
return write_compressed(d, txt, length);
return write_to_descriptor_uncompressed(d->descriptor, txt, length);
}
void read_from_buffer(DESCRIPTOR_DATA *d) {
/*
* Hold horses if pending command already.
*/
if (d->incomm[0] != '\0')
return;
int i, k;
/*
* Look for at least one new line.
*/
for (i = 0;d->inbuf[i] != '\n' && d->inbuf[i] != '\r';i ++) {
if (d->inbuf[i] == '\0')
return;
}
/*
* Canonical input processing.
*/
for (i = 0, k = 0;d->inbuf[i] != '\n' && d->inbuf[i] != '\r';i ++) {
if (k >= MAX_INPUT_LENGTH - 2) {
write_to_descriptor(d, "Line too long.\n\r", 0);
/* skip the rest of the line */
for (;d->inbuf[i] != '\0';i ++) {
if (d->inbuf[i] == '\n' || d->inbuf[i] == '\r')
break;
}
d->inbuf[i] = '\n';
d->inbuf[i + 1] = '\0';
break;
}
if (d->inbuf[i] == (signed char)IAC) {
if ( !memcmp( &d->inbuf[i], mccp_do, strlen(mccp_do))) {
i += strlen(mccp_do) - 1;
compressStart(d);
}
else if ( !memcmp( &d->inbuf[i], mccp_dont, strlen(mccp_dont))) {
i += strlen(mccp_dont) - 1;
compressEnd(d);
}
}
else if (d->inbuf[i] == '\b' && k > 0)
–k;
else if (xisascii(d->inbuf[i]) && xisprint(d->inbuf[i]))
d->incomm[k ++] = d->inbuf[i];
}
/*
* Finish off the line.
*/
if (k == 0)
d->incomm[k ++] = ' ';
d->incomm[k] = '\0';
/*
* Deal with bozos with #repeat 1000 …
*/
if (k> 1 || d->incomm[0] == '!') {
if (d->incomm[0] != '!' && str_cmp(d->incomm, d->inlast)) {
d->repeat = 0;
}
else {
if ( ++d->repeat >= 25) {
sprintf(log_buf, "%s input spamming!", d->host);
log_string(log_buf);
d->repeat = 0;
write_to_descriptor(d, "\n\r*** PUT A LID ON IT!!! ***\n\r", 0);
/*
strcpy( d->incomm, "quit" );
*/
}
}
}
/*
* Do '!' substitution.
*/
if (d->incomm[0] == '!' && d->incomm[1] != '!')
strcpy(d->incomm, d->inlast);
else
strcpy(d->inlast, d->incomm);
/*
* Shift the input buffer.
*/
while (d->inbuf[i] == '\n' || d->inbuf[i] == '\r')
i ++;
for (k = 0;(d->inbuf[k] = d->inbuf[i + k]) != '\0';k ++)
;
}
bool_t check_reconnect(DESCRIPTOR_DATA *d, char *name, bool_t fConn) {
CHAR_DATA *ch, *ch_next, *tempChar;
for (ch = char_list;ch ;ch = ch_next) {
ch_next = ch->next;
if (!ch->valid || IS_NPC(ch) || ( fConn && ch->desc) || str_cmp(d->character->charname, ch->charname))
continue;
if ( !fConn)
replace_string(&d->character->pcdata->pwd,ch->pcdata->pwd);
else {
tempChar = d->character;
extract_char(d->character, TRUE, CHAR_RETURN_IGNORED);
free_char(tempChar);
d->character = ch;
ch->desc = d;
ch->timer = 0;
send_to_char("Reconnecting.\n\r", ch);
act("$n has reconnected.", ch, NULL, NULL, TO_ROOM );
char buf[MAX_STRING_LENGTH];
sprintf(log_buf, "%s@%s reconnected.", ch->charname, d->host);
log_string(log_buf);
sprintf(buf, "%s@%s has reconnected.", ch->charname, d->host);
if ( !IS_IMP(ch))
info(buf, LEVEL_SENIOR, INFO_PLR_CONNECT);
d->connected = !ch->in_room ? CON_GET_REMORT : CON_PLAYING;
compressStart(d);
MXPSendTag( d, "<VERSION>" );
}
return TRUE;
}
return FALSE;
}
void close_socket(DESCRIPTOR_DATA *dclose) {
if (!dclose)
return;
if (dclose->outtop > 0)
process_output(dclose, FALSE );
if (dclose->snoop_by )
write_to_buffer(dclose->snoop_by, "Your victim has left the realm.\n\r");
DESCRIPTOR_DATA *d;
for (d = descriptor_list;d ;d = d->next) {
if (d->snoop_by == dclose)
d->snoop_by = NULL;
}
CHAR_DATA *ch = dclose->character;
if (ch) {
bool_t isSwitched = dclose->original ? TRUE : FALSE;
if (isSwitched)
do_return(ch, "");
sprintf(log_buf, "Closing link to %s: address %p", ch->charname, ch);
log_string(log_buf);
if (dclose->connected == CON_PLAYING || dclose->connected == CON_REDITOR || dclose->connected == CON_AEDITOR
|| dclose->connected == CON_MEDITOR || dclose->connected == CON_MPEDITOR || dclose->connected
== CON_HEDITOR || dclose->connected == CON_OEDITOR || dclose->connected == CON_GET_REMORT
|| dclose->connected == CON_SUB_CLASS || dclose->connected == CON_SUB_CLASS2
|| dclose->connected == CON_REMORT) {
act("$n has lost $s link.", ch, NULL, NULL, TO_ROOM );
ch->desc = NULL;
if (isSwitched)
dclose->character->desc = NULL;
}
else {
free_char( dclose->original ? dclose->original : dclose->character );
}
}
if ( dclose == descriptor_list ) {
descriptor_list = descriptor_list->next;
}
else {
for ( d = descriptor_list; d && (d->next != dclose); d = d->next )
;
if ( d )
d->next = dclose->next;
else
bug( "Close_socket: dclose not found.", 0 );
}
compressEnd(dclose);
close( dclose->descriptor );
free_descriptor(dclose);
}
in recycle.c
void free_descriptor(DESCRIPTOR_DATA *d) {
if ( !d)
return;
log_param("descriptor memory freed: address %p", d);
if (!compressEnd(d))
compressEnd(d);
ProtocolDestroy( d->pProtocol );
free_string( &d->host);
free_string( &d->showstr_head);
if (d->pString && *d->pString)
free_string( &*d->pString);
free_string( &d->outbuf);
if (d == descIt) {//bloody hack to solve a bug in nanny
free(d);
descIt = NULL;
}
else if (d == descItNext) {
descItNext = d->next;
free(d);
}
else
free(d);
d = NULL;
}
case CON_GET_OLD_PASSWORD:
write_to_buffer(d, "\n\r");
if (str_cmp(argument, ch->pcdata->pwd)) {
//crypt version if (str_cmp(crypt(argument,ch->charname), ch->pcdata->pwd)) {
sprintf(buf, "Wrong Password: %s@%s\n\r", ch->charname, d->host);
info(buf, LEVEL_SENIOR, INFO_BUG);
sprintf(buf, "Typed: %s\n\r", argument);
log_param("Wrong password for %s: Typed: %s\n\r", ch->charname, argument);
info(buf, LEVEL_IMP, INFO_BUG);
write_to_buffer(d, "Wrong password.\n\r");
if (d->character) {
extract_char(d->character, TRUE, CHAR_RETURN_LIST);
free_char(ch);
}
close_socket(d);
return;
}
write_to_buffer(d, echo_on_str);
if (check_playing(d, ch->charname))
return;
if (check_reconnect(d, ch->charname, TRUE))
return;
sprintf(log_buf, "%s@%s has connected.", ch->charname, d->host);
sort_connected(ch);
log_string(log_buf);
//we store the host in pcdata here cause in case of someone going linkdead we lose the descriptor
//and so cannot save the last ip he connected from.
if (ch->desc && ch->desc->host && ch->pcdata)
replace_string( &ch->pcdata->host, ch->desc->host);
connections ++;
if ( !IS_IMP(ch))
info(log_buf, LEVEL_SENIOR, INFO_PLR_CONNECT);
if (IS_IMMORTAL(ch)) {
send_to_char(get_acolor_ch(ch, C_GRN), ch);
do_help(ch, "imotd");
send_to_char(get_color_ch(ch, COL_NORM), ch);
d->connected = CON_READ_IMOTD;
}
if ( !IS_SET(ch->config, CONF_PKILL) && ch->level >= LEVEL_PK) {
do_help(ch, "pkill");
write_to_buffer(d, "\n\rWill you be PK or NPK? ");
d->connected = CON_PKILL;
}
else {
send_to_char(get_acolor_ch(ch, C_YEL), ch);
do_help(ch, "motd");
send_to_char(get_color_ch(ch, COL_NORM), ch);
d->connected = CON_READ_MOTD;
}
compressStart(ch->desc);
break;
void free_descriptor(DESCRIPTOR_DATA *d) {
if ( !d)
return;
log_param("descriptor memory freed: address %p", d);
if (!compressEnd(d))
compressEnd(d);
ProtocolDestroy( d->pProtocol );
free_string( &d->host);
free_string( &d->showstr_head);
if (d->pString && *d->pString)
free_string( &*d->pString);
free_string( &d->outbuf);
if (d == descIt) {//bloody hack to solve a bug in nanny
free(d);
descIt = NULL;
}
else if (d == descItNext) {
descItNext = d->next;
free(d);
}
else
free(d);
d = NULL;
}
static void CompressStart(descriptor_t *apDescriptor) {
/* If your mud uses MCCP (Mud Client Compression Protocol), you need to
* call whatever function normally starts compression from here - the
* ReportBug() call should then be deleted.
*
* Otherwise you can just ignore this function.
*/
if (apDescriptor->character && IS_SET(apDescriptor->character->config, CONF_MCCP))
compressStart(apDescriptor);
}
static void CompressEnd(descriptor_t *apDescriptor) {
/* If your mud uses MCCP (Mud Client Compression Protocol), you need to
* call whatever function normally starts compression from here - the
* ReportBug() call should then be deleted.
*
* Otherwise you can just ignore this function.
*/
if ((apDescriptor->character && IS_SET(apDescriptor->character->config, CONF_MCCP)) || apDescriptor->mccp)
compressEnd(apDescriptor);
}
On a side note, I never did really like how the SMAUG base chunks out data like it does. It makes more sense to me to just send as much as possible as quickly as you can, and if the socket is going to block, you wait till next time to not hold up the whole system.