added source folders
This commit is contained in:
1 parent
f23521f720
commit
cfdc19df45
145 files changed
+54574
No files matched your search
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
Rose Online Server Emulator
|
||||
Copyright (C) 2006,2007 OSRose Team http://osroseon.to.md
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
depeloped with Main erose/hrose source server + some change from the original eich source
|
||||
*/
|
||||
#include "sockets.h"
|
||||
|
||||
// Constructor
|
||||
CBaseSocket::CBaseSocket( )
|
||||
{
|
||||
sock = INVALID_SOCKET;
|
||||
isActive = false;
|
||||
}
|
||||
|
||||
// Destructor
|
||||
CBaseSocket::~CBaseSocket( )
|
||||
{
|
||||
}
|
||||
|
||||
// Close all open sockets
|
||||
void CBaseSocket::CloseSocket( void )
|
||||
{
|
||||
// Leave function, if socket isn't active
|
||||
if ( !isActive ) return;
|
||||
// Close socket
|
||||
close( sock );
|
||||
sock = INVALID_SOCKET;
|
||||
isActive = false;
|
||||
}
|
||||
|
||||
// Init winsocket, if we are using Windows
|
||||
bool InitWinSocket ( void )
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WSADATA wsa;
|
||||
return (WSAStartup(MAKEWORD(2,0),&wsa)==0);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Close winsocket, if we are using Windows
|
||||
void CloseWinSocket( void )
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WSACleanup( );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
Rose Online Server Emulator
|
||||
Copyright (C) 2006,2007 OSRose Team http://osroseon.to.md
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
developed with Main erose/hrose source server + some change from the original eich source
|
||||
*/
|
||||
#include "sockets.h"
|
||||
#include "seh.hpp"
|
||||
#include "config.h"
|
||||
|
||||
// Constructor
|
||||
CClientSocket::CClientSocket( )
|
||||
{
|
||||
PacketSize = 6; // Starting size
|
||||
PacketOffset = 0; // No bytes read, yet.
|
||||
}
|
||||
|
||||
// Destructor
|
||||
CClientSocket::~CClientSocket( )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// 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 > 0x400 - PacketOffset ) return false;
|
||||
if ( BytesToRead == 0 ) return false;
|
||||
|
||||
// Receive data from client
|
||||
ReceivedBytes = recv( sock, (char*)&Buffer[ PacketOffset ], BytesToRead, 0 );
|
||||
if ( ReceivedBytes <= 0 ) return false;
|
||||
|
||||
// Update pointer
|
||||
PacketOffset += ReceivedBytes;
|
||||
|
||||
// If the packet is not complete, leave the function
|
||||
if ( ReceivedBytes != BytesToRead ) return true;
|
||||
|
||||
if ( PacketSize == 6 )
|
||||
{
|
||||
// We received the headerblock
|
||||
#ifndef USE124
|
||||
PacketSize = DecryptBufferHeader( &CryptStatus, CryptTable, Buffer );
|
||||
#else
|
||||
CPacket* header = (CPacket*)&Buffer;
|
||||
PacketSize = header->Size;
|
||||
#endif
|
||||
|
||||
// Did we receive an incorrect buffer?
|
||||
if ( PacketSize < 6 )
|
||||
{
|
||||
Log(MSG_ERROR, "(SID:%i) Client sent incorrect blockheader.", sock );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Is the packet larger than just the header, then continue receiving
|
||||
if ( PacketSize > 6 ) return true;
|
||||
}
|
||||
|
||||
#ifndef USE124
|
||||
// We received the whole packet - Now we try to decrypt it
|
||||
if ( !DecryptBufferData( CryptTable, Buffer ) )
|
||||
{
|
||||
Log(MSG_ERROR, "(SID:%i) Client sent illegal block.", sock );
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
cryptPacket( (char*)Buffer, this->ct);
|
||||
#endif
|
||||
CPacket* pak = (CPacket*)&Buffer;
|
||||
|
||||
//comment to prevent packet logging
|
||||
FILE *fh = NULL;
|
||||
fopen_s (&fh, "log/inoutpackets.log", "a+");
|
||||
if ( fh != NULL ) {
|
||||
fprintf( fh, "(SID:%08u) IN %04x: ", 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 );
|
||||
}
|
||||
|
||||
// Handle actions for this packet
|
||||
if ( !GS->OnReceivePacket( this, pak ) )
|
||||
{
|
||||
//Log(MSG_ERROR, "onrecieve packet returned false");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Reset values for the next packet
|
||||
PacketSize = 6;
|
||||
PacketOffset = 0;
|
||||
//Log(MSG_DEBUG, "onrecieve packet returned true");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Send a packet to this client
|
||||
void CClientSocket::SendPacket( CPacket *P )
|
||||
{
|
||||
//first log it so we don't have to worry about encryption. Comment to prevent logging
|
||||
bool LogFile = true;
|
||||
FILE *fh = NULL;
|
||||
fopen_s (&fh, "log/receivedpackets.log", "a+");
|
||||
|
||||
if ( fh != NULL && LogFile)
|
||||
{
|
||||
fprintf( fh, "(SID:%08u) OUT %04x: ", 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 );
|
||||
}
|
||||
|
||||
|
||||
// :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
|
||||
|
||||
unsigned char* Buffer2 = (unsigned char*)P;
|
||||
unsigned Size = P->Size;
|
||||
#ifndef USE124
|
||||
if(this == NULL)
|
||||
{
|
||||
Log(MSG_WARNING,"tried to send a packet to a socket that doesn't exist any more");
|
||||
return;
|
||||
}
|
||||
//__seh_try
|
||||
//{
|
||||
// EncryptBuffer( CryptTable, Buffer );
|
||||
//}
|
||||
//__seh_except(info, context)
|
||||
//{
|
||||
// Log(MSG_WARNING,"Caught a bad packet %s. Send cancelled", Buffer);
|
||||
// return;
|
||||
//}
|
||||
//__seh_end
|
||||
EncryptBuffer( CryptTable, Buffer2 );
|
||||
#endif
|
||||
send( sock, (char*)Buffer2, Size, 0 );
|
||||
|
||||
//record teh packet that we just sent
|
||||
//CPacket* pak = (CPacket*)&Buffer;
|
||||
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Send a packet to a client without encrypting the source packet
|
||||
//-------------------------------------------------------------------------
|
||||
void CClientSocket::SendPacketCpy( CPacket *P )
|
||||
{
|
||||
CPacket NewPacket;
|
||||
|
||||
memcpy( &NewPacket, P, sizeof( CPacket ) );
|
||||
SendPacket( &NewPacket );
|
||||
}
|
||||
|
||||
// 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->isserver == true)
|
||||
{
|
||||
//Log( MSG_INFO,"ISC PACKET in ClientMainThread");
|
||||
thisplayer->ISCThread();
|
||||
}
|
||||
else
|
||||
if(!thisplayer->ReceiveData( ))
|
||||
{
|
||||
thisplayer->isActive = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
thisplayer->GS->DisconnectClient( thisplayer );
|
||||
pthread_exit(NULL);
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,549 @@
|
||||
/*
|
||||
Rose Online Server Emulator
|
||||
Copyright (C) 2006,2007 OSRose Team http://osroseon.to.md
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
developed with Main erose/hrose source server + some change from the original eich source
|
||||
*/
|
||||
#include "sockets.h"
|
||||
#include <iostream>
|
||||
|
||||
// Constructor
|
||||
CServerSocket::CServerSocket( )
|
||||
{
|
||||
#ifdef USE124
|
||||
csum = new char [0x200];
|
||||
csumlen = buildChecksum(csum, "TRose.exe");
|
||||
if(csumlen < 0)
|
||||
std::cout << "Failed to generate checksum, error: " << csumlen << std::endl;
|
||||
else
|
||||
std::cout << "Generated checksum" << std::endl;
|
||||
#endif
|
||||
ConnectedClients = 0;
|
||||
}
|
||||
|
||||
// Destructor
|
||||
CServerSocket::~CServerSocket( )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Start up our server
|
||||
bool CServerSocket::StartServer( )
|
||||
{
|
||||
//struct sockaddr_in ain;
|
||||
int test;
|
||||
sock = socket( AF_INET, SOCK_STREAM, 0 );
|
||||
if (sock == INVALID_SOCKET)
|
||||
{
|
||||
Log( MSG_FATALERROR, "Could not create a socket" );
|
||||
return false;
|
||||
}
|
||||
|
||||
int optval = 1;
|
||||
if(setsockopt(sock, SOL_SOCKET,SO_KEEPALIVE,(const char*)&optval,sizeof(optval))==-1)
|
||||
{
|
||||
Log(MSG_ERROR, "setsockopt:SO_KEEPALIVE" );
|
||||
}
|
||||
setsockopt(sock, IPPROTO_TCP,TCP_NODELAY,(const char*)&optval,sizeof(optval));
|
||||
ain.sin_family = AF_INET;
|
||||
ain.sin_addr.s_addr = INADDR_ANY;
|
||||
ain.sin_port = htons( port );
|
||||
memset(&(ain.sin_zero), '\0', 8);
|
||||
if ( bind( sock, (const sockaddr*)&ain, sizeof( struct sockaddr ) ) )
|
||||
{
|
||||
|
||||
Log( MSG_FATALERROR, "Could not bind socket" );
|
||||
std::cout <<"socket " << sock << std::endl;
|
||||
std::cin >> test;
|
||||
closesocket( sock );
|
||||
sock = INVALID_SOCKET;
|
||||
return false;
|
||||
}
|
||||
if ( listen( sock, SOMAXCONN ) == -1 )
|
||||
{
|
||||
Log( MSG_FATALERROR, "Could not listen on socket" );
|
||||
closesocket( sock );
|
||||
sock = INVALID_SOCKET;
|
||||
return false;
|
||||
}
|
||||
if (LOG_THISSERVER == LOG_CHARACTER_SERVER)
|
||||
{
|
||||
//struct sockaddr_in ain;
|
||||
sckISC = socket( AF_INET, SOCK_STREAM, 0 );
|
||||
if (sckISC == INVALID_SOCKET) {
|
||||
Log( MSG_ERROR, "Could not create valid ISC socket (WSK2 ERROR: %i)", WSAGetLastError( ) );
|
||||
return false;
|
||||
}
|
||||
optval = 1;
|
||||
if(setsockopt(sckISC, SOL_SOCKET,SO_KEEPALIVE,(const char*)&optval,sizeof(optval))==-1)
|
||||
{
|
||||
Log(MSG_ERROR, "setsockopt:SO_KEEPALIVE" );
|
||||
}
|
||||
setsockopt(sckISC, IPPROTO_TCP,TCP_NODELAY,(const char*)&optval,sizeof(optval));
|
||||
sain.sin_family = AF_INET;
|
||||
sain.sin_addr.s_addr = INADDR_ANY;
|
||||
sain.sin_port = htons( Config.CharsPort);//29110 );
|
||||
memset(&(sain.sin_zero), '\0', 8);
|
||||
if ( bind( sckISC, (const sockaddr*)&sain, sizeof( struct sockaddr ) ) )
|
||||
{
|
||||
Log( MSG_FATALERROR, "Could not bind socket" );
|
||||
closesocket( sckISC );
|
||||
sckISC = INVALID_SOCKET;
|
||||
return false;
|
||||
}
|
||||
if ( listen( sckISC, SOMAXCONN ) == -1 )
|
||||
{
|
||||
Log( MSG_FATALERROR, "Could not listen on socket" );
|
||||
closesocket( sckISC );
|
||||
sckISC = INVALID_SOCKET;
|
||||
return false;
|
||||
}
|
||||
Log( MSG_INFO, "opened ISC poort %i",29110 );
|
||||
|
||||
}
|
||||
|
||||
if (LOG_THISSERVER == LOG_WORLD_SERVER)
|
||||
{
|
||||
struct sockaddr_in aina; //if this doesn't work. change back to ain
|
||||
sckISC = socket( AF_INET, SOCK_STREAM, 0 );
|
||||
if (sckISC == INVALID_SOCKET) {
|
||||
Log( MSG_ERROR, "Could not create valid ISC socket (WSK2 ERROR: %i)", WSAGetLastError( ) );
|
||||
return false;
|
||||
}
|
||||
aina.sin_family = AF_INET;
|
||||
aina.sin_addr.s_addr = inet_addr(Config.CharIP);//( "127.0.0.1" );
|
||||
aina.sin_port = htons( Config.CharPort);//29110 );
|
||||
if ( connect( sckISC, (const sockaddr*)&aina, sizeof( aina ) ) == SOCKET_ERROR ) {
|
||||
Log( MSG_ERROR, "Could not connect to ISC (WSK2 ERROR: %i)", WSAGetLastError( ) );
|
||||
closesocket( sckISC );
|
||||
sckISC = INVALID_SOCKET;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
sckISCII = socket( AF_INET, SOCK_STREAM, 0 );
|
||||
if (sckISCII == INVALID_SOCKET) {
|
||||
Log( MSG_ERROR, "Could not create valid ISC socket (WSK2 ERROR: %i)", WSAGetLastError( ) );
|
||||
return false;
|
||||
}
|
||||
optval = 1;
|
||||
if(setsockopt(sckISCII, SOL_SOCKET,SO_KEEPALIVE,(const char*)&optval,sizeof(optval))==-1)
|
||||
{
|
||||
Log(MSG_ERROR, "setsockopt:SO_KEEPALIVE" );
|
||||
}
|
||||
setsockopt(sckISCII, IPPROTO_TCP,TCP_NODELAY,(const char*)&optval,sizeof(optval));
|
||||
sain.sin_family = AF_INET;
|
||||
sain.sin_addr.s_addr = INADDR_ANY;
|
||||
sain.sin_port = htons( Config.WorldsPort );//29210 );
|
||||
memset(&(sain.sin_zero), '\0', 8);
|
||||
if ( bind( sckISCII, (const sockaddr*)&sain, sizeof( struct sockaddr ) ) )
|
||||
{
|
||||
Log( MSG_FATALERROR, "Could not bind socket" );
|
||||
closesocket( sckISCII );
|
||||
sckISCII = INVALID_SOCKET;
|
||||
return false;
|
||||
}
|
||||
if ( listen( sckISCII, SOMAXCONN ) == -1 )
|
||||
{
|
||||
Log( MSG_FATALERROR, "Could not listen on socket" );
|
||||
closesocket( sckISCII );
|
||||
sckISCII = INVALID_SOCKET;
|
||||
return false;
|
||||
}
|
||||
Log( MSG_INFO, "opened ISC poort %i",Config.WorldsPort );//29210 );
|
||||
}
|
||||
if (LOG_THISSERVER == LOG_LOGIN_SERVER)
|
||||
{
|
||||
struct sockaddr_in aina; //may need to change back to ain
|
||||
sckISC = socket( AF_INET, SOCK_STREAM, 0 );
|
||||
if (sckISC == INVALID_SOCKET) {
|
||||
Log( MSG_ERROR, "Could not create valid ISC socket (WSK2 ERROR: %i)", WSAGetLastError( ) );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
isActive = true;
|
||||
|
||||
if ( !this->OnServerReady( ) )
|
||||
{
|
||||
Log( MSG_FATALERROR, "Server could not start" );
|
||||
closesocket( sock );
|
||||
sock = INVALID_SOCKET;
|
||||
isActive = false;
|
||||
return false;
|
||||
}
|
||||
Log( MSG_INFO, "Server started on port %i and is listening.", port );
|
||||
//ISCThread( );
|
||||
ServerLoop( );
|
||||
// Nothing past here is ever really called
|
||||
OnServerDie( );
|
||||
closesocket( sock );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Raven0123
|
||||
void CServerSocket::CryptISCPak( char* pak )
|
||||
{
|
||||
return;
|
||||
unsigned paksize = *((unsigned short*)&pak[0]);
|
||||
for( unsigned short i = 2; i < paksize; i ++ )
|
||||
pak[i] ^= 0x81 * i * paksize;
|
||||
}
|
||||
|
||||
// Raven0123
|
||||
//void CServerSocket::ISCThread()
|
||||
bool CClientSocket::ISCThread()
|
||||
{
|
||||
unsigned char buffer[0x400];
|
||||
unsigned recvd = 0;
|
||||
unsigned bufsize = 0;
|
||||
unsigned readlen = 6;
|
||||
bool go = true;
|
||||
|
||||
do {
|
||||
|
||||
recvd = recv( sock, (char*)&buffer[bufsize], readlen-bufsize, 0 );
|
||||
if( recvd == 0){
|
||||
return false;
|
||||
}
|
||||
|
||||
if( recvd == SOCKET_ERROR ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bufsize += recvd;
|
||||
if( bufsize != readlen ) continue;//return;//continue;
|
||||
if( bufsize == 6 ) {
|
||||
readlen = *((unsigned short*)&buffer[0]);
|
||||
if( readlen < 6 ) Log( MSG_ERROR, "Invalid server Packet Header" );
|
||||
if( readlen > 6 ) continue;//return;//continue;
|
||||
}
|
||||
|
||||
GS->OnReceivePacket( this, (CPacket*)&buffer[0] );
|
||||
go = false;
|
||||
|
||||
bufsize = 0;
|
||||
readlen = 6;
|
||||
} while ( go==true );
|
||||
return true;
|
||||
}
|
||||
|
||||
// Server is started, lets run our loop :D
|
||||
void CServerSocket::ServerLoop( )
|
||||
{
|
||||
fd_set fds;
|
||||
int activity;
|
||||
maxfd = 0;
|
||||
sockaddr_in ClientInfo;
|
||||
SOCKET NewSocket;
|
||||
timeval timeout;
|
||||
maxfd = sock;
|
||||
OnServerStep();
|
||||
do
|
||||
{
|
||||
if (!Ping( ))
|
||||
isActive = false;
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 1000;
|
||||
NewSocket = INVALID_SOCKET;
|
||||
FD_ZERO( &fds );
|
||||
if(!Config.usethreads)
|
||||
FillFDS( &fds );
|
||||
FD_SET( sock, &fds );
|
||||
activity = select( maxfd+1, &fds, NULL, NULL, &timeout );
|
||||
if ( activity == 0 )
|
||||
{
|
||||
// continue;
|
||||
FD_ZERO( &fds );
|
||||
if(!Config.usethreads)
|
||||
FillFDS( &fds );
|
||||
FD_SET( sckISC, &fds );
|
||||
activity = select( maxfd+1, &fds, NULL, NULL, &timeout );
|
||||
if ( activity == 0 )continue;
|
||||
if ( activity < 0 && errno != EINTR )
|
||||
{
|
||||
#ifdef _WIN32
|
||||
Log( MSG_ERROR, "Select command failed. Error #%i", WSAGetLastError() );
|
||||
#else
|
||||
Log( MSG_ERROR, "Select command failed. Error #%i", errno );
|
||||
#endif
|
||||
isActive = false;
|
||||
}
|
||||
if ( FD_ISSET( sckISC, &fds ) )
|
||||
{
|
||||
int clientinfolen = sizeof( sockaddr_in );
|
||||
#ifdef _WIN32
|
||||
NewSocket = accept( sckISC, (sockaddr*)&ClientInfo, (int*)&clientinfolen );
|
||||
#else
|
||||
NewSocket = accept( sckISC, (sockaddr*)&ClientInfo, (socklen_t*)&clientinfolen );
|
||||
#endif
|
||||
// TODO: check if server is full
|
||||
if (NewSocket != INVALID_SOCKET)
|
||||
{
|
||||
AddUser( NewSocket, &ClientInfo, true );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef _WIN32
|
||||
Log( MSG_ERROR, "Error accepting socket: %i", WSAGetLastError() );
|
||||
#else
|
||||
Log( MSG_ERROR, "Error accepting socket: %i", errno );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( activity < 0 && errno != EINTR )
|
||||
{
|
||||
#ifdef _WIN32
|
||||
Log( MSG_ERROR, "Select command failed. Error #%i", WSAGetLastError() );
|
||||
#else
|
||||
Log( MSG_ERROR, "Select command failed. Error #%i", errno );
|
||||
#endif
|
||||
isActive = false;
|
||||
}
|
||||
if ( FD_ISSET( sock, &fds ) )
|
||||
{
|
||||
int clientinfolen = sizeof( sockaddr_in );
|
||||
#ifdef _WIN32
|
||||
NewSocket = accept( sock, (sockaddr*)&ClientInfo, (int*)&clientinfolen );
|
||||
#else
|
||||
NewSocket = accept( sock, (sockaddr*)&ClientInfo, (socklen_t*)&clientinfolen );
|
||||
#endif
|
||||
// TODO: check if server is full
|
||||
if (NewSocket != INVALID_SOCKET)
|
||||
AddUser( NewSocket, &ClientInfo, false );
|
||||
else
|
||||
{
|
||||
#ifdef _WIN32
|
||||
Log( MSG_ERROR, "Error accepting socket: %i", WSAGetLastError() );
|
||||
#else
|
||||
Log( MSG_ERROR, "Error accepting socket: %i", errno );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if(!Config.usethreads)
|
||||
HandleClients( &fds );
|
||||
} while( isActive );
|
||||
}
|
||||
|
||||
// Fills out an FDS for the server
|
||||
void CServerSocket::FillFDS( fd_set* fds )
|
||||
{
|
||||
for(UINT i=0;i<ClientList.size( );i++)
|
||||
{
|
||||
CClientSocket* client = ClientList.at( i );
|
||||
if(client->isActive)
|
||||
{
|
||||
FD_SET( (unsigned)client->sock, fds );
|
||||
if(client->sock>maxfd)
|
||||
maxfd=client->sock;
|
||||
}
|
||||
else
|
||||
{
|
||||
DisconnectClient( client );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle all our clients
|
||||
void CServerSocket::HandleClients( fd_set* fds )
|
||||
{
|
||||
for(UINT i=0;i<ClientList.size( );i++)
|
||||
{
|
||||
CClientSocket* client = ClientList.at( i );
|
||||
if(!client->isActive)
|
||||
continue;
|
||||
if(FD_ISSET( client->sock, fds ))
|
||||
{
|
||||
if (client->isserver == true)
|
||||
{
|
||||
//Log( MSG_INFO,"ISC PACKET in HandleClients");
|
||||
if(!client->ISCThread()){
|
||||
client->isActive = false;
|
||||
DisconnectClient( client );}
|
||||
}
|
||||
else
|
||||
if(!client->ReceiveData( ) )
|
||||
{
|
||||
client->isActive = false;
|
||||
DisconnectClient( client );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add a new user to our server
|
||||
void CServerSocket::AddUser( SOCKET sock, sockaddr_in* ClientInfo, bool server )
|
||||
{
|
||||
ConnectedClients++;
|
||||
CClientSocket* thisclient = this->CreateClientSocket( );
|
||||
if (thisclient==NULL)
|
||||
{
|
||||
closesocket( thisclient->sock );
|
||||
if (thisclient!=0) delete thisclient;
|
||||
thisclient=0;
|
||||
return;
|
||||
}
|
||||
#ifdef USE124
|
||||
thisclient->ct = new char[TABLE_SIZE];
|
||||
buildCryptTable(thisclient->ct, csum, csumlen);
|
||||
#endif
|
||||
thisclient->CryptTable = CryptTable;
|
||||
thisclient->CryptStatus.CurAddValue = 0;
|
||||
thisclient->CryptStatus.CurEncryptionValue = CryptTable->EncryptionStartValue;
|
||||
thisclient->GS = this;
|
||||
thisclient->sock = sock;
|
||||
thisclient->isActive = true;
|
||||
|
||||
if (!OnClientConnect( thisclient )) {
|
||||
closesocket( thisclient->sock );
|
||||
if (thisclient!=0) delete thisclient;
|
||||
thisclient=0;
|
||||
return;
|
||||
}
|
||||
thisclient->ClientIP = "";
|
||||
thisclient->ClientIP = inet_ntoa( ClientInfo->sin_addr );
|
||||
char *tmp;
|
||||
memset(&thisclient->ClientSubNet, '\0', 12 );
|
||||
sprintf_s(thisclient->ClientSubNet, "%i.%i.%i",
|
||||
(ClientInfo->sin_addr.s_addr )&0xFF, (ClientInfo->sin_addr.s_addr>>8 )&0xFF,
|
||||
(ClientInfo->sin_addr.s_addr>>16)&0xFF);
|
||||
ClientList.push_back( thisclient );
|
||||
if(Config.usethreads)
|
||||
{
|
||||
pthread_create( &threads[sock], NULL, ClientMainThread, (PVOID)thisclient);
|
||||
}
|
||||
memcpy( &thisclient->clientinfo, ClientInfo, sizeof(struct sockaddr_in));
|
||||
if(server==true)
|
||||
{
|
||||
thisclient->isserver=true;
|
||||
Log( MSG_INFO, "Server connected from %s", inet_ntoa( ClientInfo->sin_addr ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
thisclient->isserver=false;
|
||||
Log( MSG_INFO, "User connected from %s", inet_ntoa( ClientInfo->sin_addr ) );
|
||||
}
|
||||
}
|
||||
|
||||
// Disconnect our user
|
||||
void CServerSocket::DisconnectClient( CClientSocket* thisclient )
|
||||
{
|
||||
ConnectedClients--;
|
||||
OnClientDisconnect( thisclient );
|
||||
closesocket( thisclient->sock );
|
||||
thisclient->isActive = false;
|
||||
thisclient->sock = INVALID_SOCKET;
|
||||
for(UINT i=0;i<ClientList.size( );i++)
|
||||
{
|
||||
CClientSocket* client = ClientList.at( i );
|
||||
if( client == thisclient )
|
||||
{
|
||||
ClientList.erase( ClientList.begin( ) + i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
DeleteClientSocket( thisclient );
|
||||
}
|
||||
|
||||
// This function creates an appropriate client socket
|
||||
CClientSocket* CServerSocket::CreateClientSocket ( )
|
||||
{
|
||||
CClientSocket* thisclient;
|
||||
thisclient = new (nothrow) CClientSocket( );
|
||||
return thisclient;
|
||||
}
|
||||
|
||||
// This function deletes an old client socket
|
||||
void CServerSocket::DeleteClientSocket( CClientSocket* thisclient )
|
||||
{
|
||||
if (thisclient->isserver)
|
||||
Log( MSG_INFO, "Server disconnected" );
|
||||
else
|
||||
Log( MSG_INFO, "User disconnected" );
|
||||
delete thisclient;
|
||||
}
|
||||
|
||||
//This function loads the encryption
|
||||
void CServerSocket::LoadEncryption( )
|
||||
{
|
||||
GenerateCryptTables( CryptTable, 0x87654321 );
|
||||
//port = ConfigGetInt("server.conf", "loginport", 29000);
|
||||
}
|
||||
|
||||
// This function is called just before proccessing clients
|
||||
void CServerSocket::OnServerStep( )
|
||||
{
|
||||
}
|
||||
|
||||
// This function is called just before the server starts
|
||||
bool CServerSocket::OnServerReady( )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// This function is called just before the server dies
|
||||
void CServerSocket::OnServerDie( )
|
||||
{
|
||||
// DOESNT WORK - DAMN CONSOLE APPS
|
||||
}
|
||||
|
||||
// This function is called, if a client receives data
|
||||
bool CServerSocket::OnReceivePacket( CClientSocket* thisclient, CPacket *P )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// This function is called, if a client connects
|
||||
bool CServerSocket::OnClientConnect( CClientSocket* thisclient )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// This function is called, if a client disconnects
|
||||
void CServerSocket::OnClientDisconnect( CClientSocket* thisclient )
|
||||
{
|
||||
}
|
||||
|
||||
// Raven0123
|
||||
void CServerSocket::SendISCPacket( CPacket* pak )
|
||||
{
|
||||
send( sckISC, (char*)pak, pak->Size, 0 );
|
||||
}
|
||||
|
||||
void CServerSocket::ReceivedISCPacket( CPacket* pak )
|
||||
{
|
||||
Log( MSG_DEBUG, "GOT ISC PACKET (BASESERVER) - 0x%04x %04x", pak->Command, pak->Size );
|
||||
}
|
||||
|
||||
bool CServerSocket::DoSQL(char *Format, ...) {
|
||||
int retval;
|
||||
char Buffer[0x1500];
|
||||
va_list ap; va_start( ap, Format );
|
||||
vsprintf_s( Buffer, Format, ap );
|
||||
va_end ( ap );
|
||||
retval = mysql_query( mysql, Buffer );
|
||||
if( retval != 0 ) Log( MSG_ERROR, "MySQL Query Error '%s'", mysql_error( mysql ) );
|
||||
return (retval==0);
|
||||
}
|
||||
|
||||
bool CServerSocket::Ping( )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/*******************************************************************************************
|
||||
___ ___ ___ ___
|
||||
___| _ \/ _ \/ __| __|
|
||||
/ -_) / (_) \__ \ _|
|
||||
\___|_|_\\___/|___/___|
|
||||
|
||||
eROSE Server Develped by Brett19.
|
||||
hROSE Team: Brett19 and bdaan
|
||||
Year: 2006
|
||||
Release Date: Summer-Winter 2006
|
||||
*******************************************************************************************/
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <ctype.h>
|
||||
|
||||
// Find the entry
|
||||
bool ConfigGetEntry( const char *pcFile, const char *pcNameMust, char* &pcResult )
|
||||
{
|
||||
char pcBuffer[ 512 ];
|
||||
char *pcName, *pcPar, *pcPoint;
|
||||
unsigned len;
|
||||
|
||||
pcResult=0;
|
||||
|
||||
// Open file
|
||||
FILE* fh = NULL;
|
||||
fopen_s (&fh, pcFile, "r");
|
||||
if ( fh == NULL ) return false;
|
||||
|
||||
do
|
||||
{
|
||||
fgets( pcBuffer, 510, fh );
|
||||
len = (unsigned)strlen( pcBuffer );
|
||||
if ( pcBuffer[ len-1 ] == '\n' ) --len;
|
||||
pcBuffer[ len ] = 0;
|
||||
|
||||
pcName = pcBuffer;
|
||||
while ( *pcName==' ' || *pcName=='\t' ) ++pcName;
|
||||
if ( *pcName==0 || *pcName=='#' ) continue;
|
||||
pcPoint = pcName;
|
||||
while ( *pcPoint!=' ' && *pcPoint!='\t' && *pcPoint!='#' && *pcPoint!='=' && *pcPoint!=0 ) ++pcPoint;
|
||||
if ( *pcPoint==0 || *pcPoint=='#' ) continue;
|
||||
pcPar = pcPoint;
|
||||
while ( *pcPar==' ' || *pcPar=='\t' || *pcPar=='=' ) ++pcPar;
|
||||
*pcPoint=0;
|
||||
|
||||
#ifdef _WIN32
|
||||
if ( !_strcmpi( pcName, pcNameMust ) )
|
||||
{
|
||||
pcResult = _strdup( pcPar );
|
||||
pcPoint = pcResult + strlen( pcPar );
|
||||
if ( *pcPoint==0 ) return true;
|
||||
--pcPoint;
|
||||
while( *pcPoint==' ' || *pcPoint=='\t' ) *pcPoint--=0;
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
if ( strcasecmp( pcName, pcNameMust )==0 )
|
||||
{
|
||||
pcResult = _strdup( pcPar );
|
||||
pcPoint = pcResult + strlen( pcPar );
|
||||
if ( *pcPoint==0 ) return true;
|
||||
--pcPoint;
|
||||
while( *pcPoint==' ' || *pcPoint=='\t' ) *pcPoint--=0;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
} while ( !feof( fh ) );
|
||||
|
||||
// Close file
|
||||
fclose( fh );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
// Returns a text
|
||||
// -----------------------------------------------------------------------------------------
|
||||
char *ConfigGetString( const char *pcFile, const char *pcName, const char *pcDefault )
|
||||
{
|
||||
char *pcRet, *pcRetReal, *pcRetOld;
|
||||
if ( !ConfigGetEntry( pcFile, pcName, pcRet ) ) return _strdup( pcDefault );
|
||||
if (pcRet==0) return _strdup( pcDefault );
|
||||
pcRetOld = pcRet;
|
||||
if ( *pcRet=='"' )
|
||||
{
|
||||
++pcRet;
|
||||
pcRet[ strlen(pcRet) - 1 ] = 0;
|
||||
}
|
||||
|
||||
pcRetReal = _strdup( pcRet );
|
||||
free( pcRetOld );
|
||||
|
||||
return pcRetReal;
|
||||
}
|
||||
|
||||
// Returns a number
|
||||
unsigned ConfigGetInt( const char *pcFile, const char *pcName, unsigned uDefault )
|
||||
{
|
||||
char *pcRet;
|
||||
unsigned uRet;
|
||||
if ( !ConfigGetEntry( pcFile, pcName, pcRet ) ) return uDefault;
|
||||
if (pcRet==0) return uDefault;
|
||||
|
||||
uRet = atoi( pcRet );
|
||||
free( pcRet );
|
||||
|
||||
return uRet;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,24 @@
|
||||
/*******************************************************************************************
|
||||
___ ___ ___ ___
|
||||
___| _ \/ _ \/ __| __|
|
||||
/ -_) / (_) \__ \ _|
|
||||
\___|_|_\\___/|___/___|
|
||||
|
||||
eROSE Server Develped by Brett19.
|
||||
hROSE Team: Brett19 and bdaan
|
||||
Year: 2006
|
||||
Release Date: Summer-Winter 2006
|
||||
*******************************************************************************************/
|
||||
#ifndef __ROSE_CONFIG_FUNCTIONS__
|
||||
#define __ROSE_CONFIG_FUNCTIONS__
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
// Config load functions
|
||||
// -----------------------------------------------------------------------------------------
|
||||
char *ConfigGetString( const char *pcFile, const char *pcName, const char *pcDefault );
|
||||
unsigned ConfigGetInt( const char *pcFile, const char *pcName, unsigned uDefault );
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
#include "database.h"
|
||||
#include "../log.h"
|
||||
|
||||
// constructor
|
||||
CDatabase::CDatabase( char* server , char* username, char* password, char* database, unsigned int port , MYSQL* mysql)
|
||||
{
|
||||
Server = server;
|
||||
Username = username;
|
||||
Password = password;
|
||||
Database = database;
|
||||
Port = port;
|
||||
Mysql = mysql;
|
||||
LastPing = time( NULL );
|
||||
SQLMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
mysql_init( Mysql );
|
||||
}
|
||||
|
||||
// deconstructor
|
||||
CDatabase::~CDatabase( )
|
||||
{
|
||||
}
|
||||
|
||||
// disconnect from mysql
|
||||
void CDatabase::Disconnect( )
|
||||
{
|
||||
mysql_close( Mysql );
|
||||
}
|
||||
|
||||
int CDatabase::Connect( )
|
||||
{
|
||||
Log( MSG_INFO, "Connecting to MySQL" );
|
||||
if(!mysql_real_connect( Mysql, Server, Username, Password, Database,Port, NULL, 0 ))
|
||||
{
|
||||
Log( MSG_FATALERROR, "Error connecting to MySQL server: %s\n", mysql_error( Mysql ) );
|
||||
return -1;
|
||||
}
|
||||
// Get timeout so we know when to ping - Drakia
|
||||
MYSQL_RES *myresult = QStore("SELECT @@wait_timeout");
|
||||
MYSQL_ROW row = mysql_fetch_row( myresult );
|
||||
Timeout = atoi(row[0]) - 60; // Set the timeout to 1 minute before the connection will timeout
|
||||
QFree( );
|
||||
Log( MSG_INFO, "MySQL Ping Timeout: %d seconds", Timeout );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// reconnect to mysql
|
||||
int CDatabase::Reconnect( )
|
||||
{
|
||||
Log( MSG_INFO, "Reconnecting to Mysql" );
|
||||
if(!mysql_real_connect( Mysql, Server, Username, Password, Database,Port, NULL, 0 ))
|
||||
{
|
||||
Log( MSG_FATALERROR, "Error reconnecting to MySQL server: %s\n", mysql_error( Mysql ) );
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// execute query
|
||||
bool CDatabase::QExecute( const char *Format,... )
|
||||
{
|
||||
bool Qfail = true;
|
||||
char query[80000];
|
||||
va_list ap;
|
||||
va_start( ap, Format );
|
||||
vsprintf_s (query, Format, ap);
|
||||
va_end ( ap );
|
||||
Log( MSG_QUERY, query );
|
||||
pthread_mutex_lock( &SQLMutex );
|
||||
while(Qfail)
|
||||
{
|
||||
if(mysql_query( Mysql, query )!=0)
|
||||
{
|
||||
Log( MSG_FATALERROR, "Could not execute query: %s", mysql_error( Mysql ) );
|
||||
if(Reconnect( )==-1)
|
||||
{
|
||||
Log( MSG_FATALERROR, "Could not execute query: %s", mysql_error( Mysql ) );
|
||||
pthread_mutex_unlock( &SQLMutex );
|
||||
return false;
|
||||
}
|
||||
else Qfail = false;
|
||||
}
|
||||
else Qfail = false;
|
||||
}
|
||||
pthread_mutex_unlock( &SQLMutex );
|
||||
return true;
|
||||
}
|
||||
|
||||
MYSQL_RES* CDatabase::QStore( const char *Format, ...)
|
||||
{
|
||||
bool Qfail = true;
|
||||
char query[80000];
|
||||
va_list ap;
|
||||
va_start( ap, Format );
|
||||
vsprintf_s( query, Format, ap );
|
||||
va_end ( ap );
|
||||
result = NULL;
|
||||
Log( MSG_QUERY, query );
|
||||
//Log( MSG_INFO, query );
|
||||
//Log( MSG_INFO, "Locking pthread mutex" );
|
||||
pthread_mutex_lock( &SQLMutex );
|
||||
//Log( MSG_INFO, "Locked pthread mutex" );
|
||||
while(Qfail)
|
||||
{
|
||||
if(mysql_query( Mysql, query )!=0)
|
||||
{
|
||||
Log( MSG_FATALERROR, "Could not execute query: %s", mysql_error( Mysql ) );
|
||||
if(Reconnect( )==-1)
|
||||
{
|
||||
Log( MSG_FATALERROR, "Could not execute query: %s", mysql_error( Mysql ) );
|
||||
pthread_mutex_unlock( &SQLMutex );
|
||||
return NULL;
|
||||
}
|
||||
else Qfail = false;
|
||||
}
|
||||
else Qfail = false;
|
||||
// Log( MSG_INFO, "mysql answer: %s", mysql_error( Mysql ) );
|
||||
}
|
||||
//Log( MSG_INFO, "reading mysql result" );
|
||||
result = mysql_store_result( Mysql );
|
||||
//Log( MSG_INFO, "returning mysql result" );
|
||||
return result;
|
||||
}
|
||||
|
||||
MYSQL_RES* CDatabase::QUse( const char *Format, ...)
|
||||
{
|
||||
bool Qfail = true;
|
||||
char query[1024];
|
||||
va_list ap;
|
||||
va_start( ap, Format );
|
||||
vsprintf_s( query, Format, ap );
|
||||
va_end ( ap );
|
||||
result = NULL;
|
||||
Log( MSG_QUERY, query );
|
||||
pthread_mutex_lock( &SQLMutex );
|
||||
while(Qfail)
|
||||
{
|
||||
if(mysql_query( Mysql, query )!=0)
|
||||
{
|
||||
Log( MSG_FATALERROR, "Could not execute query: %s", mysql_error( Mysql ) );
|
||||
if(Reconnect( )==-1)
|
||||
{
|
||||
Log( MSG_FATALERROR, "Could not execute query: %s", mysql_error( Mysql ) );
|
||||
pthread_mutex_unlock( &SQLMutex );
|
||||
return NULL;
|
||||
}
|
||||
else Qfail = false;
|
||||
}
|
||||
else Qfail = false;
|
||||
}
|
||||
result = mysql_use_result( Mysql );
|
||||
return result;
|
||||
}
|
||||
|
||||
bool CDatabase::DoSQL(const char *Format, ...) {
|
||||
int retval;
|
||||
char Buffer[1024];
|
||||
va_list ap; va_start( ap, Format );
|
||||
vsprintf_s( Buffer, Format, ap );
|
||||
va_end ( ap );
|
||||
retval = mysql_query( Mysql, Buffer );
|
||||
if( retval!=0 ) Log( MSG_ERROR, "MySQL Query Error '%s'", mysql_error( Mysql ) );
|
||||
return (retval==0);
|
||||
}
|
||||
|
||||
void CDatabase::QFree( )
|
||||
{
|
||||
mysql_free_result( result );
|
||||
pthread_mutex_unlock( &SQLMutex );
|
||||
}
|
||||
|
||||
bool CDatabase::Ping( )
|
||||
{
|
||||
if ( time( NULL ) > ( LastPing + Timeout ) ) {
|
||||
Log(MSG_INFO, "MySql Ping");
|
||||
LastPing = time( NULL );
|
||||
MYSQL_RES *res = QStore("SELECT @@wait_timeout");
|
||||
if (res == NULL) {
|
||||
Log( MSG_ERROR, "MySQL Ping Failed, Attempting reconnect" );
|
||||
QFree( );
|
||||
return !Reconnect( );
|
||||
}
|
||||
MYSQL_ROW row = mysql_fetch_row(res);
|
||||
Timeout = atoi(row[0]) - 60;
|
||||
QFree( );
|
||||
Log( MSG_INFO, "MySql Pong, new Timeout: %d seconds", Timeout);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#ifndef _ROSE_DATABASE_
|
||||
#define _ROSE_DATABASE_
|
||||
#include "../sockets.h"
|
||||
|
||||
class CDatabase
|
||||
{
|
||||
public:
|
||||
CDatabase( char* , char*, char*, char*, unsigned int, MYSQL* );
|
||||
~CDatabase( );
|
||||
|
||||
char* Server;
|
||||
char* Username;
|
||||
char* Password;
|
||||
char* Database;
|
||||
unsigned int Port;
|
||||
unsigned int Timeout;
|
||||
time_t LastPing;
|
||||
int Connect( );
|
||||
int Reconnect( );
|
||||
void Disconnect( );
|
||||
bool QExecute( const char *format,... );
|
||||
MYSQL_RES* QUse( const char *format,... );
|
||||
MYSQL_RES* QStore( const char *format,... );
|
||||
bool DoSQL(const char *Format, ...);
|
||||
void QFree( );
|
||||
bool Ping( );
|
||||
|
||||
MYSQL* Mysql;
|
||||
MYSQL_RES* result;
|
||||
pthread_mutex_t SQLMutex;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,91 @@
|
||||
#include "sockets.h"
|
||||
|
||||
CPacket::CPacket( unsigned short mycommand, unsigned short mysize, unsigned short myunused )
|
||||
{
|
||||
Command = mycommand;
|
||||
Size = mysize;
|
||||
Unused = myunused;
|
||||
}
|
||||
CPacket::~CPacket( ) { }
|
||||
|
||||
void CPacket::StartPacket( unsigned short mycommand, unsigned short mysize, unsigned short myunused )
|
||||
{
|
||||
Command = mycommand;
|
||||
Size = mysize;
|
||||
Unused = myunused;
|
||||
}
|
||||
void CPacket::AddByte( unsigned char value )
|
||||
{
|
||||
Buffer[Size-6] = value;
|
||||
Size += 1;
|
||||
}
|
||||
void CPacket::AddWord( unsigned short value )
|
||||
{
|
||||
*((unsigned short*)&Buffer[Size-6]) = value;
|
||||
Size += 2;
|
||||
}
|
||||
void CPacket::AddDWord( unsigned value )
|
||||
{
|
||||
*((unsigned*)&Buffer[Size-6]) = value;
|
||||
Size += 4;
|
||||
}
|
||||
void CPacket::AddQWord( unsigned long long value )
|
||||
{
|
||||
*((unsigned long long*)&Buffer[Size-6]) = value;
|
||||
Size += 8;
|
||||
}
|
||||
void CPacket::AddFloat( float value )
|
||||
{
|
||||
*((float*)&Buffer[Size-6]) = value;
|
||||
Size += 4;
|
||||
}
|
||||
void CPacket::AddString( char* value )
|
||||
{
|
||||
for(unsigned char c=0; c<(unsigned)strlen(value); c++)
|
||||
AddByte( value[c] );
|
||||
}
|
||||
void CPacket::SetByte( unsigned short pos, unsigned char value )
|
||||
{
|
||||
Buffer[pos] = value;
|
||||
}
|
||||
void CPacket::SetWord( unsigned short pos, unsigned short value )
|
||||
{
|
||||
*((unsigned short*)&Buffer[pos]) = value;
|
||||
}
|
||||
void CPacket::SetDWord( unsigned short pos, unsigned value )
|
||||
{
|
||||
*((unsigned*)&Buffer[pos]) = value;
|
||||
}
|
||||
void CPacket::SetQWord( unsigned short pos, unsigned long long value )
|
||||
{
|
||||
*((unsigned long long*)&Buffer[pos]) = value;
|
||||
}
|
||||
void CPacket::SetFloat( unsigned short pos, float value )
|
||||
{
|
||||
*((float*)&Buffer[pos]) = value;
|
||||
}
|
||||
unsigned char CPacket::GetByte( unsigned short pos )
|
||||
{
|
||||
return Buffer[pos];
|
||||
}
|
||||
unsigned short CPacket::GetWord( unsigned short pos )
|
||||
{
|
||||
return *((unsigned short*)&Buffer[pos]);
|
||||
}
|
||||
unsigned CPacket::GetDWord( unsigned short pos )
|
||||
{
|
||||
return *((unsigned*)&Buffer[pos]);
|
||||
}
|
||||
unsigned long long CPacket::GetQWord( unsigned short pos )
|
||||
{
|
||||
return *((unsigned long long*)&Buffer[pos]);
|
||||
}
|
||||
float CPacket::GetFloat( unsigned short pos )
|
||||
{
|
||||
return *((float*)&Buffer[pos]);
|
||||
}
|
||||
|
||||
char* CPacket::GetString( unsigned short pos )
|
||||
{
|
||||
return (char*)&Buffer[pos];
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
#ifdef _WIN32
|
||||
#include <conio.h>
|
||||
#include <windows.h>
|
||||
#include <cstdio>
|
||||
#endif
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <time.h>
|
||||
#include "log.h"
|
||||
|
||||
// Basic colors
|
||||
typedef enum
|
||||
{
|
||||
BLACK,
|
||||
BLUE,
|
||||
GREEN,
|
||||
CYAN,
|
||||
RED,
|
||||
MAGENTA,
|
||||
BROWN,
|
||||
LIGHTGRAY,
|
||||
DARKGRAY,
|
||||
LIGHTBLUE,
|
||||
LIGHTGREEN,
|
||||
LIGHTCYAN,
|
||||
LIGHTRED,
|
||||
LIGHTMAGENTA,
|
||||
YELLOW,
|
||||
WHITE
|
||||
} COLORS;
|
||||
|
||||
// Our base colors
|
||||
static int __BACKGROUND = BLACK;
|
||||
static int __FOREGROUND = LIGHTGRAY;
|
||||
|
||||
// Change console text color
|
||||
void textcolor(int color)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
__FOREGROUND = color;
|
||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color + (__BACKGROUND << 4));
|
||||
#else
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
// This function logs based on flags
|
||||
void Log( enum msg_type flag, const char *Format, ... )
|
||||
{
|
||||
va_list ap; // For arguments
|
||||
va_start( ap, Format );
|
||||
|
||||
// Timestamp
|
||||
time_t rtime;
|
||||
time (&rtime);
|
||||
char timestamp[26];
|
||||
ctime_s (timestamp, sizeof (timestamp), &rtime);
|
||||
timestamp[strlen (timestamp) - 1] = ' ';
|
||||
|
||||
switch (flag) {
|
||||
case MSG_NONE: // direct printf replacement
|
||||
textcolor(WHITE);
|
||||
vprintf( Format, ap );
|
||||
break;
|
||||
case MSG_STATUS:
|
||||
textcolor(GREEN);
|
||||
printf("[STATUS]: ");
|
||||
break;
|
||||
case MSG_SQL:
|
||||
textcolor(CYAN);
|
||||
printf("[SQL]: ");
|
||||
break;
|
||||
case MSG_INFO:
|
||||
textcolor(LIGHTGREEN);
|
||||
printf("[INFO]: ");
|
||||
break;
|
||||
case MSG_NOTICE:
|
||||
textcolor(LIGHTCYAN);
|
||||
printf("[NOTICE]: ");
|
||||
break;
|
||||
case MSG_WARNING:
|
||||
textcolor(YELLOW);
|
||||
printf("[WARNING]: ");
|
||||
break;
|
||||
case MSG_DEBUG:
|
||||
textcolor(LIGHTBLUE);
|
||||
printf("[DEBUG]: ");
|
||||
break;
|
||||
case MSG_ERROR:
|
||||
textcolor(RED);
|
||||
printf("[ERROR]: ");
|
||||
break;
|
||||
case MSG_FATALERROR:
|
||||
textcolor(LIGHTRED);
|
||||
printf("[FATAL ERROR]: ");
|
||||
break;
|
||||
case MSG_HACK:
|
||||
textcolor(LIGHTRED);
|
||||
printf("[HACK]: ");
|
||||
break;
|
||||
case MSG_LOAD:
|
||||
textcolor(BROWN);
|
||||
printf("[LOADING]: ");
|
||||
break;
|
||||
case MSG_GMACTION:
|
||||
textcolor(MAGENTA);
|
||||
printf("[GM ACTION]: ");
|
||||
break;
|
||||
case MSG_START:
|
||||
textcolor(MAGENTA);
|
||||
vprintf( Format, ap );
|
||||
printf( "\r\n" );
|
||||
break;
|
||||
//case MSG_SDEBUG:
|
||||
// textcolor(MAGENTA);
|
||||
// printf("[SDEBUG]: ");
|
||||
// break;
|
||||
//case MSG_QUERY:
|
||||
// textcolor(LIGHTBLUE);
|
||||
// printf("[QUERY]: ");
|
||||
// break;
|
||||
//default:
|
||||
// textcolor(MAGENTA);
|
||||
// printf("[UNKNOWN CASE]: ");
|
||||
// break;
|
||||
}
|
||||
textcolor(LIGHTGRAY);
|
||||
if(flag!=MSG_QUERY)
|
||||
{
|
||||
printf( "%s- ", timestamp );
|
||||
vprintf( Format, ap );
|
||||
printf( (flag==MSG_LOAD) ? "\r" : "\n" );
|
||||
}
|
||||
FILE *fh = NULL;
|
||||
switch(LOG_THISSERVER)
|
||||
{
|
||||
case LOG_LOGIN_SERVER:
|
||||
fopen_s (&fh, LOG_DIRECTORY LOG_FILENAME_LOGINFILE, "a+");
|
||||
break;
|
||||
case LOG_CHARACTER_SERVER:
|
||||
fopen_s (&fh, LOG_DIRECTORY LOG_FILENAME_CHARFILE, "a+");
|
||||
break;
|
||||
case LOG_WORLD_SERVER:
|
||||
fopen_s (&fh, LOG_DIRECTORY LOG_FILENAME_WORLDFILE, "a+");
|
||||
break;
|
||||
case LOG_SAME_FILE:
|
||||
fopen_s (&fh, LOG_DIRECTORY LOG_DEFAULT_FILE, "a+");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(flag == MSG_QUERY)
|
||||
{
|
||||
if(fh != NULL)
|
||||
fclose(fh);
|
||||
fopen_s (&fh, LOG_DIRECTORY "queries.txt", "a+");
|
||||
}
|
||||
if ( fh != NULL )
|
||||
{
|
||||
fprintf( fh, "%s- ", timestamp );
|
||||
vfprintf( fh, Format, ap );
|
||||
fputc( '\n', fh );
|
||||
fclose( fh );
|
||||
}
|
||||
|
||||
va_end ( ap );
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
Open Source Rose Online Team - http://osroseon.to.md/
|
||||
note: the Server is develop with erose source server + eich source
|
||||
*/
|
||||
#ifndef __ROSE_LOGGING_FUNCTIONS__
|
||||
#define __ROSE_LOGGING_FUNCTIONS__
|
||||
|
||||
// Log path
|
||||
#ifdef _WIN32
|
||||
# define LOG_DIRECTORY "log/"
|
||||
#endif
|
||||
|
||||
#ifdef __unix__
|
||||
# define LOG_DIRECTORY "/var/log/roseserver/"
|
||||
#endif
|
||||
|
||||
#define LOG_LOGIN_SERVER 0x01
|
||||
#define LOG_CHARACTER_SERVER 0x02
|
||||
#define LOG_WORLD_SERVER 0x03
|
||||
#define LOG_SAME_FILE 0x04
|
||||
|
||||
// Log File names
|
||||
extern unsigned char LOG_THISSERVER;
|
||||
#define LOG_FILENAME_LOGINFILE "loginserver.log"
|
||||
#define LOG_FILENAME_CHARFILE "charserver.log"
|
||||
#define LOG_FILENAME_WORLDFILE "worldserver.log"
|
||||
#define LOG_DEFAULT_FILE "server.log"
|
||||
#define LOG_FILENAME_ERRORFILE "errors.log"
|
||||
|
||||
#define LOG_LOGINPACKETS "loginpacket.log"
|
||||
#define LOG_CHARPACKETS "charpackets.log"
|
||||
#define LOG_WORLDPACKETS "worldpackets.log"
|
||||
#define LOG_DEFAULTPACKETS "packets.log"
|
||||
|
||||
// Error Types
|
||||
enum msg_type {
|
||||
MSG_NONE,
|
||||
MSG_STATUS,
|
||||
MSG_SQL,
|
||||
MSG_INFO,
|
||||
MSG_NOTICE,
|
||||
MSG_WARNING,
|
||||
MSG_DEBUG,
|
||||
MSG_ERROR,
|
||||
MSG_FATALERROR,
|
||||
MSG_HACK,
|
||||
MSG_LOAD,
|
||||
MSG_SDEBUG,
|
||||
MSG_GMACTION,
|
||||
MSG_START,
|
||||
MSG_QUERY,
|
||||
MSG_QUESTDEBUG
|
||||
};
|
||||
|
||||
// Logging function
|
||||
void Log( msg_type flag, const char* Format, ... );
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,739 @@
|
||||
/* Copyright (C) 2000-2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef _mysql_h
|
||||
#define _mysql_h
|
||||
|
||||
#ifdef __CYGWIN__ /* CYGWIN implements a UNIX API */
|
||||
#undef WIN
|
||||
#undef _WIN
|
||||
#undef _WIN32
|
||||
#undef _WIN64
|
||||
#undef __WIN__
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef _global_h /* If not standard header */
|
||||
#include <sys/types.h>
|
||||
#ifdef __LCC__
|
||||
#include <winsock.h> /* For windows */
|
||||
#endif
|
||||
typedef char my_bool;
|
||||
#if (defined(_WIN32) || defined(_WIN64)) && !defined(__WIN__)
|
||||
#define __WIN__
|
||||
#endif
|
||||
#if !defined(__WIN__)
|
||||
#define STDCALL
|
||||
#else
|
||||
#define STDCALL __stdcall
|
||||
#endif
|
||||
typedef char * gptr;
|
||||
|
||||
#ifndef my_socket_defined
|
||||
#ifdef __WIN__
|
||||
#define my_socket SOCKET
|
||||
#else
|
||||
typedef int my_socket;
|
||||
#endif /* __WIN__ */
|
||||
#endif /* my_socket_defined */
|
||||
#endif /* _global_h */
|
||||
|
||||
#include "mysql_com.h"
|
||||
#include "mysql_time.h"
|
||||
#include "mysql_version.h"
|
||||
#include "typelib.h"
|
||||
|
||||
#include "my_list.h" /* for LISTs used in 'MYSQL' and 'MYSQL_STMT' */
|
||||
|
||||
extern unsigned int mysql_port;
|
||||
extern char *mysql_unix_port;
|
||||
|
||||
#define CLIENT_NET_READ_TIMEOUT 365*24*3600 /* Timeout on read */
|
||||
#define CLIENT_NET_WRITE_TIMEOUT 365*24*3600 /* Timeout on write */
|
||||
|
||||
#ifdef __NETWARE__
|
||||
#pragma pack(push, 8) /* 8 byte alignment */
|
||||
#endif
|
||||
|
||||
#define IS_PRI_KEY(n) ((n) & PRI_KEY_FLAG)
|
||||
#define IS_NOT_NULL(n) ((n) & NOT_NULL_FLAG)
|
||||
#define IS_BLOB(n) ((n) & BLOB_FLAG)
|
||||
#define IS_NUM(t) ((t) <= FIELD_TYPE_INT24 || (t) == FIELD_TYPE_YEAR)
|
||||
#define IS_NUM_FIELD(f) ((f)->flags & NUM_FLAG)
|
||||
#define INTERNAL_NUM_FIELD(f) (((f)->type <= FIELD_TYPE_INT24 && ((f)->type != FIELD_TYPE_TIMESTAMP || (f)->length == 14 || (f)->length == 8)) || (f)->type == FIELD_TYPE_YEAR)
|
||||
|
||||
|
||||
typedef struct st_mysql_field {
|
||||
char *name; /* Name of column */
|
||||
char *org_name; /* Original column name, if an alias */
|
||||
char *table; /* Table of column if column was a field */
|
||||
char *org_table; /* Org table name, if table was an alias */
|
||||
char *db; /* Database for table */
|
||||
char *catalog; /* Catalog for table */
|
||||
char *def; /* Default value (set by mysql_list_fields) */
|
||||
unsigned long length; /* Width of column (create length) */
|
||||
unsigned long max_length; /* Max width for selected set */
|
||||
unsigned int name_length;
|
||||
unsigned int org_name_length;
|
||||
unsigned int table_length;
|
||||
unsigned int org_table_length;
|
||||
unsigned int db_length;
|
||||
unsigned int catalog_length;
|
||||
unsigned int def_length;
|
||||
unsigned int flags; /* Div flags */
|
||||
unsigned int decimals; /* Number of decimals in field */
|
||||
unsigned int charsetnr; /* Character set */
|
||||
enum enum_field_types type; /* Type of field. See mysql_com.h for types */
|
||||
} MYSQL_FIELD;
|
||||
|
||||
typedef char **MYSQL_ROW; /* return data as array of strings */
|
||||
typedef unsigned int MYSQL_FIELD_OFFSET; /* offset to current field */
|
||||
|
||||
#ifndef _global_h
|
||||
#if defined(NO_CLIENT_LONG_LONG)
|
||||
typedef unsigned long my_ulonglong;
|
||||
#elif defined (__WIN__)
|
||||
typedef unsigned __int64 my_ulonglong;
|
||||
#else
|
||||
typedef unsigned long long my_ulonglong;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define MYSQL_COUNT_ERROR (~(my_ulonglong) 0)
|
||||
|
||||
typedef struct st_mysql_rows {
|
||||
struct st_mysql_rows *next; /* list of rows */
|
||||
MYSQL_ROW data;
|
||||
unsigned long length;
|
||||
} MYSQL_ROWS;
|
||||
|
||||
typedef MYSQL_ROWS *MYSQL_ROW_OFFSET; /* offset to current row */
|
||||
|
||||
#include "my_alloc.h"
|
||||
|
||||
typedef struct st_mysql_data {
|
||||
my_ulonglong rows;
|
||||
unsigned int fields;
|
||||
MYSQL_ROWS *data;
|
||||
MEM_ROOT alloc;
|
||||
#if !defined(CHECK_EMBEDDED_DIFFERENCES) || defined(EMBEDDED_LIBRARY)
|
||||
MYSQL_ROWS **prev_ptr;
|
||||
#endif
|
||||
} MYSQL_DATA;
|
||||
|
||||
enum mysql_option
|
||||
{
|
||||
MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_COMPRESS, MYSQL_OPT_NAMED_PIPE,
|
||||
MYSQL_INIT_COMMAND, MYSQL_READ_DEFAULT_FILE, MYSQL_READ_DEFAULT_GROUP,
|
||||
MYSQL_SET_CHARSET_DIR, MYSQL_SET_CHARSET_NAME, MYSQL_OPT_LOCAL_INFILE,
|
||||
MYSQL_OPT_PROTOCOL, MYSQL_SHARED_MEMORY_BASE_NAME, MYSQL_OPT_READ_TIMEOUT,
|
||||
MYSQL_OPT_WRITE_TIMEOUT, MYSQL_OPT_USE_RESULT,
|
||||
MYSQL_OPT_USE_REMOTE_CONNECTION, MYSQL_OPT_USE_EMBEDDED_CONNECTION,
|
||||
MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH
|
||||
};
|
||||
|
||||
struct st_mysql_options {
|
||||
unsigned int connect_timeout, read_timeout, write_timeout;
|
||||
unsigned int port, protocol;
|
||||
unsigned long client_flag;
|
||||
char *host,*user,*password,*unix_socket,*db;
|
||||
struct st_dynamic_array *init_commands;
|
||||
char *my_cnf_file,*my_cnf_group, *charset_dir, *charset_name;
|
||||
char *ssl_key; /* PEM key file */
|
||||
char *ssl_cert; /* PEM cert file */
|
||||
char *ssl_ca; /* PEM CA file */
|
||||
char *ssl_capath; /* PEM directory of CA-s? */
|
||||
char *ssl_cipher; /* cipher to use */
|
||||
char *shared_memory_base_name;
|
||||
unsigned long max_allowed_packet;
|
||||
my_bool use_ssl; /* if to use SSL or not */
|
||||
my_bool compress,named_pipe;
|
||||
/*
|
||||
On connect, find out the replication role of the server, and
|
||||
establish connections to all the peers
|
||||
*/
|
||||
my_bool rpl_probe;
|
||||
/*
|
||||
Each call to mysql_real_query() will parse it to tell if it is a read
|
||||
or a write, and direct it to the slave or the master
|
||||
*/
|
||||
my_bool rpl_parse;
|
||||
/*
|
||||
If set, never read from a master, only from slave, when doing
|
||||
a read that is replication-aware
|
||||
*/
|
||||
my_bool no_master_reads;
|
||||
#if !defined(CHECK_EMBEDDED_DIFFERENCES) || defined(EMBEDDED_LIBRARY)
|
||||
my_bool separate_thread;
|
||||
#endif
|
||||
enum mysql_option methods_to_use;
|
||||
char *client_ip;
|
||||
/* Refuse client connecting to server if it uses old (pre-4.1.1) protocol */
|
||||
my_bool secure_auth;
|
||||
|
||||
/* function pointers for local infile support */
|
||||
int (*local_infile_init)(void **, const char *, void *);
|
||||
int (*local_infile_read)(void *, char *, unsigned int);
|
||||
void (*local_infile_end)(void *);
|
||||
int (*local_infile_error)(void *, char *, unsigned int);
|
||||
void *local_infile_userdata;
|
||||
};
|
||||
|
||||
enum mysql_status
|
||||
{
|
||||
MYSQL_STATUS_READY,MYSQL_STATUS_GET_RESULT,MYSQL_STATUS_USE_RESULT
|
||||
};
|
||||
|
||||
enum mysql_protocol_type
|
||||
{
|
||||
MYSQL_PROTOCOL_DEFAULT, MYSQL_PROTOCOL_TCP, MYSQL_PROTOCOL_SOCKET,
|
||||
MYSQL_PROTOCOL_PIPE, MYSQL_PROTOCOL_MEMORY
|
||||
};
|
||||
/*
|
||||
There are three types of queries - the ones that have to go to
|
||||
the master, the ones that go to a slave, and the adminstrative
|
||||
type which must happen on the pivot connectioin
|
||||
*/
|
||||
enum mysql_rpl_type
|
||||
{
|
||||
MYSQL_RPL_MASTER, MYSQL_RPL_SLAVE, MYSQL_RPL_ADMIN
|
||||
};
|
||||
|
||||
struct st_mysql_methods;
|
||||
|
||||
typedef struct st_mysql
|
||||
{
|
||||
NET net; /* Communication parameters */
|
||||
gptr connector_fd; /* ConnectorFd for SSL */
|
||||
char *host,*user,*passwd,*unix_socket,*server_version,*host_info,*info;
|
||||
char *db;
|
||||
struct charset_info_st *charset;
|
||||
MYSQL_FIELD *fields;
|
||||
MEM_ROOT field_alloc;
|
||||
my_ulonglong affected_rows;
|
||||
my_ulonglong insert_id; /* id if insert on table with NEXTNR */
|
||||
my_ulonglong extra_info; /* Used by mysqlshow */
|
||||
unsigned long thread_id; /* Id for connection in server */
|
||||
unsigned long packet_length;
|
||||
unsigned int port;
|
||||
unsigned long client_flag,server_capabilities;
|
||||
unsigned int protocol_version;
|
||||
unsigned int field_count;
|
||||
unsigned int server_status;
|
||||
unsigned int server_language;
|
||||
unsigned int warning_count;
|
||||
struct st_mysql_options options;
|
||||
enum mysql_status status;
|
||||
my_bool free_me; /* If free in mysql_close */
|
||||
my_bool reconnect; /* set to 1 if automatic reconnect */
|
||||
|
||||
/* session-wide random string */
|
||||
char scramble[SCRAMBLE_LENGTH+1];
|
||||
|
||||
/*
|
||||
Set if this is the original connection, not a master or a slave we have
|
||||
added though mysql_rpl_probe() or mysql_set_master()/ mysql_add_slave()
|
||||
*/
|
||||
my_bool rpl_pivot;
|
||||
/*
|
||||
Pointers to the master, and the next slave connections, points to
|
||||
itself if lone connection.
|
||||
*/
|
||||
struct st_mysql* master, *next_slave;
|
||||
|
||||
struct st_mysql* last_used_slave; /* needed for round-robin slave pick */
|
||||
/* needed for send/read/store/use result to work correctly with replication */
|
||||
struct st_mysql* last_used_con;
|
||||
|
||||
LIST *stmts; /* list of all statements */
|
||||
const struct st_mysql_methods *methods;
|
||||
void *thd;
|
||||
/*
|
||||
Points to boolean flag in MYSQL_RES or MYSQL_STMT. We set this flag
|
||||
from mysql_stmt_close if close had to cancel result set of this object.
|
||||
*/
|
||||
my_bool *unbuffered_fetch_owner;
|
||||
} MYSQL;
|
||||
|
||||
typedef struct st_mysql_res {
|
||||
my_ulonglong row_count;
|
||||
MYSQL_FIELD *fields;
|
||||
MYSQL_DATA *data;
|
||||
MYSQL_ROWS *data_cursor;
|
||||
unsigned long *lengths; /* column lengths of current row */
|
||||
MYSQL *handle; /* for unbuffered reads */
|
||||
MEM_ROOT field_alloc;
|
||||
unsigned int field_count, current_field;
|
||||
MYSQL_ROW row; /* If unbuffered read */
|
||||
MYSQL_ROW current_row; /* buffer to current row */
|
||||
my_bool eof; /* Used by mysql_fetch_row */
|
||||
/* mysql_stmt_close() had to cancel this result */
|
||||
my_bool unbuffered_fetch_cancelled;
|
||||
const struct st_mysql_methods *methods;
|
||||
} MYSQL_RES;
|
||||
|
||||
#define MAX_MYSQL_MANAGER_ERR 256
|
||||
#define MAX_MYSQL_MANAGER_MSG 256
|
||||
|
||||
#define MANAGER_OK 200
|
||||
#define MANAGER_INFO 250
|
||||
#define MANAGER_ACCESS 401
|
||||
#define MANAGER_CLIENT_ERR 450
|
||||
#define MANAGER_INTERNAL_ERR 500
|
||||
|
||||
#if !defined(MYSQL_SERVER) && !defined(MYSQL_CLIENT)
|
||||
#define MYSQL_CLIENT
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct st_mysql_manager
|
||||
{
|
||||
NET net;
|
||||
char *host,*user,*passwd;
|
||||
unsigned int port;
|
||||
my_bool free_me;
|
||||
my_bool eof;
|
||||
int cmd_status;
|
||||
int last_errno;
|
||||
char* net_buf,*net_buf_pos,*net_data_end;
|
||||
int net_buf_size;
|
||||
char last_error[MAX_MYSQL_MANAGER_ERR];
|
||||
} MYSQL_MANAGER;
|
||||
|
||||
typedef struct st_mysql_parameters
|
||||
{
|
||||
unsigned long *p_max_allowed_packet;
|
||||
unsigned long *p_net_buffer_length;
|
||||
} MYSQL_PARAMETERS;
|
||||
|
||||
#if !defined(MYSQL_SERVER) && !defined(EMBEDDED_LIBRARY)
|
||||
#define max_allowed_packet (*mysql_get_parameters()->p_max_allowed_packet)
|
||||
#define net_buffer_length (*mysql_get_parameters()->p_net_buffer_length)
|
||||
#endif
|
||||
|
||||
/*
|
||||
Set up and bring down the server; to ensure that applications will
|
||||
work when linked against either the standard client library or the
|
||||
embedded server library, these functions should be called.
|
||||
*/
|
||||
int STDCALL mysql_server_init(int argc, char **argv, char **groups);
|
||||
void STDCALL mysql_server_end(void);
|
||||
/*
|
||||
mysql_server_init/end need to be called when using libmysqld or
|
||||
libmysqlclient (exactly, mysql_server_init() is called by mysql_init() so
|
||||
you don't need to call it explicitely; but you need to call
|
||||
mysql_server_end() to free memory). The names are a bit misleading
|
||||
(mysql_SERVER* to be used when using libmysqlCLIENT). So we add more general
|
||||
names which suit well whether you're using libmysqld or libmysqlclient. We
|
||||
intend to promote these aliases over the mysql_server* ones.
|
||||
*/
|
||||
#define mysql_library_init mysql_server_init
|
||||
#define mysql_library_end mysql_server_end
|
||||
|
||||
MYSQL_PARAMETERS *STDCALL mysql_get_parameters(void);
|
||||
|
||||
/*
|
||||
Set up and bring down a thread; these function should be called
|
||||
for each thread in an application which opens at least one MySQL
|
||||
connection. All uses of the connection(s) should be between these
|
||||
function calls.
|
||||
*/
|
||||
my_bool STDCALL mysql_thread_init(void);
|
||||
void STDCALL mysql_thread_end(void);
|
||||
|
||||
/*
|
||||
Functions to get information from the MYSQL and MYSQL_RES structures
|
||||
Should definitely be used if one uses shared libraries.
|
||||
*/
|
||||
|
||||
my_ulonglong STDCALL mysql_num_rows(MYSQL_RES *res);
|
||||
unsigned int STDCALL mysql_num_fields(MYSQL_RES *res);
|
||||
my_bool STDCALL mysql_eof(MYSQL_RES *res);
|
||||
MYSQL_FIELD *STDCALL mysql_fetch_field_direct(MYSQL_RES *res,
|
||||
unsigned int fieldnr);
|
||||
MYSQL_FIELD * STDCALL mysql_fetch_fields(MYSQL_RES *res);
|
||||
MYSQL_ROW_OFFSET STDCALL mysql_row_tell(MYSQL_RES *res);
|
||||
MYSQL_FIELD_OFFSET STDCALL mysql_field_tell(MYSQL_RES *res);
|
||||
|
||||
unsigned int STDCALL mysql_field_count(MYSQL *mysql);
|
||||
my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql);
|
||||
my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql);
|
||||
unsigned int STDCALL mysql_errno(MYSQL *mysql);
|
||||
const char * STDCALL mysql_error(MYSQL *mysql);
|
||||
const char *STDCALL mysql_sqlstate(MYSQL *mysql);
|
||||
unsigned int STDCALL mysql_warning_count(MYSQL *mysql);
|
||||
const char * STDCALL mysql_info(MYSQL *mysql);
|
||||
unsigned long STDCALL mysql_thread_id(MYSQL *mysql);
|
||||
const char * STDCALL mysql_character_set_name(MYSQL *mysql);
|
||||
int STDCALL mysql_set_character_set(MYSQL *mysql, char *csname);
|
||||
|
||||
MYSQL * STDCALL mysql_init(MYSQL *mysql);
|
||||
my_bool STDCALL mysql_ssl_set(MYSQL *mysql, const char *key,
|
||||
const char *cert, const char *ca,
|
||||
const char *capath, const char *cipher);
|
||||
my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
|
||||
const char *passwd, const char *db);
|
||||
MYSQL * STDCALL mysql_real_connect(MYSQL *mysql, const char *host,
|
||||
const char *user,
|
||||
const char *passwd,
|
||||
const char *db,
|
||||
unsigned int port,
|
||||
const char *unix_socket,
|
||||
unsigned long clientflag);
|
||||
int STDCALL mysql_select_db(MYSQL *mysql, const char *db);
|
||||
int STDCALL mysql_query(MYSQL *mysql, const char *q);
|
||||
int STDCALL mysql_send_query(MYSQL *mysql, const char *q,
|
||||
unsigned long length);
|
||||
int STDCALL mysql_real_query(MYSQL *mysql, const char *q,
|
||||
unsigned long length);
|
||||
MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql);
|
||||
MYSQL_RES * STDCALL mysql_use_result(MYSQL *mysql);
|
||||
|
||||
/* perform query on master */
|
||||
my_bool STDCALL mysql_master_query(MYSQL *mysql, const char *q,
|
||||
unsigned long length);
|
||||
my_bool STDCALL mysql_master_send_query(MYSQL *mysql, const char *q,
|
||||
unsigned long length);
|
||||
/* perform query on slave */
|
||||
my_bool STDCALL mysql_slave_query(MYSQL *mysql, const char *q,
|
||||
unsigned long length);
|
||||
my_bool STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q,
|
||||
unsigned long length);
|
||||
|
||||
/* local infile support */
|
||||
|
||||
#define LOCAL_INFILE_ERROR_LEN 512
|
||||
|
||||
void
|
||||
mysql_set_local_infile_handler(MYSQL *mysql,
|
||||
int (*local_infile_init)(void **, const char *,
|
||||
void *),
|
||||
int (*local_infile_read)(void *, char *,
|
||||
unsigned int),
|
||||
void (*local_infile_end)(void *),
|
||||
int (*local_infile_error)(void *, char*,
|
||||
unsigned int),
|
||||
void *);
|
||||
|
||||
void
|
||||
mysql_set_local_infile_default(MYSQL *mysql);
|
||||
|
||||
|
||||
/*
|
||||
enable/disable parsing of all queries to decide if they go on master or
|
||||
slave
|
||||
*/
|
||||
void STDCALL mysql_enable_rpl_parse(MYSQL* mysql);
|
||||
void STDCALL mysql_disable_rpl_parse(MYSQL* mysql);
|
||||
/* get the value of the parse flag */
|
||||
int STDCALL mysql_rpl_parse_enabled(MYSQL* mysql);
|
||||
|
||||
/* enable/disable reads from master */
|
||||
void STDCALL mysql_enable_reads_from_master(MYSQL* mysql);
|
||||
void STDCALL mysql_disable_reads_from_master(MYSQL* mysql);
|
||||
/* get the value of the master read flag */
|
||||
my_bool STDCALL mysql_reads_from_master_enabled(MYSQL* mysql);
|
||||
|
||||
enum mysql_rpl_type STDCALL mysql_rpl_query_type(const char* q, int len);
|
||||
|
||||
/* discover the master and its slaves */
|
||||
my_bool STDCALL mysql_rpl_probe(MYSQL* mysql);
|
||||
|
||||
/* set the master, close/free the old one, if it is not a pivot */
|
||||
int STDCALL mysql_set_master(MYSQL* mysql, const char* host,
|
||||
unsigned int port,
|
||||
const char* user,
|
||||
const char* passwd);
|
||||
int STDCALL mysql_add_slave(MYSQL* mysql, const char* host,
|
||||
unsigned int port,
|
||||
const char* user,
|
||||
const char* passwd);
|
||||
|
||||
int STDCALL mysql_shutdown(MYSQL *mysql,
|
||||
enum mysql_enum_shutdown_level
|
||||
shutdown_level);
|
||||
int STDCALL mysql_dump_debug_info(MYSQL *mysql);
|
||||
int STDCALL mysql_refresh(MYSQL *mysql,
|
||||
unsigned int refresh_options);
|
||||
int STDCALL mysql_kill(MYSQL *mysql,unsigned long pid);
|
||||
int STDCALL mysql_set_server_option(MYSQL *mysql,
|
||||
enum enum_mysql_set_option
|
||||
option);
|
||||
int STDCALL mysql_ping(MYSQL *mysql);
|
||||
const char * STDCALL mysql_stat(MYSQL *mysql);
|
||||
const char * STDCALL mysql_get_server_info(MYSQL *mysql);
|
||||
const char * STDCALL mysql_get_client_info(void);
|
||||
unsigned long STDCALL mysql_get_client_version(void);
|
||||
const char * STDCALL mysql_get_host_info(MYSQL *mysql);
|
||||
unsigned long STDCALL mysql_get_server_version(MYSQL *mysql);
|
||||
unsigned int STDCALL mysql_get_proto_info(MYSQL *mysql);
|
||||
MYSQL_RES * STDCALL mysql_list_dbs(MYSQL *mysql,const char *wild);
|
||||
MYSQL_RES * STDCALL mysql_list_tables(MYSQL *mysql,const char *wild);
|
||||
MYSQL_RES * STDCALL mysql_list_processes(MYSQL *mysql);
|
||||
int STDCALL mysql_options(MYSQL *mysql,enum mysql_option option,
|
||||
const char *arg);
|
||||
void STDCALL mysql_free_result(MYSQL_RES *result);
|
||||
void STDCALL mysql_data_seek(MYSQL_RES *result,
|
||||
my_ulonglong offset);
|
||||
MYSQL_ROW_OFFSET STDCALL mysql_row_seek(MYSQL_RES *result,
|
||||
MYSQL_ROW_OFFSET offset);
|
||||
MYSQL_FIELD_OFFSET STDCALL mysql_field_seek(MYSQL_RES *result,
|
||||
MYSQL_FIELD_OFFSET offset);
|
||||
MYSQL_ROW STDCALL mysql_fetch_row(MYSQL_RES *result);
|
||||
unsigned long * STDCALL mysql_fetch_lengths(MYSQL_RES *result);
|
||||
MYSQL_FIELD * STDCALL mysql_fetch_field(MYSQL_RES *result);
|
||||
MYSQL_RES * STDCALL mysql_list_fields(MYSQL *mysql, const char *table,
|
||||
const char *wild);
|
||||
unsigned long STDCALL mysql_escape_string(char *to,const char *from,
|
||||
unsigned long from_length);
|
||||
unsigned long STDCALL mysql_hex_string(char *to,const char *from,
|
||||
unsigned long from_length);
|
||||
unsigned long STDCALL mysql_real_escape_string(MYSQL *mysql,
|
||||
char *to,const char *from,
|
||||
unsigned long length);
|
||||
void STDCALL mysql_debug(const char *debug);
|
||||
char * STDCALL mysql_odbc_escape_string(MYSQL *mysql,
|
||||
char *to,
|
||||
unsigned long to_length,
|
||||
const char *from,
|
||||
unsigned long from_length,
|
||||
void *param,
|
||||
char *
|
||||
(*extend_buffer)
|
||||
(void *, char *to,
|
||||
unsigned long *length));
|
||||
void STDCALL myodbc_remove_escape(MYSQL *mysql,char *name);
|
||||
unsigned int STDCALL mysql_thread_safe(void);
|
||||
my_bool STDCALL mysql_embedded(void);
|
||||
MYSQL_MANAGER* STDCALL mysql_manager_init(MYSQL_MANAGER* con);
|
||||
MYSQL_MANAGER* STDCALL mysql_manager_connect(MYSQL_MANAGER* con,
|
||||
const char* host,
|
||||
const char* user,
|
||||
const char* passwd,
|
||||
unsigned int port);
|
||||
void STDCALL mysql_manager_close(MYSQL_MANAGER* con);
|
||||
int STDCALL mysql_manager_command(MYSQL_MANAGER* con,
|
||||
const char* cmd, int cmd_len);
|
||||
int STDCALL mysql_manager_fetch_line(MYSQL_MANAGER* con,
|
||||
char* res_buf,
|
||||
int res_buf_size);
|
||||
my_bool STDCALL mysql_read_query_result(MYSQL *mysql);
|
||||
|
||||
|
||||
/*
|
||||
The following definitions are added for the enhanced
|
||||
client-server protocol
|
||||
*/
|
||||
|
||||
/* statement state */
|
||||
enum enum_mysql_stmt_state
|
||||
{
|
||||
MYSQL_STMT_INIT_DONE= 1, MYSQL_STMT_PREPARE_DONE, MYSQL_STMT_EXECUTE_DONE,
|
||||
MYSQL_STMT_FETCH_DONE
|
||||
};
|
||||
|
||||
|
||||
/* bind structure */
|
||||
typedef struct st_mysql_bind
|
||||
{
|
||||
unsigned long *length; /* output length pointer */
|
||||
my_bool *is_null; /* Pointer to null indicator */
|
||||
void *buffer; /* buffer to get/put data */
|
||||
enum enum_field_types buffer_type; /* buffer type */
|
||||
unsigned long buffer_length; /* buffer length, must be set for str/binary */
|
||||
|
||||
/* Following are for internal use. Set by mysql_stmt_bind_param */
|
||||
unsigned char *inter_buffer; /* for the current data position */
|
||||
unsigned long offset; /* offset position for char/binary fetch */
|
||||
unsigned long internal_length; /* Used if length is 0 */
|
||||
unsigned int param_number; /* For null count and error messages */
|
||||
unsigned int pack_length; /* Internal length for packed data */
|
||||
my_bool is_unsigned; /* set if integer type is unsigned */
|
||||
my_bool long_data_used; /* If used with mysql_send_long_data */
|
||||
my_bool internal_is_null; /* Used if is_null is 0 */
|
||||
void (*store_param_func)(NET *net, struct st_mysql_bind *param);
|
||||
void (*fetch_result)(struct st_mysql_bind *, unsigned char **row);
|
||||
void (*skip_result)(struct st_mysql_bind *, MYSQL_FIELD *,
|
||||
unsigned char **row);
|
||||
} MYSQL_BIND;
|
||||
|
||||
|
||||
/* statement handler */
|
||||
typedef struct st_mysql_stmt
|
||||
{
|
||||
MEM_ROOT mem_root; /* root allocations */
|
||||
LIST list; /* list to keep track of all stmts */
|
||||
MYSQL *mysql; /* connection handle */
|
||||
MYSQL_BIND *params; /* input parameters */
|
||||
MYSQL_BIND *bind; /* output parameters */
|
||||
MYSQL_FIELD *fields; /* result set metadata */
|
||||
MYSQL_DATA result; /* cached result set */
|
||||
MYSQL_ROWS *data_cursor; /* current row in cached result */
|
||||
/* copy of mysql->affected_rows after statement execution */
|
||||
my_ulonglong affected_rows;
|
||||
my_ulonglong insert_id; /* copy of mysql->insert_id */
|
||||
/*
|
||||
mysql_stmt_fetch() calls this function to fetch one row (it's different
|
||||
for buffered, unbuffered and cursor fetch).
|
||||
*/
|
||||
int (*read_row_func)(struct st_mysql_stmt *stmt,
|
||||
unsigned char **row);
|
||||
unsigned long stmt_id; /* Id for prepared statement */
|
||||
unsigned int last_errno; /* error code */
|
||||
unsigned int param_count; /* input parameter count */
|
||||
unsigned int field_count; /* number of columns in result set */
|
||||
enum enum_mysql_stmt_state state; /* statement state */
|
||||
char last_error[MYSQL_ERRMSG_SIZE]; /* error message */
|
||||
char sqlstate[SQLSTATE_LENGTH+1];
|
||||
/* Types of input parameters should be sent to server */
|
||||
my_bool send_types_to_server;
|
||||
my_bool bind_param_done; /* input buffers were supplied */
|
||||
my_bool bind_result_done; /* output buffers were supplied */
|
||||
/* mysql_stmt_close() had to cancel this result */
|
||||
my_bool unbuffered_fetch_cancelled;
|
||||
/*
|
||||
Is set to true if we need to calculate field->max_length for
|
||||
metadata fields when doing mysql_stmt_store_result.
|
||||
*/
|
||||
my_bool update_max_length;
|
||||
} MYSQL_STMT;
|
||||
|
||||
enum enum_stmt_attr_type
|
||||
{
|
||||
/*
|
||||
When doing mysql_stmt_store_result calculate max_length attribute
|
||||
of statement metadata. This is to be consistent with the old API,
|
||||
where this was done automatically.
|
||||
In the new API we do that only by request because it slows down
|
||||
mysql_stmt_store_result sufficiently.
|
||||
*/
|
||||
STMT_ATTR_UPDATE_MAX_LENGTH
|
||||
};
|
||||
|
||||
|
||||
typedef struct st_mysql_methods
|
||||
{
|
||||
my_bool (*read_query_result)(MYSQL *mysql);
|
||||
my_bool (*advanced_command)(MYSQL *mysql,
|
||||
enum enum_server_command command,
|
||||
const char *header,
|
||||
unsigned long header_length,
|
||||
const char *arg,
|
||||
unsigned long arg_length,
|
||||
my_bool skip_check);
|
||||
MYSQL_DATA *(*read_rows)(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
|
||||
unsigned int fields);
|
||||
MYSQL_RES * (*use_result)(MYSQL *mysql);
|
||||
void (*fetch_lengths)(unsigned long *to,
|
||||
MYSQL_ROW column, unsigned int field_count);
|
||||
void (*flush_use_result)(MYSQL *mysql);
|
||||
#if !defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY)
|
||||
MYSQL_FIELD * (*list_fields)(MYSQL *mysql);
|
||||
my_bool (*read_prepare_result)(MYSQL *mysql, MYSQL_STMT *stmt);
|
||||
int (*stmt_execute)(MYSQL_STMT *stmt);
|
||||
int (*read_binary_rows)(MYSQL_STMT *stmt);
|
||||
int (*unbuffered_fetch)(MYSQL *mysql, char **row);
|
||||
void (*free_embedded_thd)(MYSQL *mysql);
|
||||
const char *(*read_statistics)(MYSQL *mysql);
|
||||
my_bool (*next_result)(MYSQL *mysql);
|
||||
int (*read_change_user_result)(MYSQL *mysql, char *buff, const char *passwd);
|
||||
#endif
|
||||
} MYSQL_METHODS;
|
||||
|
||||
|
||||
MYSQL_STMT * STDCALL mysql_stmt_init(MYSQL *mysql);
|
||||
int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query,
|
||||
unsigned long length);
|
||||
int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt);
|
||||
int STDCALL mysql_stmt_fetch(MYSQL_STMT *stmt);
|
||||
int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind,
|
||||
unsigned int column,
|
||||
unsigned long offset);
|
||||
int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt);
|
||||
unsigned long STDCALL mysql_stmt_param_count(MYSQL_STMT * stmt);
|
||||
my_bool STDCALL mysql_stmt_attr_set(MYSQL_STMT *stmt,
|
||||
enum enum_stmt_attr_type attr_type,
|
||||
const void *attr);
|
||||
my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt,
|
||||
enum enum_stmt_attr_type attr_type,
|
||||
void *attr);
|
||||
my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bnd);
|
||||
my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bnd);
|
||||
my_bool STDCALL mysql_stmt_close(MYSQL_STMT * stmt);
|
||||
my_bool STDCALL mysql_stmt_reset(MYSQL_STMT * stmt);
|
||||
my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt);
|
||||
my_bool STDCALL mysql_stmt_send_long_data(MYSQL_STMT *stmt,
|
||||
unsigned int param_number,
|
||||
const char *data,
|
||||
unsigned long length);
|
||||
MYSQL_RES *STDCALL mysql_stmt_result_metadata(MYSQL_STMT *stmt);
|
||||
MYSQL_RES *STDCALL mysql_stmt_param_metadata(MYSQL_STMT *stmt);
|
||||
unsigned int STDCALL mysql_stmt_errno(MYSQL_STMT * stmt);
|
||||
const char *STDCALL mysql_stmt_error(MYSQL_STMT * stmt);
|
||||
const char *STDCALL mysql_stmt_sqlstate(MYSQL_STMT * stmt);
|
||||
MYSQL_ROW_OFFSET STDCALL mysql_stmt_row_seek(MYSQL_STMT *stmt,
|
||||
MYSQL_ROW_OFFSET offset);
|
||||
MYSQL_ROW_OFFSET STDCALL mysql_stmt_row_tell(MYSQL_STMT *stmt);
|
||||
void STDCALL mysql_stmt_data_seek(MYSQL_STMT *stmt, my_ulonglong offset);
|
||||
my_ulonglong STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt);
|
||||
my_ulonglong STDCALL mysql_stmt_affected_rows(MYSQL_STMT *stmt);
|
||||
my_ulonglong STDCALL mysql_stmt_insert_id(MYSQL_STMT *stmt);
|
||||
unsigned int STDCALL mysql_stmt_field_count(MYSQL_STMT *stmt);
|
||||
|
||||
my_bool STDCALL mysql_commit(MYSQL * mysql);
|
||||
my_bool STDCALL mysql_rollback(MYSQL * mysql);
|
||||
my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode);
|
||||
my_bool STDCALL mysql_more_results(MYSQL *mysql);
|
||||
int STDCALL mysql_next_result(MYSQL *mysql);
|
||||
void STDCALL mysql_close(MYSQL *sock);
|
||||
|
||||
|
||||
/* status return codes */
|
||||
#define MYSQL_NO_DATA 100
|
||||
|
||||
#define mysql_reload(mysql) mysql_refresh((mysql),REFRESH_GRANT)
|
||||
|
||||
#ifdef USE_OLD_FUNCTIONS
|
||||
MYSQL * STDCALL mysql_connect(MYSQL *mysql, const char *host,
|
||||
const char *user, const char *passwd);
|
||||
int STDCALL mysql_create_db(MYSQL *mysql, const char *DB);
|
||||
int STDCALL mysql_drop_db(MYSQL *mysql, const char *DB);
|
||||
#define mysql_reload(mysql) mysql_refresh((mysql),REFRESH_GRANT)
|
||||
#endif
|
||||
#define HAVE_MYSQL_REAL_CONNECT
|
||||
|
||||
/*
|
||||
The following functions are mainly exported because of mysqlbinlog;
|
||||
They are not for general usage
|
||||
*/
|
||||
|
||||
#define simple_command(mysql, command, arg, length, skip_check) \
|
||||
(*(mysql)->methods->advanced_command)(mysql, command, \
|
||||
NullS, 0, arg, length, skip_check)
|
||||
unsigned long net_safe_read(MYSQL* mysql);
|
||||
|
||||
#ifdef __NETWARE__
|
||||
#pragma pack(pop) /* restore alignment */
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _mysql_h */
|
||||
@@ -0,0 +1,530 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include "rosecrypt.hpp"
|
||||
#include <cstdlib>
|
||||
|
||||
#define LOGINSERVER_CRYPTTABLE_START_VALUE 0x0042D266
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// This structure saves values while the tables are generated
|
||||
//-------------------------------------------------------------------------
|
||||
struct CCryptTableControlStruct
|
||||
{
|
||||
unsigned CountTableMod[4];
|
||||
unsigned char CurTableMod ;
|
||||
unsigned ValueTableMod[4];
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// This structure is used by the encryption routines
|
||||
//-------------------------------------------------------------------------
|
||||
typedef unsigned long long int u64;
|
||||
|
||||
struct CCryptBuffer
|
||||
{
|
||||
u64 AddBufferLen : 11;
|
||||
u64 Command : 11;
|
||||
u64 AddTableValue : 11;
|
||||
u64 EncryptAddValue : 4;
|
||||
u64 EncryptValue : 3;
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// This table is used to calculate a checksum (size of 256 bytes)
|
||||
//-------------------------------------------------------------------------
|
||||
const unsigned char CheckSumTable[] =
|
||||
"\x00\x5E\xBC\xE2\x61\x3F\xDD\x83\xC2\x9C\x7E\x20\xA3\xFD\x1F\x41"
|
||||
"\x9D\xC3\x21\x7F\xFC\xA2\x40\x1E\x5F\x01\xE3\xBD\x3E\x60\x82\xDC"
|
||||
"\x23\x7D\x9F\xC1\x42\x1C\xFE\xA0\xE1\xBF\x5D\x03\x80\xDE\x3C\x62"
|
||||
"\xBE\xE0\x02\x5C\xDF\x81\x63\x3D\x7C\x22\xC0\x9E\x1D\x43\xA1\xFF"
|
||||
"\x46\x18\xFA\xA4\x27\x79\x9B\xC5\x84\xDA\x38\x66\xE5\xBB\x59\x07"
|
||||
"\xDB\x85\x67\x39\xBA\xE4\x06\x58\x19\x47\xA5\xFB\x78\x26\xC4\x9A"
|
||||
"\x65\x3B\xD9\x87\x04\x5A\xB8\xE6\xA7\xF9\x1B\x45\xC6\x98\x7A\x24"
|
||||
"\xF8\xA6\x44\x1A\x99\xC7\x25\x7B\x3A\x64\x86\xD8\x5B\x05\xE7\xB9"
|
||||
"\x8C\xD2\x30\x6E\xED\xB3\x51\x0F\x4E\x10\xF2\xAC\x2F\x71\x93\xCD"
|
||||
"\x11\x4F\xAD\xF3\x70\x2E\xCC\x92\xD3\x8D\x6F\x31\xB2\xEC\x0E\x50"
|
||||
"\xAF\xF1\x13\x4D\xCE\x90\x72\x2C\x6D\x33\xD1\x8F\x0C\x52\xB0\xEE"
|
||||
"\x32\x6C\x8E\xD0\x53\x0D\xEF\xB1\xF0\xAE\x4C\x12\x91\xCF\x2D\x73"
|
||||
"\xCA\x94\x76\x28\xAB\xF5\x17\x49\x08\x56\xB4\xEA\x69\x37\xD5\x8B"
|
||||
"\x57\x09\xEB\xB5\x36\x68\x8A\xD4\x95\xCB\x29\x77\xF4\xAA\x48\x16"
|
||||
"\xE9\xB7\x55\x0B\x88\xD6\x34\x6A\x2B\x75\x97\xC9\x4A\x14\xF6\xA8"
|
||||
"\x74\x2A\xC8\x96\x15\x4B\xA9\xF7\xB6\xE8\x0A\x54\xD7\x89\x6B\x35";
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Private function, that generates the next value for the tables
|
||||
//----------------------------------------------------------------------------
|
||||
unsigned ctGenerateNextValue( CCryptTable *CryptTables, CCryptTableControlStruct *ControlStruct )
|
||||
{
|
||||
// Get the last value depending on the current TableMod.
|
||||
int Value = ControlStruct->ValueTableMod[ ControlStruct->CurTableMod ];
|
||||
|
||||
// Update generatecount, depending on the current TableMod
|
||||
ControlStruct->CountTableMod [ ControlStruct->CurTableMod ];
|
||||
|
||||
// Calculate and return the next value
|
||||
switch ( ControlStruct->CurTableMod )
|
||||
{
|
||||
case 0:
|
||||
Value = (int(Value * 0x8088405)) + 1;
|
||||
ControlStruct->ValueTableMod[ 0 ] = Value;
|
||||
return int(Value + (Value<0?0xFFFF:0)) >> 0x10;
|
||||
case 1:
|
||||
Value = (0x3039 - (int(Value * 0x3E39B193))) & 0x7FFFFFFF;
|
||||
ControlStruct->ValueTableMod[ 1 ] = Value;
|
||||
return Value;
|
||||
case 2:
|
||||
Value = (int(Value * 0x41C64E6D) + 0x3039);
|
||||
ControlStruct->ValueTableMod[ 2 ] = Value;
|
||||
return int(Value + (Value<0?0xFFFF:0)) >> 0x10;
|
||||
case 3:
|
||||
Value = (int(Value * 0x343FD) + 0x269EC3) & 0x7FFFFFFF;
|
||||
ControlStruct->ValueTableMod[ 3 ] = Value;
|
||||
return int(Value + (Value<0?0xFFFF:0)) >> 0x10;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Private functions, that searches a value in an existing table to
|
||||
// check if this value already exists.
|
||||
//-------------------------------------------------------------------------
|
||||
bool ctValueExistsInTable( CCryptTable *CryptTables, unsigned char Table, unsigned Value, unsigned short EntryCount )
|
||||
{
|
||||
for ( unsigned short i=0; i<EntryCount; ++i )
|
||||
if ( (unsigned)CryptTables->Tables[ Table ][ i ] == Value ) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// This function generates a new crypt table depending on the ModValue
|
||||
// parameter.
|
||||
//-------------------------------------------------------------------------
|
||||
void GenerateCryptTables( CCryptTable* &CryptTables, unsigned ModValue )
|
||||
{
|
||||
CCryptTableControlStruct ControlStruct;
|
||||
unsigned char TableFuncList[ 17 ];
|
||||
unsigned char table;
|
||||
unsigned short entry;
|
||||
unsigned value;
|
||||
int ivalue;
|
||||
|
||||
// Allocate memory for structure
|
||||
CryptTables = (CCryptTable*)malloc( sizeof( CCryptTable ) );
|
||||
CryptTables->Tables = (unsigned **)calloc( 16, sizeof( unsigned ) );
|
||||
|
||||
// Prepare values
|
||||
ModValue = (int(ModValue * 0x41C64E6D) + 0x3039);
|
||||
ModValue = int(ModValue + ((int)ModValue<0?0xFFFF:0)) >> 0x10;
|
||||
|
||||
// Startvalue for checksum variable for each user
|
||||
CryptTables->EncryptionStartValue = ModValue;
|
||||
|
||||
// set startvalues
|
||||
for ( table=0; table<4; ++table )
|
||||
{
|
||||
ControlStruct.CountTableMod[ table ] = 0;
|
||||
ControlStruct.ValueTableMod[ table ] = ModValue;
|
||||
}
|
||||
|
||||
// Generate TableMod list for creation
|
||||
ControlStruct.CurTableMod = 0;
|
||||
for ( table=0; table<0x11; ++table )
|
||||
{
|
||||
ivalue = ctGenerateNextValue( CryptTables, &ControlStruct ) & 0x80000003;
|
||||
if ( ivalue<0 ) ivalue = ( ( ivalue - 1 ) | 0xFFFFFFFC ) + 1;
|
||||
TableFuncList[ table ] = ( unsigned char )ivalue;
|
||||
}
|
||||
|
||||
// Create tables
|
||||
for ( table=0; table<16; ++table )
|
||||
{
|
||||
// Prepare creation loop for current table
|
||||
CryptTables->Tables[ table ] = (unsigned*)calloc( 0x800, sizeof( unsigned ) );
|
||||
ControlStruct.CurTableMod = TableFuncList[ table ] & 3;
|
||||
|
||||
// Generate current table
|
||||
entry = 0;
|
||||
do
|
||||
{
|
||||
// Generate next value
|
||||
value = ctGenerateNextValue( CryptTables, &ControlStruct );
|
||||
|
||||
// Check, if value already exist in table 0
|
||||
if ( ctValueExistsInTable( CryptTables, 0, value, entry ) ) continue;
|
||||
|
||||
// Save value to memory
|
||||
CryptTables->Tables[ table ][ entry ] = value;
|
||||
|
||||
++entry;
|
||||
} while ( entry<0x800 );
|
||||
}
|
||||
|
||||
// Generate additional table
|
||||
CryptTables->AddTable = (unsigned short*)calloc( 0x200, sizeof( unsigned short ) );
|
||||
ControlStruct.CurTableMod = table = (unsigned char)(TableFuncList[ 0x10 ]) & 3;
|
||||
entry = 0;
|
||||
do
|
||||
{
|
||||
// Generate next value
|
||||
value = ctGenerateNextValue( CryptTables, &ControlStruct ) & 0x7FF;
|
||||
|
||||
// Check, if value already exist
|
||||
for ( ivalue=0; ivalue<=(int)entry; ++ivalue )
|
||||
if ( (unsigned)CryptTables->AddTable[ivalue] == value ) { value=0xFFFFFFFF; break; }
|
||||
|
||||
// If value exist, continue
|
||||
if ( value==0xFFFFFFFF ) continue;
|
||||
|
||||
// Save value
|
||||
CryptTables->AddTable[ entry++ ] = value;
|
||||
} while ( entry<0x200 );
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// This function generates a new crypt table used by the Login Server
|
||||
//-------------------------------------------------------------------------
|
||||
void GenerateLoginServerCryptTables( CCryptTable* &CryptTables )
|
||||
{
|
||||
CCryptTableControlStruct ControlStruct;
|
||||
unsigned char table;
|
||||
unsigned short entry;
|
||||
unsigned value;
|
||||
int ivalue;
|
||||
|
||||
// Allocate memory for structure
|
||||
CryptTables = (CCryptTable*)malloc( sizeof( CCryptTable ) );
|
||||
CryptTables->Tables = (unsigned **)calloc( 16, sizeof( unsigned ) );
|
||||
|
||||
// Set default startvalues
|
||||
for ( table=0; table<4; ++table )
|
||||
{
|
||||
ControlStruct.CountTableMod[ table ] = 0;
|
||||
ControlStruct.ValueTableMod[ table ] = LOGINSERVER_CRYPTTABLE_START_VALUE;
|
||||
}
|
||||
|
||||
// Another startvalue
|
||||
CryptTables->EncryptionStartValue = LOGINSERVER_CRYPTTABLE_START_VALUE;
|
||||
|
||||
// Generate default tables
|
||||
for ( table=0; table<16; ++table )
|
||||
{
|
||||
// Prepare creation loop for current table
|
||||
ControlStruct.CurTableMod = table & 3;
|
||||
CryptTables->Tables[ table ] = (unsigned*)calloc( 0x800, sizeof( unsigned ) );
|
||||
|
||||
entry = 0;
|
||||
do
|
||||
{
|
||||
// Generate next value depend on CurTableMod
|
||||
value = ctGenerateNextValue( CryptTables, &ControlStruct );
|
||||
|
||||
// Only take value, if it doesn't exist in table 0 already
|
||||
if ( ctValueExistsInTable( CryptTables, 0, value, entry ) ) continue;
|
||||
|
||||
// Save value to structure
|
||||
CryptTables->Tables[ table ][ entry ] = value;
|
||||
|
||||
++entry;
|
||||
} while ( entry<0x800 );
|
||||
}
|
||||
|
||||
// Create additional table
|
||||
CryptTables->AddTable = (unsigned short*)calloc( 0x200, sizeof( unsigned short ) );
|
||||
entry = 0;
|
||||
do
|
||||
{
|
||||
// Generate next value for table
|
||||
ControlStruct.CountTableMod[1];
|
||||
ivalue = ControlStruct.ValueTableMod[1];
|
||||
ivalue *= 0x3E39B193;
|
||||
value = (0x3039 - (unsigned)ivalue) & 0x7FFFFFFF;
|
||||
ControlStruct.ValueTableMod[1] = value;
|
||||
|
||||
// Don't save, if value already exist
|
||||
value &= 0x7FF;
|
||||
for ( ivalue=0; ivalue<=(int)entry; ++ivalue )
|
||||
if ( (unsigned)CryptTables->AddTable[ivalue] == value ) { value=0xFFFFFFFF; break; }
|
||||
|
||||
// If value already exist, continue
|
||||
if ( value==0xFFFFFFFF ) continue;
|
||||
|
||||
// Save value to structure
|
||||
CryptTables->AddTable[ entry ] = value;
|
||||
|
||||
++entry;
|
||||
} while ( entry<0x200 );
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// This function frees the memory of a crypt table
|
||||
//-------------------------------------------------------------------------
|
||||
void FreeCryptTables( CCryptTable* &CryptTables )
|
||||
{
|
||||
unsigned char c;
|
||||
|
||||
// Free every table
|
||||
for ( c=0; c<16; ++c )
|
||||
free( CryptTables->Tables[ c ] );
|
||||
|
||||
// Free memory
|
||||
free( CryptTables->AddTable );
|
||||
free( CryptTables->Tables );
|
||||
free( CryptTables );
|
||||
|
||||
CryptTables = NULL;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// This function decrypts a received 6-byte buffer and returns the full
|
||||
// size of the incoming packet (including this 6-byte header).
|
||||
// If the buffer is incorrect, this function returns a zero.
|
||||
//-------------------------------------------------------------------------
|
||||
int DecryptBufferHeader( CCryptStatus *ri, CCryptTable *CryptTables, unsigned char *Buffer )
|
||||
{
|
||||
CCryptBuffer TempBuffer;
|
||||
unsigned BigBuffer;
|
||||
unsigned char c;
|
||||
|
||||
// Read "AddTableValue" from buffer
|
||||
BigBuffer = *((unsigned*)Buffer);
|
||||
TempBuffer.AddTableValue = ( ( Buffer[4] >> 0x03 ) & 0x0007 ) | ( ( BigBuffer ) & 0x0038 ) | \
|
||||
( ( BigBuffer >> 0x03 ) & 0x01C0 ) | ( ( BigBuffer >> 0x11 ) & 0x0600 );
|
||||
|
||||
// Decrypt header in the buffer
|
||||
for ( c=0; c<5; ++c )
|
||||
Buffer[c] ^= CryptTables->Tables[ c ][ TempBuffer.AddTableValue ];
|
||||
|
||||
BigBuffer = *((unsigned*)Buffer);
|
||||
TempBuffer.EncryptValue = ( BigBuffer >> 0x0F ) & 0x0007 ;
|
||||
TempBuffer.Command = ( ( BigBuffer >> 0x0C ) & 0x0007 ) | ( ( BigBuffer << 0x03 ) & 0x0038 ) | \
|
||||
( ( Buffer[4] << 0x06 ) & 0x01C0 ) | ( ( BigBuffer >> 0x13 ) & 0x0600 );
|
||||
TempBuffer.AddBufferLen = ( ( BigBuffer >> 0x06 ) & 0x0007 ) | ( ( BigBuffer >> 0x0F ) & 0x0038 ) | \
|
||||
( ( BigBuffer >> 0x11 ) & 0x01C0 ) | ( ( Buffer[4] << 0x03 ) & 0x0600 );
|
||||
TempBuffer.EncryptAddValue = ( ( BigBuffer >> 0x1E ) & 0x0003 ) | ( ( BigBuffer >> 0x13 ) & 0x000C );
|
||||
|
||||
// Size correct?
|
||||
if ( TempBuffer.AddBufferLen < 0x06 || TempBuffer.AddBufferLen > 0x400 )
|
||||
return 0;
|
||||
|
||||
// Header Checksum correct? ~ not implented yet ~
|
||||
/*
|
||||
if ( ((unsigned)( TempBuffer.AddTableValue + TempBuffer.EncryptAddValue ) & 7 ) != \
|
||||
((unsigned)( TempBuffer.EncryptValue ) & 7 ) )
|
||||
return 0;
|
||||
*/
|
||||
|
||||
// Save CryptBuffer temporary to buffer for later use
|
||||
*((unsigned*)Buffer) = *((unsigned *)&TempBuffer) ;
|
||||
Buffer[4] = ((unsigned char*)&TempBuffer)[4];
|
||||
|
||||
// Update encryption value
|
||||
ri->CurEncryptionValue = ( ri->CurEncryptionValue * 0x343FD ) + 0x269EC3;
|
||||
|
||||
// Everything went ok
|
||||
return TempBuffer.AddBufferLen;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// This function will decrypt the full buffer after it is received.
|
||||
// If it fails, it will return FALSE.
|
||||
//-------------------------------------------------------------------------
|
||||
bool DecryptBufferData( CCryptTable *CryptTables, unsigned char *Buffer )
|
||||
{
|
||||
CCryptBuffer TempBuffer;
|
||||
unsigned short c, BufferLen;
|
||||
unsigned char CheckSum;
|
||||
|
||||
// Read CryptBuffer from received buffer
|
||||
*((unsigned *)&TempBuffer) = *((unsigned*)Buffer);
|
||||
((unsigned char*)&TempBuffer)[4] = Buffer[4];
|
||||
|
||||
// Calculate CheckSum for bufferheader
|
||||
for ( CheckSum=0, c=0; c<5; ++c )
|
||||
CheckSum = CheckSumTable[ (unsigned char)Buffer[ c ] ^ CheckSum ];
|
||||
|
||||
// Calculate real buffer length and check it
|
||||
BufferLen = (unsigned short)(TempBuffer.AddBufferLen - TempBuffer.EncryptValue);
|
||||
if ( BufferLen < 0x06 ) return false;
|
||||
|
||||
// Decrypt buffer data
|
||||
if ( BufferLen > 0x06 )
|
||||
{
|
||||
for ( c=6; c<BufferLen; ++c )
|
||||
{
|
||||
Buffer[c] ^= CryptTables->Tables[ (TempBuffer.EncryptAddValue + c) & 0x000F ] \
|
||||
[ (TempBuffer.AddTableValue + c) & 0x07FF ];
|
||||
CheckSum = CheckSumTable [ (unsigned char)Buffer[ c ] ^ CheckSum ];
|
||||
}
|
||||
}
|
||||
|
||||
// Check CheckSum
|
||||
if ( Buffer[5] != CheckSum )
|
||||
return false;
|
||||
|
||||
// Complete buffer
|
||||
*((unsigned short*)(Buffer )) = BufferLen ;
|
||||
*((unsigned short*)(Buffer+2)) = TempBuffer.Command;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// This functions will encrypt a buffer. The buffer must have at least a
|
||||
// size of 6 bytes. The first two bytes must be the size of the buffer.
|
||||
//-------------------------------------------------------------------------
|
||||
void EncryptBuffer( CCryptTable *CryptTables, unsigned char *Buffer )
|
||||
{
|
||||
CCryptBuffer TempBuffer;
|
||||
unsigned short c;
|
||||
unsigned char CheckSum;
|
||||
unsigned EncryptValue;
|
||||
|
||||
// Generate some random values for encrypting
|
||||
TempBuffer.AddTableValue = (rand( ) % 0x800);
|
||||
TempBuffer.EncryptAddValue = (rand( ) % 0x10 );
|
||||
TempBuffer.EncryptValue = TempBuffer.AddTableValue + TempBuffer.EncryptAddValue;
|
||||
|
||||
// Fill other fields with values from Buffer
|
||||
TempBuffer.AddBufferLen = *((unsigned short*)(Buffer ));
|
||||
TempBuffer.Command = *((unsigned short*)(Buffer+2));
|
||||
|
||||
// Build new bufferheader
|
||||
|
||||
Buffer[4] = (((unsigned)TempBuffer.AddBufferLen ) & 0x00000007 ) ^ \
|
||||
(((unsigned)TempBuffer.Command >> 0x03 ) & 0x000000C0 );
|
||||
EncryptValue = (((unsigned)TempBuffer.AddBufferLen >> 0x03 ) & 0x00000007 );
|
||||
EncryptValue |= (((unsigned)TempBuffer.AddBufferLen << 0x06 ) & 0x00007000 );
|
||||
EncryptValue |= (((unsigned)TempBuffer.AddBufferLen << 0x13 ) & 0x30000000 );
|
||||
EncryptValue |= (((unsigned)TempBuffer.Command << 0x17 ) & 0x03800000 );
|
||||
EncryptValue |= (((unsigned)TempBuffer.Command << 0x0F ) & 0x001C0000 );
|
||||
EncryptValue |= (((unsigned)TempBuffer.Command ) & 0x000001C0 );
|
||||
EncryptValue |= (((unsigned)TempBuffer.EncryptValue << 0x09 ) & 0x00000E00 );
|
||||
EncryptValue |= (((unsigned)TempBuffer.EncryptAddValue << 0x1A ) & 0x0C000000 );
|
||||
EncryptValue |= (((unsigned)TempBuffer.EncryptAddValue << 0x1C ) & 0xC0000000 );
|
||||
|
||||
*((unsigned*)Buffer) = EncryptValue;
|
||||
|
||||
// Encrypt bufferheader
|
||||
for ( CheckSum=0, c=0; c<5; ++c )
|
||||
{
|
||||
CheckSum = CheckSumTable [ ((unsigned char*)&TempBuffer)[ c ] ^ CheckSum ];
|
||||
Buffer[c] ^= CryptTables->Tables[ c ][ TempBuffer.AddTableValue ];
|
||||
}
|
||||
|
||||
|
||||
// Encrypt bufferdata if exists
|
||||
if ( TempBuffer.AddBufferLen > 0x06 )
|
||||
{
|
||||
for ( c=6; c<TempBuffer.AddBufferLen; ++c )
|
||||
{
|
||||
CheckSum = CheckSumTable [ (unsigned char)Buffer[ c ] ^ CheckSum ];
|
||||
Buffer[c] ^= CryptTables->Tables[ (TempBuffer.EncryptAddValue + c) & 0x000F ] \
|
||||
[ (TempBuffer.AddTableValue + c) & 0x07FF ];
|
||||
}
|
||||
}
|
||||
Buffer[ 5 ] = CheckSum;
|
||||
|
||||
// Complete bufferheader
|
||||
EncryptValue = *((unsigned*)Buffer) & 0xFF9C7FC7;
|
||||
EncryptValue |= (((unsigned)TempBuffer.AddTableValue << 0x03 ) & 0x00000038 );
|
||||
EncryptValue |= (((unsigned)TempBuffer.AddTableValue << 0x09 ) & 0x00038000 );
|
||||
EncryptValue |= (((unsigned)TempBuffer.AddTableValue << 0x0C ) & 0x00600000 );
|
||||
Buffer[ 4 ] = (Buffer[4]&0xC7) | (((unsigned)TempBuffer.AddTableValue ) & 0x38 );
|
||||
*((unsigned*)Buffer) = EncryptValue;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
bool CryptISCPak( unsigned char* pak )
|
||||
{
|
||||
unsigned paksize = *((unsigned short*)&pak[0]);
|
||||
for( unsigned short i = 2; i < paksize; i ++ )
|
||||
pak[i] ^= 0x81 * i * paksize;
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef USE124
|
||||
// This encryption code was taken from the dRose source. Not sure who to credit other than them.
|
||||
// To use 124 you will need the 124 trose.exe in your server directory.
|
||||
int buildChecksum(char* csum, char* path)
|
||||
{
|
||||
char buf[0x200];
|
||||
int bytesread=0;
|
||||
FILE* fh;
|
||||
|
||||
if (path==0) path = "TRose.exe";
|
||||
fh = fopen( path, "rb" );
|
||||
if ( fh == NULL ) return -1;
|
||||
|
||||
fseek(fh, -512, SEEK_END);
|
||||
bytesread = fread(buf, 1, 0x200, fh);
|
||||
fclose(fh);
|
||||
|
||||
if (bytesread!=0x200) return -2;
|
||||
|
||||
short keylen = buf[0x0f];
|
||||
char* key = new char[keylen+1];
|
||||
unsigned short key_ct[] = {0x94, 0x20, 0x5F, 0x53, 0x14, 0xF2, 0x61, 0x11, 0x54, 0xFF, 0x72, 0x99, 0x44, 0xF4, 0xA1, 0xAA, 0xBA, 0xC2, 0x54, 0x52, 0x6F, 0x73, 0x65, 0x2E, 0x65, 0x78, 0x65};
|
||||
|
||||
for(int i=0; i<keylen; i++)
|
||||
key[i] = key_ct[i] ^ buf[0x18A + i];
|
||||
|
||||
int csumlen=0;
|
||||
int multiplier=1;
|
||||
for(int i=keylen; i>0; i--) {
|
||||
int tmp = (key[i-1]-0x30)*multiplier;
|
||||
multiplier *= 0x0a;
|
||||
csumlen += tmp;
|
||||
}
|
||||
|
||||
delete [] key;
|
||||
|
||||
unsigned short csumtable[] = {0x34, 0x5C, 0x3D, 0x52, 0xCE, 0xF3, 0x12, 0xD4, 0x05, 0x91, 0xEE, 0xFF, 0x49, 0xC2, 0xD2};
|
||||
|
||||
int tmp=0;
|
||||
for(int i=0; i<csumlen; i++) {
|
||||
csum[i] = csumtable[tmp] ^ buf[0x87 + i];
|
||||
if (tmp==0x0e) tmp=0; else tmp++;
|
||||
}
|
||||
|
||||
return csumlen;
|
||||
}
|
||||
|
||||
void buildCryptTable(char* crypttable, char* checksum, int checksumlen)
|
||||
{
|
||||
for (int i=0; i<0x008; i++) crypttable[i]=0;
|
||||
for (int i=0; i<0x100; i++) crypttable[i+8]=i;
|
||||
|
||||
int csumpos=0;
|
||||
int modifier=0;
|
||||
|
||||
for (int i=0; i<0x40*4; i++) {
|
||||
int curpos=crypttable[8+i];
|
||||
|
||||
modifier = (checksum[csumpos] + curpos + modifier) & 0xff;
|
||||
crypttable[8+i] = crypttable[modifier+8];
|
||||
crypttable[modifier+8] = curpos;
|
||||
|
||||
csumpos=++csumpos%checksumlen;
|
||||
}
|
||||
}
|
||||
|
||||
void cryptPacket(char *packet, char *crypttable)
|
||||
{
|
||||
unsigned short paksize=(*((unsigned short*)&packet[0])) - 2;
|
||||
|
||||
for(int i=0; i<paksize; i++) {
|
||||
unsigned tmp1=(*((unsigned*)&crypttable[0]) + 1) & 0xff;
|
||||
unsigned tmp2=(unsigned)crypttable[tmp1+8];
|
||||
unsigned tmp3=((*((unsigned*)&crypttable[4]) + tmp2) & 0xff);
|
||||
unsigned tmp4=crypttable[tmp3+8];
|
||||
*((unsigned*)&crypttable[0]) = tmp1;
|
||||
*((unsigned*)&crypttable[4]) = tmp3;
|
||||
crypttable[tmp3+8] = tmp2;
|
||||
crypttable[tmp1+8] = tmp4;
|
||||
packet[i+2] = crypttable[((tmp4 + tmp2) & 0xff) + 8] ^ packet[i+2];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifndef __ROSE_SERVER__CRYPTION_ROUTINES__HEADER_FILE__
|
||||
#define __ROSE_SERVER__CRYPTION_ROUTINES__HEADER_FILE__
|
||||
//#define USE124
|
||||
//-------------------------------------------------------------------------
|
||||
// This structure contains generated tables, which are needed to
|
||||
// encrypt and decrypt packets.
|
||||
//-------------------------------------------------------------------------
|
||||
struct CCryptTable
|
||||
{
|
||||
unsigned** Tables; // Main encryption table
|
||||
unsigned short* AddTable; // Less important encryption table
|
||||
|
||||
unsigned EncryptionStartValue; // Start value for sending clients
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// This structure contains informations about current encrypt-values.
|
||||
// Startvalues should be "EncryptionStartValue" from the CCryptTable for
|
||||
// CurEncryptionValue and zero for CurAddValue.
|
||||
// * This values changes every incoming encryption.
|
||||
//-------------------------------------------------------------------------
|
||||
struct CCryptStatus
|
||||
{
|
||||
unsigned CurEncryptionValue; // Current encryption value
|
||||
unsigned CurAddValue; // Current additional value
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Functions, used to generate and delete CryptTables
|
||||
//-------------------------------------------------------------------------
|
||||
void GenerateCryptTables ( CCryptTable* &CryptTables, unsigned ModValue );
|
||||
void GenerateLoginServerCryptTables ( CCryptTable* &CryptTables );
|
||||
void FreeCryptTables ( CCryptTable* &CryptTables );
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Functions, used to decrypt/encrypt a buffer - serverside
|
||||
//-------------------------------------------------------------------------
|
||||
int DecryptBufferHeader ( CCryptStatus *ri, CCryptTable *CryptTables, unsigned char *Buffer );
|
||||
bool DecryptBufferData ( CCryptTable *CryptTables, unsigned char *Buffer );
|
||||
void EncryptBuffer ( CCryptTable *CryptTables, unsigned char *Buffer );
|
||||
bool CryptISCPak( unsigned char* pak ); // Raven0123
|
||||
//-------------------------------------------------------------------------
|
||||
#ifndef USE124
|
||||
#define TABLE_SIZE (256+8)
|
||||
|
||||
int buildChecksum(char* csum, char* path=0);
|
||||
void buildCryptTable(char* crypttable, char* checksum, int checksumlen);
|
||||
void cryptPacket(char *packet, char *crypttable);
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,29 @@
|
||||
|
||||
//#include <cstring>
|
||||
#include "seh.hpp"
|
||||
|
||||
#ifdef __WIN32__
|
||||
|
||||
EXCEPTION_DISPOSITION __SEH_HANDLER::ExceptionRouter(PEXCEPTION_RECORD pRecord,
|
||||
__SEH_EXCEPTION_REGISTRATION* pReg,
|
||||
PCONTEXT pContext,
|
||||
PEXCEPTION_RECORD pRecord2)
|
||||
{
|
||||
return pReg->exthandler->ExceptionHandler(pRecord, pReg, pContext, pRecord2);
|
||||
}
|
||||
|
||||
EXCEPTION_DISPOSITION __SEH_HANDLER::ExceptionHandler(PEXCEPTION_RECORD pRecord,
|
||||
__SEH_EXCEPTION_REGISTRATION* pReg,
|
||||
PCONTEXT pContext,
|
||||
PEXCEPTION_RECORD pRecord2)
|
||||
{
|
||||
/*std::memcpy(&excContext, pContext, sizeof(_CONTEXT));
|
||||
std::memcpy(&excRecord, pRecord, sizeof(_EXCEPTION_RECORD));*/
|
||||
memcpy(&excContext, pContext, sizeof(_CONTEXT));
|
||||
memcpy(&excRecord, pRecord, sizeof(_EXCEPTION_RECORD));
|
||||
longjmp(context, 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
|
||||
#ifndef __FV_SEH_H__
|
||||
#define __FV_SEH_H__
|
||||
|
||||
#ifdef __WIN32__
|
||||
#include <windows.h>
|
||||
#include <excpt.h>
|
||||
#endif
|
||||
|
||||
#include <setjmp.h>
|
||||
//#include <fv/defs.hpp>
|
||||
|
||||
//NAMESPACE_BEGIN(PU)
|
||||
//NAMESPACE_BEGIN(SEH)
|
||||
|
||||
#ifdef __WIN32__
|
||||
|
||||
class __SEH_HANDLER;
|
||||
|
||||
typedef struct tag__SEH_EXCEPTION_REGISTRATION
|
||||
{
|
||||
tag__SEH_EXCEPTION_REGISTRATION* prev;
|
||||
PEXCEPTION_HANDLER handler;
|
||||
__SEH_HANDLER* exthandler;
|
||||
} __SEH_EXCEPTION_REGISTRATION;
|
||||
|
||||
|
||||
class __SEH_HANDLER
|
||||
{
|
||||
public:
|
||||
__SEH_HANDLER() { }
|
||||
static EXCEPTION_DISPOSITION ExceptionRouter(PEXCEPTION_RECORD pRecord,
|
||||
__SEH_EXCEPTION_REGISTRATION* pReg,
|
||||
PCONTEXT pContext,
|
||||
PEXCEPTION_RECORD pRecord2);
|
||||
|
||||
virtual EXCEPTION_DISPOSITION ExceptionHandler(PEXCEPTION_RECORD pRecord,
|
||||
__SEH_EXCEPTION_REGISTRATION* pReg,
|
||||
PCONTEXT pContext,
|
||||
PEXCEPTION_RECORD pRecord2);
|
||||
|
||||
jmp_buf context;
|
||||
EXCEPTION_RECORD excRecord;
|
||||
CONTEXT excContext;
|
||||
};
|
||||
|
||||
#define __seh_try \
|
||||
{ \
|
||||
__SEH_EXCEPTION_REGISTRATION _lseh_er; \
|
||||
__SEH_HANDLER _lseh_handler; \
|
||||
\
|
||||
_lseh_er.handler = \
|
||||
reinterpret_cast<PEXCEPTION_HANDLER>(__SEH_HANDLER::ExceptionRouter); \
|
||||
_lseh_er.exthandler = &_lseh_handler; \
|
||||
asm volatile ("movl %%fs:0, %0" : "=r" (_lseh_er.prev)); \
|
||||
asm volatile ("movl %0, %%fs:0" : : "r" (&_lseh_er)); \
|
||||
int _lseh_setjmp_res = setjmp(_lseh_handler.context); \
|
||||
while(true) { \
|
||||
if(_lseh_setjmp_res != 0) { \
|
||||
break; \
|
||||
} \
|
||||
|
||||
#define __seh_finally \
|
||||
break; \
|
||||
} \
|
||||
while(true) {
|
||||
|
||||
|
||||
#define __seh_except(rec, ctx) \
|
||||
break; \
|
||||
} \
|
||||
PEXCEPTION_RECORD rec = &_lseh_handler.excRecord; \
|
||||
PCONTEXT ctx = &_lseh_handler.excContext; \
|
||||
\
|
||||
asm volatile ("movl %0, %%fs:0" : : "r" (_lseh_er.prev)); \
|
||||
if(_lseh_setjmp_res != 0)
|
||||
|
||||
#define __seh_end }
|
||||
|
||||
#else
|
||||
|
||||
#define __seh_try
|
||||
|
||||
#define __seh_except(rec, ctx) if(false) {
|
||||
|
||||
#define __seh_end }
|
||||
|
||||
#define __seh_finally
|
||||
|
||||
#endif
|
||||
|
||||
//NAMESPACE_END(SEH)
|
||||
//NAMESPACE_END(PU)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,438 @@
|
||||
/*
|
||||
Rose Online Server Emulator
|
||||
Copyright (C) 2006,2007 OSRose Team http://osroseon.to.md
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
depeloped with Main erose/hrose source server + some change from the original eich source
|
||||
*/
|
||||
//#define _CRT_NO_TIME_T
|
||||
#ifndef __ROSE_SOCKETS__
|
||||
#define __ROSE_SOCKETS__
|
||||
#define USEIFO
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
#define close closesocket
|
||||
#ifdef FD_SETSIZE
|
||||
#undef FD_SETSIZE
|
||||
#endif
|
||||
#define FD_SETSIZE 1024
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#include <unistd.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <cstdarg>
|
||||
#include <errno.h>
|
||||
#define SOCKET int
|
||||
#define INVALID_SOCKET -1
|
||||
#define SOCKET_ERROR -1
|
||||
#define PVOID void *
|
||||
#define ioctlsocket ioctl
|
||||
#define SOCKADDR struct sockaddr
|
||||
#define closesocket close
|
||||
#endif
|
||||
|
||||
#include "mysql.h"
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <exception>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <cmath>
|
||||
#include <map>
|
||||
#include "pthread.h"
|
||||
#include <vector>
|
||||
#include <csignal>
|
||||
#include "log.h"
|
||||
#include "rosecrypt.hpp"
|
||||
#include "config.h"
|
||||
#include "database/database.h"
|
||||
#pragma comment(lib, "Ws2_32.lib")
|
||||
// Just some defs for easier use
|
||||
typedef char SBYTE;
|
||||
typedef unsigned char BYTE;
|
||||
typedef short SWORD;
|
||||
typedef unsigned short WORD;
|
||||
typedef long SDWORD;
|
||||
typedef unsigned long DWORD;
|
||||
typedef long long SQWORD;
|
||||
typedef unsigned long long QWORD;
|
||||
typedef unsigned __int8 byte;
|
||||
typedef unsigned __int16 word;
|
||||
typedef unsigned __int32 dword;
|
||||
typedef unsigned __int64 qword;
|
||||
typedef char* strings;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::system;
|
||||
using std::vector;
|
||||
using std::map;
|
||||
using std::nothrow;
|
||||
using std::string;
|
||||
#define STARTPACKET(p,c,s) CPacket p; p.Command = c; p.Size = s;
|
||||
#define SETBYTE(p,o,v) p.Buffer[o]=v;
|
||||
#define SETWORD(p,o,v) *((unsigned short*)&p.Buffer[o])=v;
|
||||
#define SETDWORD(p,o,v) *((unsigned*)&p.Buffer[o])=v;
|
||||
#define SETQWORD(p,o,v) *((long long*)&p.Buffer[o])=v;
|
||||
#define SETFLOAT(p,o,v) *((float*)&p.Buffer[o])=v;
|
||||
|
||||
#define BEGINPACKET(p,c) CPacket p; p.Command = c; p.Size = 6;
|
||||
#define RESETPACKET(p,c) p.Command = c; p.Size = 6;
|
||||
#define ADDBYTE(p,v) { p.Buffer[p.Size-6]=v; p.Size+=1; }
|
||||
#define ADDWORD(p,v) { *((WORD*)&p.Buffer[p.Size-6])=v; p.Size+=2; }
|
||||
#define ADDDWORD(p,v) { *((unsigned*)&p.Buffer[p.Size-6])=v; p.Size+=4; }
|
||||
#define ADDQWORD(p,v) { *((QWORD*)&p.Buffer[p.Size-6])=v; p.Size+=8; }
|
||||
#define ADDFLOAT(p,v) { *((float*)&p.Buffer[p.Size-6])=v; p.Size+=4; }
|
||||
#define ADDSTRING(p,v) { for(int q=0; q<(int)strlen((char*)v); q++) ADDBYTE(p,(v)[q]); }
|
||||
#define GETBYTE(p,o) (p.Buffer[o])
|
||||
#define GETWORD(p,o) *((WORD*)&p.Buffer[o])
|
||||
#define GETDWORD(p,o) *((DWORD*)&p.Buffer[o])
|
||||
#define GETQWORD(p,o) *((QWORD*)&p.Buffer[o])
|
||||
#define GETFLOAT(p,o) *((float*)&p.Buffer[o])
|
||||
#define pi 3.1415926535897932384626433832795
|
||||
#define r2d pi/180
|
||||
#define ZONE_SIZE 6400
|
||||
#define ENTITY_NO_TYPE 0
|
||||
#define ENTITY_PLAYER 1
|
||||
#define ENTITY_MONSTER 2
|
||||
#define ENTITY_NPC 3
|
||||
#define ENTITY_SUMMON 4
|
||||
#define ENTITY_DROP 5
|
||||
|
||||
// Structures
|
||||
// Packet information
|
||||
struct CPacket
|
||||
{
|
||||
unsigned short Size; // Packet size
|
||||
unsigned short Command; // Packet command
|
||||
unsigned short Unused; // unused
|
||||
unsigned char Buffer[0x400]; // Packet data //0x600
|
||||
|
||||
CPacket( unsigned short mycommand=0, unsigned short mysize=6, unsigned short myunused=0 );
|
||||
~CPacket( );
|
||||
void StartPacket( unsigned short mycommand, unsigned short mysize=6, unsigned short myunused=0 );
|
||||
void AddByte( unsigned char value );
|
||||
void AddWord( unsigned short value );
|
||||
void AddDWord( unsigned value );
|
||||
void AddQWord( unsigned long long value );
|
||||
void AddFloat( float value );
|
||||
void AddString( char* value );
|
||||
void SetByte( unsigned short pos, unsigned char value );
|
||||
void SetWord( unsigned short pos, unsigned short value );
|
||||
void SetDWord( unsigned short pos, unsigned value );
|
||||
void SetQWord( unsigned short pos, unsigned long long value );
|
||||
void SetFloat( unsigned short pos, float value );
|
||||
unsigned char GetByte( unsigned short pos );
|
||||
unsigned short GetWord( unsigned short pos );
|
||||
unsigned GetDWord( unsigned short pos );
|
||||
unsigned long long GetQWord( unsigned short pos );
|
||||
float GetFloat( unsigned short pos );
|
||||
char* GetString( unsigned short pos );
|
||||
|
||||
// Functions added by Drakia
|
||||
template <class T> void Add( T value ) {
|
||||
*((T*)&Buffer[Size]) = value;
|
||||
Size += sizeof(T);
|
||||
}
|
||||
void AddString( char* value, bool NullTerminate ) {
|
||||
for (dword i = 0; i < strlen((const char*)value); i++) {
|
||||
Add<byte>(value[i]);
|
||||
}
|
||||
if (NullTerminate) Add<byte>(0);
|
||||
}
|
||||
template <class T> void AddString( char* value ) {
|
||||
Add<T>(strlen((const char*)value));
|
||||
AddString(value, false);
|
||||
}
|
||||
void AddBytes( byte* value, dword len ) {
|
||||
for (dword i = 0; i < len; i++)
|
||||
Add<byte>((byte)value[i]);
|
||||
}
|
||||
};
|
||||
|
||||
// SQL Configuration
|
||||
struct CROSEServerConfigSQL
|
||||
{
|
||||
char* pcServer; // IP
|
||||
char* pcDatabase; // Database
|
||||
char* pcUserName; // UserName
|
||||
char* pcPassword; // Password
|
||||
int pcPort; // port
|
||||
};
|
||||
|
||||
// Server configuration
|
||||
struct CROSEServerConfig
|
||||
{
|
||||
// GLOBAL
|
||||
CROSEServerConfigSQL SQLServer; // SQL Information
|
||||
bool usethreads; // Use Threads (in sockets)
|
||||
bool Verbose; // print server information?
|
||||
unsigned MaxConnections; // Max connections
|
||||
unsigned UserPerThread; // User per thread
|
||||
bool AllowMultipleConnections; // Allow multiple connection from same ip?
|
||||
bool StayInServerLoop; // Server actived?
|
||||
UINT ServerID; //id from this server
|
||||
UINT ParentID; //id from the server to connect
|
||||
char* ServerName; //Server name
|
||||
UINT ServerType; //0 login - 1 server(char) - 2 channel(world)
|
||||
|
||||
// LOGINSERVER
|
||||
unsigned int MinimumAccessLevel; // Minimum access level
|
||||
char* LoginIP; // LoginIP [external]
|
||||
unsigned int LoginPort; // Login port
|
||||
unsigned int LoginPass;
|
||||
bool CreateLoginAccount; // Create account in login if not exist?
|
||||
bool Testserver; // channel for test ?
|
||||
|
||||
// CHARSEVER
|
||||
unsigned long int DeleteTime; // Delete time
|
||||
char* CharIP; // CharIP
|
||||
unsigned int CharPort; // Char port
|
||||
unsigned int CharPass;
|
||||
unsigned int CharsPort;
|
||||
|
||||
// WORLDSERVER
|
||||
char* WorldIP;
|
||||
unsigned int WorldPort;
|
||||
unsigned int WorldsPort;
|
||||
unsigned int WorldPass;
|
||||
UINT EXP_RATE;
|
||||
UINT DROP_RATE;
|
||||
UINT BASE_DROP_CHANCE;
|
||||
UINT ZULY_RATE;
|
||||
UINT AUTOSAVE;
|
||||
UINT SAVETIME;
|
||||
UINT MapDelay;
|
||||
UINT VisualDelay;
|
||||
UINT WorldDelay;
|
||||
UINT DeathDelay; //Set a timer delay so that we don't have a problem with monster death
|
||||
UINT AIWatch; //Set an AI script number to watch for. Debug only
|
||||
UINT SpawnType;
|
||||
|
||||
char* WELCOME_MSG;
|
||||
UINT DROP_TYPE;
|
||||
int MaxStat;
|
||||
int Partygap;
|
||||
int FairyMode;
|
||||
int FairyStay;
|
||||
int FairyWait;
|
||||
int FairyMax;
|
||||
int ScrollFairy;
|
||||
int FairyTestMode;
|
||||
int PlayerDmg;
|
||||
int MonsterDmg;
|
||||
int Cfmode;
|
||||
int BlueChance;
|
||||
int StatChance;
|
||||
int SlotChance;
|
||||
int RefineChance;
|
||||
int Rare_Refine;
|
||||
int KillOnFail;
|
||||
int MaxLevel;
|
||||
int DropMultiple;
|
||||
int KTPointRate;
|
||||
UINT AttkMult;
|
||||
UINT SkillMult;
|
||||
UINT DropDelay;
|
||||
|
||||
|
||||
// COMMAND LEVELS
|
||||
int Command_Go;
|
||||
int Command_Who;
|
||||
int Command_Who2;
|
||||
int Command_Broadcast;
|
||||
int Command_Mute;
|
||||
int Command_Tele;
|
||||
int Command_Level;
|
||||
int Command_LevelUp;
|
||||
int Command_TeleToMe;
|
||||
int Command_Save;
|
||||
int Command_Reload;
|
||||
int Command_Ann;
|
||||
int Command_SSpawn;
|
||||
int Command_Set;
|
||||
int Command_ESpawn;
|
||||
int Command_DSpawn;
|
||||
int Command_DelSpawn;
|
||||
int Command_Pak;
|
||||
int Command_Pak2;
|
||||
int Command_Pakm;
|
||||
int Command_Info;
|
||||
int Command_Exp;
|
||||
int Command_Mon;
|
||||
int Command_Kick;
|
||||
int Command_Job;
|
||||
int Command_Cha;
|
||||
int Command_Item;
|
||||
int Command_Drop;
|
||||
int Command_GiveZuly;
|
||||
int Command_Npc;
|
||||
int Command_GiveFairy;
|
||||
int Command_ManageFairy;
|
||||
int Command_ChangeFairyWait;
|
||||
int Command_ChangeFairyStay;
|
||||
int Command_ChangeFairyTestMode;
|
||||
int Command_Move;
|
||||
int Command_Goto;
|
||||
int Command_PlayerInfo;
|
||||
int Command_Give2;
|
||||
int Command_Ban;
|
||||
int Command_Ani;
|
||||
int Command_Summon;
|
||||
int Command_ReloadQuest;
|
||||
int Command_Shutdown;
|
||||
int Command_DQuest;
|
||||
int Command_IQuest;
|
||||
int Command_ShopType;
|
||||
int Command_Stat;
|
||||
int Command_KillInRange;
|
||||
int Command_GoToMap;
|
||||
int Command_Heal;
|
||||
int Command_ServerInfo;
|
||||
int Command_TargetInfo;
|
||||
int Command_Hide;
|
||||
int Command_Class;
|
||||
int Command_Monster;
|
||||
int Command_GlobalTime;
|
||||
int Command_Here;
|
||||
int Command_Face;
|
||||
int Command_Hair;
|
||||
int Command_Pvp;
|
||||
int Command_go;
|
||||
int Command_Convert;
|
||||
int Command_Rate;
|
||||
int Command_Moveto;
|
||||
int Command_Settime;
|
||||
int Command_Transx;
|
||||
int Command_Partylvl;
|
||||
int Command_Pdmg;
|
||||
int Command_Mdmg;
|
||||
int Command_Rules;
|
||||
int Command_Cfmode;
|
||||
|
||||
char* Command_GlobalPrefix;
|
||||
|
||||
};
|
||||
|
||||
|
||||
// Classes
|
||||
// Base class
|
||||
class CBaseSocket
|
||||
{
|
||||
public:
|
||||
CBaseSocket( ); // Constructor
|
||||
virtual ~CBaseSocket( ); // Destructor
|
||||
void CloseSocket( void ); // Close Socket
|
||||
SOCKET sock; // This is our socket
|
||||
SOCKET sckISC; // Raven0123
|
||||
SOCKET sckISCII;
|
||||
bool isActive; // Is this socket connected?
|
||||
bool isserver;
|
||||
CCryptTable* CryptTable; // This is for decrypting incomming packets
|
||||
#ifdef USE124
|
||||
char* csum;
|
||||
int csumlen;
|
||||
#endif
|
||||
string ClientIP; // Client IP
|
||||
char ClientSubNet[12]; // Lan Subnet
|
||||
};
|
||||
// Client class
|
||||
class CClientSocket : public CBaseSocket
|
||||
{
|
||||
public:
|
||||
CClientSocket( ); // Client Constructor
|
||||
~CClientSocket( ); // Client Destructor
|
||||
bool ReceiveData( ); // Receive packet
|
||||
void SendPacket( CPacket *P ); // Send Packet
|
||||
void SendPacketCpy( CPacket *P ); // Send a packet without encrypting the orginal packet
|
||||
CCryptStatus CryptStatus; // Status of the encryption
|
||||
class CServerSocket* GS; // Pointer to Server class
|
||||
bool ISCThread(); // Raven0123
|
||||
struct sockaddr_in clientinfo;
|
||||
void* player;
|
||||
#ifdef USE124
|
||||
char* ct;
|
||||
#endif
|
||||
private:
|
||||
unsigned short PacketSize; // Size of the current packet
|
||||
unsigned short PacketOffset; // Current offset of the data
|
||||
unsigned char Buffer[ 0xFFF ]; // Buffer to receive data into
|
||||
unsigned char tempBuffer[0xFFF];
|
||||
};
|
||||
|
||||
// Server class
|
||||
class CServerSocket : public CBaseSocket
|
||||
{
|
||||
private:
|
||||
//void CryptISCPak( char* pak ); // Raven0123
|
||||
//void ISCThread(); // Raven0123
|
||||
//SOCKET sckISC; // Raven0123
|
||||
|
||||
public:
|
||||
void CryptISCPak( char* pak ); // Raven0123
|
||||
CServerSocket( ); // Constructor
|
||||
~CServerSocket( ); // Destructor
|
||||
|
||||
bool StartServer( ); // Start Server
|
||||
void FillFDS( fd_set* fds ); // Create FDS table
|
||||
void HandleClients( fd_set* fds ); // Handle Clients
|
||||
void AddUser( SOCKET sock, sockaddr_in* ClientInfo, bool server ); // Add User
|
||||
void DisconnectClient( CClientSocket* thisclient ); // Disconnect Client
|
||||
bool DoSQL(char *Format, ...);
|
||||
|
||||
// Virtual Functions
|
||||
virtual void LoadEncryption( ); //load encryption
|
||||
virtual void ServerLoop( ); // Main Loop
|
||||
virtual CClientSocket* CreateClientSocket( ); // Create a client
|
||||
virtual void DeleteClientSocket( CClientSocket* thisclient ); // Delete client
|
||||
virtual bool OnServerReady( ); // Executed with server is ready
|
||||
virtual void OnServerStep( ); // Executed
|
||||
virtual void OnServerDie( );
|
||||
virtual bool OnReceivePacket( CClientSocket* thisclient, CPacket* P );
|
||||
virtual void ReceivedISCPacket( CPacket* pak ); // Raven0123
|
||||
virtual bool OnClientConnect( CClientSocket* thisclient );
|
||||
virtual void OnClientDisconnect( CClientSocket* thisclient );
|
||||
|
||||
// Variables
|
||||
CROSEServerConfig Config; // Hold server configuration
|
||||
int maxfd;
|
||||
MYSQL *mysql;
|
||||
virtual bool Ping( ); // Used to ping the mysql server
|
||||
vector<CClientSocket*> ClientList;
|
||||
UINT ConnectedClients;
|
||||
unsigned short port;
|
||||
struct sockaddr_in ain;
|
||||
struct sockaddr_in sain;
|
||||
|
||||
pthread_t threads[65535];
|
||||
|
||||
void SendISCPacket( CPacket* pak ); // Raven0123
|
||||
};
|
||||
PVOID ClientMainThread( PVOID ); // Handle clients
|
||||
bool InitWinSocket ( void ); // Init windows sockets (wsa)
|
||||
void CloseWinSocket( void ); // Close Windows sockets (wsa)
|
||||
// -----------------------------------------------------------------------------------------
|
||||
|
||||
#endif
|
||||
Reference in new issue
Block a user