]>
Commit | Line | Data |
---|---|---|
1 | /* ------------------------------------------------------------------------- | |
2 | * Project: GSocket (Generic Socket) for WX | |
3 | * Name: gsockunx.h | |
4 | * Copyright: (c) Guilhem Lavaux | |
5 | * Licence: wxWindows Licence | |
6 | * Purpose: GSocket Unix header | |
7 | * CVSID: $Id$ | |
8 | * ------------------------------------------------------------------------- | |
9 | */ | |
10 | ||
11 | #ifndef _WX_UNIX_GSOCKUNX_H_ | |
12 | #define _WX_UNIX_GSOCKUNX_H_ | |
13 | ||
14 | class wxGSocketIOHandler; | |
15 | ||
16 | class GSocket | |
17 | { | |
18 | public: | |
19 | GSocket(); | |
20 | virtual ~GSocket(); | |
21 | bool IsOk() { return m_ok; } | |
22 | void Close(); | |
23 | void Shutdown(); | |
24 | GSocketError SetLocal(GAddress *address); | |
25 | GSocketError SetPeer(GAddress *address); | |
26 | GAddress *GetLocal(); | |
27 | GAddress *GetPeer(); | |
28 | GSocketError SetServer(); | |
29 | GSocket *WaitConnection(); | |
30 | bool SetReusable(); | |
31 | bool SetBroadcast(); | |
32 | bool DontDoBind(); | |
33 | GSocketError Connect(GSocketStream stream); | |
34 | GSocketError SetNonOriented(); | |
35 | int Read(char *buffer, int size); | |
36 | int Write(const char *buffer, int size); | |
37 | GSocketEventFlags Select(GSocketEventFlags flags); | |
38 | void SetNonBlocking(bool non_block); | |
39 | void SetTimeout(unsigned long millisec); | |
40 | GSocketError WXDLLIMPEXP_NET GetError(); | |
41 | void SetCallback(GSocketEventFlags flags, | |
42 | GSocketCallback callback, char *cdata); | |
43 | void UnsetCallback(GSocketEventFlags flags); | |
44 | GSocketError GetSockOpt(int level, int optname, void *optval, int *optlen); | |
45 | GSocketError SetSockOpt(int level, int optname, | |
46 | const void *optval, int optlen); | |
47 | //attach or detach from main loop | |
48 | void Notify(bool flag); | |
49 | virtual void Detected_Read(); | |
50 | virtual void Detected_Write(); | |
51 | void SetInitialSocketBuffers(int recv, int send) | |
52 | { | |
53 | m_initialRecvBufferSize = recv; | |
54 | m_initialSendBufferSize = send; | |
55 | } | |
56 | ||
57 | protected: | |
58 | //enable or disable event callback using gsocket gui callback table | |
59 | void EnableEvents(bool flag = true); | |
60 | void DisableEvents() { EnableEvents(false); } | |
61 | void Enable(GSocketEvent event); | |
62 | void Disable(GSocketEvent event); | |
63 | GSocketError Input_Timeout(); | |
64 | GSocketError Output_Timeout(); | |
65 | int Recv_Stream(char *buffer, int size); | |
66 | int Recv_Dgram(char *buffer, int size); | |
67 | int Send_Stream(const char *buffer, int size); | |
68 | int Send_Dgram(const char *buffer, int size); | |
69 | bool m_ok; | |
70 | int m_initialRecvBufferSize; | |
71 | int m_initialSendBufferSize; | |
72 | public: | |
73 | /* DFE: We can't protect these data member until the GUI code is updated */ | |
74 | /* protected: */ | |
75 | int m_fd; | |
76 | wxGSocketIOHandler *m_handler; | |
77 | GAddress *m_local; | |
78 | GAddress *m_peer; | |
79 | GSocketError m_error; | |
80 | ||
81 | bool m_non_blocking; | |
82 | bool m_server; | |
83 | bool m_stream; | |
84 | bool m_establishing; | |
85 | bool m_reusable; | |
86 | bool m_broadcast; | |
87 | bool m_dobind; | |
88 | unsigned long m_timeout; | |
89 | ||
90 | // true if socket should fire events | |
91 | bool m_use_events; | |
92 | ||
93 | /* Callbacks */ | |
94 | GSocketEventFlags m_detected; | |
95 | GSocketCallback m_cbacks[GSOCK_MAX_EVENT]; | |
96 | char *m_data[GSOCK_MAX_EVENT]; | |
97 | ||
98 | // pointer for storing extra (usually GUI-specific) data | |
99 | void *m_gui_dependent; | |
100 | }; | |
101 | ||
102 | /* Definition of GAddress */ | |
103 | struct _GAddress | |
104 | { | |
105 | struct sockaddr *m_addr; | |
106 | size_t m_len; | |
107 | ||
108 | GAddressType m_family; | |
109 | int m_realfamily; | |
110 | ||
111 | GSocketError m_error; | |
112 | }; | |
113 | ||
114 | /* GAddress */ | |
115 | ||
116 | GSocketError _GAddress_translate_from(GAddress *address, | |
117 | struct sockaddr *addr, int len); | |
118 | GSocketError _GAddress_translate_to (GAddress *address, | |
119 | struct sockaddr **addr, int *len); | |
120 | GSocketError _GAddress_Init_INET(GAddress *address); | |
121 | GSocketError _GAddress_Init_UNIX(GAddress *address); | |
122 | ||
123 | // A version of GSocketManager which uses FDs for socket IO | |
124 | // | |
125 | // This class uses GSocket::m_gui_dependent field to store the 2 (for input and | |
126 | // output) FDs associated with the socket. | |
127 | class GSocketFDBasedManager : public GSocketManager | |
128 | { | |
129 | public: | |
130 | // no special initialization/cleanup needed when using FDs | |
131 | virtual bool OnInit() { return true; } | |
132 | virtual void OnExit() { } | |
133 | ||
134 | // allocate/free the storage we need | |
135 | virtual bool Init_Socket(GSocket *socket) | |
136 | { | |
137 | socket->m_gui_dependent = malloc(sizeof(int)*2); | |
138 | int * const fds = wx_static_cast(int *, socket->m_gui_dependent); | |
139 | ||
140 | fds[0] = -1; | |
141 | fds[1] = -1; | |
142 | ||
143 | return true; | |
144 | } | |
145 | virtual void Destroy_Socket(GSocket *socket) | |
146 | { | |
147 | free(socket->m_gui_dependent); | |
148 | } | |
149 | ||
150 | virtual void Enable_Events(GSocket *socket) | |
151 | { | |
152 | Install_Callback(socket, GSOCK_INPUT); | |
153 | Install_Callback(socket, GSOCK_OUTPUT); | |
154 | } | |
155 | virtual void Disable_Events(GSocket *socket) | |
156 | { | |
157 | Uninstall_Callback(socket, GSOCK_INPUT); | |
158 | Uninstall_Callback(socket, GSOCK_OUTPUT); | |
159 | } | |
160 | ||
161 | protected: | |
162 | // identifies either input or output direction | |
163 | // | |
164 | // NB: the values of this enum shouldn't change | |
165 | enum SocketDir | |
166 | { | |
167 | FD_INPUT, | |
168 | FD_OUTPUT | |
169 | }; | |
170 | ||
171 | // get the FD index corresponding to the given GSocketEvent | |
172 | SocketDir GetDirForEvent(GSocket *socket, GSocketEvent event) | |
173 | { | |
174 | switch ( event ) | |
175 | { | |
176 | default: | |
177 | wxFAIL_MSG( "unexpected socket event" ); | |
178 | // fall through | |
179 | ||
180 | case GSOCK_LOST: | |
181 | // fall through | |
182 | ||
183 | case GSOCK_INPUT: | |
184 | return FD_INPUT; | |
185 | ||
186 | case GSOCK_OUTPUT: | |
187 | return FD_OUTPUT; | |
188 | ||
189 | case GSOCK_CONNECTION: | |
190 | // FIXME: explain this? | |
191 | return socket->m_server ? FD_INPUT : FD_OUTPUT; | |
192 | } | |
193 | } | |
194 | ||
195 | // access the FDs we store | |
196 | int& FD(GSocket *socket, SocketDir d) | |
197 | { | |
198 | return wx_static_cast(int *, socket->m_gui_dependent)[d]; | |
199 | } | |
200 | }; | |
201 | ||
202 | // Common base class for all ports using X11-like (and hence implemented in | |
203 | // X11, Motif and GTK) AddInput() and RemoveInput() functions | |
204 | class GSocketInputBasedManager : public GSocketFDBasedManager | |
205 | { | |
206 | public: | |
207 | virtual void Install_Callback(GSocket *socket, GSocketEvent event) | |
208 | { | |
209 | wxCHECK_RET( socket->m_fd != -1, | |
210 | "shouldn't be called on invalid socket" ); | |
211 | ||
212 | const SocketDir d = GetDirForEvent(socket, event); | |
213 | ||
214 | int& fd = FD(socket, d); | |
215 | if ( fd != -1 ) | |
216 | RemoveInput(fd); | |
217 | ||
218 | fd = AddInput(socket, d); | |
219 | } | |
220 | ||
221 | virtual void Uninstall_Callback(GSocket *socket, GSocketEvent event) | |
222 | { | |
223 | const SocketDir d = GetDirForEvent(socket, event); | |
224 | ||
225 | int& fd = FD(socket, d); | |
226 | if ( fd != -1 ) | |
227 | { | |
228 | RemoveInput(fd); | |
229 | fd = -1; | |
230 | } | |
231 | } | |
232 | ||
233 | private: | |
234 | // these functions map directly to XtAdd/RemoveInput() or | |
235 | // gdk_input_add/remove() | |
236 | virtual int AddInput(GSocket *socket, SocketDir d) = 0; | |
237 | virtual void RemoveInput(int fd) = 0; | |
238 | }; | |
239 | ||
240 | #endif /* _WX_UNIX_GSOCKUNX_H_ */ |