/* --------------------------------------------------------------------------- ------------------------------------------------------------------------- DP_socket method definitions ------------------------------------------------------------------------- ------------------------------------------------------------------------- /**/ void DP_socket::SendAckPacket(int PacketID) { if (!Remote_ID || !BlockingReads) return; DPPACKET PacketAck; PacketAck.DataSize = 0; PacketAck.MessageNum = -1; PacketAck.Port = SocketPort; PacketAck.MessageType = PACKET_ACK; PacketAck.Reserved = PacketID; // OutQueue.AddPacketToQueue(&PacketAck); HRESULT hRet; hRet = g_pDP->Send(Local_ID, Remote_ID, 0, &PacketAck, PacketSize(&PacketAck)); _RPT3(_CRT_WARN, "DP_socket::SendAckPacket -- Sent acknowledgement of message #%d from player 0x%x to player 0x%x\n", PacketID, Local_ID, Remote_ID); } /* --------------------------------------------------------------------------- ------------------------------------------------------------------------- /**/ void DP_socket::AddConnection(DPPACKET* Packet, DWORD Size) { DP_socket *OldSock = DP->FindSocket(Packet->Reserved); if (OldSock) { OldSock->SendAckPacket(Packet->MessageNum); return; } HRESULT hRet; DP_address NewAddr; NewAddr.Port = -1; NewAddr.Remote_ID = Packet->Reserved; DPNAME Name; memset(&Name, 0, sizeof(Name)); Name.dwSize = sizeof(Name); hRet = g_pDP->CreatePlayer(&NewAddr.Local_ID, &Name, NULL, NULL, 0, 0); if (hRet != DP_OK) return; DP_socket *NewSock; NewSock = new DP_socket(-1, &NewAddr); NewSock->NextConnect = ConnectRequests; ConnectRequests = NewSock; NewSock->Remote_Fast_Socket = *((int*) &Packet->Data); NewSock->SendAckPacket(Packet->MessageNum); NewSock->SendConnectAck(); NewSock->InQueue.Serial = 1; } /* --------------------------------------------------------------------------- ------------------------------------------------------------------------- /**/ void DP_socket::SendConnectAck() { DPPACKET ConnectAck; ConnectAck.DataSize = 0; ConnectAck.MessageNum = -1; ConnectAck.Port = SocketPort; ConnectAck.MessageType = PACKET_CONNECT_ACK; ConnectAck.Reserved = Local_ID; OutQueue.AddPacketToQueue(&ConnectAck); Send(); /* HRESULT hRet; hRet = g_pDP->Send(Local_ID, Remote_ID, 0, &ConnectAck, PacketSize(&ConnectAck)); _RPT2(_CRT_WARN, "DP_socket::write -- Sent connection acknowledgement from player 0x%x to player 0x%x\n", Local_ID, Remote_ID); */ } /* --------------------------------------------------------------------------- ------------------------------------------------------------------------- /**/ void DP_socket::SendConnectRequest() { DPPACKET ConnectRequest; ConnectRequest.DataSize = 4; ConnectRequest.Port = SocketPort; ConnectRequest.MessageType = PACKET_CONNECT; ConnectRequest.Reserved = Local_ID; *((unsigned long*) ConnectRequest.Data) = FastID; OutQueue.AddPacketToQueue(&ConnectRequest); } /* --------------------------------------------------------------------------- ------------------------------------------------------------------------- /**/ void DP_socket::Send() { if (!OutQueue.DataSize()) return; HRESULT hRet; hRet = g_pDP->Send(Local_ID, Remote_ID, 0, OutQueue.Data, OutQueue.DataSize()); _RPT3(_CRT_WARN, "DP_socket::Send -- Sent %d bytes from player 0x%x to player 0x%x\n", OutQueue.DataSize(), Local_ID, Remote_ID); } /* --------------------------------------------------------------------------- ------------------------------------------------------------------------- /**/ int DP_socket::write(void* buf, int size, net_address *addr) { DPPACKET Packet; Packet.DataSize = size; Packet.MessageType = PACKET_DATA; Packet.Port = SocketPort; Packet.Reserved = FastID; memcpy(Packet.Data, buf, size); if (!BlockingReads) { /* OutQueue.Acknowledge(((DPPACKET*) OutQueue.Data)->MessageNum); OutQueue.AddPacketToQueue(&Packet); */ HRESULT hRet; if (!addr) { hRet = g_pDP->Send(Local_ID, Remote_ID, 0, &Packet, PacketSize(&Packet)); _RPT3(_CRT_WARN, "DP_socket::write (fast) -- Sent %d bytes from player 0x%x to player 0x%x\n", OutQueue.DataSize(), Local_ID, Remote_ID); } else { hRet = g_pDP->Send(Local_ID, ((DP_address*) addr)->Remote_ID, 0, &Packet, PacketSize(&Packet)); _RPT3(_CRT_WARN, "DP_socket::write (fast addr) -- Sent %d bytes from player 0x%x to player 0x%x\n", OutQueue.DataSize(), Local_ID, ((DP_address*) addr)->Remote_ID); } } else { OutQueue.AddPacketToQueue(&Packet); Send(); } return size; } /* --------------------------------------------------------------------------- ------------------------------------------------------------------------- /**/ int DP_socket::read(void *buf, int size, net_address **addr) { DWORD BytesRead = 0; time_marker Start, Now; do { while (!ready_to_read() && BlockingReads && Now.diff_time(&Start) < DPREAD_TIMEOUT) { DP->select(0); } BytesRead += read_backup(buf, size); } while (size && Now.diff_time(&Start) < DPREAD_TIMEOUT && BlockingReads); _RPT2(_CRT_WARN, "DP_socket::read -- Read %d bytes from player 0x%x\n", BytesRead, Remote_ID); if (addr) { DP_address *NewAddr = new DP_address(); NewAddr->Local_ID = Local_ID; NewAddr->Remote_ID = Last_Received_ID; NewAddr->Port = -1; *addr = NewAddr; } return BytesRead; } /* --------------------------------------------------------------------------- ------------------------------------------------------------------------- /**/ DP_socket::~DP_socket() { _RPT2(_CRT_WARN, "Deleting socket from player 0x%x to player 0x%x\n", Local_ID, Remote_ID); if (backup) jfree(backup); DP->remove_socket_from_list(this); if (Local_ID == FastID) FastID = 0; if (Local_ID != ServerPlayer) g_pDP->DestroyPlayer(Local_ID); } /* --------------------------------------------------------------------------- ------------------------------------------------------------------------- /**/ DP_socket::DP_socket(int port, DP_address *dest) { Connecting = 0; ConnectRequests = NULL; backup = NULL; backup_size = backup_end = backup_start = 0; BlockingReads = 1; status = INIT; DP->add_socket_to_list(this); // setup an outgoing packet structure if (dest) { if (port != -1) SocketPort = port; else SocketPort = dest->Port; Remote_ID = dest->Remote_ID; Local_ID = dest->Local_ID; } else { SocketPort = port; Remote_ID = DPID_ALLPLAYERS; Local_ID = 0; } _ASSERT(SocketPort != 0xcdcdcdcd); _RPT1(_CRT_WARN, "Creating new socket on port %d\n", SocketPort); } /* --------------------------------------------------------------------------- ------------------------------------------------------------------------- /**/ void DP_socket::send_ping_packet() { //send_data(0); // send a 0 length data packet to remote host } /* --------------------------------------------------------------------------- ------------------------------------------------------------------------- /**/ void DP_socket::clear() { } /* --------------------------------------------------------------------------- ------------------------------------------------------------------------- /**/ int DP_socket::ready_to_write() { return 1; } /* --------------------------------------------------------------------------- ------------------------------------------------------------------------- /**/ int DP_socket::ProcessPacket() { DPPACKET Packet; InQueue.Read(&Packet); switch (Packet.MessageType) { case PACKET_ACK: OutQueue.Acknowledge(Packet.Reserved); _RPT1(_CRT_WARN, "Got acknowledgement for packet #%d\n", Packet.Reserved); return 0; case PACKET_CONNECT: // Pitch it, we're getting a dupe connect from this player if (BlockingReads) SendAckPacket(Packet.MessageNum); _RPT1(_CRT_WARN, "Got duplicate connect request from 0x%x\n", Packet.Reserved); Send(); break; case PACKET_CONNECT_ACK: if (Remote_ID == ServerPlayer) { Remote_ID = Packet.Reserved; Connecting = 0; _RPT1(_CRT_WARN, "Got connect acknowledgement from 0x%x\n", Packet.Reserved); // SendAckPacket(Packet.MessageNum); } SendAckPacket(Packet.MessageNum); break; case PACKET_DATA: if (BlockingReads) SendAckPacket(Packet.MessageNum); SendAckPacket(Packet.MessageNum); add_backup((unsigned char*) &Packet.Data, Packet.DataSize); _RPT3(_CRT_WARN, "Read %d bytes from packet 0x%x:%d\n", Packet.DataSize, Local_ID, Packet.MessageNum); return Packet.DataSize; break; default: break; } return 0; } /* --------------------------------------------------------------------------- ------------------------------------------------------------------------- /**/ int DP_socket::ready_to_read() { static time_marker Last; time_marker Now; if (backup_end - backup_start > 0) { return backup_end - backup_start; } /* if (ConnectRequests) return 1; */ if (BlockingReads) if (OutQueue.DataSize() && Now.diff_time(&Last) > DPRESEND_TIMEOUT) { Send(); Last.get_time(); } DPID Source_ID, *From; DWORD flags; if (Remote_ID == DPID_ALLPLAYERS || Connecting) { flags = DPRECEIVE_TOPLAYER; From = &Source_ID; } else { flags = DPRECEIVE_FROMPLAYER | DPRECEIVE_TOPLAYER; From = &Remote_ID; } HRESULT hRet = DP_OK; // while (hRet == DP_OK) { DWORD DataSize = OVERSIZE_PACKET_SIZE + PACKET_HEADER_SIZE; DPPACKET *Pack = (DPPACKET*) &BigPacket; hRet = g_pDP->Receive(From, &Local_ID, flags, Pack, &DataSize); if (hRet == DPERR_BUFFERTOOSMALL) { Pack = (DPPACKET*) malloc(DataSize); hRet = g_pDP->Receive(From, &Local_ID, flags, Pack, &DataSize); } if (hRet == DP_OK) { Last_Received_ID = *From; if (*From == Local_ID || *From == 0 || DataSize < PACKET_HEADER_SIZE) { _RPT0(_CRT_WARN, "Useless network packet, tossed out...\n"); // return 0; } switch (Pack->MessageType) { case PACKET_CONNECT: DP->HandlePacket(Pack, DataSize); break; case PACKET_DATA: case PACKET_ACK: case PACKET_CONNECT_ACK: InQueue.AddPackets(Pack, DataSize); do { ProcessPacket(); } while (InQueue.Count()); // && (backup_end - backup_start <= 0)); break; } } if (Pack != (DPPACKET*) &BigPacket) delete Pack; // } if (backup_end - backup_start > 0) { return backup_end - backup_start; } if (ConnectRequests) return 1; return 0; } /* --------------------------------------------------------------------------- ------------------------------------------------------------------------- /**/ int DP_socket::read_backup(void *&buf, int &size) // read previously buffered data { int s = backup_end - backup_start; if (s && size) { if (size >= s) { memcpy(buf, backup + backup_start, s); buf = (void*) ((uchar*) buf + s); backup_start = backup_end = 0; size -= s; return s; } else { memcpy(buf, backup + backup_start, size); buf = (void*) ((uchar*) + size); int ret = size; backup_start += size; size = 0; return ret; } } else return 0; } /* --------------------------------------------------------------------------- ------------------------------------------------------------------------- /**/ void DP_socket::add_backup(uchar *buf, int size) { if (size) { if (backup_size - backup_end >= size) { memcpy(backup + backup_end, buf, size); backup_end += size; } else { backup_size += backup_end + size - backup_size; backup = (uchar*) jrealloc(backup, backup_size, "backup buffer"); add_backup(buf, size); } } } /* --------------------------------------------------------------------------- ------------------------------------------------------------------------- /**/ DP_address *DP_socket::GetAddress() { DP_address *NewAddr = new DP_address; NewAddr->Local_ID = Local_ID; NewAddr->Remote_ID = Remote_Fast_Socket; NewAddr->Port = SocketPort; NewAddr->SessionGUID = GUID_NULL; return NewAddr; } /* --------------------------------------------------------------------------- ------------------------------------------------------------------------- /**/ net_socket *DP_socket::accept(net_address *&from) { if (ConnectRequests) { DP_socket *last = NULL, *ret = ConnectRequests; while (ret->NextConnect) { last = ret; ret = ret->NextConnect; } from = ret->GetAddress(); if (last) last->NextConnect = NULL; else ConnectRequests = NULL; return ret; } else return NULL; }