View Single Post
  #6  
Old 02-01-2002, 11:18 AM
alkrun
Sarnak
 
Join Date: Jan 2002
Posts: 66
Default

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;
}
Reply With Quote