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;
}
|