initial network stuff
[chaz/yoink] / src / Moof / Socket.hh
1
2 /*] Copyright (c) 2009-2010, Charles McGarvey [**************************
3 **] All rights reserved.
4 *
5 * vi:ts=4 sw=4 tw=75
6 *
7 * Distributable under the terms and conditions of the 2-clause BSD license;
8 * see the file COPYING for a complete text of the license.
9 *
10 **************************************************************************/
11
12 #ifndef _MOOF_SOCKET_HH_
13 #define _MOOF_SOCKET_HH_
14
15 #include <cstring>
16 #include <sstream>
17 #include <string>
18 #include <vector>
19
20 #include <arpa/inet.h>
21 #include <netdb.h>
22 #include <sys/socket.h>
23 #include <sys/types.h>
24
25 #include <Moof/Log.hh>
26 #include <Moof/Packet.hh>
27 #include <Moof/Thread.hh>
28
29
30 namespace Mf {
31
32
33 class SocketAddress
34 {
35 public:
36
37 SocketAddress(int type = SOCK_STREAM)
38 {
39 mType = type;
40 memset(&mAddress.in4, 0, sizeof(mAddress.in4));
41 mAddress.in4.sin_family = AF_INET;
42 mAddress.in4.sin_port = 0;
43 mAddress.in4.sin_addr.s_addr = INADDR_ANY;
44 mName = "[any]";
45 mSize = sizeof(mAddress.in4);
46 }
47
48 SocketAddress(const std::string& name, const std::string& service,
49 int type = SOCK_STREAM, int family = AF_INET)
50 {
51 ASSERT(type == SOCK_STREAM || type == SOCK_DGRAM);
52 ASSERT(family == AF_INET || family == AF_INET6 || family == AF_UNSPEC);
53
54 struct addrinfo hints;
55 memset(&hints, 0, sizeof(hints));
56 hints.ai_family = family;
57 hints.ai_socktype = type;
58 hints.ai_flags = AI_PASSIVE | AI_CANONNAME;
59
60 struct addrinfo* addr;
61 int status = getaddrinfo(name.length() > 0 ? name.c_str() : 0,
62 service.length() > 0 ? service.c_str() : 0, &hints, &addr);
63 if (status != 0)
64 {
65 Mf::logError("uh oh, that didn't work!");
66 return;
67 }
68
69 mType = addr->ai_socktype;
70 memcpy(&mAddress.sa, addr->ai_addr, addr->ai_addrlen);
71 mName = addr->ai_canonname;
72 mSize = addr->ai_addrlen;
73
74 freeaddrinfo(addr);
75 }
76
77 SocketAddress(const std::string& name, const struct addrinfo* addr)
78 {
79 mType = addr->ai_socktype;
80 memcpy(&mAddress.sa, addr->ai_addr, addr->ai_addrlen);
81 mName = name;
82 mSize = addr->ai_addrlen;
83 }
84
85 SocketAddress(const struct sockaddr* addr, size_t size,
86 int type = SOCK_STREAM)
87 {
88 mType = type;
89 memcpy(&mAddress.sa, addr, size);
90 mSize = size;
91
92 char name[128] = {'\0'};
93 inet_ntop(addr->sa_family, (struct sockaddr_in*)addr,
94 name, sizeof(name));
95 mName = name;
96 }
97
98
99 const std::string& name() const
100 {
101 return mName;
102 }
103
104 unsigned short port() const
105 {
106 return ntohs(mAddress.in4.sin_port);
107 }
108
109 int type() const
110 {
111 return mType;
112 }
113
114 int family() const
115 {
116 return mAddress.sa.sa_family;
117 }
118
119
120 const struct sockaddr* address() const
121 {
122 return &mAddress.sa;
123 }
124
125 size_t size() const
126 {
127 return mSize;
128 }
129
130
131 static int resolve(const std::string& name, const std::string& service,
132 int type, int family, std::vector<SocketAddress>& resolved)
133 {
134 ASSERT(type == SOCK_STREAM || type == SOCK_DGRAM);
135 ASSERT(family == AF_INET || family == AF_INET6 || family == AF_UNSPEC);
136
137 struct addrinfo hints;
138 memset(&hints, 0, sizeof(hints));
139 hints.ai_family = family;
140 hints.ai_socktype = type;
141 hints.ai_flags = AI_PASSIVE | AI_CANONNAME;
142
143 struct addrinfo* list;
144 int status = getaddrinfo(name.length() > 0 ? name.c_str() : 0,
145 service.length() > 0 ? service.c_str() : 0, &hints, &list);
146 if (status != 0) return -1;
147
148 resolved.clear();
149
150 const char* canonicalName = list->ai_canonname;
151 struct addrinfo* addr = list;
152 while (addr != 0)
153 {
154 resolved.push_back(SocketAddress(canonicalName, addr));
155 addr = addr->ai_next;
156 }
157
158 freeaddrinfo(list);
159 return 0;
160 }
161
162
163 private:
164
165 union
166 {
167 sockaddr sa;
168 sockaddr_in in4;
169 sockaddr_in6 in6;
170 } mAddress;
171 size_t mSize;
172 std::string mName;
173 int mType;
174 };
175
176
177 class Socket
178 {
179 public:
180
181 Socket(const SocketAddress& address) :
182 mAddress(address)
183 {
184 mFd = socket(address.family(), address.type(), 0);
185 }
186
187 ~Socket()
188 {
189 close(mFd);
190 }
191
192
193 bool isConnected() const
194 {
195 return false;
196 }
197
198 const SocketAddress& address() const
199 {
200 return mAddress;
201 }
202
203
204 void write(const Packet& packet)
205 {
206 write(mAddress, packet);
207 }
208
209 void write(const SocketAddress& address, const Packet& packet)
210 {
211 sendto(mFd, packet.bytes(), packet.size(), 0,
212 address.address(), address.size());
213 }
214
215 Packet read()
216 {
217 char buffer[1024];
218 int size = recv(mFd, buffer, sizeof(buffer), 0);
219
220 return Packet(buffer, size);
221 }
222
223 Packet read(SocketAddress& address)
224 {
225 union
226 {
227 sockaddr sa;
228 sockaddr_storage storage;
229 } addr;
230 socklen_t length = sizeof(addr);
231
232 char buffer[1024];
233 int size = recvfrom(mFd, buffer, sizeof(buffer), 0,
234 &addr.sa, &length);
235
236 address = SocketAddress(&addr.sa, length, SOCK_DGRAM);
237 return Packet(buffer, size);
238 }
239
240
241 private:
242
243 int mFd;
244 SocketAddress mAddress;
245 };
246
247
248 class ResolverTask : public ThreadedTask
249 {
250 public:
251
252 ResolverTask(const std::string& name, const std::string& service,
253 int type = SOCK_STREAM, int family = AF_UNSPEC) :
254 mIsDone(false)
255 {
256 mFunction = boost::bind(&ResolverTask::resolve,
257 this, name, service, type, family);
258 }
259
260
261 bool isDone() const
262 {
263 return mIsDone;
264 }
265
266 void run()
267 {
268 if (!mThread) mThread = Mf::detachFunction(mFunction);
269 }
270
271
272 const std::vector<SocketAddress>& addresses() const
273 {
274 return mAddressList;
275 }
276
277
278 private:
279
280 int resolve(const std::string& name, const std::string& service,
281 int type, int family)
282 {
283 int status = SocketAddress::resolve(name, service,
284 type, family, mAddressList);
285 mIsDone = true;
286 return status;
287 }
288
289
290 std::vector<SocketAddress> mAddressList;
291 bool mIsDone;
292 Function mFunction;
293 };
294
295
296 } // namespace Mf
297
298 #endif // _MOOF_SOCKET_HH_
299
This page took 0.042135 seconds and 4 git commands to generate.