00001 /* 00002 Copyright 2003 by Marc J. Rochkind. All rights reserved. 00003 May be copied only for purposes and under conditions described 00004 on the Web page www.basepath.com/aup/copyright.htm. 00005 00006 The Example Files are provided "as is," without any warranty; 00007 without even the implied warranty of merchantability or fitness 00008 for a particular purpose. The author and his publisher are not 00009 responsible for any damages, direct or incidental, resulting 00010 from the use or non-use of these Example Files. 00011 00012 The Example Files may contain defects, and some contain deliberate 00013 coding mistakes that were included for educational reasons. 00014 You are responsible for determining if and how the Example Files 00015 are to be used. 00016 00017 */ 00018 #include "ux.hpp" 00019 00020 #include <arpa/inet.h> 00021 00022 using namespace Ux; 00023 00024 /** 00025 Calls inet_pton. Throws errors from inet_pton, or EINVAL if inet_pton returns 0. 00026 */ 00027 void SockIPv4::set(const char *str) 00028 { 00029 switch (::inet_pton(AF_INET, str, &ipv4)) { 00030 case 0: 00031 throw Error(EINVAL); 00032 case -1: 00033 throw Error(errno); 00034 } 00035 } 00036 00037 /** 00038 Calls inet_ntop. 00039 */ 00040 const char *SockIPv4::get_string(char *buf, socklen_t bufsize) const 00041 { 00042 if (::inet_ntop(AF_INET, &ipv4, buf, bufsize) == NULL) 00043 throw Error(errno); 00044 return buf; 00045 } 00046 00047 /** 00048 Sets object to zeros. 00049 */ 00050 void SockIPv6::set(uint8_t *ip = NULL) 00051 { 00052 if (ip == NULL) 00053 memset(ipv6, 0, sizeof(ipv6)); 00054 else 00055 memcpy(ipv6, ip, sizeof(ipv6)); 00056 } 00057 00058 /** 00059 Calls inet_pton. Throws errors from inet_pton, or EINVAL if inet_pton returns 0. 00060 */ 00061 void SockIPv6::set(const char *str) 00062 { 00063 switch (::inet_pton(AF_INET6, str, ipv6)) { 00064 case 0: 00065 throw Error(EINVAL); 00066 case -1: 00067 throw Error(errno); 00068 } 00069 } 00070 00071 /** 00072 Calls inet_ntop. 00073 */ 00074 const char *SockIPv6::get_string(char *buf, socklen_t bufsize) const 00075 { 00076 if (::inet_ntop(AF_INET6, ipv6, buf, bufsize) == NULL) 00077 throw Error(errno); 00078 return buf; 00079 } 00080 00081 /** 00082 Sets up socet address directly from a path. Can throw ENAMETOOLONG. 00083 */ 00084 void SockAddrUn::set(const char *path) 00085 { 00086 struct sockaddr_un *p = (struct sockaddr_un *)&sa_storage; 00087 00088 p->sun_family = AF_UNIX; 00089 if (strlen(path) >= sizeof(p->sun_path)) 00090 throw Error(ENAMETOOLONG); 00091 strcpy(p->sun_path, path); 00092 set_len(sizeof(struct sockaddr_un)); 00093 } 00094 00095 /** 00096 Sets up socet address directly from a struct in_addr. 00097 */ 00098 void SockAddrIn::set(in_port_t port, struct in_addr& sa) 00099 { 00100 struct sockaddr_in *p = (struct sockaddr_in *)&sa_storage; 00101 00102 p->sin_family = AF_INET; 00103 p->sin_port = port; 00104 p->sin_addr = sa; 00105 set_len(sizeof(struct sockaddr_in)); 00106 } 00107 00108 /** 00109 Sets up socet address directly from an IPv4 as a 32-bit number. 00110 */ 00111 void SockAddrIn::set(in_port_t port, in_addr_t ipv4) 00112 { 00113 struct in_addr sa; 00114 00115 sa.s_addr = ipv4; 00116 set(port, sa); 00117 } 00118 00119 /** 00120 Sets up socet address directly from dotted string. 00121 */ 00122 void SockAddrIn::set(in_port_t port, const char *dotted) 00123 { 00124 set(port, SockIPv4(dotted).get_ipv4()); 00125 } 00126 00127 /** 00128 Calls getaddrinfo. 00129 */ 00130 /* static */ void SockAddr::getaddrinfo(const char *nodename, const char *servname, 00131 const struct addrinfo *hint, struct addrinfo **infop) 00132 { 00133 int r; 00134 00135 if ((r = ::getaddrinfo(nodename, servname, hint, infop)) != 0) 00136 throw Error(r, EC_EAI); 00137 } 00138 00139 /** 00140 Calls getaddrinfo, but doesn't require setting up a separate hint structure. 00141 */ 00142 /* static */ void SockAddr::getaddrinfo(const char *nodename, const char *servname, int family, int type, 00143 int flags, struct addrinfo **infop) 00144 { 00145 struct addrinfo hint; 00146 00147 memset(&hint, 0, sizeof(hint)); 00148 hint.ai_family = family; 00149 hint.ai_socktype = type; 00150 hint.ai_flags = flags; 00151 getaddrinfo(nodename, servname, &hint, infop); 00152 } 00153 00154 /** 00155 Calls getaddrinfo and then sets up the socket address from a nodename and servname (port). 00156 */ 00157 void SockAddr::set_server(const char *nodename, const char *servname) 00158 { 00159 struct addrinfo *infop; 00160 00161 getaddrinfo(nodename, servname, AF_INET, SOCK_STREAM, AI_PASSIVE, &infop); 00162 memcpy(&sa_storage, infop->ai_addr, infop->ai_addrlen); 00163 set_len(infop->ai_addrlen); 00164 set_protocol(infop->ai_protocol); 00165 } 00166 00167 /** 00168 Calls getnameinfo. 00169 */ 00170 /* static */ void SockAddr::getnameinfo(const struct sockaddr *sa, socklen_t sa_len, char *nodename, 00171 socklen_t nodelen, char *servname, socklen_t servlen, unsigned flags) 00172 { 00173 int r; 00174 00175 if ((r = ::getnameinfo(sa, sa_len, nodename, nodelen, servname, servlen, flags)) != 0) 00176 throw Error(r, EC_EAI); 00177 } 00178 00179 /** 00180 Calls socket. 00181 */ 00182 void Socket::socket(int domain, int type, int protocol) 00183 { 00184 if ((fd = ::socket(domain, type, protocol)) == -1) 00185 throw Error(errno); 00186 } 00187 00188 /** 00189 Calls bind. 00190 */ 00191 void Socket::bind(const SockAddr& sa) 00192 { 00193 if (::bind(fd, sa.get_addr(), sa.get_len()) == -1) 00194 throw Error(errno); 00195 } 00196 00197 /** 00198 Calls listen. 00199 */ 00200 void Socket::listen(int backlog) 00201 { 00202 if (::listen(fd, backlog) == -1) 00203 throw Error(errno); 00204 } 00205 00206 /** 00207 Calls accept. 00208 */ 00209 Socket Socket::accept(SockAddr *sa) 00210 { 00211 int r; 00212 00213 if (sa == NULL) 00214 r = ::accept(fd, NULL, NULL); 00215 else 00216 r = ::accept(fd, sa->get_addr(), sa->get_len_ptr()); 00217 if (r == -1) 00218 throw Error(errno); 00219 return Socket(r); 00220 } 00221 00222 /** 00223 Calls connect. 00224 */ 00225 void Socket::connect(const SockAddr& sa) 00226 { 00227 if (::connect(fd, sa.get_addr(), sa.get_len()) == -1) 00228 throw Error(errno); 00229 } 00230 00231 /** 00232 Calls setsockopt. 00233 */ 00234 void Socket::setsockopt(int level, int option, const void *value, socklen_t value_len) 00235 { 00236 if (::setsockopt(fd, level, option, value, value_len) == -1) 00237 throw Error(errno); 00238 } 00239 00240 /** 00241 Calls getsockopt. 00242 */ 00243 void Socket::getsockopt(int level, int option, void *value, socklen_t& value_len) 00244 { 00245 if (::getsockopt(fd, level, option, value, &value_len) == -1) 00246 throw Error(errno); 00247 } 00248 00249 /** 00250 Calls sendto. 00251 */ 00252 ssize_t Socket::sendto(const void *message, size_t length, int flags, const struct sockaddr *sa, 00253 socklen_t sa_len) 00254 { 00255 ssize_t n; 00256 00257 if ((n = ::sendto(fd, message, length, flags, sa, sa_len)) == -1) 00258 throw Error(errno); 00259 return n; 00260 } 00261 00262 /** 00263 Calls recvfrom. 00264 */ 00265 ssize_t Socket::recvfrom(void *buffer, size_t length, int flags, struct sockaddr *sa, 00266 socklen_t *sa_len) 00267 { 00268 ssize_t n; 00269 00270 if ((n = ::recvfrom(fd, buffer, length, flags, sa, sa_len)) == -1) 00271 throw Error(errno); 00272 return n; 00273 } 00274 00275 /** 00276 Calls sendmsg. 00277 */ 00278 ssize_t Socket::sendmsg(const struct msghdr *message, int flags) 00279 { 00280 ssize_t n; 00281 00282 if ((n = ::sendmsg(fd, message, flags)) == -1) 00283 throw Error(errno); 00284 return n; 00285 } 00286 00287 /** 00288 Calls recvmsg. 00289 */ 00290 ssize_t Socket::recvmsg(struct msghdr *message, int flags) 00291 { 00292 ssize_t n; 00293 00294 if ((n = ::recvmsg(fd, message, flags)) == -1) 00295 throw Error(errno); 00296 return n; 00297 } 00298 00299 /** 00300 Calls send. 00301 */ 00302 ssize_t Socket::send(const void *data, size_t length, int flags) 00303 { 00304 ssize_t n; 00305 00306 if ((n = ::send(fd, data, length, flags)) == -1) 00307 throw Error(errno); 00308 return n; 00309 } 00310 00311 /** 00312 Calls recv. 00313 */ 00314 ssize_t Socket::recv(void *buffer, size_t length, int flags) 00315 { 00316 ssize_t n; 00317 00318 if ((n = ::recv(fd, buffer, length, flags)) == -1) 00319 throw Error(errno); 00320 return n; 00321 } 00322 /** 00323 Calls getpeername. 00324 */ 00325 void Socket::getpeername(SockAddr& sa) 00326 { 00327 if (::getpeername(fd, sa.get_addr(), sa.get_len_ptr()) == -1) 00328 throw Error(errno); 00329 } 00330 00331 /** 00332 Calls getsockname. 00333 */ 00334 void Socket::getsockname(SockAddr& sa) 00335 { 00336 if (::getsockname(fd, sa.get_addr(), sa.get_len_ptr()) == -1) 00337 throw Error(errno); 00338 } 00339 00340 /** 00341 Calls socketpair. Arguments rearranged so array comes first, which allows default arguments. 00342 */ 00343 /* static */ void Socket::socketpair(Socket sv[2], int domain, int type, int protocol) 00344 { 00345 int fds[2]; 00346 00347 if (::socketpair(domain, type, protocol, fds) == -1) 00348 throw Error(errno); 00349 sv[0].set(fds[0]); 00350 sv[1].set(fds[1]); 00351 } 00352 00353 /** 00354 Calls shutdown. 00355 */ 00356 void Socket::shutdown(int how) 00357 { 00358 if (::shutdown(fd, how) == -1) 00359 throw Error(errno); 00360 } 00361 00362 /** 00363 Calls sockatmark; return converted to bool. 00364 */ 00365 bool Socket::sockatmark(void) 00366 { 00367 #if _XOPEN_VERSION >= 600 00368 int r; 00369 00370 if ((r = ::sockatmark(fd)) == -1) 00371 throw Error(errno); 00372 return r == 1; 00373 #else 00374 throw Error(ENOSYS); 00375 #endif 00376 }