/**************************************************************************
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* *
* Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* *
* In order to use any part of this Merc Diku Mud, you must comply with *
* both the original Diku license in 'license.doc' as well the Merc *
* license in 'license.txt'. In particular, you may not remove either of *
* these copyright notices. *
* *
* Much time and thought has gone into this software and you are *
* benefiting. We hope that you share your changes too. What goes *
* around, comes around. *
***************************************************************************
* ROM 2.4 is copyright 1993-1998 Russ Taylor *
* ROM has been brought to you by the ROM consortium *
* Russ Taylor (rtaylor@hypercube.org) *
* Gabrielle Taylor (gtaylor@hypercube.org) *
* Brian Moore (zump@rom.org) *
* By using this code, you have agreed to follow the terms of the *
* ROM license, in the file Rom24/doc/rom.license *
***************************************************************************
* 1stMud ROM Derivative (c) 2001-2004 by Markanth *
* http://www.firstmud.com/ <markanth@firstmud.com> *
* By using this code you have agreed to follow the term of *
* the 1stMud license in ../doc/1stMud/LICENSE *
***************************************************************************/
#ifndef __COMM_DESCRIPTOR_H_
#define __COMM_DESCRIPTOR_H_ 1
int
d_print (Descriptor * d, const char *txt)
{
int length;
if (!d || NullStr (txt))
return 0;
length = strlen (txt);
if (d->outtop == 0)
{
if (!d->fcommand)
{
d->outbuf[d->outtop++] = '\n';
d->outbuf[d->outtop++] = '\r';
}
if (d->fPrompt)
{
d->outbuf[d->outtop++] = '\n';
d->outbuf[d->outtop++] = '\r';
d->fPrompt = false;
}
}
while (d->outtop + length >= d->outsize)
{
char *tmpbuf;
if (d->outsize >= 32000)
{
bug ("Buffer overflow. Closing.");
close_socket (d);
return -1;
}
d->outsize *= 2;
alloc_mem (tmpbuf, char, d->outsize);
strncpy (tmpbuf, d->outbuf, d->outtop);
free_mem (d->outbuf);
d->outbuf = tmpbuf;
}
strncpy (d->outbuf + d->outtop, txt, length);
d->outtop += length;
return length;
}
int
d_println (Descriptor * d, const char *txt)
{
if (!d)
return 0;
return (d_print (d, txt) + d_print (d, NEWLINE));
}
int
d_printf (Descriptor * d, const char *txt, ...)
{
va_list args;
char buf[MPL];
if (!d || NullStr (txt))
return 0;
va_start (args, txt);
vsnprintf (buf, sizeof (buf), txt, args);
va_end (args);
return d_print (d, buf);
}
int
d_printlnf (Descriptor * d, const char *txt, ...)
{
char buf[MPL];
if (!d)
return 0;
buf[0] = NUL;
if (!NullStr (txt))
{
va_list args;
va_start (args, txt);
vsnprintf (buf, sizeof (buf), txt, args);
va_end (args);
}
return d_println (d, buf);
}
int
write_to_socket (SOCKET desc, const char *txt, int length)
{
int iStart, nWrite = 0, nBlock;
if (length <= 0)
{
length = strlen (txt);
}
for (iStart = 0; iStart < length; iStart += nWrite)
{
nBlock = Min (length - iStart, 4096);
nWrite = send (desc, txt + iStart, nBlock, 0);
if (nWrite < 0)
{
#ifdef WIN32
if (WSAGetLastError () == WSAEWOULDBLOCK)
break;
#else
#ifndef EAGAIN
#define EAGAIN 11
#endif
#ifndef ENOSR
#define ENOSR 63
#endif
if (errno == EAGAIN || errno == ENOSR)
break;
#endif
socket_error ("write_to_socket()");
return -1;
}
}
return iStart + Min (0, nWrite);
}
int
d_write (Descriptor * d, const char *txt, int length)
{
if (!d)
return 0;
if (length <= 0)
length = strlen (txt);
d->bytes_normal += length;
#ifndef DISABLE_MCCP
if (d->out_compress)
{
z_stream *s = d->out_compress;
int bad_write_loop = 0, totalwritten = 0, written = 0, len;
s->next_in = (unsigned char *) txt;
s->avail_in = length;
while (s->avail_in && bad_write_loop < 5)
{
s->avail_out =
COMPRESS_BUF_SIZE - (s->next_out - d->out_compress_buf);
if (s->avail_out)
{
if (deflate (s, Z_SYNC_FLUSH) != Z_OK)
{
logf ("d_write() - compression error.");
return -1;
}
}
len = d->out_compress->next_out - d->out_compress_buf;
written =
write_to_socket (d->descriptor,
(char *) d->out_compress_buf, len);
if (written > 0)
{
d->bytes_compressed += written;
if (written < len)
{
memmove (d->out_compress_buf,
d->out_compress_buf + written, len - written);
}
d->out_compress->next_out = d->out_compress_buf + len - written;
totalwritten += written;
}
else
{
bad_write_loop++;
}
}
if (bad_write_loop == 5)
{
if (totalwritten)
{
return totalwritten;
}
return -1;
}
return length;
}
else
#endif
return write_to_socket (d->descriptor, txt, length);
}
#ifdef __cplusplus
int
Descriptor::wrap (const char *buf)
{
Descriptor *d = this;
#else
int
dwrap (Descriptor * d, const char *buf)
{
#endif
static char out[MSL * 5];
int width;
int pos;
char *p;
if (!d)
return 0;
width = ScrWidth (d);
p = reformat_desc ((char *) buf);
pos = 0;
out[0] = NUL;
do
{
pos = get_line_len (p, width);
if (pos > 0)
{
strncat (out, p, pos);
p += pos;
strcat (out, NEWLINE);
}
else
{
strcat (out, p);
break;
}
}
while (true);
return d_print (d, out);
}
int
dwrapln (Descriptor * d, const char *buf)
{
if (!d)
return 0;
return (dwrap (d, buf) + d_print (d, NEWLINE));
}
int
dwrapf (Descriptor * d, const char *buf, ...)
{
va_list args;
char format[MPL];
if (!d || NullStr (buf))
return 0;
va_start (args, buf);
vsnprintf (format, sizeof (format), buf, args);
va_end (args);
return dwrap (d, format);
}
int
dwraplnf (Descriptor * d, const char *buf, ...)
{
char format[MPL];
if (!d)
return 0;
format[0] = NUL;
if (!NullStr (buf))
{
va_list args;
va_start (args, buf);
vsnprintf (format, sizeof (format), buf, args);
va_end (args);
}
return d_println (d, format);
}
#endif