]>
Dogcows Code - chaz/yoink/blob - src/Moof/Socket.hh
f1604663b038c37ff408061ca50db4d914ccd38a
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_
25 #include <arpa/inet.h>
27 #include <sys/socket.h>
28 #include <sys/types.h>
32 #include <sys/ioctl.h>
36 #include <Moof/Log.hh>
37 #include <Moof/Packet.hh>
38 #include <Moof/Thread.hh>
42 #define SO_NONBLOCK 1024
57 mAddress
.sa
.sa_family
= AF_UNSPEC
;
58 mAddress
.v4
.sin_port
= 0;
61 SocketAddress(const std::string
& service
, const std::string
& name
,
62 int type
= SOCK_STREAM
, int family
= AF_UNSPEC
)
64 init(service
, name
, type
, family
);
67 SocketAddress(const std::string
& service
,
68 int type
= SOCK_STREAM
, int family
= AF_UNSPEC
)
70 init(service
, type
, family
);
73 SocketAddress(const struct addrinfo
* addr
, const std::string
& name
)
75 mType
= addr
->ai_socktype
;
76 memcpy(&mAddress
.sa
, addr
->ai_addr
, addr
->ai_addrlen
);
78 mSize
= addr
->ai_addrlen
;
81 SocketAddress(const struct sockaddr
* addr
, size_t size
,
82 int type
= SOCK_STREAM
)
85 memcpy(&mAddress
.sa
, addr
, size
);
91 static SocketAddress
broadcast(const std::string
& service
)
93 return SocketAddress(service
, "255.255.255.255", SOCK_DGRAM
);
97 void init(const std::string
& service
, const std::string
& name
= "",
98 int type
= SOCK_STREAM
, int family
= AF_UNSPEC
)
100 ASSERT(type
== SOCK_STREAM
|| type
== SOCK_DGRAM
);
101 ASSERT(family
== AF_INET
|| family
== AF_INET6
|| family
== AF_UNSPEC
);
103 struct addrinfo hints
;
104 memset(&hints
, 0, sizeof(hints
));
105 hints
.ai_family
= family
;
106 hints
.ai_socktype
= type
;
107 hints
.ai_flags
= AI_PASSIVE
;
109 struct addrinfo
* addr
;
110 int status
= getaddrinfo(name
.length() > 0 ? name
.c_str() : 0,
111 service
.c_str(), &hints
, &addr
);
114 mType
= addr
->ai_socktype
;
115 memcpy(&mAddress
.sa
, addr
->ai_addr
, addr
->ai_addrlen
);
116 mSize
= addr
->ai_addrlen
;
118 if (name
!= "") mName
= name
;
119 else setNameFromAddress();
125 Mf::logWarning(gai_strerror(status
));
128 mAddress
.sa
.sa_family
= AF_UNSPEC
;
129 mAddress
.v4
.sin_port
= 0;
133 void init(const std::string
& service
,
134 int type
= SOCK_STREAM
, int family
= AF_UNSPEC
)
136 init(service
, "", type
, family
);
140 const std::string
& name() const
145 void setName(const std::string
& name
)
150 unsigned short port() const
152 return ntohs(mAddress
.v4
.sin_port
);
162 return mAddress
.sa
.sa_family
;
166 const struct sockaddr
* address() const
168 return mSize
!= 0 ? &mAddress
.sa
: 0;
177 static int resolve(const std::string
& service
, const std::string
& name
,
178 int type
, int family
, std::vector
<SocketAddress
>& resolved
)
180 ASSERT(type
== SOCK_STREAM
|| type
== SOCK_DGRAM
);
181 ASSERT(family
== AF_INET
|| family
== AF_INET6
|| family
== AF_UNSPEC
);
185 struct addrinfo hints
;
186 memset(&hints
, 0, sizeof(hints
));
187 hints
.ai_family
= family
;
188 hints
.ai_socktype
= type
;
189 hints
.ai_flags
= AI_PASSIVE
;
191 struct addrinfo
* list
;
192 int status
= getaddrinfo(name
.length() > 0 ? name
.c_str() : 0,
193 service
.length() > 0 ? service
.c_str() : 0, &hints
, &list
);
196 struct addrinfo
* addr
= list
;
199 resolved
.push_back(SocketAddress(addr
, name
));
200 addr
= addr
->ai_next
;
207 Mf::logWarning(gai_strerror(status
));
216 void setNameFromAddress()
219 // inet_ntop was introduced in Vista
220 mName
= inet_ntoa(mAddress
.v4
.sin_addr
);
222 char name
[INET6_ADDRSTRLEN
] = {'\0'};
223 inet_ntop(mAddress
.sa
.sa_family
, &mAddress
.sa
, name
, sizeof(name
));
234 sockaddr_storage storage
;
246 Socket(const SocketAddress
& address
) :
250 mFd
= socket(address
.family(), address
.type(), 0);
256 if (mFd
!= -1) closesocket(mFd
);
258 if (mFd
!= -1) close(mFd
);
263 bool isConnected() const
268 const SocketAddress
& address() const
276 return ::connect(mFd
, mAddress
.address(), mAddress
.size());
281 return ::bind(mFd
, mAddress
.address(), mAddress
.size());
284 int listen(int backlog
= SOMAXCONN
)
286 return ::listen(mFd
, backlog
> 0 ? backlog
: SOMAXCONN
);
295 int set(int option
, int value
= 0)
297 if (option
== SO_NONBLOCK
)
300 int flags
= fcntl(mFd
, F_GETFL
);
301 return fcntl(mFd
, F_SETFL
, (value
? O_NONBLOCK
: 0) | flags
);
303 return ioctl(mFd
, FIONBIO
, value
);
306 return setsockopt(mFd
, SOL_SOCKET
, option
, &value
, sizeof(value
));
309 int set(int option
, const std::string
& value
)
311 return setsockopt(mFd
, SOL_SOCKET
, option
,
312 value
.c_str(), value
.length());
315 int get(int option
, int& value
)
317 if (option
== SO_NONBLOCK
)
320 int flags
= fcntl(mFd
, F_GETFL
);
321 return flags
& O_NONBLOCK
;
323 return ioctl(mFd
, FIONBIO
, &value
);
326 socklen_t optlen
= sizeof(value
);
327 return getsockopt(mFd
, SOL_SOCKET
, option
, &value
, &optlen
);
330 int get(int option
, std::string
& value
)
332 char str
[64] = {'\0'};
333 socklen_t optlen
= sizeof(str
);
334 int result
= getsockopt(mFd
, SOL_SOCKET
, option
, &str
, &optlen
);
339 void write(const Packet
& packet
)
341 write(mAddress
, packet
);
344 void write(const SocketAddress
& address
, const Packet
& packet
)
346 sendto(mFd
, packet
.bytes(), packet
.size(), 0,
347 address
.address(), address
.size());
353 int size
= recv(mFd
, buffer
, sizeof(buffer
), 0);
355 return Packet(buffer
, size
);
358 Packet
read(SocketAddress
& address
)
363 sockaddr_storage storage
;
365 socklen_t length
= sizeof(addr
);
368 int size
= recvfrom(mFd
, buffer
, sizeof(buffer
), 0,
371 address
= SocketAddress(&addr
.sa
, length
, mAddress
.type());
372 return Packet(buffer
, size
);
380 // for accepting a socket from fd
384 sockaddr_storage storage
;
386 socklen_t length
= sizeof(addr
);
388 mFd
= ::accept(fd
, &addr
.sa
, &length
);
389 mAddress
= SocketAddress(&addr
.sa
, length
);
394 SocketAddress mAddress
;
398 class ResolverTask
: public ThreadedTask
402 ResolverTask(const std::string
& service
, const std::string
& name
,
403 int type
= SOCK_STREAM
, int family
= AF_UNSPEC
) :
406 mFunction
= boost::bind(&ResolverTask::resolve
,
407 this, service
, name
, type
, family
);
418 if (!mThread
) mThread
= Mf::detachFunction(mFunction
);
422 const std::vector
<SocketAddress
>& addresses() const
430 int resolve(const std::string
& service
, const std::string
& name
,
431 int type
, int family
)
433 int status
= SocketAddress::resolve(service
, name
,
434 type
, family
, mAddressList
);
440 std::vector
<SocketAddress
> mAddressList
;
448 #endif // _MOOF_SOCKET_HH_
This page took 0.047783 seconds and 4 git commands to generate.