]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/connection.h
Add minetest.get_mapgen_object to API
[dragonfireclient.git] / src / connection.h
index 6eb2f2824642cc86661fd4c788e5c090d515e366..f5cddcbf4d7b74158e06722a471b1014cb489872 100644 (file)
@@ -1,18 +1,18 @@
 /*
-Minetest-c55
-Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
 
 This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
+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 General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License along
+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.
 */
@@ -20,14 +20,17 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef CONNECTION_HEADER
 #define CONNECTION_HEADER
 
-#include <iostream>
-#include <fstream>
-#include "debug.h"
-#include "common_irrlicht.h"
+#include "irrlichttypes_bloated.h"
 #include "socket.h"
-#include "utility.h"
 #include "exceptions.h"
 #include "constants.h"
+#include "util/pointer.h"
+#include "util/container.h"
+#include "util/thread.h"
+#include <iostream>
+#include <fstream>
+#include <list>
+#include <map>
 
 namespace con
 {
@@ -59,6 +62,14 @@ class ConnectionException : public BaseException
        {}
 };
 
+class ConnectionBindFailed : public BaseException
+{
+public:
+       ConnectionBindFailed(const char *s):
+               BaseException(s)
+       {}
+};
+
 /*class ThrottlingException : public BaseException
 {
 public:
@@ -99,15 +110,6 @@ class ProcessedSilentlyException : public BaseException
        {}
 };
 
-inline u16 readPeerId(u8 *packetdata)
-{
-       return readU16(&packetdata[4]);
-}
-inline u8 readChannel(u8 *packetdata)
-{
-       return readU8(&packetdata[6]);
-}
-
 #define SEQNUM_MAX 65535
 inline bool seqnum_higher(u16 higher, u16 lower)
 {
@@ -142,14 +144,14 @@ SharedBuffer<u8> makeOriginalPacket(
                SharedBuffer<u8> data);
 
 // Split data in chunks and add TYPE_SPLIT headers to them
-core::list<SharedBuffer<u8> > makeSplitPacket(
+std::list<SharedBuffer<u8> > makeSplitPacket(
                SharedBuffer<u8> data,
                u32 chunksize_max,
                u16 seqnum);
 
 // Depending on size, make a TYPE_ORIGINAL or TYPE_SPLIT packet
 // Increments split_seqnum if a split packet is made
-core::list<SharedBuffer<u8> > makeAutoSplitPacket(
+std::list<SharedBuffer<u8> > makeAutoSplitPacket(
                SharedBuffer<u8> data,
                u32 chunksize_max,
                u16 &split_seqnum);
@@ -167,7 +169,7 @@ struct IncomingSplitPacket
                reliable = false;
        }
        // Key is chunk number, value is data without headers
-       core::map<u16, SharedBuffer<u8> > chunks;
+       std::map<u16, SharedBuffer<u8> > chunks;
        u32 chunk_count;
        float time; // Seconds from adding
        bool reliable; // If true, isn't deleted on timeout
@@ -268,12 +270,12 @@ with a buffer in the receiving and transmitting end.
        for fast access to the smallest one.
 */
 
-typedef core::list<BufferedPacket>::Iterator RPBSearchResult;
+typedef std::list<BufferedPacket>::iterator RPBSearchResult;
 
 class ReliablePacketBuffer
 {
 public:
-       
+       ReliablePacketBuffer();
        void print();
        bool empty();
        u32 size();
@@ -286,10 +288,11 @@ class ReliablePacketBuffer
        void incrementTimeouts(float dtime);
        void resetTimedOuts(float timeout);
        bool anyTotaltimeReached(float timeout);
-       core::list<BufferedPacket> getTimedOuts(float timeout);
+       std::list<BufferedPacket> getTimedOuts(float timeout);
 
 private:
-       core::list<BufferedPacket> m_list;
+       std::list<BufferedPacket> m_list;
+       u16 m_list_size;
 };
 
 /*
@@ -310,7 +313,7 @@ class IncomingSplitBuffer
        
 private:
        // Key is seqnum
-       core::map<u16, IncomingSplitPacket*> m_buf;
+       std::map<u16, IncomingSplitPacket*> m_buf;
 };
 
 class Connection;
@@ -319,28 +322,6 @@ struct Channel
 {
        Channel();
        ~Channel();
-       /*
-               Processes a packet with the basic header stripped out.
-               Parameters:
-                       packetdata: Data in packet (with no base headers)
-                       con: The connection to which the channel is associated
-                            (used for sending back stuff (ACKs))
-                       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<u8> ProcessPacket(
-                       SharedBuffer<u8> packetdata,
-                       Connection *con,
-                       u16 peer_id,
-                       u8 channelnum,
-                       bool reliable=false);
-       
-       // Returns next data from a buffer if possible
-       // throws a NoIncomingDataException if no data is available
-       // If found, sets peer_id
-       SharedBuffer<u8> CheckIncomingBuffers(Connection *con,
-                       u16 &peer_id);
 
        u16 next_outgoing_seqnum;
        u16 next_incoming_seqnum;
@@ -412,78 +393,248 @@ class Peer
        // with the id we have given to it
        bool has_sent_with_id;
        
+       float m_sendtime_accu;
+       float m_max_packets_per_second;
+       int m_num_sent;
+       int m_max_num_sent;
+
+       // Updated from configuration by Connection
+       float congestion_control_aim_rtt;
+       float congestion_control_max_rate;
+       float congestion_control_min_rate;
 private:
 };
 
-class Connection
+/*
+       Connection
+*/
+
+struct OutgoingPacket
+{
+       u16 peer_id;
+       u8 channelnum;
+       SharedBuffer<u8> data;
+       bool reliable;
+
+       OutgoingPacket(u16 peer_id_, u8 channelnum_, SharedBuffer<u8> data_,
+                       bool reliable_):
+               peer_id(peer_id_),
+               channelnum(channelnum_),
+               data(data_),
+               reliable(reliable_)
+       {
+       }
+};
+
+enum ConnectionEventType{
+       CONNEVENT_NONE,
+       CONNEVENT_DATA_RECEIVED,
+       CONNEVENT_PEER_ADDED,
+       CONNEVENT_PEER_REMOVED,
+       CONNEVENT_BIND_FAILED,
+};
+
+struct ConnectionEvent
+{
+       enum ConnectionEventType type;
+       u16 peer_id;
+       Buffer<u8> data;
+       bool timeout;
+       Address address;
+
+       ConnectionEvent(): type(CONNEVENT_NONE) {}
+
+       std::string describe()
+       {
+               switch(type){
+               case CONNEVENT_NONE:
+                       return "CONNEVENT_NONE";
+               case CONNEVENT_DATA_RECEIVED:
+                       return "CONNEVENT_DATA_RECEIVED";
+               case CONNEVENT_PEER_ADDED: 
+                       return "CONNEVENT_PEER_ADDED";
+               case CONNEVENT_PEER_REMOVED: 
+                       return "CONNEVENT_PEER_REMOVED";
+               case CONNEVENT_BIND_FAILED: 
+                       return "CONNEVENT_BIND_FAILED";
+               }
+               return "Invalid ConnectionEvent";
+       }
+       
+       void dataReceived(u16 peer_id_, SharedBuffer<u8> data_)
+       {
+               type = CONNEVENT_DATA_RECEIVED;
+               peer_id = peer_id_;
+               data = data_;
+       }
+       void peerAdded(u16 peer_id_, Address address_)
+       {
+               type = CONNEVENT_PEER_ADDED;
+               peer_id = peer_id_;
+               address = address_;
+       }
+       void peerRemoved(u16 peer_id_, bool timeout_, Address address_)
+       {
+               type = CONNEVENT_PEER_REMOVED;
+               peer_id = peer_id_;
+               timeout = timeout_;
+               address = address_;
+       }
+       void bindFailed()
+       {
+               type = CONNEVENT_BIND_FAILED;
+       }
+};
+
+enum ConnectionCommandType{
+       CONNCMD_NONE,
+       CONNCMD_SERVE,
+       CONNCMD_CONNECT,
+       CONNCMD_DISCONNECT,
+       CONNCMD_SEND,
+       CONNCMD_SEND_TO_ALL,
+       CONNCMD_DELETE_PEER,
+};
+
+struct ConnectionCommand
+{
+       enum ConnectionCommandType type;
+       u16 port;
+       Address address;
+       u16 peer_id;
+       u8 channelnum;
+       Buffer<u8> data;
+       bool reliable;
+       
+       ConnectionCommand(): type(CONNCMD_NONE) {}
+
+       void serve(u16 port_)
+       {
+               type = CONNCMD_SERVE;
+               port = port_;
+       }
+       void connect(Address address_)
+       {
+               type = CONNCMD_CONNECT;
+               address = address_;
+       }
+       void disconnect()
+       {
+               type = CONNCMD_DISCONNECT;
+       }
+       void send(u16 peer_id_, u8 channelnum_,
+                       SharedBuffer<u8> data_, bool reliable_)
+       {
+               type = CONNCMD_SEND;
+               peer_id = peer_id_;
+               channelnum = channelnum_;
+               data = data_;
+               reliable = reliable_;
+       }
+       void sendToAll(u8 channelnum_, SharedBuffer<u8> data_, bool reliable_)
+       {
+               type = CONNCMD_SEND_TO_ALL;
+               channelnum = channelnum_;
+               data = data_;
+               reliable = reliable_;
+       }
+       void deletePeer(u16 peer_id_)
+       {
+               type = CONNCMD_DELETE_PEER;
+               peer_id = peer_id_;
+       }
+};
+
+class Connection: public SimpleThread
 {
 public:
-       Connection(
-               u32 protocol_id,
-               u32 max_packet_size,
-               float timeout,
-               PeerHandler *peerhandler
-       );
+       Connection(u32 protocol_id, u32 max_packet_size, float timeout, bool ipv6);
+       Connection(u32 protocol_id, u32 max_packet_size, float timeout, bool ipv6,
+                       PeerHandler *peerhandler);
        ~Connection();
-       void setTimeoutMs(int timeout){ m_socket.setTimeoutMs(timeout); }
-       // Start being a server
+       void * Thread();
+
+       /* Interface */
+
+       ConnectionEvent getEvent();
+       ConnectionEvent waitEvent(u32 timeout_ms);
+       void putCommand(ConnectionCommand &c);
+       
+       void SetTimeoutMs(int timeout){ m_bc_receive_timeout = timeout; }
        void Serve(unsigned short port);
-       // Connect to a server
        void Connect(Address address);
        bool Connected();
-
        void Disconnect();
-
-       // Sets peer_id
-       SharedBuffer<u8> GetFromBuffers(u16 &peer_id);
-
-       // The peer_id of sender is stored in peer_id
-       // Return value: I guess this always throws an exception or
-       //               actually gets data
-       // May call PeerHandler methods
-       u32 Receive(u16 &peer_id, u8 *data, u32 datasize);
-       
-       // These will automatically package the data as an original or split
+       u32 Receive(u16 &peer_id, SharedBuffer<u8> &data);
        void SendToAll(u8 channelnum, SharedBuffer<u8> data, bool reliable);
        void Send(u16 peer_id, u8 channelnum, SharedBuffer<u8> data, bool reliable);
-       // Send data as a packet; it will be wrapped in base header and
-       // optionally to a reliable packet.
-       void SendAsPacket(u16 peer_id, u8 channelnum,
+       void RunTimeouts(float dtime); // dummy
+       u16 GetPeerID(){ return m_peer_id; }
+       Address GetPeerAddress(u16 peer_id);
+       float GetPeerAvgRTT(u16 peer_id);
+       void DeletePeer(u16 peer_id);
+       
+private:
+       void putEvent(ConnectionEvent &e);
+       void processCommand(ConnectionCommand &c);
+       void send(float dtime);
+       void receive();
+       void runTimeouts(float dtime);
+       void serve(u16 port);
+       void connect(Address address);
+       void disconnect();
+       void sendToAll(u8 channelnum, SharedBuffer<u8> data, bool reliable);
+       void send(u16 peer_id, u8 channelnum, SharedBuffer<u8> data, bool reliable);
+       void sendAsPacket(u16 peer_id, u8 channelnum,
+                       SharedBuffer<u8> data, bool reliable);
+       void rawSendAsPacket(u16 peer_id, u8 channelnum,
                        SharedBuffer<u8> data, bool reliable);
-       // Sends a raw packet
-       void RawSend(const BufferedPacket &packet);
+       void rawSend(const BufferedPacket &packet);
+       Peer* getPeer(u16 peer_id);
+       Peer* getPeerNoEx(u16 peer_id);
+       std::list<Peer*> getPeers();
+       bool getFromBuffers(u16 &peer_id, SharedBuffer<u8> &dst);
+       // Returns next data from a buffer if possible
+       // If found, returns true; if not, false.
+       // If found, sets peer_id and dst
+       bool checkIncomingBuffers(Channel *channel, u16 &peer_id,
+                       SharedBuffer<u8> &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<u8> processPacket(Channel *channel,
+                       SharedBuffer<u8> packetdata, u16 peer_id,
+                       u8 channelnum, bool reliable);
+       bool deletePeer(u16 peer_id, bool timeout);
        
-       // May call PeerHandler methods
-       void RunTimeouts(float dtime);
-
-       // Can throw a PeerNotFoundException
-       Peer* GetPeer(u16 peer_id);
-       // returns NULL if failed
-       Peer* GetPeerNoEx(u16 peer_id);
-       core::list<Peer*> GetPeers();
+       Queue<OutgoingPacket> m_outgoing_queue;
+       MutexedQueue<ConnectionEvent> m_event_queue;
+       MutexedQueue<ConnectionCommand> m_command_queue;
        
-       // Calls PeerHandler::deletingPeer
-       // Returns false if peer was not found
-       bool deletePeer(u16 peer_id, bool timeout);
+       u32 m_protocol_id;
+       u32 m_max_packet_size;
+       float m_timeout;
+       UDPSocket m_socket;
+       u16 m_peer_id;
+       
+       std::map<u16, Peer*> m_peers;
+       JMutex m_peers_mutex;
 
+       // Backwards compatibility
+       PeerHandler *m_bc_peerhandler;
+       int m_bc_receive_timeout;
+       
        void SetPeerID(u16 id){ m_peer_id = id; }
-       u16 GetPeerID(){ return m_peer_id; }
        u32 GetProtocolID(){ return m_protocol_id; }
-
-       // For debug printing
        void PrintInfo(std::ostream &out);
        void PrintInfo();
+       std::string getDesc();
        u16 m_indentation;
-
-private:
-       u32 m_protocol_id;
-       float m_timeout;
-       PeerHandler *m_peerhandler;
-       core::map<u16, Peer*> m_peers;
-       u16 m_peer_id;
-       //bool m_waiting_new_peer_id;
-       u32 m_max_packet_size;
-       UDPSocket m_socket;
 };
 
 } // namespace