1 /*
2 * @file Socket.h
3 * @brief Abstract class to perform API global operations
4 *
5 * @author Mohamed Amine Mzoughi <mohamed-amine.mzoughi@laposte.net>
6 * @date 2017-02-10
7 */
8 
9 #ifndef INCLUDE_ASOCKET_H_
10 #define INCLUDE_ASOCKET_H_
11 
12 #if defined (_WIN32) && !defined (WINDOWS)
13 #define WINDOWS
14 #endif
15 
16 #include <cstdio>         // snprintf
17 #include <exception>
18 #include <functional>
19 #include <memory>
20 #include <stdarg.h>       // va_start, etc.
21 #include <stdexcept>
22 
23 #ifdef WINDOWS
24 #include <winsock2.h>
25 #include <ws2tcpip.h>
26 
27 // Need to link with Ws2_32.lib
28 #pragma comment(lib,"WS2_32.lib")
29 
30 #else
31 #include <arpa/inet.h>
32 #include <errno.h>
33 #include <netinet/in.h>
34 #include <netdb.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <string.h>
39 #include <sys/types.h>
40 #include <sys/socket.h>
41 #include <unistd.h>
42 #endif
43 
44 #include <limits>
45 #define ACCEPT_WAIT_INF_DELAY std::numeric_limits<size_t>::max()
46 
47 class ASocket
48 {
49 public:
50    // Public definitions
51    //typedef std::function<int(void*, double, double, double, double)> ProgressFnCallback;
52    typedef std::function<void(const std::string&)>                   LogFnCallback;
53 
54    // socket file descriptor id
55    #ifdef WINDOWS
56    typedef SOCKET Socket;
57    #else
58    typedef int Socket;
59    #define INVALID_SOCKET -1
60    #endif
61 
62    enum SettingsFlag
63    {
64       NO_FLAGS = 0x00,
65       ENABLE_LOG = 0x01,
66       ALL_FLAGS = 0xFF
67    };
68 
69    /* Please provide your logger thread-safe routine, otherwise, you can turn off
70    * error log messages printing by not using the flag ALL_FLAGS or ENABLE_LOG */
71    explicit ASocket(const LogFnCallback& oLogger,
72                     const SettingsFlag eSettings = ALL_FLAGS);
73    virtual ~ASocket() = 0;
74 
75    static int SelectSockets(const Socket* pSocketsToSelect, const size_t count,
76                             const size_t msec, size_t& selectedIndex);
77 
78    static int SelectSocket(const Socket sd, const size_t msec);
79 
80    static struct timeval TimevalFromMsec(unsigned int time_msec);
81 
82    // String Helpers
83    static std::string StringFormat(const std::string strFormat, ...);
84 
85 protected:
86    // Log printer callback
87    /*mutable*/const LogFnCallback         m_oLog;
88 
89    SettingsFlag         m_eSettingsFlags;
90 
91    #ifdef WINDOWS
92    static WSADATA s_wsaData;
93    #endif
94 
95 private:
96    friend class SocketGlobalInitializer;
97    class SocketGlobalInitializer {
98    public:
99       static SocketGlobalInitializer& instance();
100 
101       SocketGlobalInitializer(SocketGlobalInitializer const&) = delete;
102       SocketGlobalInitializer(SocketGlobalInitializer&&) = delete;
103 
104       SocketGlobalInitializer& operator=(SocketGlobalInitializer const&) = delete;
105       SocketGlobalInitializer& operator=(SocketGlobalInitializer&&) = delete;
106 
107       ~SocketGlobalInitializer();
108 
109    private:
110       SocketGlobalInitializer();
111    };
112    SocketGlobalInitializer& m_globalInitializer;
113 };
114 
115 class EResolveError : public std::logic_error
116 {
117 public:
EResolveError(const std::string & strMsg)118    explicit EResolveError(const std::string &strMsg) : std::logic_error(strMsg) {}
119 };
120 
121 #endif
122