08 Oct, 2012, Davenge wrote in the 1st comment:
Votes: 0
Hey everyone, I'm working with an SWFOTE(smaug//swr) mud and I seem to be struggling to get rid of the Line too long. malarchy where it limits inputted commands to 254 characters. I'm assuming it does this do to memory allocation issues, but I'm struggling to see all the elements I would need to change to understand/visualize so that emotes and inputs can be unlimited in character lengths. From getting the input, to process_dns to then read_from_buffer(which has the actually 254 character length if-check)… I could just take the if-check out but then, like I said, I'm worried about memory allocation issues. Do I need to be? If anyone has done this before or could point me to a C codebase in which they have unlimited inputs for buffers/commands, I'd greatly appreciate it!

Thanks, Davenge.
08 Oct, 2012, Davion wrote in the 2nd comment:
Votes: 0
My Smaug/SWR is pretty … non existent :). So! Take what you will from this. Your error message is generated from within your code. First thing I'd do is locate this error message. If it has a hard coded number, eg.
if( strlen(buf) > 256)
the 256, being the magic number, this is bad. You will want to define a constant. Most of the merc tree have something called MAX_INPUT_LENGTH(or MIL). This constant should be the limiter to how much input a person can send. It should always be less than MAX_STRING_LENGTH (or MSL). To increase the string acceptance on your MUD you should just need to increase MAX_INPUT_LENGTH and be done with it.

If 256 is hardcoded as a magic number into your game, then you'll want to grep for 256 and find other places its in there. I know this happens with MAX_LEVEL in most ROM muds. Often greping for 60/50 can save you a lot of issues with balance :).
08 Oct, 2012, quixadhal wrote in the 3rd comment:
Votes: 0
If you wanted it to be really unlimited (which you don't), you would need to replace the code that reads from the socket in such a way that it grabs chunks from the socket buffer in a loop, realloc'ing the buffer as you go, until you've exhausted the packets from that descriptor. If you haven't yet found the end-of-input token (usually CR, LF, or some combination thereof), you let it sit and hope the rest of the packet fragments come in next time through the loop.

I don't suggest this, as it's overkill for a MUD, but that's how you'd be "unlimited"…. at least up to the amount of RAM you have to work with. :)

I can tell you that SmaugFUSS (v 1.9) has a MAX_INBUF_SIZE define, but the code in comm.c has 254 hardcoded… it really should be (MAX_INBUF_SIZE - 2) because of the way it manipulates the string. IE: If it finds LF before CR (which backwards DikuMUD clients sometimes use), you really want it to nuke the LF at position N-2, becasue there will be a useless CR at N-1 that you don't want to have left for future processing.
08 Oct, 2012, Davenge wrote in the 4th comment:
Votes: 0
Seems I'm not good enough with this side of C and how it works with muds, file descriptors etc. Need some help, I'd really like players to be able to have unlimited sized RP posts/says/chats and bios and descriptions.

Anyone able to help me? Or teach me? Someone that really understands how the information flows back and fourth from the client and server and can help me achieve what I need.
08 Oct, 2012, quixadhal wrote in the 5th comment:
Votes: 0
First, step back and look at your actual design goal and think about what the simplest way of implementing it is.

You say you'd really like the players to have unlimited sized things. You don't really mean that. Either you THINK that sounds good, without knowing what it actually means, or you WANT players to be bombarded with so much spam they'll run screaming and never set foot near your game again.

The old school terminal size was 80x25, which resulted in a screen taking up 2000 characters. Most MUDs tend to still stick to this idea when designing room descriptions and other "large" blocks of text. Even if you assume people today have larger screens, it's likely most players won't have more than 150x50, which is 7500 characters.

So, how much text do you REALLY want someone to be able to spam at a time?

If we use the classic 80x25 screen model, the usual input buffer size of 256 characters means a "tell" or "chat message" can fill up 3 rows of text. Assuming your players are actually PLAYING, and not just sitting around doing nothing but chatting, how many 3 line messages are they going to be able to read while combat messages scroll?

Now, let's bump the buffer size to 1024. That means a single tell can now fill HALF the user's screen. Is that really what you want? Remember what a text mud is about. How many times have you expressed a single idea that has needed to span half a screen's worth of real estate?

Given that today's players may well have larger windows, I think 1024 might be a quite reasonable size to use. However, realize that even on a large screen, that's still likely to be 5 to 10 LINES of text, which will scroll right along with all the combat messages, the "Joe walks in from the south" messages, and everything else competing for attention. Even if you have people who like to talk in giant run-on sentances, how many are going to be able to actually READ all that?

For comparison, everything above this line has taken 1930 characters.

So, with that in mind, do you really (REALLY!) want to allow unlimited text input? Or would you rather allow input to be large enough that the majority of people will very rarely ever run into the issue of having hit the limit? And if you DO really want such things to be unlimited, are you prepared to deal with players using that as a form of griefing?
09 Oct, 2012, Runter wrote in the 6th comment:
Votes: 0
Well, I think he can really want unlimited input while still saying he doesn't want unlimited sized descriptions, gossips, etc. A common problem is when you allow, for example, descriptions with 100 character lengths but inputs only accept 50 characters. (Deflated for this example.) So you could enter the amount of text the description allows and still have it cut off. So I think it's completely legit to say you want user to be able to input very long things, without technology standing in the way of it happening, and then set limits from there.
09 Oct, 2012, quixadhal wrote in the 7th comment:
Votes: 0
So, you're OK with a user deciding to input a 20MB text file, pasted into their telnet client? Or a griefer trying to crash the MUD by piping /dev/true into it? I happen to agree that the kind of pathetic limits put into place back when MUD's needed to run in 4M of memory are a bit silly these days, but I also think if you can't break up your input into chunks that fit on a normal sized screen, you have a personal problem.

256 characters is *usually* enough, but I've occasionally found myself running over it in chat. I can't imagine needing more than 2K for a single input sequence, regardless of the use. That moves beyond the realm of text input, and approaches file uploading, IMO.

From a purely technical point of view, expecting anything larger than a typical TCP/IP packet can contain is probably a recipie for failure, especially when dealing with the DikuMUD lack of a proper TELNET stack. For most purposes, packets over 4K are likely to be fragmented, and above 8K almost certainly will be fragmented. For the MUD admin/coder, that means every so often they'll attempt to process something that chops a TELNET sequence or color code in half, and wonder why it isn't working right.

Having said that, if the OP really wants to do this, the idea is pretty simple.

SmaugFUSS (and likely the SWFOTE he's using) has a read_from_descriptor() function that does the actual transfer of data from the socket to a fixed buffer. It's a large buffer (128K?), but the idea is to grab as much as possible and stuff it in there, then let the main loop process single lines at a time, which in turn have their own smaller buffers (1024 or 256 characters).

You'd change that to realloc() more memory as long as there were stuff to be read. You may also want to impose some kind of timeout, in case somebody DOES spam 20G of data, so you don't spend several minutes trying to read it.

read_from_buffer() is the part that pulls each command/line out, and that would also want to be modified so that instead of a hard limit, it scans for the first CR, LF, or NUL, then allocates a new buffer of that size to return. Be sure you free the old one first, or you'll leak memory.
09 Oct, 2012, Tyche wrote in the 8th comment:
Votes: 0
It's even a problem for a working Telnet stack. I believe there's a discussion about the size of Telnet sub-negotiation sequences in the ZMP forum here.
I think the only answer is to use some reasonable working size for what you expect and then flush the input and inform the client of the problem if
they exceed that (or disconnect the client if need be).
09 Oct, 2012, Davenge wrote in the 9th comment:
Votes: 0
Well, I guess I wasn't very clear about why I wanted it to do this. I will elaborate. In daily gameplay, yes, going over 256 characters is highly unlikely. However, there are RPers who play coded muds, such as myself, who when they post in an RP situation, their posts can be multiple paragraphs long. Describing the actions of their character, speaking, internal thoughts, character twitches and qwerks. RP is a turn based thing typically, and one post is one turn. So, taking multiple posts to do something could be troublesome. of course, I can think of ways to circumvent the "turn" system by passing flags or something. And running with maybe a higher limit like 1024.

Let me show you the problem I am having.

bool read_from_descriptor( DESCRIPTOR_DATA * d )
{
unsigned int iStart, iErr;

/*
* Hold horses if pending command already.
*/
if( d->incomm[0] != '\0' )
return TRUE;

/*
* Check for overflow.
*/
iStart = strlen( d->inbuf );
if( iStart >= sizeof( d->inbuf ) - 10 )
{
log_printf( "%s input overflow!", d->host );
write_to_descriptor( d->descriptor, "\n\r*** PUT A LID ON IT!!! ***\n\r", 0 );
return FALSE;
}

for( ;; )
{
int nRead;

nRead = recv( d->descriptor, d->inbuf + iStart, sizeof( d->inbuf ) - 10 - iStart, 0 );
iErr = errno;
if( nRead > 0 )
{
iStart += nRead;
if( d->inbuf[iStart - 1] == '\n' || d->inbuf[iStart - 1] == '\r' )
break;
}
else if( nRead == 0 && d->connected >= CON_PLAYING )
{
log_string_plus( "EOF encountered on read.", LOG_COMM, LEVEL_IMMORTAL );
return FALSE;
}
else if( iErr == EWOULDBLOCK )
break;
else
{
perror( "Read_from_descriptor" );
return FALSE;
}
}

d->inbuf[iStart] = '\0';
return TRUE;
}


This is my read from descriptor, I got here yesterday and was completely confused by many things. However, since then I have switched which version of the SWFOTE I am using and this part makes more sense. Allow inbuf to be declared without a size, and then as it reads in data from the socket via the read. Use some sort of "new" command to redefine to a higher size each time it got full? I'd understand a bit better how to do that with C++, as the "new" command makes it simple. So, do I just need to study memory allocation in C? This is assuming the recv(…) is just a hyped up read command. I also didn't really understand how the descriptors work, but I'm willing to overlook…
09 Oct, 2012, quixadhal wrote in the 10th comment:
Votes: 0
First things first.

d->inbuf[] is part of the descripitor structure, so take a look at mud.h to see how large it's actually declared. In SmaugFUSS, it's MAX_INBUF_SIZE, which is #define'd as 1024.

Now, before messing with read_from_descriptor(), look for the function which was actually causing your problem. You said you wre getting a "Line too long" message, and grep shows that to be in read_from_buffer(), which is in comm.c.

Looking at the SmaugFUSS version, it has a couple spots where it SHOULD be using MAX_INBUF_SIZE, but instead of using an old constant of 254. So, changing that will already partially fix your problem.

void read_from_buffer( DESCRIPTOR_DATA * d )
{
int i, j, k, iac = 0;

/*
* Hold horses if pending command already.
*/
if( d->incomm[0] != '\0' )
return;

/*
* Look for at least one new line.
*/
for( i = 0; d->inbuf[i] != '\n' && d->inbuf[i] != '\r' && i < MAX_INBUF_SIZE; i++ ) /* <<< HERE */
{
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_INBUF_SIZE - 2 ) /* <<< and HERE */
{
write_to_descriptor( d, "Line too long.\r\n", 0 );


I changed mine to be MIS-2, because some Diku clients send lines incorrectly as LFCR, so you might find your end-of-line at len-1 OR at len-2. 1022 bytes is still pretty good sized.

If that isn't enough, you can then modify the #define for MAX_INBUF_SIZE to something larger and see what happens. I would seriously advise against anything larger than 4096, for reasons I stated above.

If you really think you have to have more than a fixed constant, you can THEN delve into allocating and resizing memory, but I will repeat that nobody but you will ever know or care that you did all the work to make that happen, and debugging memory issues is one of the most annoying things you can possibly do.

Note that if you do make things larger than MAX_STRING_LENGTH, you have a whole other world of hurt waiting for you, as you then have to change the ENTIRE way the MUD handles strings.
09 Oct, 2012, Davenge wrote in the 11th comment:
Votes: 0
Ya, I've already done that now that I understand it all a bit better and realize I won't have memory issues. A thousand character is a lot. It will do for now. Thanks for the help!
0.0/11