Ejemplo n.º 1
0
Archivo: Os.c Proyecto: broonie/ohNet
THandle OsNetworkAccept(THandle aHandle, TIpAddress* aClientAddress, uint32_t* aClientPort)
{
    SOCKET h;
    OsNetworkHandle* newHandle;
    OsNetworkHandle* handle = (OsNetworkHandle*)aHandle;
    WSAEVENT event;
    HANDLE handles[2];
    DWORD ret;
    struct sockaddr_in addr;
    socklen_t len = sizeof(addr);

    *aClientAddress = 0;
    *aClientPort = 0;
    if (SocketInterrupted(handle)) {
        return kHandleNull;
    }
    sockaddrFromEndpoint(&addr, 0, 0);
    event = WSACreateEvent();
    if (NULL == event) {
        return kHandleNull;
    }
    if (0 != WSAEventSelect(handle->iSocket, event, FD_ACCEPT|FD_CLOSE)) {
        WSACloseEvent(event);
        return kHandleNull;
    }

    h = accept(handle->iSocket, (struct sockaddr*)&addr, &len);
    if (INVALID_SOCKET==h && WSAEWOULDBLOCK==WSAGetLastError()) {
        handles[0] = event;
        handles[1] = handle->iEvent;
        ret = WSAWaitForMultipleEvents(2, &handles[0], FALSE, INFINITE, FALSE);
        if (WAIT_OBJECT_0 == ret) {
            h = accept(handle->iSocket, (struct sockaddr*)&addr, &len);
        }
    }
    SetSocketBlocking(handle->iSocket);
    WSACloseEvent(event);
    if (INVALID_SOCKET == h) {
        return kHandleNull;
    }

    newHandle = CreateHandle(handle->iCtx, h);
    if (NULL == newHandle) {
        return kHandleNull;
    }

    *aClientAddress = addr.sin_addr.s_addr;
    *aClientPort = SwapEndian16(addr.sin_port);
    return (THandle)newHandle;
}
Ejemplo n.º 2
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);
}
Ejemplo 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 = 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);
}
Ejemplo n.º 4
0
Archivo: Os.c Proyecto: broonie/ohNet
int32_t OsNetworkPort(THandle aHandle, uint32_t* aPort)
{
    int32_t err;
    OsNetworkHandle* handle = (OsNetworkHandle*)aHandle;

    struct sockaddr_in addr;
    socklen_t len = sizeof(addr);
    err = getsockname(handle->iSocket, (struct sockaddr*)&addr, &len);
    
    if (err == 0) {
        uint16_t port = SwapEndian16(addr.sin_port);
        *aPort = port;
    }
    return err;
}
Ejemplo n.º 5
0
Archivo: Os.c Proyecto: broonie/ohNet
int32_t OsNetworkReceiveFrom(THandle aHandle, uint8_t* aBuffer, uint32_t aBytes, TIpAddress* aAddress, uint16_t* aPort)
{
    int32_t received;
    OsNetworkHandle* handle = (OsNetworkHandle*)aHandle;
    struct sockaddr_in addr;
    int len = sizeof(addr);
    WSAEVENT event;
    HANDLE handles[2];
    DWORD ret;

    if (SocketInterrupted(handle)) {
        return -1;
    }

    sockaddrFromEndpoint(&addr, 0, 0);

    event = WSACreateEvent();
    if (NULL == event) {
        return -1;
    }
    if (0 != WSAEventSelect(handle->iSocket, event, FD_READ|FD_CLOSE)) {
        WSACloseEvent(event);
        return -1;
    }

    received = recvfrom(handle->iSocket, (char*)aBuffer, aBytes, 0, (struct sockaddr*)&addr, &len);
    if (SOCKET_ERROR==received && WSAEWOULDBLOCK==WSAGetLastError()) {
        handles[0] = event;
        handles[1] = handle->iEvent;
        ret = WSAWaitForMultipleEvents(2, &handles[0], FALSE, INFINITE, FALSE);
        if (WAIT_OBJECT_0 == ret) {
            received = recvfrom(handle->iSocket, (char*)aBuffer, aBytes, 0, (struct sockaddr*)&addr, &len);
        }
    }

    SetSocketBlocking(handle->iSocket);
    WSACloseEvent(event);
    *aAddress = addr.sin_addr.s_addr;
    *aPort = SwapEndian16(addr.sin_port);
    return received;
}
Ejemplo n.º 6
0
	void HandleIPv4Packet(Devices::NIC::GenericNIC* interface, void* packet, uint64_t length, IPv4Address source, IPv4Address destip)
	{
		UDPPacket* udp = (UDPPacket*) packet;
		uint64_t actuallength = SwapEndian16(udp->length) - sizeof(UDPPacket);

		uint16_t sourceport = SwapEndian16(udp->sourceport);
		uint16_t destport = SwapEndian16(udp->destport);

		// IPv4PortAddress target;
		// target.ip = source;
		// target.port = SwapEndian16(udp->destport);

		bool triedonce = false;

		// feel dirty
		retry:

		// check for full mapping.
		bool found = false;
		Socket::SocketObj* skt = udpsocketmapv4->Get(SocketFullMappingv4 { IPv4PortAddress { destip, destport }, IPv4PortAddress { source, sourceport } });
		if(skt)
			found = true;

		// multiphase search: check for sourceip + sourceport + destport
		if(!skt && !found)
		{
			skt = udpsocketmapv4->Get(SocketFullMappingv4 { IPv4PortAddress { source, sourceport }, IPv4PortAddress { IPv4Address { 0xFFFFFFFF }, destport } });
			if(skt)
				found = true;
		}

		// check for sourceip + destport
		if(!skt && !found)
		{
			skt = udpsocketmapv4->Get(SocketFullMappingv4 { IPv4PortAddress { source, 0 }, IPv4PortAddress { IPv4Address { 0xFFFFFFFF}, destport } });
			if(skt)
				found = true;
		}

		// check for sourceport + destport
		if(!skt && !found)
		{
			skt = udpsocketmapv4->Get(SocketFullMappingv4 { IPv4PortAddress { IPv4Address { 0 }, sourceport }, IPv4PortAddress { IPv4Address { 0xFFFFFFFF }, destport } });
			if(skt)
				found = true;
		}

		// finally, only destport.
		if(!skt && !found)
		{
			skt = udpsocketmapv4->Get(SocketFullMappingv4 { IPv4PortAddress { IPv4Address { 0 }, 0 }, IPv4PortAddress { IPv4Address { 0xFFFFFFFF }, destport } });
			if(skt)
				found = true;
		}

		if(found)
		{
			// send into socket buffer.
			skt->recvbuffer->Write((uint8_t*) packet + sizeof(UDPPacket), actuallength);
			skt->packetsizes->Write(actuallength);
			skt->packetcount++;
			return;
		}

		// if we got here, it didn't find.
		if(!triedonce)
		{
			triedonce = true;
			source = IPv4Address { 0 };
			goto retry;
		}

		Log("No sockets found for target, discarding packet.");

		UNUSED(interface);
		UNUSED(length);
	}
Ejemplo n.º 7
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;
			}
		}
	}
Ejemplo n.º 8
0
Archivo: UDP.cpp Proyecto: zhiayang/mx
	void HandleIPv4Packet(Devices::NIC::GenericNIC* interface, void* packet, uint64_t length, IPv4Address source, IPv4Address destip)
	{
		UDPPacket* udp = (UDPPacket*) packet;
		uint64_t actuallength = SwapEndian16(udp->length) - sizeof(UDPPacket);

		uint16_t sourceport = SwapEndian16(udp->sourceport);
		uint16_t destport = SwapEndian16(udp->destport);

		// IPv4PortAddress target;
		// target.ip = source;
		// target.port = SwapEndian16(udp->destport);


		Log("Received UDP packet from source IP %d.%d.%d.%d", source.b1, source.b2, source.b3, source.b4);


		IPv4Address matchAny { 0xFFFFFFFF };
		IPv4Address zero { 0 };

		bool triedonce = false;

		// feel dirty
		retry:

		// check for full mapping.
		bool found = false;
		Socket* skt = (*udpsocketmapv4)[SocketFullMappingv4 { IPv4PortAddress { destip, destport }, IPv4PortAddress { source, sourceport } }];
		if(skt)
		{
			found = true;
		}

		// multiphase search: check for sourceip + sourceport + destport
		if(!skt && !found)
		{
			skt = (*udpsocketmapv4)[SocketFullMappingv4 { IPv4PortAddress { source, sourceport }, IPv4PortAddress { matchAny, destport } }];
			if(skt)
			{
				found = true;
			}
		}

		// check for sourceip + destport
		if(!skt && !found)
		{
			skt = (*udpsocketmapv4)[SocketFullMappingv4 { IPv4PortAddress { source, 0 }, IPv4PortAddress { matchAny, destport } }];
			if(skt)
				found = true;
		}

		// check for sourceport + destport
		if(!skt && !found)
		{
			skt = (*udpsocketmapv4)[SocketFullMappingv4 { IPv4PortAddress { zero, sourceport }, IPv4PortAddress { matchAny, destport } }];
			if(skt)
				found = true;
		}

		// finally, only destport.
		if(!skt && !found)
		{
			skt = (*udpsocketmapv4)[SocketFullMappingv4 { IPv4PortAddress { zero, 0 }, IPv4PortAddress { matchAny, destport } }];
			if(skt)
				found = true;
		}

		if(found)
		{
			// send into socket buffer.
			skt->recvbuffer.Write((uint8_t*) packet + sizeof(UDPPacket), actuallength);
			Log("wrote received data (%d bytes) (from %d.%d.%d.%d) into socket", actuallength, source.b1, source.b2, source.b3, source.b4);

			return;
		}

		// if we got here, it didn't find.
		if(!triedonce)
		{
			triedonce = true;
			source = IPv4Address { 0 };

			goto retry;
		}

		Log("No open UDP sockets found for target, discarding packet.");

		UNUSED(interface);
		UNUSED(length);
	}