EQEmulator Forums

EQEmulator Forums (https://www.eqemulator.org/forums/index.php)
-   Archive::Development (https://www.eqemulator.org/forums/forumdisplay.php?f=621)
-   -   Multiple World Servers, multiple ip addresses, same box bugf (https://www.eqemulator.org/forums/showthread.php?t=198)

alkrun 02-01-2002 06:03 AM

Multiple World Servers, multiple ip addresses, same box bugf
 
This is for anyone looking to run multiple world servers on the same box. It just fixes the bind() code for the world server (I also removed some of the #ifdef WIN32s that weren't really needed for Win32). The zone servers need one fix to function correctly.

The basic setup I use is:

c:\eqemu (stable 'production' server)
c:\eqemu.dev (development server)

I have a win2k server with two static IP addresses.

I run minilogin and have both LoginServer.ini files pointing to that login server. I've dumped the eq database (mysqldump eq > eqdb.sql) and created a second eq database (eqdev). In the eqemu.dev folder, I point db.ini to the different database name. In theory I guess you could use the same database for both production and development builds if you weren't going to edit the database, but you'd still need two directories so you can have two different world / zone configs.

alkrun 02-01-2002 06:07 AM

console.cpp

Code:

bool InitTCP()
{
        struct sockaddr_in address;
        int reuse_addr = 1;
        unsigned long nonblocking = 1;
        struct hostent *phostent = NULL;

#ifdef WIN32
        WORD version = MAKEWORD (1,1);
        WSADATA wsadata;
        WSAStartup (version, &wsadata);
#endif

  /* Setup internet address information. 
    This is used with the bind() call */
        unsigned long lAddr = INADDR_NONE;

        memset((char *) &address, 0, sizeof(address));
        address.sin_family = AF_INET;
        address.sin_port = htons(PORT);
        address.sin_addr.s_addr = htonl(INADDR_ANY);

        //GET WORLD SERVER ADDRESS
        if((lAddr = inet_addr(net.GetWorldAddress())) != INADDR_NONE){
                if((phostent = gethostbyaddr((char*)&lAddr, sizeof(unsigned long), AF_INET)) != NULL){
                        memcpy ((char*)&(address.sin_addr), phostent->h_addr, phostent->h_length);
                }
        }else if((phostent = gethostbyname(net.GetWorldAddress())) != NULL){
                memcpy ((char*)&(address.sin_addr), phostent->h_addr, phostent->h_length);
        }

        /* Setting up TCP port for new TCP connections */
        listening_socketTCP = socket(AF_INET, SOCK_STREAM, 0);
        if (listening_socketTCP == INVALID_SOCKET)
        {
                return false;
        }

// dont think following is good stuff for TCP, good for UDP
//        setsockopt(listening_socketTCP, SOL_SOCKET, SO_REUSEADDR, (char *) &reuse_addr, sizeof(reuse_addr));

        if (bind(listening_socketTCP, (struct sockaddr *) &address, sizeof(address)) < 0)
        {
#ifdef WIN32
                cout << "Listening TCP socket failed(bind). Error: " << WSAGetLastError() << endl;
                closesocket(listening_socketTCP);
#else
                cout << "Listening TCP socket failed(bind). Error: " << strerror(errno) << endl;
                close(listening_socketTCP);
#endif
                return false;
        }

#ifdef WIN32
        ioctlsocket (listening_socketTCP, FIONBIO, &nonblocking);
#else
        fcntl(listening_socketTCP, F_SETFL, O_NONBLOCK);
#endif

        if (listen (listening_socketTCP, SOMAXCONN) == SOCKET_ERROR)
        {
#ifdef WIN32
                cout << "Listening TCP socket failed. Error: " << WSAGetLastError() << endl;
                closesocket (listening_socketTCP);
#else
                cout << "Listening TCP socket failed. Error: " << strerror(errno) << endl;
                close(listening_socketTCP);
#endif
                return false;
        }else{
                char szBuf[128];
                u_char *pAddr = &address.sin_addr.S_un.S_un_b.s_b1;
                sprintf(szBuf, "World Server listening on address:%u.%u.%u.%u port:%u",
                        pAddr[0], pAddr[1], pAddr[2], pAddr[3], PORT);
                cout << szBuf << endl;
        }

        return true;
}


alkrun 02-01-2002 06:08 AM

loginserver.cpp

Code:

bool InitLoginServer() {
        if (AttemptingConnect) {
                cout << "Error: InitLoginServer() while already attempting connect" << endl;
                return false;
        }
        if (!net.LoginServerInfo) {
                cout << "Error: Login server info not loaded" << endl;
                return false;
        }

        AttemptingConnect = true;
#ifdef WIN32
        SOCKET tmpsock = INVALID_SOCKET;
#else
        int tmpsock = INVALID_SOCKET;
#endif
        unsigned long nonblocking = 1;
    struct sockaddr_in        server_sin;
    struct in_addr        in;
        struct hostent *phostent = NULL;

#ifdef WIN32
        WORD version = MAKEWORD (1,1);
        WSADATA wsadata;
        WSAStartup (version, &wsadata);
#endif

        if ((tmpsock = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)        {
#ifdef WIN32
                cout << "LoginServer connect: Allocating socket failed. Error: " << WSAGetLastError();
#else
                cout << "LoginServer connect: Allocating socket failed. Error: " << strerror(errno);
#endif
                AttemptingConnect = false;
                return false;
        }

        struct sockaddr_in worldaddress;

        unsigned long lWorldAddr = INADDR_NONE;
        memset((char *) &worldaddress, 0, sizeof(worldaddress));
        worldaddress.sin_family = AF_INET;
        worldaddress.sin_port = htons(INADDR_ANY);
        worldaddress.sin_addr.s_addr = htonl(INADDR_ANY);

        //GET WORLD SERVER ADDRESS
        if((lWorldAddr = inet_addr(net.GetWorldAddress())) != INADDR_NONE){
                if((phostent = gethostbyaddr((char*)&lWorldAddr, sizeof(unsigned long), AF_INET)) != NULL){
                        memcpy ((char*)&(worldaddress.sin_addr), phostent->h_addr, phostent->h_length);
                }
        }else if((phostent = gethostbyname(net.GetWorldAddress())) != NULL){
                memcpy ((char*)&(worldaddress.sin_addr), phostent->h_addr, phostent->h_length);
        }

        if (bind(tmpsock, (struct sockaddr *) &worldaddress, sizeof(worldaddress)) < 0)
        {
#ifdef WIN32
                cout << "Login socket failed(bind). Error: " << WSAGetLastError() << endl;
                closesocket(tmpsock);
#else
                cout << "Login socket failed(bind). Error: " << strerror(errno) << endl;
                close(tmpsock);
#endif
                return false;
        }
        server_sin.sin_family = AF_INET;

        if ((phostent = gethostbyname(net.GetLoginAddress())) == NULL) {
#ifdef WIN32
                cout << "Unable to get the host name. Error: " << WSAGetLastError();
            closesocket(tmpsock);
#else
                cout << "Unable to get the host name. Error: " << strerror(errno);
            close(tmpsock);
#endif
                AttemptingConnect = false;
                return false;
        }
        memcpy ((char*)&(server_sin.sin_addr), phostent->h_addr, phostent->h_length);
        server_sin.sin_port = htons(LOGIN_PORT);

        // Establish a connection to the server socket.
#ifdef WIN32
        if (connect (tmpsock, (PSOCKADDR) &server_sin, sizeof (server_sin)) == SOCKET_ERROR) {
                cout << "LoginServer connect: Connecting to the server failed. Error: " << WSAGetLastError() << endl;
                closesocket(tmpsock);
#else
        if (connect (tmpsock, (struct sockaddr *) &server_sin, sizeof (server_sin)) == SOCKET_ERROR) {
                cout << "LoginServer connect: Connecting to the server failed. Error: " << strerror(errno) << endl;
                close(tmpsock);
#endif
                AttemptingConnect = false;
                return false;
        }       
#ifdef WIN32
        ioctlsocket (tmpsock, FIONBIO, &nonblocking);
#else
        fcntl(tmpsock, F_SETFL, O_NONBLOCK);
#endif

        in.s_addr = server_sin.sin_addr.s_addr;
        cout << "Connected to LoginServer: " << net.GetLoginAddress() << ":" << ntohs(server_sin.sin_port) << endl;
        loginserver = new LoginServer(in.s_addr, ntohs(server_sin.sin_port), tmpsock);
        AttemptingConnect = false;
#ifdef WIN32
        _beginthread(LoginServerLoop, 0, NULL);
#else
        pthread_t thread;
        pthread_create(&thread, NULL, LoginServerLoop, NULL);
#endif
        return true;
}


alkrun 02-01-2002 06:11 AM

net.cpp

Comment out the 'server listening' message, is sent in InitTCP now'
Code:

//        cout << "World server listening on port:" << PORT << endl;

Change the UDP port
Code:

bool NetConnection::Init()
{
        struct sockaddr_in address;
        int reuse_addr = 1;
       
        // Disgrace: for windows compile
#ifdef WIN32
        unsigned long nonblocking = 1;
        WORD version = MAKEWORD (1,1);
        WSADATA wsadata;
        WSAStartup (version, &wsadata);
#endif
        struct hostent *phostent = NULL;


  /* Setup internet address information. 
    This is used with the bind() call */
        memset((char *) &address, 0, sizeof(address));
        address.sin_family = AF_INET;
        address.sin_port = htons(PORT);
        address.sin_addr.s_addr = htonl(INADDR_ANY);
        unsigned long lAddr = INADDR_NONE;

        //GET WORLD SERVER ADDRESS
        if((lAddr = inet_addr(net.GetWorldAddress())) != INADDR_NONE){
                if((phostent = gethostbyaddr((char*)&lAddr, sizeof(unsigned long), AF_INET)) != NULL){
                        memcpy ((char*)&(address.sin_addr), phostent->h_addr, phostent->h_length);
                }
        }else if((phostent = gethostbyname(net.GetWorldAddress())) != NULL){
                memcpy ((char*)&(address.sin_addr), phostent->h_addr, phostent->h_length);
        }

        /* Setting up UDP port for new clients */
        listening_socket = socket(AF_INET, SOCK_DGRAM, 0);
        if (listening_socket < 0)
        {
       
                return false;
        }

        // Disgrace: for windows compile
#ifndef WIN32
        setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr));
#else
        setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR, (char *) &reuse_addr, sizeof(reuse_addr));
#endif

        if (bind(listening_socket, (struct sockaddr *) &address, sizeof(address)) < 0)
        {
                // Disgrace: for windows compile
                #ifdef WIN32
                        closesocket(listening_socket);
                #else
                        close(listening_socket);
                #endif
               
                return false;
        }

        // Disgrace: for windows compile
#ifndef WIN32
        fcntl(listening_socket, F_SETFL, O_NONBLOCK);
#else
        ioctlsocket (listening_socket, FIONBIO, &nonblocking);
#endif


        return true;
}


Zeitgeist 02-01-2002 08:23 AM

wow alkrun you're going to town =)

alkrun 02-01-2002 11:18 AM

AND A ZONE SERVER FIX

worldserver.cpp

Code:

bool InitWorldServer(bool DoTimer) {
        if (AttemptingConnect) {
                cout << "Error: InitWorldServer() while already attempting connect" << endl;
                return false;
        }
        AttemptingConnect = true;
#ifdef BUILD_FOR_WINDOWS
        SOCKET tmpsock = INVALID_SOCKET;
#else
        int tmpsock = INVALID_SOCKET;
#endif
        unsigned long nonblocking = 1;
    struct sockaddr_in        server_sin;
    struct in_addr        in;
#ifdef BUILD_FOR_WINDOWS
        WORD version = MAKEWORD (1,1);
        WSADATA wsadata;
        WSAStartup (version, &wsadata);
#endif
        struct hostent *phostent = NULL;

        if ((tmpsock = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)        {
#ifdef BUILD_FOR_WINDOWS
                cout << "WorldServer connect: Allocating socket failed. Error: " << WSAGetLastError();
#else
                cout << "WorldServer connect: Allocating socket failed. Error: " << strerror(errno);
#endif
                AttemptingConnect = false;
                return false;
        }

        unsigned long lZoneAddr = INADDR_NONE;
        struct hostent *pZoneHostent = NULL;
        struct sockaddr_in zone_sin;
        zone_sin.sin_family = AF_INET;
        zone_sin.sin_addr.s_addr = htonl(INADDR_ANY);
        zone_sin.sin_port = htons(INADDR_ANY);

        //GET WORLD SERVER ADDRESS
        if((lZoneAddr = inet_addr(net.GetZoneAddress())) != INADDR_NONE){
                if((pZoneHostent = gethostbyaddr((char*)&lZoneAddr, sizeof(unsigned long), AF_INET)) != NULL){
                        memcpy ((char*)&(zone_sin.sin_addr), pZoneHostent->h_addr, pZoneHostent->h_length);
                        if(bind(tmpsock, (struct sockaddr *) &zone_sin, sizeof(zone_sin)) == SOCKET_ERROR){
#ifdef WIN32
                                closesocket(tmpsock);
#else
                                close(tmpsock);
#endif
                        }
                }
        }else if((pZoneHostent = gethostbyname(net.GetZoneAddress())) != NULL){
                memcpy ((char*)&(zone_sin.sin_addr), pZoneHostent->h_addr, pZoneHostent->h_length);
                if(bind(tmpsock, (struct sockaddr *) &zone_sin, sizeof(zone_sin)) == SOCKET_ERROR){
#ifdef WIN32
                                closesocket(tmpsock);
#else
                                close(tmpsock);
#endif
                }
        }

        server_sin.sin_family = AF_INET;

        if ((phostent = gethostbyname(net.GetWorldAddress())) == NULL) {
#ifdef BUILD_FOR_WINDOWS
                cout << "Unable to get the host name. Error: " << WSAGetLastError();
            closesocket(tmpsock);
#else
                cout << "Unable to get the host name. Error: " << strerror(errno);
            close(tmpsock);
#endif
                AttemptingConnect = false;
                return false;
        }
#ifdef BUILD_FOR_WINDOWS
        memcpy ((char FAR *)&(server_sin.sin_addr), phostent->h_addr, phostent->h_length);
#else
        memcpy ((char*)&(server_sin.sin_addr), phostent->h_addr, phostent->h_length);
#endif
        server_sin.sin_port = htons(PORT);

        // Establish a connection to the server socket.
#ifdef BUILD_FOR_WINDOWS
        if (connect (tmpsock, (PSOCKADDR) &server_sin, sizeof (server_sin)) == SOCKET_ERROR) {
                cout << "WorldServer connect: Connecting to the server failed. Error: " << WSAGetLastError() << endl;
                closesocket(tmpsock);
#else
        if (connect (tmpsock, (struct sockaddr *) &server_sin, sizeof (server_sin)) == SOCKET_ERROR) {
                cout << "WorldServer connect: Connecting to the server failed. Error: " << strerror(errno) << endl;
                close(tmpsock);
#endif
                AttemptingConnect = false;
                return false;
        }       
#ifdef BUILD_FOR_WINDOWS
        ioctlsocket (tmpsock, FIONBIO, &nonblocking);
#else
        fcntl(tmpsock, F_SETFL, O_NONBLOCK);
#endif

// had to put a mini-receivedata here to handel switching the TCP
// connection to Zoneserver mode when enabled console commands
        int status = 0;
        uchar buffer[1024];
        memset(buffer, 0, sizeof(buffer));
        Timer con_timeout(15000);
        con_timeout.Start();
        while (1) {
                if (DoTimer)
                        Timer::SetCurrentTime();
                status = recv(tmpsock, (char*) buffer, sizeof(buffer), 0);
                if (status >= 1) {
//DumpPacket(buffer, status);
                        if (strncmp((char*) buffer, "Username: ", 10) == 0) {
                                send(tmpsock, "*ZONESERVER*\r\n", 14, 0);
                        }
                        else if (strncmp((char*) buffer, "ZoneServer Mode", 15) == 0 || strncmp((char*) buffer, "*ZONESERVER*\r\nZoneServer Mode", 29) == 0) {
                                // Connection successful
                                break;
                        }
                        else if (strncmp((char*) buffer, "Not Authorized.", 15) == 0 || strncmp((char*) buffer, "*ZONESERVER*\r\nNot Authorized.", 29) == 0) {
                                // Connection failed. Worldserver said get lost
#ifdef BUILD_FOR_WINDOWS
                                closesocket(tmpsock);
#else
                                close(tmpsock);
#endif
                                AttemptingConnect = false;
                                return false;
                        }
                        else if (strncmp((char*) buffer, "*ZONESERVER*\r\n", 14) == 0) {
                                // Catch the echo, wait for next packet
                        }
                        else {
                                cout << "WorldServer connect: Connecting to the server failed: switch stage. Unexpected response." << endl;
DumpPacket(buffer, status);
#ifdef BUILD_FOR_WINDOWS
                                closesocket(tmpsock);
#else
                                close(tmpsock);
#endif
                                AttemptingConnect = false;
                                return false;
                        }
                }
                else if (status == SOCKET_ERROR) {
#ifdef BUILD_FOR_WINDOWS
                        if (!(WSAGetLastError() == WSAEWOULDBLOCK)) {
                                cout << "WorldServer connect: Connecting to the server failed: switch stage. Error: " << WSAGetLastError() << endl;
                                closesocket(tmpsock);
#else // Pyro: fix for linux
                        if (!(errno == EWOULDBLOCK)) {
                                cout << "WorldServer connect: Connecting to the server failed: switch stage. Error: " << strerror(errno) << endl;
                                close(tmpsock);
#endif
                                AttemptingConnect = false;
                                return false;
                        }
                }
                if (con_timeout.Check()) {
                        cout << "WorldServer connect: Connecting to the server failed: switch stage. Time out." << endl;
#ifdef BUILD_FOR_WINDOWS
                        closesocket(tmpsock);
#else
                        close(tmpsock);
#endif
                        AttemptingConnect = false;
                        return false;
                }
                Sleep(1);
        }


        in.s_addr = server_sin.sin_addr.s_addr;
        cout << "Connected to worldserver: " << inet_ntoa(in) << ":" << ntohs(server_sin.sin_port) << endl;
        worldserver = new WorldServer(in.s_addr, ntohs(server_sin.sin_port), tmpsock);
        AttemptingConnect = false;
#ifdef BUILD_FOR_WINDOWS
        _beginthread(WorldServerLoop, 0, NULL);
#else
        pthread_t thread;
        pthread_create(&thread, NULL, WorldServerLoop, NULL);
#endif
        return true;
}


Trumpcard 02-01-2002 11:41 AM

Wow... Someone get this fellow a developer tag!

Great work Alk !


All times are GMT -4. The time now is 07:32 AM.

Powered by vBulletin®, Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.