]>
Commit | Line | Data |
---|---|---|
c9bccf23 | 1 | /////////////////////////////////////////////////////////////////////////////// |
80fdcdb9 | 2 | // Name: wx/private/sckaddr.h |
c9bccf23 VZ |
3 | // Purpose: wxSockAddressImpl |
4 | // Author: Vadim Zeitlin | |
5 | // Created: 2008-12-28 | |
c9bccf23 VZ |
6 | // Copyright: (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org> |
7 | // Licence: wxWindows licence | |
8 | /////////////////////////////////////////////////////////////////////////////// | |
9 | ||
10 | #ifndef _WX_PRIVATE_SOCKADDR_H_ | |
11 | #define _WX_PRIVATE_SOCKADDR_H_ | |
12 | ||
d98a58c5 | 13 | #ifdef __WINDOWS__ |
c9bccf23 | 14 | #include "wx/msw/wrapwin.h" |
67badd57 VZ |
15 | |
16 | #if wxUSE_IPV6 | |
17 | #include <ws2tcpip.h> | |
18 | #endif | |
c9bccf23 VZ |
19 | #elif defined(__VMS__) |
20 | #include <socket.h> | |
21 | ||
22 | struct sockaddr_un | |
23 | { | |
24 | u_char sun_len; /* sockaddr len including null */ | |
25 | u_char sun_family; /* AF_UNIX */ | |
26 | char sun_path[108]; /* path name (gag) */ | |
27 | }; | |
4d8988f7 | 28 | #include <in.h> |
c9bccf23 VZ |
29 | #else // generic Unix |
30 | #include <sys/types.h> | |
31 | #include <sys/socket.h> | |
32 | #include <netinet/in.h> | |
33 | #include <sys/un.h> | |
34 | #endif // platform | |
35 | ||
36 | #include <stdlib.h> // for calloc() | |
37 | ||
38 | // this is a wrapper for sockaddr_storage if it's available or just sockaddr | |
39 | // otherwise | |
40 | union wxSockAddressStorage | |
41 | { | |
42 | #if wxUSE_IPV6 | |
43 | sockaddr_storage addr_storage; | |
44 | #endif | |
45 | sockaddr addr; | |
46 | }; | |
47 | ||
48 | // ---------------------------------------------------------------------------- | |
49 | // helpers for wxSockAddressImpl | |
50 | // ---------------------------------------------------------------------------- | |
51 | ||
52 | // helper class mapping sockaddr_xxx types to corresponding AF_XXX values | |
53 | // | |
54 | // FIXME-VC6: we could leave the template undefined if not for VC6 which | |
55 | // absolutely does need to have a generic version defining the | |
56 | // template "interface" to compile the code below | |
57 | template <class T> struct AddressFamily { enum { value = AF_UNSPEC }; }; | |
58 | ||
59 | template <> struct AddressFamily<sockaddr_in> { enum { value = AF_INET }; }; | |
60 | ||
61 | #if wxUSE_IPV6 | |
62 | template <> struct AddressFamily<sockaddr_in6> { enum { value = AF_INET6 }; }; | |
63 | #endif // wxUSE_IPV6 | |
64 | ||
65 | #ifdef wxHAS_UNIX_DOMAIN_SOCKETS | |
66 | template <> struct AddressFamily<sockaddr_un> { enum { value = AF_UNIX }; }; | |
67 | #endif // wxHAS_UNIX_DOMAIN_SOCKETS | |
68 | ||
69 | // ---------------------------------------------------------------------------- | |
70 | // wxSockAddressImpl | |
71 | // ---------------------------------------------------------------------------- | |
72 | ||
73 | // Represents a socket endpoint, e.g. an (address, port) pair for PF_INET | |
74 | // sockets. It can be initialized from an existing sockaddr struct and also | |
75 | // provides access to sockaddr stored internally so that it can be easily used | |
76 | // with e.g. connect(2). | |
77 | // | |
78 | // This class also performs (synchronous, hence potentially long) name lookups | |
79 | // if necessary, i.e. if the host name strings don't contain addresses in | |
80 | // numerical form (quad dotted for IPv4 or standard hexadecimal for IPv6). | |
81 | // Notice that internally the potentially Unicode host names are encoded as | |
82 | // UTF-8 before being passed to the lookup function but the host names should | |
83 | // really be ASCII anyhow. | |
84 | class wxSockAddressImpl | |
85 | { | |
86 | public: | |
87 | // as this is passed to socket() it should be a PF_XXX and not AF_XXX (even | |
88 | // though they're the same in practice) | |
89 | enum Family | |
90 | { | |
91 | FAMILY_INET = PF_INET, | |
92 | #if wxUSE_IPV6 | |
93 | FAMILY_INET6 = PF_INET6, | |
94 | #endif | |
95 | #ifdef wxHAS_UNIX_DOMAIN_SOCKETS | |
96 | FAMILY_UNIX = PF_UNIX, | |
97 | #endif | |
98 | FAMILY_UNSPEC = PF_UNSPEC | |
99 | }; | |
100 | ||
101 | // default ctor creates uninitialized object, use one of CreateXXX() below | |
102 | wxSockAddressImpl() | |
103 | { | |
104 | InitUnspec(); | |
105 | } | |
106 | ||
107 | // ctor from an existing sockaddr | |
108 | wxSockAddressImpl(const sockaddr& addr, int len) | |
109 | { | |
110 | switch ( addr.sa_family ) | |
111 | { | |
112 | case PF_INET: | |
113 | #if wxUSE_IPV6 | |
114 | case PF_INET6: | |
115 | #endif | |
116 | #ifdef wxHAS_UNIX_DOMAIN_SOCKETS | |
117 | case PF_UNIX: | |
118 | #endif | |
119 | m_family = static_cast<Family>(addr.sa_family); | |
120 | break; | |
121 | ||
122 | default: | |
123 | wxFAIL_MSG( "unsupported socket address family" ); | |
124 | InitUnspec(); | |
125 | return; | |
126 | } | |
127 | ||
128 | InitFromSockaddr(addr, len); | |
129 | } | |
130 | ||
131 | // copy ctor and assignment operators | |
132 | wxSockAddressImpl(const wxSockAddressImpl& other) | |
133 | { | |
134 | InitFromOther(other); | |
135 | } | |
136 | ||
137 | wxSockAddressImpl& operator=(const wxSockAddressImpl& other) | |
138 | { | |
2a32b807 PC |
139 | if (this != &other) |
140 | { | |
141 | free(m_addr); | |
142 | InitFromOther(other); | |
143 | } | |
c9bccf23 VZ |
144 | return *this; |
145 | } | |
146 | ||
147 | // dtor frees the memory used by m_addr | |
148 | ~wxSockAddressImpl() | |
149 | { | |
150 | free(m_addr); | |
151 | } | |
152 | ||
153 | ||
154 | // reset the address to the initial uninitialized state | |
155 | void Clear() | |
156 | { | |
157 | free(m_addr); | |
158 | ||
159 | InitUnspec(); | |
160 | } | |
161 | ||
162 | // initialize the address to be of specific address family, it must be | |
163 | // currently uninitialized (you may call Clear() to achieve this) | |
164 | void CreateINET(); | |
165 | void CreateINET6(); | |
166 | #ifdef wxHAS_UNIX_DOMAIN_SOCKETS | |
167 | void CreateUnix(); | |
168 | #endif // wxHAS_UNIX_DOMAIN_SOCKETS | |
7172db18 VZ |
169 | void Create(Family family) |
170 | { | |
171 | switch ( family ) | |
172 | { | |
173 | case FAMILY_INET: | |
174 | CreateINET(); | |
175 | break; | |
176 | ||
177 | #if wxUSE_IPV6 | |
178 | case FAMILY_INET6: | |
179 | CreateINET6(); | |
180 | break; | |
3b84c807 | 181 | #endif // wxUSE_IPV6 |
7172db18 VZ |
182 | |
183 | #ifdef wxHAS_UNIX_DOMAIN_SOCKETS | |
184 | case FAMILY_UNIX: | |
7172db18 VZ |
185 | CreateUnix(); |
186 | break; | |
3b84c807 | 187 | #endif // wxHAS_UNIX_DOMAIN_SOCKETS |
7172db18 VZ |
188 | |
189 | default: | |
190 | wxFAIL_MSG( "unsupported socket address family" ); | |
191 | } | |
192 | } | |
c9bccf23 VZ |
193 | |
194 | // simple accessors | |
195 | Family GetFamily() const { return m_family; } | |
196 | bool Is(Family family) const { return m_family == family; } | |
197 | bool IsOk() const { return m_family != FAMILY_UNSPEC; } | |
198 | const sockaddr *GetAddr() const { return m_addr; } | |
199 | sockaddr *GetWritableAddr() { return m_addr; } | |
200 | int GetLen() const { return m_len; } | |
201 | ||
202 | // accessors for INET or INET6 address families | |
203 | #if wxUSE_IPV6 | |
204 | #define CALL_IPV4_OR_6(func, args) \ | |
205 | Is(FAMILY_INET6) ? func##6(args) : func##4(args) | |
206 | #define CALL_IPV4_OR_6_VOID(func) \ | |
207 | Is(FAMILY_INET6) ? func##6() : func##4() | |
208 | #else | |
209 | #define CALL_IPV4_OR_6(func, args) func##4(args) | |
210 | #define CALL_IPV4_OR_6_VOID(func) func##4() | |
211 | #endif // IPv6 support on/off | |
212 | ||
213 | wxString GetHostName() const; | |
214 | bool SetHostName(const wxString& name) | |
215 | { | |
216 | return CALL_IPV4_OR_6(SetHostName, (name)); | |
217 | } | |
218 | ||
219 | wxUint16 GetPort() const { return CALL_IPV4_OR_6_VOID(GetPort); } | |
220 | bool SetPort(wxUint16 port) { return CALL_IPV4_OR_6(SetPort, (port)); } | |
221 | bool SetPortName(const wxString& name, const char *protocol); | |
222 | ||
223 | bool SetToAnyAddress() { return CALL_IPV4_OR_6_VOID(SetToAnyAddress); } | |
224 | ||
225 | #undef CALL_IPV4_OR_6 | |
226 | ||
227 | // accessors for INET addresses only | |
228 | bool GetHostAddress(wxUint32 *address) const; | |
229 | bool SetHostAddress(wxUint32 address); | |
230 | ||
231 | bool SetToBroadcastAddress() { return SetHostAddress(INADDR_BROADCAST); } | |
232 | ||
233 | // accessors for INET6 addresses only | |
234 | #if wxUSE_IPV6 | |
235 | bool GetHostAddress(in6_addr *address) const; | |
236 | bool SetHostAddress(const in6_addr& address); | |
237 | #endif // wxUSE_IPV6 | |
238 | ||
239 | #ifdef wxHAS_UNIX_DOMAIN_SOCKETS | |
240 | // methods valid for Unix address family addresses only | |
241 | bool SetPath(const wxString& path); | |
242 | wxString GetPath() const; | |
243 | #endif // wxHAS_UNIX_DOMAIN_SOCKETS | |
244 | ||
245 | private: | |
246 | void DoAlloc(int len) | |
247 | { | |
248 | m_addr = static_cast<sockaddr *>(calloc(1, len)); | |
249 | m_len = len; | |
250 | } | |
251 | ||
252 | // FIXME-VC6: VC6 doesn't grok Foo<T>() call syntax so we need the extra | |
253 | // dummy parameter of type T, use the macros in sckaddr.cpp to | |
254 | // hide it | |
255 | template <class T> | |
256 | T *Alloc(T *) | |
257 | { | |
258 | DoAlloc(sizeof(T)); | |
259 | ||
260 | return reinterpret_cast<T *>(m_addr); | |
261 | } | |
262 | ||
263 | template <class T> | |
264 | T *Get(T *) const | |
265 | { | |
266 | wxCHECK_MSG( static_cast<int>(m_family) == AddressFamily<T>::value, | |
267 | NULL, | |
268 | "socket address family mismatch" ); | |
269 | ||
270 | return reinterpret_cast<T *>(m_addr); | |
271 | } | |
272 | ||
273 | void InitUnspec() | |
274 | { | |
275 | m_family = FAMILY_UNSPEC; | |
276 | m_addr = NULL; | |
277 | m_len = 0; | |
278 | } | |
279 | ||
280 | void InitFromSockaddr(const sockaddr& addr, int len) | |
281 | { | |
282 | DoAlloc(len); | |
283 | memcpy(m_addr, &addr, len); | |
284 | } | |
285 | ||
286 | void InitFromOther(const wxSockAddressImpl& other) | |
287 | { | |
288 | m_family = other.m_family; | |
289 | ||
290 | if ( other.m_addr ) | |
291 | { | |
292 | InitFromSockaddr(*other.m_addr, other.m_len); | |
293 | } | |
294 | else // no address to copy | |
295 | { | |
296 | m_addr = NULL; | |
297 | m_len = 0; | |
298 | } | |
299 | } | |
300 | ||
301 | // IPv4/6 implementations of public functions | |
302 | bool SetHostName4(const wxString& name); | |
303 | ||
304 | bool SetPort4(wxUint16 port); | |
305 | wxUint16 GetPort4() const; | |
306 | ||
307 | bool SetToAnyAddress4() { return SetHostAddress(INADDR_ANY); } | |
308 | ||
309 | #if wxUSE_IPV6 | |
310 | bool SetHostName6(const wxString& name); | |
311 | ||
312 | bool SetPort6(wxUint16 port); | |
313 | wxUint16 GetPort6() const; | |
314 | ||
315 | bool SetToAnyAddress6(); | |
316 | #endif // wxUSE_IPV6 | |
317 | ||
318 | Family m_family; | |
319 | sockaddr *m_addr; | |
320 | int m_len; | |
321 | }; | |
322 | ||
323 | #endif // _WX_PRIVATE_SOCKADDR_H_ |