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