]>
Commit | Line | Data |
---|---|---|
c9bccf23 VZ |
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" | |
67badd57 VZ |
16 | |
17 | #if wxUSE_IPV6 | |
18 | #include <ws2tcpip.h> | |
19 | #endif | |
c9bccf23 VZ |
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 | }; | |
4d8988f7 | 29 | #include <in.h> |
c9bccf23 VZ |
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 | free(m_addr); | |
141 | ||
142 | InitFromOther(other); | |
143 | ||
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 | |
169 | ||
170 | // simple accessors | |
171 | Family GetFamily() const { return m_family; } | |
172 | bool Is(Family family) const { return m_family == family; } | |
173 | bool IsOk() const { return m_family != FAMILY_UNSPEC; } | |
174 | const sockaddr *GetAddr() const { return m_addr; } | |
175 | sockaddr *GetWritableAddr() { return m_addr; } | |
176 | int GetLen() const { return m_len; } | |
177 | ||
178 | // accessors for INET or INET6 address families | |
179 | #if wxUSE_IPV6 | |
180 | #define CALL_IPV4_OR_6(func, args) \ | |
181 | Is(FAMILY_INET6) ? func##6(args) : func##4(args) | |
182 | #define CALL_IPV4_OR_6_VOID(func) \ | |
183 | Is(FAMILY_INET6) ? func##6() : func##4() | |
184 | #else | |
185 | #define CALL_IPV4_OR_6(func, args) func##4(args) | |
186 | #define CALL_IPV4_OR_6_VOID(func) func##4() | |
187 | #endif // IPv6 support on/off | |
188 | ||
189 | wxString GetHostName() const; | |
190 | bool SetHostName(const wxString& name) | |
191 | { | |
192 | return CALL_IPV4_OR_6(SetHostName, (name)); | |
193 | } | |
194 | ||
195 | wxUint16 GetPort() const { return CALL_IPV4_OR_6_VOID(GetPort); } | |
196 | bool SetPort(wxUint16 port) { return CALL_IPV4_OR_6(SetPort, (port)); } | |
197 | bool SetPortName(const wxString& name, const char *protocol); | |
198 | ||
199 | bool SetToAnyAddress() { return CALL_IPV4_OR_6_VOID(SetToAnyAddress); } | |
200 | ||
201 | #undef CALL_IPV4_OR_6 | |
202 | ||
203 | // accessors for INET addresses only | |
204 | bool GetHostAddress(wxUint32 *address) const; | |
205 | bool SetHostAddress(wxUint32 address); | |
206 | ||
207 | bool SetToBroadcastAddress() { return SetHostAddress(INADDR_BROADCAST); } | |
208 | ||
209 | // accessors for INET6 addresses only | |
210 | #if wxUSE_IPV6 | |
211 | bool GetHostAddress(in6_addr *address) const; | |
212 | bool SetHostAddress(const in6_addr& address); | |
213 | #endif // wxUSE_IPV6 | |
214 | ||
215 | #ifdef wxHAS_UNIX_DOMAIN_SOCKETS | |
216 | // methods valid for Unix address family addresses only | |
217 | bool SetPath(const wxString& path); | |
218 | wxString GetPath() const; | |
219 | #endif // wxHAS_UNIX_DOMAIN_SOCKETS | |
220 | ||
221 | private: | |
222 | void DoAlloc(int len) | |
223 | { | |
224 | m_addr = static_cast<sockaddr *>(calloc(1, len)); | |
225 | m_len = len; | |
226 | } | |
227 | ||
228 | // FIXME-VC6: VC6 doesn't grok Foo<T>() call syntax so we need the extra | |
229 | // dummy parameter of type T, use the macros in sckaddr.cpp to | |
230 | // hide it | |
231 | template <class T> | |
232 | T *Alloc(T *) | |
233 | { | |
234 | DoAlloc(sizeof(T)); | |
235 | ||
236 | return reinterpret_cast<T *>(m_addr); | |
237 | } | |
238 | ||
239 | template <class T> | |
240 | T *Get(T *) const | |
241 | { | |
242 | wxCHECK_MSG( static_cast<int>(m_family) == AddressFamily<T>::value, | |
243 | NULL, | |
244 | "socket address family mismatch" ); | |
245 | ||
246 | return reinterpret_cast<T *>(m_addr); | |
247 | } | |
248 | ||
249 | void InitUnspec() | |
250 | { | |
251 | m_family = FAMILY_UNSPEC; | |
252 | m_addr = NULL; | |
253 | m_len = 0; | |
254 | } | |
255 | ||
256 | void InitFromSockaddr(const sockaddr& addr, int len) | |
257 | { | |
258 | DoAlloc(len); | |
259 | memcpy(m_addr, &addr, len); | |
260 | } | |
261 | ||
262 | void InitFromOther(const wxSockAddressImpl& other) | |
263 | { | |
264 | m_family = other.m_family; | |
265 | ||
266 | if ( other.m_addr ) | |
267 | { | |
268 | InitFromSockaddr(*other.m_addr, other.m_len); | |
269 | } | |
270 | else // no address to copy | |
271 | { | |
272 | m_addr = NULL; | |
273 | m_len = 0; | |
274 | } | |
275 | } | |
276 | ||
277 | // IPv4/6 implementations of public functions | |
278 | bool SetHostName4(const wxString& name); | |
279 | ||
280 | bool SetPort4(wxUint16 port); | |
281 | wxUint16 GetPort4() const; | |
282 | ||
283 | bool SetToAnyAddress4() { return SetHostAddress(INADDR_ANY); } | |
284 | ||
285 | #if wxUSE_IPV6 | |
286 | bool SetHostName6(const wxString& name); | |
287 | ||
288 | bool SetPort6(wxUint16 port); | |
289 | wxUint16 GetPort6() const; | |
290 | ||
291 | bool SetToAnyAddress6(); | |
292 | #endif // wxUSE_IPV6 | |
293 | ||
294 | Family m_family; | |
295 | sockaddr *m_addr; | |
296 | int m_len; | |
297 | }; | |
298 | ||
299 | #endif // _WX_PRIVATE_SOCKADDR_H_ |