Exemplo n.º 1
0
	void TCPConnection::SendIPv4Packet(uint8_t* packet, uint64_t length, uint8_t flags)
	{
		/*
			SYN: The active open is performed by the client sending a SYN to the server. The client sets the segment's sequence number to a random value A.
			SYN-ACK: In response, the server replies with a SYN-ACK. The acknowledgment number is set to one more than the received sequence number i.e. A+1, and the sequence number that the server chooses for the packet is another random number, B.
			ACK: Finally, the client sends an ACK back to the server. The sequence number is set to the received acknowledgement value i.e. A+1, and the acknowledgement number is set to one more than the received sequence number i.e. B+1.
		*/

		if(this->state == ConnectionState::Disconnected)
		{
			Log(1, "Error: cannot send packet through a disconnected socket.");
			return;
		}

		// setup a fake IPv4 header.
		IP::PseudoIPv4Header* pseudo = new IP::PseudoIPv4Header;
		pseudo->source = this->sourceip4;
		pseudo->dest = this->destip4;

		pseudo->zeroes = 0;
		pseudo->protocol = (uint8_t) IP::ProtocolType::TCP;
		pseudo->length = SwapEndian16(sizeof(TCPPacket) + (uint16_t) length);

		// calculate the pseudo header's checksum separately.
		uint16_t pseudocheck = IP::CalculateIPChecksum_Partial(0, pseudo, sizeof(IP::PseudoIPv4Header));

		uint8_t* raw = new uint8_t[sizeof(TCPPacket) + length];
		TCPPacket* tcp = (TCPPacket*) raw;
		tcp->clientport = SwapEndian16(this->clientport);
		tcp->serverport = SwapEndian16(this->serverport);

		tcp->sequence = SwapEndian32(this->localsequence + this->localcumlsequence);
		tcp->ackid = SwapEndian32(this->nextack);
		this->localcumlsequence += length;

		tcp->HeaderLength = 0x50;
		tcp->Flags = flags;

		// 32k
		tcp->WindowSize = SwapEndian16(TCP_MAXWINDOW);

		tcp->Checksum = 0;
		tcp->UrgentPointer = 0;

		Memory::Copy(raw + sizeof(TCPPacket), packet, length);
		uint16_t tcpcheck = IP::CalculateIPChecksum_Partial(pseudocheck, tcp, sizeof(TCPPacket) + length);

		tcp->Checksum = SwapEndian16(IP::CalculateIPChecksum_Finalise(tcpcheck));

		// this->socket->WriteTCP(raw, sizeof(TCPPacket) + length);
		IP::SendIPv4Packet(this->socket->interface, raw, (uint16_t) (sizeof(TCPPacket) + length), 48131, this->destip4, IP::ProtocolType::TCP);
		this->AlreadyAcked = true;

		delete pseudo;
		delete tcp;
	}
Exemplo n.º 2
0
/*
 * Class:     org_openhome_net_device_DvInvocation
 * Method:    DvInvocationGetAdapter
 * Signature: (J)I
 */
JNIEXPORT jint JNICALL Java_org_openhome_net_device_DvInvocation_DvInvocationGetAdapter
  (JNIEnv *aEnv, jclass aClass, jlong aInvocation)
{
	DvInvocationC invocation = (DvInvocationC) (size_t)aInvocation;
	TIpAddress adapter;
	aEnv = aEnv;
	aClass = aClass;
	
	DvInvocationGetAdapter(invocation, &adapter);
#ifdef DEFINE_LITTLE_ENDIAN
    return (jint) SwapEndian32(adapter);
#elif defined DEFINE_BIG_ENDIAN
    return (jint) adapter;
#else
# error Endianness not defined
#endif
}
Exemplo n.º 3
0
inline int String0::Compare(const String0& s) const
{
#ifdef FAST_STRING_COMPARE
	if((chr[KIND] | s.chr[KIND]) == 0) {
	#ifdef CPU_64
		uint64 a64 = SwapEndian64(q[0]);
		uint64 b64 = SwapEndian64(s.q[0]);
		if(a64 != b64)
			return a64 < b64 ? -1 : 1;
		uint32 a32 = SwapEndian32(w[2]);
		uint32 b32 = SwapEndian32(s.w[2]);
		if(a32 != b32)
			return a32 < b32 ? -1 : 1;
	#else
		uint32 a32 = SwapEndian32(w[0]);
		uint32 b32 = SwapEndian32(s.w[0]);
		if(a32 != b32)
			return a32 < b32 ? -1 : 1;
		a32 = SwapEndian32(w[1]);
		b32 = SwapEndian32(s.w[1]);
		if(a32 != b32)
			return a32 < b32 ? -1 : 1;
		a32 = SwapEndian32(w[2]);
		b32 = SwapEndian32(s.w[2]);
		if(a32 != b32)
			return a32 < b32 ? -1 : 1;
	#endif
		uint16 a16 = SwapEndian16(v[6]);
		uint16 b16 = SwapEndian16(s.v[6]);
		if(a16 != b16)
			return a16 < b16 ? -1 : 1;
		return 0;
	}
#endif
	return LCompare(s);
}
Exemplo n.º 4
0
inline int String0::Compare(const String0& s) const
{
#ifdef FAST_STRING_COMPARE
	if((chr[KIND] | s.chr[KIND]) == 0) {
	#ifdef CPU_64
		uint64 a64 = q[0];
		uint64 b64 = s.q[0];
		if(a64 != b64)
			return SwapEndian64(a64) < SwapEndian64(b64) ? -1 : 1;
		uint32 a32 = w[2];
		uint32 b32 = s.w[2];
		if(a32 != b32)
			return SwapEndian32(a32) < SwapEndian32(b32) ? -1 : 1;
	#else
		uint32 a32 = w[0];
		uint32 b32 = s.w[0];
		if(a32 != b32)
			return SwapEndian32(a32) < SwapEndian32(b32) ? -1 : 1;
		a32 = w[1];
		b32 = s.w[1];
		if(a32 != b32)
			return SwapEndian32(a32) < SwapEndian32(b32) ? -1 : 1;
		a32 = w[2];
		b32 = s.w[2];
		if(a32 != b32)
			return SwapEndian32(a32) < SwapEndian32(b32) ? -1 : 1;
	#endif
		uint16 a16 = v[6];
		uint16 b16 = s.v[6];
		if(a16 != b16)
			return SwapEndian16(a16) < SwapEndian16(b16) ? -1 : 1;
		return 0;
	}
#endif
	return LCompare(s);
}
Exemplo n.º 5
0
	void TCPConnection::HandleIncoming(uint8_t* packet, uint64_t bytes, uint64_t HeaderSize)
	{
		// at this stage the checksum should be verified (and set to zero), so we can ignore that.
		TCPPacket* tcp = (TCPPacket*) packet;
		HeaderSize *= 4;

		// check if we got options.
		if(HeaderSize > sizeof(TCPPacket))
		{
			uint64_t optsize = HeaderSize - sizeof(TCPPacket);
			uint64_t offset = sizeof(TCPPacket);
			while(offset < optsize)
			{
				switch(packet[offset])
				{
					case 2:
						this->maxsegsize = SwapEndian16(*(packet + offset + 2));
						offset += 4;
						break;
				}
			}
		}




		// check if ack.
		if(!(tcp->Flags & 0x10))
		{
			Log("TCP ACK flag not set, discarding.");
			return;
		}

		uint64_t datalength = bytes - HeaderSize;
		this->lastpackettime = Time::Now();
		this->nextack = SwapEndian32(tcp->sequence) + (uint32_t) datalength;
		this->servercumlsequence += __max(datalength, 1);
		this->PacketReceived = true;

		switch(this->state)
		{
			case ConnectionState::Disconnected:
			{
				Log(1, "TCP Stack error: Received packet from closed connection");
				return;
			}

			case ConnectionState::WatingSYNReply:
			{
				// check if we're synchronising
				if(tcp->Flags & 0x2)
				{
					this->serversequence = SwapEndian32(tcp->sequence);
					this->servercumlsequence = 1;
					this->localcumlsequence = 1;
					this->nextack = 1;
				}
				break;
			}

			case ConnectionState::WaitingConnectionACK:
			{
				// handshake complete.
				Log("Established connection to %d.%d.%d.%d : %d; Relative local seq: %d, Relative server seq: %d", this->destip4.b1, this->destip4.b2, this->destip4.b3, this->destip4.b4, this->serverport, this->localcumlsequence, this->servercumlsequence);

				this->state = ConnectionState::Connected;
				break;
			}



			// disconnections:
			case ConnectionState::WaitingDisconnectACK:
			{
				// servers will either send an 'ACK', followed by a 'FIN, then ACK', or a 'FIN, ACK' directly.
				// handle both cases.
				if(tcp->Flags & 0x1 && tcp->Flags & 0x10)
				{
					// this is a FIN, ACK
					// don't respond.
					this->state = ConnectionState::Disconnected;
					return;
				}
				else if(tcp->Flags & 0x10)
				{
					// server sent an ACK, expect stuff later
					this->state = ConnectionState::WaitingDisconnectFINACK;
					return;
				}
				else
				{
					Log(1, "Invalid TCP response to FIN, ACK; state machine broken.");
				}
				break;
			}

			case ConnectionState::WaitingDisconnectFINACK:
			{
				// well we're expecting a FIN, ACK.
				if(tcp->Flags & 0x1 && tcp->Flags & 0x10)
				{
					this->nextack++;
					this->SendPacket(0, 0, 0x10);
					this->state = ConnectionState::Disconnected;
					Log("Disconnected from %d.%d.%d.%d : %d.", this->destip4.b1, this->destip4.b2, this->destip4.b3, this->destip4.b4, this->serverport);
					return;
				}
				else
				{
					Log(1, "Invalid TCP response to FIN, ACK; state machine broken.");
				}
				break;
			}





			case ConnectionState::Connected:
			{
				// first check if the server wants us to D/C
				if(tcp->Flags & 0x1)
				{
					// damn it, that f****r
					// send an ACK to that.
					this->nextack++;
					this->SendPacket(0, 0, 0x10);
					this->state = ConnectionState::WaitingDisconnectACK;
					return;
				}

				this->AlreadyAcked = false;

				// copy the packet data to the correct place.
				if(datalength > 0 && tcp->Flags & 0x8)
				{
					// push.
					// fine, bastard.
					uint64_t offset = SwapEndian32(tcp->sequence) - this->serversequence - 1;
					this->socket->recvbuffer.MoveWritePointer(offset);
					this->socket->recvbuffer.Write(packet + HeaderSize, datalength);

					Log("pushed %d bytes to offset %d", datalength, offset);
				}
				else if(datalength > 0 && (SwapEndian32(tcp->sequence) >= this->servercumlsequence) && (this->bufferfill + datalength) < TCP_MAXWINDOW)
				{
					uint64_t offset = SwapEndian32(tcp->sequence) - this->serversequence - 1;
					// uint64_t prp = this->packetbuffer->GetWritePointer();

					Log("Copying %d bytes to offset %d", datalength, offset);
					this->socket->recvbuffer.MoveWritePointer(offset);
					this->socket->recvbuffer.Write(packet + HeaderSize, datalength);

					this->bufferfill += datalength;
				}
				else if((this->bufferfill + (bytes - HeaderSize)) >= TCP_MAXWINDOW)
				{
					// shit.
					// push data to application,
					// send collective ACK.

					HALT("");

					// flush tcp to application.
					uint8_t* buf = new uint8_t[GLOBAL_MTU];
					this->packetbuffer.Read(buf, GLOBAL_MTU);
					this->socket->recvbuffer.Write(buf, GLOBAL_MTU);

					delete[] buf;
				}
				break;
			}
		}
	}