Exemple #1
0
void SendAbort (void)
{
	BYTE dis[2] = { PRE_FAKE, PRE_DISCONNECT };
	int i, j;

	if (doomcom.numnodes > 1)
	{
		if (consoleplayer == 0)
		{
			// The host needs to let everyone know
			for (i = 1; i < doomcom.numnodes; ++i)
			{
				for (j = 4; j > 0; --j)
				{
					PreSend (dis, 2, &sendaddress[i]);
				}
			}
		}
		else
		{
			// Guests only need to let the host know.
			for (i = 4; i > 0; --i)
			{
				PreSend (dis, 2, &sendaddress[1]);
			}
		}
	}
}
Exemple #2
0
bool Guest_WaitForOthers (void *userdata)
{
	sockaddr_in *from;
	PreGamePacket packet;

	while ( (from = PreGet (&packet, sizeof(packet), false)) )
	{
		if (packet.Fake != PRE_FAKE || FindNode(from) != 1)
		{
			continue;
		}
		switch (packet.Message)
		{
		case PRE_CONACK:
			StartScreen->NetProgress (packet.NumPresent);
			break;

		case PRE_ALLHERE:
			if (doomcom.numnodes == 2)
			{
				int node;

				packet.NumNodes = packet.NumNodes;
				doomcom.numnodes = packet.NumNodes + 2;
				sendplayer[0] = packet.ConsoleNum;	// My player number
				doomcom.consoleplayer = packet.ConsoleNum;
				StartScreen->NetMessage ("Console player number: %d", doomcom.consoleplayer);
				for (node = 0; node < packet.NumNodes; node++)
				{
					sendaddress[node+2].sin_addr.s_addr = packet.machines[node].address;
					sendaddress[node+2].sin_port = packet.machines[node].port;
					sendplayer[node+2] = packet.machines[node].player;

					// [JC] - fixes problem of games not starting due to
					// no address family being assigned to nodes stored in
					// sendaddress[] from the All Here packet.
					sendaddress[node+2].sin_family = AF_INET;
				}
			}

			StartScreen->NetMessage ("Received All Here, sending ACK.");
			packet.Fake = PRE_FAKE;
			packet.Message = PRE_ALLHEREACK;
			PreSend (&packet, 2, &sendaddress[1]);
			break;

		case PRE_GO:
			StartScreen->NetMessage ("Received \"Go.\"");
			return true;

		case PRE_DISCONNECT:
			I_FatalError ("The host cancelled the game.");
			break;
		}
	}

	return false;
}
Exemple #3
0
static void SendConAck (int num_connected, int num_needed)
{
	PreGamePacket packet;

	packet.Fake = PRE_FAKE;
	packet.Message = PRE_CONACK;
	packet.NumNodes = num_needed;
	packet.NumPresent = num_connected;
	for (int node = 1; node < doomcom.numnodes; ++node)
	{
		PreSend (&packet, 4, &sendaddress[node]);
	}
	StartScreen->NetProgress (doomcom.numnodes);
}
Exemple #4
0
bool Guest_ContactHost (void *userdata)
{
	sockaddr_in *from;
	PreGamePacket packet;

	// Let the host know we are here.
	packet.Fake = PRE_FAKE;
	packet.Message = PRE_CONNECT;
	PreSend (&packet, 2, &sendaddress[1]);

	// Listen for a reply.
	while ( (from = PreGet (&packet, sizeof(packet), true)) )
	{
		if (packet.Fake == PRE_FAKE && FindNode(from) == 1)
		{
			if (packet.Message == PRE_CONACK)
			{
				StartScreen->NetMessage ("Total players: %d", packet.NumNodes);
				StartScreen->NetInit ("Waiting for other players", packet.NumNodes);
				StartScreen->NetProgress (packet.NumPresent);
				return true;
			}
			else if (packet.Message == PRE_DISCONNECT)
			{
				doomcom.numnodes = 0;
				I_FatalError ("The host cancelled the game.");
			}
			else if (packet.Message == PRE_ALLFULL)
			{
				doomcom.numnodes = 0;
				I_FatalError ("The game is full.");
			}
		}
	}

	// In case the progress bar could not be marqueed, bump it.
	StartScreen->NetProgress (0);

	return false;
}
Exemple #5
0
void HostGame (int i)
{
	PreGamePacket packet;
	int numplayers;
	int node;
	int gotack[MAXNETNODES+1];

	if ((i == Args->NumArgs() - 1) || !(numplayers = atoi (Args->GetArg(i+1))))
	{	// No player count specified, assume 2
		numplayers = 2;
	}

	if (numplayers == 1)
	{ // Special case: Only 1 player, so don't bother starting the network
		netgame = false;
		multiplayer = true;
		doomcom.id = DOOMCOM_ID;
		doomcom.numplayers = doomcom.numnodes = 1;
		doomcom.consoleplayer = 0;
		return;
	}

	StartNetwork (false);

	// [JC] - this computer is starting the game, therefore it should
	// be the Net Arbitrator.
	doomcom.consoleplayer = 0;
	Printf ("Console player number: %d\n", doomcom.consoleplayer);

	doomcom.numnodes = 1;

	atterm (SendAbort);

	StartScreen->NetInit ("Waiting for players", numplayers);

	// Wait for numplayers-1 different connections
	if (!StartScreen->NetLoop (Host_CheckForConnects, (void *)(intptr_t)numplayers))
	{
		exit (0);
	}

	// Now inform everyone of all machines involved in the game
	memset (gotack, 0, sizeof(gotack));
	StartScreen->NetMessage ("Sending all here.");
	StartScreen->NetInit ("Done waiting", 1);

	if (!StartScreen->NetLoop (Host_SendAllHere, (void *)gotack))
	{
		exit (0);
	}

	popterm ();

	// Now go
	StartScreen->NetMessage ("Go");
	packet.Fake = PRE_FAKE;
	packet.Message = PRE_GO;
	for (node = 1; node < doomcom.numnodes; node++)
	{
		// If we send the packets eight times to each guest,
		// hopefully at least one of them will get through.
		for (int i = 8; i != 0; --i)
		{
			PreSend (&packet, 2, &sendaddress[node]);
		}
	}

	StartScreen->NetMessage ("Total players: %d", doomcom.numnodes);

	doomcom.id = DOOMCOM_ID;
	doomcom.numplayers = doomcom.numnodes;

	// On the host, each player's number is the same as its node number
	for (i = 0; i < doomcom.numnodes; ++i)
	{
		sendplayer[i] = i;
	}
}
Exemple #6
0
bool Host_SendAllHere (void *userdata)
{
	int *gotack = (int *)userdata;	// ackcount is at gotack[MAXNETNODES]
	PreGamePacket packet;
	int node;
	sockaddr_in *from;

	// Send out address information to all guests. Guests that have already
	// acknowledged receipt effectively get just a heartbeat packet.
	packet.Fake = PRE_FAKE;
	packet.Message = PRE_ALLHERE;
	for (node = 1; node < doomcom.numnodes; node++)
	{
		int machine, spot = 0;

		packet.ConsoleNum = node;
		if (!gotack[node])
		{
			for (spot = 0, machine = 1; machine < doomcom.numnodes; machine++)
			{
				if (node != machine)
				{
					packet.machines[spot].address = sendaddress[machine].sin_addr.s_addr;
					packet.machines[spot].port = sendaddress[machine].sin_port;
					packet.machines[spot].player = node;

					spot++;	// fixes problem of new address replacing existing address in
							// array; it's supposed to increment the index before getting
							// and storing in the packet the next address.
				}
			}
			packet.NumNodes = doomcom.numnodes - 2;
		}
		else
		{
			packet.NumNodes = 0;
		}
		PreSend (&packet, 4 + spot*8, &sendaddress[node]);
	}

	// Check for replies.
	while ( (from = PreGet (&packet, sizeof(packet), false)) )
	{
		if (packet.Fake == PRE_FAKE && packet.Message == PRE_ALLHEREACK)
		{
			node = FindNode (from);
			if (node >= 0)
			{
				if (!gotack[node])
				{
					gotack[node] = true;
					gotack[MAXNETNODES]++;
				}
			}
			PreSend (&packet, 2, from);
		}
	}

	// If everybody has replied, then this loop can end.
	return gotack[MAXNETNODES] == doomcom.numnodes - 1;
}
Exemple #7
0
bool Host_CheckForConnects (void *userdata)
{
	PreGamePacket packet;
	int numplayers = (int)(intptr_t)userdata;
	sockaddr_in *from;
	int node;

	while ( (from = PreGet (&packet, sizeof(packet), false)) )
	{
		if (packet.Fake != PRE_FAKE)
		{
			continue;
		}
		switch (packet.Message)
		{
		case PRE_CONNECT:
			node = FindNode (from);
			if (doomcom.numnodes == numplayers)
			{
				if (node == -1)
				{
					const BYTE *s_addr_bytes = (const BYTE *)&from->sin_addr;
					StartScreen->NetMessage ("Got extra connect from %d.%d.%d.%d:%d",
						s_addr_bytes[0], s_addr_bytes[1], s_addr_bytes[2], s_addr_bytes[3],
						from->sin_port);
					packet.Message = PRE_ALLFULL;
					PreSend (&packet, 2, from);
				}
			}
			else
			{
				if (node == -1)
				{
					node = doomcom.numnodes++;
					sendaddress[node] = *from;
					StartScreen->NetMessage ("Got connect from node %d.", node);
				}

				// Let the new guest (and everyone else) know we got their message.
				SendConAck (doomcom.numnodes, numplayers);
			}
			break;

		case PRE_DISCONNECT:
			node = FindNode (from);
			if (node >= 0)
			{
				StartScreen->NetMessage ("Got disconnect from node %d.", node);
				doomcom.numnodes--;
				while (node < doomcom.numnodes)
				{
					sendaddress[node] = sendaddress[node+1];
					node++;
				}

				// Let remaining guests know that somebody left.
				SendConAck (doomcom.numnodes, numplayers);
			}
			break;
		}
	}
	if (doomcom.numnodes < numplayers)
	{
		return false;
	}

	// It's possible somebody bailed out after all players were found.
	// Unfortunately, this isn't guaranteed to catch all of them.
	// Oh well. Better than nothing.
	while ( (from = PreGet (&packet, sizeof(packet), false)) )
	{
		if (packet.Fake == PRE_FAKE && packet.Message == PRE_DISCONNECT)
		{
			node = FindNode (from);
			if (node >= 0)
			{
				doomcom.numnodes--;
				while (node < doomcom.numnodes)
				{
					sendaddress[node] = sendaddress[node+1];
					node++;
				}
				// Let remaining guests know that somebody left.
				SendConAck (doomcom.numnodes, numplayers);
			}
			break;
		}
	}
	return doomcom.numnodes >= numplayers;
}
void ClientSession::ConnectCompletion()
{
	CRASH_ASSERT(LThreadType == THREAD_IO_WORKER);
	
	if (1 == InterlockedExchange(&mConnected, 1))
	{
		/// already exists?
		CRASH_ASSERT(false);
		return;
	}

	bool resultOk = true;
	do 
	{
		if ( SOCKET_ERROR == setsockopt( mSocket, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0 ))
		{
			printf_s("[DEBUG] SO_UPDATE_ACCEPT_CONTEXT error: %d\n", GetLastError());
			resultOk = false;
			break;
		}
		/*
		int opt = 1;
		if (SOCKET_ERROR == setsockopt(mSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&opt, sizeof(int)))
		{
			printf_s("[DEBUG] TCP_NODELAY error: %d\n", GetLastError());
			resultOk = false;
			break;
		}

		opt = 0;
		if (SOCKET_ERROR == setsockopt(mSocket, SOL_SOCKET, SO_RCVBUF, (const char*)&opt, sizeof(int)))
		{
			printf_s("[DEBUG] SO_RCVBUF change error: %d\n", GetLastError());
			resultOk = false;
			break;
		}

		int addrlen = sizeof(SOCKADDR_IN);
		if (SOCKET_ERROR == getpeername(mSocket, (SOCKADDR*)&mClientAddr, &addrlen))
		{
			printf_s("[DEBUG] getpeername error: %d\n", GetLastError());
			resultOk = false;
			break;
		}

		HANDLE handle = CreateIoCompletionPort((HANDLE)mSocket, GIocpManager->GetComletionPort(), (ULONG_PTR)this, 0);
		if (handle != GIocpManager->GetComletionPort())
		{
			printf_s("[DEBUG] CreateIoCompletionPort error: %d\n", GetLastError());
			resultOk = false;
			break;
		}
		*/
	} while (false);


	if (!resultOk)
	{
		DisconnectRequest(DR_ONCONNECT_ERROR);
		return;
	}

	printf_s("[DEBUG] Client Connected: IP=%s, PORT=%d\n", inet_ntoa(mClientAddr.sin_addr), ntohs(mClientAddr.sin_port));

	if (false == PreSend())
	{
		printf_s("[DEBUG] PreSend error: %d\n", GetLastError());
	}

	/// 타이머 테스트를 위해 10ms 후에 player 가동 ㄱㄱ
	//DoSyncAfter(10, mPlayer, &Player::Start, 1000);
}