]>
Dogcows Code - chaz/yoink/blob - src/Moof/Socket.hh
2 /*] Copyright (c) 2009-2010, Charles McGarvey [**************************
3 **] All rights reserved.
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.
10 **************************************************************************/
12 #ifndef _MOOF_SOCKET_HH_
13 #define _MOOF_SOCKET_HH_
26 #include <arpa/inet.h>
28 #include <sys/socket.h>
29 #include <sys/types.h>
33 #include <sys/ioctl.h>
37 #include <Moof/Log.hh>
38 #include <Moof/Packet.hh>
39 #include <Moof/Thread.hh>
43 #define SO_NONBLOCK 1024
58 mAddr
.sa
.sa_family
= AF_UNSPEC
;
59 mAddr
.in
.sin_port
= 0;
62 SocketAddress(const std::string
& service
, const std::string
& name
,
63 int type
= SOCK_STREAM
, int family
= AF_UNSPEC
)
65 init(service
, name
, type
, family
);
68 SocketAddress(const std::string
& service
,
69 int type
= SOCK_STREAM
, int family
= AF_UNSPEC
)
71 init(service
, type
, family
);
74 SocketAddress(const struct addrinfo
* addr
, const std::string
& name
)
76 mType
= addr
->ai_socktype
;
77 memcpy(&mAddr
.sa
, addr
->ai_addr
, addr
->ai_addrlen
);
79 mSize
= addr
->ai_addrlen
;
82 SocketAddress(const struct sockaddr
* addr
, size_t size
,
83 int type
= SOCK_STREAM
)
86 memcpy(&mAddr
.sa
, addr
, size
);
92 static SocketAddress
broadcast(const std::string
& service
)
94 std::istringstream
stream(service
);
98 struct sockaddr_in addr
;
99 addr
.sin_family
= AF_INET
;
100 addr
.sin_port
= htons(port
);
101 addr
.sin_addr
.s_addr
= INADDR_BROADCAST
;
102 memset(&addr
.sin_zero
, 0, sizeof(addr
.sin_zero
));
103 return SocketAddress((sockaddr
*)&addr
, sizeof(addr
), SOCK_DGRAM
);
107 void init(const std::string
& service
, const std::string
& name
= "",
108 int type
= SOCK_STREAM
, int family
= AF_UNSPEC
)
110 ASSERT(type
== SOCK_STREAM
|| type
== SOCK_DGRAM
);
111 ASSERT(family
== AF_INET
|| family
== AF_INET6
|| family
== AF_UNSPEC
);
113 struct addrinfo hints
;
114 memset(&hints
, 0, sizeof(hints
));
115 hints
.ai_family
= family
;
116 hints
.ai_socktype
= type
;
117 hints
.ai_flags
= AI_PASSIVE
;
119 struct addrinfo
* addr
;
120 int status
= getaddrinfo(name
.length() > 0 ? name
.c_str() : 0,
121 service
.c_str(), &hints
, &addr
);
124 mType
= addr
->ai_socktype
;
125 memcpy(&mAddr
.sa
, addr
->ai_addr
, addr
->ai_addrlen
);
126 mSize
= addr
->ai_addrlen
;
128 if (name
!= "") mName
= name
;
129 else setNameFromAddress();
135 Mf::logWarning(gai_strerror(status
));
138 mAddr
.sa
.sa_family
= AF_UNSPEC
;
139 mAddr
.in
.sin_port
= 0;
143 void init(const std::string
& service
,
144 int type
= SOCK_STREAM
, int family
= AF_UNSPEC
)
146 init(service
, "", type
, family
);
150 const std::string
& name() const
155 void setName(const std::string
& name
)
160 unsigned short port() const
162 return ntohs(mAddr
.in
.sin_port
);
172 return mAddr
.sa
.sa_family
;
176 const struct sockaddr
* address() const
178 return mSize
!= 0 ? &mAddr
.sa
: 0;
187 static int resolve(const std::string
& service
, const std::string
& name
,
188 int type
, int family
, std::vector
<SocketAddress
>& resolved
)
190 ASSERT(type
== SOCK_STREAM
|| type
== SOCK_DGRAM
);
191 ASSERT(family
== AF_INET
|| family
== AF_INET6
|| family
== AF_UNSPEC
);
195 struct addrinfo hints
;
196 memset(&hints
, 0, sizeof(hints
));
197 hints
.ai_family
= family
;
198 hints
.ai_socktype
= type
;
199 hints
.ai_flags
= AI_PASSIVE
;
201 struct addrinfo
* list
;
202 int status
= getaddrinfo(name
.length() > 0 ? name
.c_str() : 0,
203 service
.length() > 0 ? service
.c_str() : 0, &hints
, &list
);
206 for (struct addrinfo
* addr
= list
;
207 addr
!= 0; addr
= addr
->ai_next
)
209 resolved
.push_back(SocketAddress(addr
, name
));
216 Mf::logWarning(gai_strerror(status
));
226 void setNameFromAddress()
229 // inet_ntop was introduced in Vista
230 mName
= inet_ntoa(mAddr
.in
.sin_addr
);
232 char name
[INET6_ADDRSTRLEN
] = {'\0'};
233 inet_ntop(mAddr
.sa
.sa_family
, &mAddr
.sa
, name
, sizeof(name
));
243 sockaddr_storage storage
;
257 SocketAddress address
;
265 mIsConnected(false) {}
267 Socket(const SocketAddress
& address
) :
272 Socket(const std::string
& service
, const std::string
& name
,
273 int type
= SOCK_STREAM
, int family
= AF_UNSPEC
) :
276 mAddress(SocketAddress(service
, name
, type
, family
)) {}
278 Socket(const std::string
& service
,
279 int type
= SOCK_STREAM
, int family
= AF_UNSPEC
) :
282 mAddress(SocketAddress(service
, type
, family
)) {}
285 Socket(Socket
& move
) :
287 mIsConnected(move
.mIsConnected
),
288 mAddress(move
.mAddress
)
291 move
.mIsConnected
= false;
296 mIsConnected(move
.isConnected
),
297 mAddress(move
.address
) {}
299 Socket
& operator=(Socket
& move
)
302 if (mFd
!= -1) closesocket(mFd
);
304 if (mFd
!= -1) close(mFd
);
307 mIsConnected
= move
.mIsConnected
;
308 mAddress
= move
.mAddress
;
310 move
.mIsConnected
= false;
314 Socket
& operator=(Impl move
)
317 if (mFd
!= -1) closesocket(mFd
);
319 if (mFd
!= -1) close(mFd
);
322 mIsConnected
= move
.isConnected
;
323 mAddress
= move
.address
;
331 impl
.isConnected
= mIsConnected
;
332 impl
.address
= mAddress
;
334 mIsConnected
= false;
342 if (mFd
!= -1) closesocket(mFd
);
344 if (mFd
!= -1) close(mFd
);
349 bool isConnected() const
354 const SocketAddress
& address() const
362 if (mFd
== -1) mFd
= socket(mAddress
.family(), mAddress
.type(), 0);
363 int result
= ::connect(mFd
, mAddress
.address(), mAddress
.size());
364 mIsConnected
= result
!= -1;
370 if (mFd
== -1) mFd
= socket(mAddress
.family(), mAddress
.type(), 0);
371 return ::bind(mFd
, mAddress
.address(), mAddress
.size());
374 int listen(int backlog
= SOMAXCONN
)
376 return ::listen(mFd
, backlog
> 0 ? backlog
: SOMAXCONN
);
379 int accept(Socket
& socket
)
381 Socket temp
= Socket(mFd
);
391 int set(int option
, int value
= 0)
393 if (option
== SO_NONBLOCK
)
396 int flags
= fcntl(mFd
, F_GETFL
);
397 return fcntl(mFd
, F_SETFL
, (value
? O_NONBLOCK
: 0) | flags
);
399 return ioctl(mFd
, FIONBIO
, value
);
402 return setsockopt(mFd
, SOL_SOCKET
, option
, &value
, sizeof(value
));
405 int set(int option
, const std::string
& value
)
407 return setsockopt(mFd
, SOL_SOCKET
, option
,
408 value
.data(), value
.length());
411 int get(int option
, int& value
)
413 if (option
== SO_NONBLOCK
)
416 int flags
= fcntl(mFd
, F_GETFL
);
417 return flags
& O_NONBLOCK
;
419 return ioctl(mFd
, FIONBIO
, &value
);
422 socklen_t optlen
= sizeof(value
);
423 return getsockopt(mFd
, SOL_SOCKET
, option
, &value
, &optlen
);
426 int get(int option
, std::string
& value
)
428 char str
[64] = {'\0'};
429 socklen_t optlen
= sizeof(str
);
430 int result
= getsockopt(mFd
, SOL_SOCKET
, option
, &str
, &optlen
);
436 ssize_t
write(const void* bytes
, size_t size
)
438 return send(mFd
, bytes
, size
, 0);
440 ssize_t
write(const void* bytes
, size_t size
,
441 const SocketAddress
& address
)
443 return sendto(mFd
, bytes
, size
, 0,
444 address
.address(), address
.size());
447 ssize_t
write(const Packet
& packet
)
449 return write(packet
.bytes(), packet
.size());
452 ssize_t
write(const Packet
& packet
, const SocketAddress
& address
)
454 return write(packet
.bytes(), packet
.size(), address
);
458 ssize_t
read(void* bytes
, size_t size
)
460 return recv(mFd
, bytes
, size
, 0);
463 ssize_t
read(void* bytes
, size_t size
, SocketAddress
& address
)
468 sockaddr_storage storage
;
470 socklen_t length
= sizeof(addr
);
472 ssize_t result
= recvfrom(mFd
, bytes
, size
, 0, &addr
.sa
, &length
);
475 address
= SocketAddress(&addr
.sa
, length
, mAddress
.type());
480 ssize_t
read(Packet
& packet
)
483 ssize_t result
= read(buffer
, sizeof(buffer
));
484 if (result
!= -1) packet
= Packet(buffer
, result
);
488 ssize_t
read(Packet
& packet
, SocketAddress
& address
)
491 ssize_t result
= read(buffer
, sizeof(buffer
), address
);
492 if (result
!= -1) packet
= Packet(buffer
, result
);
501 // for accepting a socket from fd
505 sockaddr_storage storage
;
507 socklen_t length
= sizeof(addr
);
509 mFd
= ::accept(fd
, &addr
.sa
, &length
);
513 mAddress
= SocketAddress(&addr
.sa
, length
);
520 SocketAddress mAddress
;
524 class ResolverTask
: public ThreadedTask
528 ResolverTask(const std::string
& service
, const std::string
& name
,
529 int type
= SOCK_STREAM
, int family
= AF_UNSPEC
) :
532 mFunction
= boost::bind(&ResolverTask::resolve
,
533 this, service
, name
, type
, family
);
544 if (!mThread
) mThread
= Mf::detachFunction(mFunction
);
548 const std::vector
<SocketAddress
>& addresses() const
556 int resolve(const std::string
& service
, const std::string
& name
,
557 int type
, int family
)
559 int status
= SocketAddress::resolve(service
, name
,
560 type
, family
, mAddressList
);
566 std::vector
<SocketAddress
> mAddressList
;
574 #endif // _MOOF_SOCKET_HH_
This page took 0.053353 seconds and 5 git commands to generate.