123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- //
- // Created by Nathan Touroux on 29/06/2017.
- //
- #ifndef NETWORK_NETWORK_H
- #define NETWORK_NETWORK_H
- #ifdef WIN32
- #include <winsock2.h>
- typedef int socklen_t;
- #define errno WSAGetLastError()
- #else
- #include <netdb.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <unistd.h>
- #define INVALID_SOCKET -1
- #define SOCKET_ERROR -1
- #define closesocket(s) close (s)
- typedef int SOCKET;
- typedef struct sockaddr_in SOCKADDR_IN;
- typedef struct sockaddr SOCKADDR;
- #endif // WIN32
- #include <iostream>
- #include <vector>
- #include <unordered_map>
- #include <thread>
- #include <atomic>
- #include <mutex>
- #include <cstdlib>
- #include <string.h>
- #define size_data unsigned long
- struct Sock
- {
- SOCKADDR_IN sin;
- SOCKET sock = SOCKET_ERROR;
- socklen_t recsize = sizeof(sin);
- std::string IP = "";
- std::string name = "";
- int port = 0;
- };
- //*********************************************** TCP DATA ***********************************************
- struct NetPacket{//should be created by NetData, contains length next to the data in "data", "size" is sizeof(size_data)+length of data
- void* data;
- size_data size;
- };
- class NetData{
- private:
- void* data;
- size_data size;
- void copy(void* data, size_data size);
- public:
- template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value>::type> NetData(T data);
- NetData(std::string str);
- NetData(const char *str);
- NetData(void *data, size_data size, bool copyData = true);
- NetData(const NetData ©);
- NetData& operator=(const NetData ©);
- ~NetData();
- bool valid();
- template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value>::type> operator T();
- operator std::string();
- void* getData();
- size_data getSize();
- NetPacket toPacket();//return a packet (the data inside should be freed)
- };
- template<typename T, typename> NetData::NetData(T data): data(nullptr), size(sizeof(T)) {
- copy(&data, size);
- }
- template<typename T, typename> NetData::operator T() {
- if(!valid()) return T();
- auto tmp = data;
- copy(data, size);
- return *static_cast<T*>(tmp);
- }
- //*********************************************** TCP CLIENT ***********************************************
- class TCPServer;
- class TCPClient{
- private:
- Sock sock;
- TCPServer *server;
- struct Data{
- void* data;
- size_data size;
- Data* next;
- };
- Data *first, *last;
- int nbData;
- std::thread *asyncThread;
- std::atomic_bool asynchronous;
- std::atomic_bool connected;
- std::mutex mutex;
- bool invalid();
- long unsafeSend(NetData data);
- NetData unsafeReceive();
- static void asyncReceive(TCPClient *client);
- void push(void* data, size_data size);
- NetData pop();
- public:
- TCPClient(bool asynchronous = true);
- TCPClient(const TCPClient &client);//just copy the asynchronous value
- ~TCPClient();
- bool accept(TCPServer *server, bool receiveName = false);//if receive name is true, the server must send a string
- // (message doesn't import) to confirm that the name is accepted or else disconnect the client
- bool connect(std::string IP, int port, std::string name = "");//if a client is already connected with this name the
- // connection will fail
- void disconnect(bool removeFromServer = true);
- bool isConnected();
- void enableAsynchronous();
- //void disableAsynchronous();
- bool asynchronousEnabled();
- //WARNING: can't send/receive raw packet when asynchronous
- long rawSend(void *data, size_data sizeByte);
- long rawReceive(void *data, size_data sizeByte);
- long send(NetData data);
- NetData receive();//receive a packet with size next to the data so knowing the size isn't important
- std::string getIP() const;
- std::string getName() const;
- int getPort() const;
- int getNbData() const;
- };
- //*********************************************** TCP SERVEUR ***********************************************
- class TCPServer{
- private:
- #ifdef WIN32
- WSADATA m_WSAData;
- #endif
- Sock hsock;
- std::vector<TCPClient> clients;
- std::unordered_map<std::string, TCPClient*> clientsByIP;
- std::unordered_map<std::string, TCPClient*> clientsByName;
- std::thread *thread;
- int port;
- int error;
- std::atomic<int> nbConnections;
- std::atomic<int> nbConnected;
- bool useName;
- bool hosting;
- bool autoReconnect;
- unsigned int maxConnectionTry;
- static void waitHost(TCPServer *data);
- bool invalid(int client);//return true if there is a problem, false if everything is fine
- TCPClient empty;
- public:
- explicit TCPServer(int port, unsigned int nbConnections, bool useName = false, bool asynchronous = true);
- ~TCPServer();
- bool host(bool waitConnections = false, bool autoReconnect = true, unsigned int maxConnectionTry = -1);
- bool acceptHost();//must not be called directly, it is used by host() method
- TCPClient& operator[](int index);
- TCPClient& operator[](std::string IP);
- TCPClient& operator()(std::string name);
- TCPClient& unavailable();//use this to compare against a client (ex: server[2] != server.unavailable())
- void eraseClient(TCPClient &client);
- std::vector<std::string> IPList();
- std::vector<std::string> namesList();
- Sock getHostSock() const;
- int getNbConnected() const;
- };
- //*********************************************** UDP ***********************************************
- class UDP{
- private:
- std::string IP;
- int port;
- Sock sock;
- sockaddr from;
- socklen_t fromaddrsize;
- public:
- UDP(std::string IP, int port);// use "" for IP to receive from any IP
- ~UDP();
- bool init();
- long rawSend(void *data, size_data sizeByte);
- long rawReceive(void *data, size_data sizeByte);
- long send(NetData data);
- NetData receive();//receive a packet with size next to the data so knowing the size isn't important
- int getPort();
- std::string getIP();
- //************************************ STATIC ************************************
- static long rawSendTo(std::string IP, int port, void *data, size_data sizeByte);
- static long sendTo(std::string IP, int port, NetData data);
- static long rawReceiveFrom(std::string IP, int port, void *data, size_data sizeByte);
- static long rawReceiveFrom(int port, void *data, size_data sizeByte);//TODO add possibility to know from wich ip it comes from
- static NetData receiveFrom(std::string IP, int port);
- static NetData receiveFrom(int port);
- };
- #endif //NETWORK_NETWORK_H
|