kismetbecomes wrote:Alternatively add a log function to your outbound packets so that you know precisely what the last packet was.
I'm sorry - I don't really want to piss you off much further PY.
But I will be lying if I would say I know how to add a log function to my outbound packets.
I hope you can be more patient with me tho.
If you have time to reply a guide or a tip how to - please do. Thanks a lot.
Don't worry.
You're not pissing me off
I'm just trying to emphasize the things I'm saying so that you don't miss them because I thought I had explained those points before.
Apparently I didn't explain it clearly enough though and if that's the case then it's my fault not yours.
You are just trying to learn and that's fine so don't worry about annoying me.
I'm here to help and teach (since I don't have time to actually dev any more) so just keep asking your questions.
I know I have the logging functionality built into my version of dev rev 4. I'm just a little surprised that it didn't make it through into the release.
Here's what you need to do to record all the packets that you send or receive.
First open up SocketClient.cpp in your "common" files
now find function
bool CClientSocket::ReceiveData( )This is where all incoming packets from the client are received and dealt with.
All we need to do is add a logging function so that we can see them all.
I added one a while ago to help with debugging but the trouble is I don't have a copy of the code prior to adding it so i can't tell you what I had to delete from the previous code.
The only thing I can do is post the entire function.
I recommend that you do not delete your existing function but simply comment it out then add this entire code afterwards so that it you want to revert then you can easily do it. This thing was a pain in the ass to make work properly when I did it.
Anyway here's the entire function
- // Receive this client's socket
- bool CClientSocket::ReceiveData( )
- {
- int ReceivedBytes;
- short BytesToRead;
-
-
- // Calculate bytes to read to get the full packet
- BytesToRead = PacketSize - PacketOffset;
- // This should never happen, but it is integrated:
- if ( BytesToRead > 0x600 - PacketOffset )
- {
- Log(MSG_WARNING,"wrong bytes to read, sid %i",sock);
- return false;
- }
-
- if ( BytesToRead == 0 )
- {
- Log(MSG_WARNING,"BytesToRead == 0, sid %i",sock);
- return false;
- }
-
-
- // Receive data from client
- ReceivedBytes = recv( sock, (char*)&Buffer[ PacketOffset ], BytesToRead, 0 );
- if ( ReceivedBytes <= 0 )
- {
- Log(MSG_WARNING,"ReceivedBytes <= 0, sid %i",sock);
- return false;
- }
-
- // Update pointer
- PacketOffset += ReceivedBytes;
-
- // If the packet is not complete, leave the function
- if ( ReceivedBytes != BytesToRead )
- {
- //Log(MSG_INFO,"Data not complete %u != %u, sid %i",ReceivedBytes,BytesToRead,sock);
- return true;
- }
-
- if ( PacketSize == 6 )
- {
- // We received the headerblock
- PacketSize = *((unsigned short*)&Buffer[0]);
- // Did we receive an incorrect buffer?
- if ( PacketSize < 6 )
- {
- Log( MSG_WARNING, "(SID:%i) Client sent incorrect blockheader., sid %i", sock );
- return false;
- }
- // Is the packet larger than just the header, then continue receiving
- if ( PacketSize > 6 )
- {
- //Log(MSG_INFO,"Data not complete, sid %i",sock);
- return true;
- }
-
- }
-
- cryptPacket( (char*)Buffer, this->CryptTable );
- CPacket* pak = (CPacket*)Buffer;
-
- Log(MSG_WARNING, "Received Packet <%04x> Size <%i>",pak->Command, (pak->Size -6));
-
- //LMA: Timestamp
- //LMA: changing directory for packet logs.
- time_t rtime;
- time(&rtime);
- char *timestamp = ctime(&rtime);
- timestamp[ strlen(timestamp)-1 ] = ' ';
-
- FILE *fh = NULL;
- switch(LOG_THISSERVER)
- {
- case LOG_LOGIN_SERVER:
- fh = fopen( PLOG_DIRECTORY LOG_LOGINPACKETS, "a+" );
- break;
- case LOG_CHARACTER_SERVER:
- fh = fopen( PLOG_DIRECTORY LOG_CHARPACKETS, "a+" );
- break;
- case LOG_WORLD_SERVER:
- if( pak->Command==0x7ec || pak->Command==0x808 )
- break;
- fh = fopen( PLOG_DIRECTORY LOG_WORLDPACKETS, "a+" );
- break;
- case LOG_SAME_FILE:
- if( pak->Command==0x7ec || pak->Command== 0x808 )
- break;
- fh = fopen( PLOG_DIRECTORY LOG_DEFAULTPACKETS, "a+" );
- break;
- }
-
- //PY incoming packet logging. Saves all incoming packets into inoutpackets.log in the log folder
- fh = fopen( "log/inoutpackets.log", "a+" );
- if ( fh != NULL )
- {
- //fprintf( fh, "(SID:%08u) IN %04x: ", sock, pak->Command );
- fprintf( fh, "%s- (SID:%08u) IN %04x: ",timestamp, sock, pak->Command );
- for ( int i=0; i<pak->Size-6; ++i )
- fprintf( fh, "%02x ", (unsigned char)pak->Buffer[i] );
- fprintf( fh, "\n" );
- fclose( fh );
- }
- //PY end
-
- // Handle actions for this packet
- if ( !GS->OnReceivePacket( this, pak ) )
- {
- //Log(MSG_WARNING,"!GS->OnReceivePacket sid %i",sock);
- return false;
- }
-
- // Reset values for the next packet
- PacketSize = 6;
- PacketOffset = 0;
-
- return true;
- }
And here's the one that sends the packets back to the client.
Do the same with this on. Just comment out the original but keep it there so that you can revert.
- // Send a packet to this client
- void CClientSocket::SendPacket( CPacket *P )
- {
- // :WARNING: IF WE ADD A CRYPT FUNCTION HERE WE MUST COPY THE
- // PACKET AND NOT USE THE ORIGINAL, IT WILL FUCK UP
- // THE SENDTOALL FUNCTIONS
-
- bool LogFile = true;
-
-
- //LMA: Stupid check.
- if(this==NULL)
- {
- Log(MSG_WARNING,"Trying to SendPacket with NULL Socket (trapped).");
- return;
- }
-
- if (!this->isActive) return;
-
- //LMA: Timestamp
- //LMA: changing dir for packet logs.
- time_t rtime;
- time(&rtime);
- char *timestamp = ctime(&rtime);
- timestamp[ strlen(timestamp)-1 ] = ' ';
-
- FILE *fh = NULL;
- switch(LOG_THISSERVER)
- {
- case LOG_LOGIN_SERVER:
- fh = fopen( PLOG_DIRECTORY LOG_LOGINPACKETS, "a+" );
- break;
- case LOG_CHARACTER_SERVER:
- fh = fopen( PLOG_DIRECTORY LOG_CHARPACKETS, "a+" );
- break;
- case LOG_WORLD_SERVER:
- if( P->Command==0x7ec || P->Command==0x808)
- break;
- fh = fopen( PLOG_DIRECTORY LOG_WORLDPACKETS, "a+" );
- break;
- case LOG_SAME_FILE:
- if( P->Command==0x7ec || P->Command==0x808 )
- break;
- fh = fopen( PLOG_DIRECTORY LOG_DEFAULTPACKETS, "a+" );
- break;
- }
-
- //PY Outgoing packet logging. Saves ALL packets into inoutpackets.log in the log folder
- fh = fopen( "log/inoutpackets.log", "a+" );
- if ( fh != NULL and LogFile)
- {
- //fprintf( fh, "(SID:%08u) OUT %04x: ", sock, P->Command );
- fprintf( fh, "%s- (SID:%08u) OUT %04x: ",timestamp, sock, P->Command );
- for ( int i=0; i<P->Size-6; ++i )
- fprintf( fh, "%02x ", (unsigned char)P->Buffer[i] );
- fprintf( fh, "\n" );
- fclose( fh );
- }
- //PY end
-
- u_long iMode = 1;
- #ifdef WIN32
- if (ioctlsocket(sock, FIONBIO, &iMode))
- {
- Log( MSG_WARNING, "ioctlsocket unblock: %i", errno);
- }
- #else
- if(ioctl(sock, F_SETFL, O_NONBLOCK)!=0)
- {
- Log( MSG_WARNING, "ioctlsocket unblock: %i", errno);
- }
- #endif
- int retval = send( sock, (char*)P, P->Size, 0 );
- if(P->Command == 0x723) //only log data for quest packets
- {
- Log(MSG_WARNING, "Send Packet <%04x> Size <%i>",P->Command, (P->Size -6));
- }
-
- iMode=0;
- #ifdef WIN32
- if(ioctlsocket(sock, FIONBIO, &iMode)==SOCKET_ERROR)
- {
- Log( MSG_WARNING, "ioctlsocket block: %i", errno);
- }
- #else
- if(ioctl(sock, F_SETFL, 0))!=0)
- {
- Log( MSG_WARNING, "ioctlsocket block: %i", errno);
- }
- #endif
- }
- // Handle client socket (threads)
- PVOID ClientMainThread( PVOID ClientSocket )
- {
- CClientSocket* thisplayer = (CClientSocket*) ClientSocket;
- fd_set fds;
- while(thisplayer->isActive)
- {
- FD_ZERO(&fds);
- FD_SET (thisplayer->sock, &fds);
- int Select = select( thisplayer->sock+1, &fds, NULL, NULL, NULL );
- if(Select == SOCKET_ERROR)
- {
- Log( MSG_ERROR,NULL,"Error in Select");
- thisplayer->isActive = false;
- }
- else
- {
- if(FD_ISSET( thisplayer->sock, &fds ))
- {
- if(!thisplayer->ReceiveData( ))
- thisplayer->isActive = false;
- }
- }
-
- }
- thisplayer->GS->DisconnectClient( thisplayer );
- pthread_exit(NULL);
- }
I've clearly commented the bits that I added but I'm pretty sure I deleted some code too. I just don't remember what.
Either way it should work fine if you just put in both entire functions.
After this, whenever it crashes you can just open inoutpackets.log and see what was the very last packet that was sent or received.
You will need to delete or empty this log file quite regularly.
It's gonna fill up very fast.
This is step 1 of setting up debug code. Do this first and then we can move on to adding other checks so that we can zero in on precisely what your issue is.
PS. The code i posted is "common" so you should probably rebuild all three servers if you want to see packets recorded from login, char and worldserver.
Most of the time i only rebuild the worldserver since the crashes are only very very rarely related to one of the others. Still it's up to you.