1 /*
2  *      dxsocket.h
3  *
4  *      Copyright 2010 David Vachulka <arch_dvx@users.sourceforge.net>
5  *
6  *      This program is free software; you can redistribute it and/or modify
7  *      it under the terms of the GNU General Public License as published by
8  *      the Free Software Foundation; either version 2 of the License, or
9  *      (at your option) any later version.
10  *
11  *      This program is distributed in the hope that it will be useful,
12  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *      GNU General Public License for more details.
15  *
16  *      You should have received a copy of the GNU General Public License
17  *      along with this program; if not, write to the Free Software
18  *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  *      MA 02110-1301, USA.
20  */
21 
22 
23 #ifndef DXSOCKET_H
24 #define DXSOCKET_H
25 
26 #ifdef WIN32
27 #include <winsock2.h>
28 #include <sys/types.h>
29 #include <ws2tcpip.h>
30 #define dxErrno WSAGetLastError()
31 const char *dxStrError(int x);
32 #else
33 #include <sys/time.h>
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <sys/poll.h>
37 #include <netdb.h>
38 #include <netinet/in.h>
39 #include <unistd.h>
40 #include <signal.h>
41 #include <fcntl.h>
42 #include <errno.h>
43 #define dxErrno errno
44 #define dxStrError strerror
45 typedef int SOCKET;
46 #define INVALID_SOCKET (-1)
47 #endif //WIN32
48 
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52 
53 char *dx_inet_ntop(int af, const void *addr, char *buf, size_t size);
54 #ifdef HAVE_INET_NTOP
55 #ifdef HAVE_ARPA_INET_H
56 #include <arpa/inet.h>
57 #endif
58 #define dx_inet_ntop(af,addr,buf,size) inet_ntop(af,addr,buf,(socklen_t)size)
59 #endif
60 int dx_inet_pton(int, const char *, void *);
61 #ifdef HAVE_INET_PTON
62 #ifdef HAVE_ARPA_INET_H
63 #include <arpa/inet.h>
64 #endif
65 #define dx_inet_pton(x,y,z) inet_pton(x,y,z)
66 #endif
67 
68 #include <fx.h>
69 #include "dxmessagechannel.h"
70 
71 #ifdef HAVE_OPENSSL
72 #include <openssl/ssl.h>
73 #endif
74 
75 #define BUFFER_SIZE 32768
76 
77 enum {
78     SOCKET_CONNECTED = FX::SEL_LAST+3,
79     SOCKET_STARTACCEPT,
80     SOCKET_LISTEN,
81     SOCKET_DISCONNECTED,
82     SOCKET_CANREAD, //new data available
83     SOCKET_WRITTEN,
84     SOCKET_ERR
85 };
86 
87 enum SocketErrorType {
88     NONEERROR,
89     UNABLEINIT, // Unable to initiliaze socket on win
90     BADHOST,
91     UNABLECREATE, // Unable to create socket
92     UNABLECONNECT, // Unable to connect
93     SSLUNCREATE, // SSL creation error
94     SSLCONNECTERROR, // SSL connect error
95     UNABLEBIND, // Unable to bind socket
96     UNABLELISTEN, // Unable to listen
97     UNABLEACCEPT, // Unable to accept connection
98     UNABLESEND, // Unable to send data
99     SSLZERO, // SSL_read() returns zero
100     SSLUNABLEREAD, // SSL read problem,
101     SSLABNORMAL, // Abnormal value from SSL read
102     UNABLEREAD, // Error in reading data
103     UNABLEREADBUFFER, //Error in reading data from inner buffer
104     TIMEOUT, // Unable connect during given timeout
105 };
106 
107 struct SocketError {
108     SocketErrorType errorType;
109     FXString errorStr;
110 };
111 
112 class dxSocket;
113 
114 class dxConnectThread : public FXThread
115 {
116     public:
117         dxConnectThread(dxSocket *parent, FXApp *app);
118         virtual ~dxConnectThread();
119         FXMessageChannel m_feedback;
120 
setListen(FXbool listen)121         void setListen(FXbool listen) { m_listen = listen; }
122     protected:
123         FXint run();
124     private:
125         dxSocket *m_socket;
126         FXbool m_listen;
127 };
128 
129 class dxSocket: public FXObject
130 {
131     FXDECLARE(dxSocket)
132     friend class dxConnectThread;
133     public:
134         dxSocket(FXApp *app, FXObject *tgt=NULL, FXSelector sel=0, FXbool isSSL=FALSE);
135         virtual ~dxSocket();
136         enum {
137             ID_SOCKET = FXMainWindow::ID_LAST+1100,
138             ID_SSLTIME, //ssl on windows
139             ID_LAST
140         };
141 
142         void listenOn();
143         void connectTo();
144         FXint read(char *buffer, FXint len);
145         FXint write(const char *buffer, size_t len, FXbool directly=FALSE);
146         FXint writeLine(const FXString &line, FXbool directly=FALSE);
147         void startConnection();
148         void setHost(const FXString &address, FXint portD, FXint portH=0);
149         void disconnect();
isConnected()150         FXbool isConnected() const { return m_connected; }
isConnecting()151         FXbool isConnecting() const { return m_connecting; }
socketDescriptor()152         int socketDescriptor() const { return m_sockfd; }
153         FXString getLocalIP();
154         FXString getHostname(const FXString &ip);
155         FXString getIP(const FXString &hostname);
156         FXString getRemoteIP();
157         FXString stringIPToBinary(const FXString &ip);
158         FXString binaryIPToString(const FXString &ip);
159         FXbool isRoutableIP(FXuint ipaddr);
160         void setTarget(FXObject *tgt);
161         void setIsSSL(FXbool isSSL);
getHost()162         FXString getHost() { return m_address; }
getPort()163         FXint getPort() { return m_portD; }
getBytesAvailable()164         FXlong getBytesAvailable() { return m_readed; }
165         FXbool isIPv4(const FXString &address);
166 
167         long onIORead(FXObject*, FXSelector, void*);
168         long onIOWrite(FXObject*, FXSelector, void*);
169     protected:
dxSocket()170         dxSocket():m_target(NULL),m_message(0),m_application(NULL),m_connect(NULL),m_connected(FALSE)
171         ,m_isSsl(FALSE),m_connecting(FALSE),m_sockaddr(NULL),m_sockfd(-1)
172 #ifdef HAVE_OPENSSL
173         ,m_ctx(NULL),m_ssl(NULL),m_bio(NULL)
174 #endif
175         ,m_portD(0),m_portH(0),m_readBuffer(NULL),m_readed(0),m_writeBuffer(NULL),m_written(0)
176         {}
177         FXObject *m_target;
178         FXSelector m_message;
179 
180         FXint listenByThread();
181         FXint connectByThread();
182     private:
183         FXApp *m_application;
184         dxConnectThread *m_connect;
185         FXbool m_connected, m_isSsl, m_connecting;
186         #ifdef WIN32
187             WSAEVENT m_event;
188         #endif
189         sockaddr *m_sockaddr;
190         SOCKET m_sockfd;
191 #ifdef HAVE_OPENSSL
192         SSL_CTX *m_ctx;
193         SSL *m_ssl;
194         BIO *m_bio;
195 #endif
196         FXString m_address, m_localIP, m_remoteIP;
197         FXint m_portD, m_portH;
198         FXchar *m_readBuffer;
199         FXlong m_readed;
200         FXchar *m_writeBuffer;
201         FXlong m_written;
202 
203         void closeConnection();
204         FXbool setSSL();
205         FXint writeData();
206         FXint writeToSocket(const char *buffer, size_t len);
207         FXint readData();
208         void addWriteInput();
209         void setListenPort(sockaddr *ad);
210         FXString getIPString(const struct sockaddr *sa);
211         void shutdownSocket(SocketErrorType err);
212         FXbool setNonBlocking();
213 };
214 
215 #endif // DXSOCKET_H
216