示例#1
0
int cProtocol125::ParsePacket(unsigned char a_PacketType)
{
	switch (a_PacketType)
	{
		default: return PARSE_UNKNOWN;
		case PACKET_ANIMATION:                 return ParseArmAnim();
		case PACKET_BLOCK_DIG:                 return ParseBlockDig();
		case PACKET_BLOCK_PLACE:               return ParseBlockPlace();
		case PACKET_CHAT:                      return ParseChat();
		case PACKET_CREATIVE_INVENTORY_ACTION: return ParseCreativeInventoryAction();
		case PACKET_DISCONNECT:                return ParseDisconnect();
		case PACKET_HANDSHAKE:                 return ParseHandshake();
		case PACKET_KEEP_ALIVE:                return ParseKeepAlive();
		case PACKET_LOGIN:                     return ParseLogin();
		case PACKET_PACKET_ENTITY_ACTION:      return ParseEntityAction();
		case PACKET_PING:                      return ParsePing();
		case PACKET_PLAYER_ABILITIES:          return ParsePlayerAbilities();
		case PACKET_PLAYER_LOOK:               return ParsePlayerLook();
		case PACKET_PLAYER_MOVE_LOOK:          return ParsePlayerMoveLook();
		case PACKET_PLAYER_ON_GROUND:          return ParsePlayerOnGround();
		case PACKET_PLAYER_POS:                return ParsePlayerPosition();
		case PACKET_PLUGIN_MESSAGE:            return ParsePluginMessage();
		case PACKET_RESPAWN:                   return ParseRespawn();
		case PACKET_SLOT_SELECTED:             return ParseSlotSelected();
		case PACKET_UPDATE_SIGN:               return ParseUpdateSign();
		case PACKET_USE_ENTITY:                return ParseUseEntity();
		case PACKET_ENCHANT_ITEM:              return ParseEnchantItem();
		case PACKET_WINDOW_CLICK:              return ParseWindowClick();
		case PACKET_WINDOW_CLOSE:              return ParseWindowClose();
	}
}
void CGnutellaSocket::OnReceive(int nErrorCode)
{
	TRACE("OnRead\n");
	/*
	if (nErrorCode)
	{
		ASSERT(0);
		return;
	}
	*/

	if (m_state == 0 || m_state == 1)
	{
		/*
		time_t timer1;
		time(&timer1);

		double diff = difftime(timer1, m_timer0);

		m_timer0 = timer1;

		ATLTRACE("", diff);
		*/

		ULONG n;
		ioctlsocket(m_socket, FIONREAD, &n);

		char buf[256+1];
		while (n)
		{
			int len = 256;
			if (len > n)
				len = n;

			int nread = Receive(buf, len);
			//if (nread == SOCKET_ERROR)
			if (nread < len)
			{
				m_state = -1;
				Close();
				return;
			}

			n -= nread;

			buf[nread] = 0;
			m_strHandshake += buf;
		}

		/*
		std::string line;
		while (1)
		{
			line = ReadLine();
			m_strHandshake += line + "\r\n";
			if (line.length() == 0)
				break;
		}
		*/

		if (m_strHandshake.length() > 4096)
		{
			// Handshake overflow
			ASSERT(0);
			m_state = -1;
			Close();
			return;//break;
		}

		if (m_state == 0)
		{
			if (m_strHandshake.length() >= 12)
			{
				if (strncmp(m_strHandshake.c_str(), "GNUTELLA/0.6", 12))
				{
					// Not a gnutella peer (disconnect)
					m_state = -1;
					Close();
					return;//break;
				}

				m_state = 1;	// Now we know it's a gnutella peer (keep receiving handshake)
			}
		}

		if (m_state == 1)
		{
			if (strstr(m_strHandshake.c_str(), "\r\n\r\n"))
			{
				m_state = 2;	// Have read entire handshake string
			}
		}

		if (m_state == 2)
		{
			int m_code = ParseHandshake();

			m_pComm->ProcessHeaders(this);

			if (m_code == 200)	// OK
			{
				m_state = 3;

				char* str =
					"GNUTELLA/0.6 200 OK\r\n"
					"\r\n";
			//	char* str = "GNUTELLA OK\n\n";
				int nWritten = Send(str, strlen(str));

				if (nWritten != strlen(str))
				{
					ASSERT(0);
				}

			//	PostMessage(m_pComm->m_hWnd, WM_USER+102, (LPARAM)(IConnection*)this, m_code);
			//	m_pComm->m_client->OnConnection(this);

				// Ping
				{
					GnutellaHeader ping;

					CoCreateGuid(&ping.Guid);	// ???
					ping.PayloadType = GnutellaPing;
					ping.TTL = 7;
					ping.Hops = 0;
					ping.PayloadLength = 0;

					int wrote = Send((const char*)&ping, sizeof(ping));
				}

			}
			else
			{
				Close();


				/*
				char* str =
					"GNUTELLA/0.6 503 FAIL\r\n"
					"\r\n";
				int nWritten = Send(str, strlen(str));

				if (nWritten != strlen(str))
				{
					ASSERT(0);
				}
*/
			}
		}
	}
	else if (m_state == 3)
	{
		int nread = Receive(m_packetbuf+m_nbufbytes, 32768-m_nbufbytes);
		if (nread == -1)
		{
			m_state = -1;
			Close();
			return;
		}

		int nbufbytes = m_nbufbytes + nread;

		// Process all complete packets
		bool bContinue;

		int offset = 0;
		int bytesleft;
		do
		{
			bytesleft = nbufbytes - offset;

			if (bytesleft < sizeof(GnutellaHeader))
			{
				// Incomplete packet
				bContinue = false;
			}
			else
			{
				GnutellaHeader* hdr = (GnutellaHeader*)(m_packetbuf+offset);

				if((hdr->PayloadType == 0x00 && hdr->PayloadLength < 32768)					  ||
					(hdr->PayloadType == 0x01 && hdr->PayloadLength >= 14 && hdr->PayloadLength < 32768)  ||
					(hdr->PayloadType == 0x02 && hdr->PayloadLength > 0 && hdr->PayloadLength < 32768)	||
					(hdr->PayloadType == 0x30 && hdr->PayloadLength > 2 && hdr->PayloadLength < 32768)   ||
					(hdr->PayloadType == 0x31 && hdr->PayloadLength < 32768)   ||
					(hdr->PayloadType == 0x32 && hdr->PayloadLength < 32768)   ||
					(hdr->PayloadType == 0x40 && hdr->PayloadLength >= 26 && hdr->PayloadLength < 32768)  ||
					(hdr->PayloadType == 0x80 && hdr->PayloadLength >  2 && hdr->PayloadLength <= 230)   ||
					(hdr->PayloadType == 0x81 && hdr->PayloadLength > 26 && hdr->PayloadLength <= 32768))
				{
					DWORD packetlen = sizeof(GnutellaHeader) + hdr->PayloadLength;

					if (bytesleft < packetlen)
					{
						// Incomplete packet
						bContinue = false;
					}
					else
					{
						ProcessPacket(hdr);

						offset += packetlen;

						bContinue = true;
					}
				}
				else
				{
					bContinue = false;

					m_state = -1;
					Close();
					return;
				}
			}
		}
		while (bContinue);

		// Move the leftover bytes to the beginning of the buffer
		if (bytesleft)
		{
			memmove(m_packetbuf, m_packetbuf+offset, bytesleft);
		}
		m_nbufbytes = bytesleft;
	}
}