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; }
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); }
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); }
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; }
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; }
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); }
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; } } }
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); }