/* Minetest Copyright (C) 2013-2017 celeron55, Perttu Ahola Copyright (C) 2017 celeron55, Loic Blot This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #pragma once #include #include "threading/thread.h" #include "connection.h" namespace con { class Connection; class ConnectionSendThread : public Thread { public: friend class UDPPeer; ConnectionSendThread(unsigned int max_packet_size, float timeout); void *run(); void Trigger(); void setParent(Connection *parent) { assert(parent != NULL); // Pre-condition m_connection = parent; } void setPeerTimeout(float peer_timeout) { m_timeout = peer_timeout; } private: void runTimeouts(float dtime); void rawSend(const BufferedPacket &packet); bool rawSendAsPacket(session_t peer_id, u8 channelnum, const SharedBuffer &data, bool reliable); void processReliableCommand(ConnectionCommand &c); void processNonReliableCommand(ConnectionCommand &c); void serve(Address bind_address); void connect(Address address); void disconnect(); void disconnect_peer(session_t peer_id); void send(session_t peer_id, u8 channelnum, const SharedBuffer &data); void sendReliable(ConnectionCommand &c); void sendToAll(u8 channelnum, const SharedBuffer &data); void sendToAllReliable(ConnectionCommand &c); void sendPackets(float dtime); void sendAsPacket(session_t peer_id, u8 channelnum, const SharedBuffer &data, bool ack = false); void sendAsPacketReliable(BufferedPacket &p, Channel *channel); bool packetsQueued(); Connection *m_connection = nullptr; unsigned int m_max_packet_size; float m_timeout; std::queue m_outgoing_queue; Semaphore m_send_sleep_semaphore; unsigned int m_iteration_packets_avaialble; unsigned int m_max_commands_per_iteration = 1; unsigned int m_max_data_packets_per_iteration; unsigned int m_max_packets_requeued = 256; }; class ConnectionReceiveThread : public Thread { public: ConnectionReceiveThread(unsigned int max_packet_size); void *run(); void setParent(Connection *parent) { assert(parent); // Pre-condition m_connection = parent; } private: void receive(SharedBuffer &packetdata, bool &packet_queued); // Returns next data from a buffer if possible // If found, returns true; if not, false. // If found, sets peer_id and dst bool getFromBuffers(session_t &peer_id, SharedBuffer &dst); bool checkIncomingBuffers( Channel *channel, session_t &peer_id, SharedBuffer &dst); /* Processes a packet with the basic header stripped out. Parameters: packetdata: Data in packet (with no base headers) peer_id: peer id of the sender of the packet in question channelnum: channel on which the packet was sent reliable: true if recursing into a reliable packet */ SharedBuffer processPacket(Channel *channel, const SharedBuffer &packetdata, session_t peer_id, u8 channelnum, bool reliable); SharedBuffer handlePacketType_Control(Channel *channel, const SharedBuffer &packetdata, Peer *peer, u8 channelnum, bool reliable); SharedBuffer handlePacketType_Original(Channel *channel, const SharedBuffer &packetdata, Peer *peer, u8 channelnum, bool reliable); SharedBuffer handlePacketType_Split(Channel *channel, const SharedBuffer &packetdata, Peer *peer, u8 channelnum, bool reliable); SharedBuffer handlePacketType_Reliable(Channel *channel, const SharedBuffer &packetdata, Peer *peer, u8 channelnum, bool reliable); struct PacketTypeHandler { SharedBuffer (ConnectionReceiveThread::*handler)(Channel *channel, const SharedBuffer &packet, Peer *peer, u8 channelnum, bool reliable); }; static const PacketTypeHandler packetTypeRouter[PACKET_TYPE_MAX]; Connection *m_connection = nullptr; }; }