00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <boost/lexical_cast.hpp>
00034 #include <sys/types.h>
00035 #include <unistd.h>
00036 #include <iostream>
00037 #include <errno.h>
00038 #include "maceConfig.h"
00039 #include "m_net.h"
00040 #include <fcntl.h>
00041
00042 #include "SockUtil.h"
00043 #include "Util.h"
00044 #include "Log.h"
00045
00046 #if !(defined _WINSOCK2_H || defined _WINSOCK_H)
00047 #define SOCKOPT_VOID_CAST
00048 #else
00049 #define SOCKOPT_VOID_CAST (char*)
00050
00051 #endif
00052
00053
00054
00055 const SockAddr SockUtil::NULL_MSOCKADDR = SockAddr();
00056 const MaceAddr SockUtil::NULL_MACEADDR = MaceAddr();
00057 const std::string SockUtil::NAT_STRING = "(NAT)";
00058
00059 using std::cerr;
00060 using std::endl;
00061
00062 class InitSockUtil {
00063 public:
00064 bool initialized;
00065
00066 InitSockUtil() : initialized(false)
00067 {
00068 SockUtil::init();
00069 initialized = true;
00070 }
00071 } foo;
00072
00073 void SockUtil::init() {
00074 if (!foo.initialized) {
00075 #if (defined _WINSOCK2_H || defined _WINSOCK_H)
00076 WSADATA data;
00077 WORD wVersionRequested = MAKEWORD( 2, 2 );
00078 ASSERTMSG(WSAStartup(wVersionRequested, &data) == 0, "Could not initialize WinSock");
00079 #endif
00080 }
00081 }
00082
00083 void SockUtil::setNonblock(socket_t s) {
00084 #ifdef HAVE_FCNTL
00085 int f;
00086 if (((f = fcntl(s, F_GETFL)) < 0) ||
00087 (fcntl(s, F_SETFL, f | O_NONBLOCK) < 0)) {
00088 Log::perror("fcntl");
00089 ABORT("fcntl: cannot set nonblock");
00090 }
00091 #else
00092 unsigned long flags = 1;
00093 if (ioctlsocket(s, FIONBIO, &flags) == SOCKET_ERROR) {
00094 int er = WSAGetLastError();
00095 std::cerr << "WSAGetLastError: " << er << std::endl;
00096 Log::perror("ioctlsocket");
00097 ABORT("ioctlsocket: cannot set nonblock");
00098 }
00099 #endif
00100 }
00101
00102 void SockUtil::setNodelay(socket_t s) {
00103 struct protoent *p;
00104 p = getprotobyname("tcp");
00105 if (!p) {
00106 ABORT("no tcp proto");
00107 }
00108 int one = 1;
00109 if (setsockopt(s, p->p_proto, TCP_NODELAY, SOCKOPT_VOID_CAST &one, sizeof(one)) < 0) {
00110 Log::perror("setsockopt");
00111 ABORT("setsockopt: cannot set TCP_NODELAY");
00112 }
00113 }
00114
00115 void SockUtil::fillSockAddr(const std::string& host, uint16_t port,
00116 struct sockaddr_in& sa) throw (AddressException) {
00117 fillSockAddr((uint32_t)Util::getAddr(host), port, sa);
00118 }
00119
00120 void SockUtil::fillSockAddr(uint32_t addr, uint16_t port, struct sockaddr_in& sa) {
00121 memset(&sa, 0, sizeof(sa));
00122 struct in_addr ina;
00123 ina.s_addr = addr;
00124 sa.sin_family = AF_INET;
00125 sa.sin_port = htons(port);
00126 sa.sin_addr = ina;
00127 }
00128
00129 void SockUtil::fillSockAddr(const SockAddr& addr, struct sockaddr_in& sa) {
00130 fillSockAddr(addr.addr, addr.port, sa);
00131 }
00132
00133 SockAddr SockUtil::getSockAddr(const std::string& hostname) throw (AddressException) {
00134 ASSERT(foo.initialized);
00135 uint16_t port = Util::getPort();
00136 size_t i = hostname.find(':');
00137 std::string host = hostname;
00138 if (i != std::string::npos) {
00139 host = hostname.substr(0, i);
00140 if (host == NAT_STRING) {
00141 return SockAddr(boost::lexical_cast<uint32_t>(hostname.substr(i + 1)), 0);
00142 }
00143 port = boost::lexical_cast<uint16_t>(hostname.substr(i + 1));
00144 }
00145 else if (host == NAT_STRING) {
00146 static uint32_t randIp = RandomUtil::randInt();
00147 return SockAddr(randIp, 0);
00148 }
00149
00150 uint32_t ip = Util::getAddr(host);
00151 return SockAddr(ip, port);
00152 }
00153
00154 int SockUtil::getErrno() {
00155 #if !(defined _WINSOCK2_H || defined _WINSOCK_H)
00156 return errno;
00157 #else
00158 return WSAGetLastError();
00159 #endif
00160 }
00161 bool SockUtil::errorWouldBlock(int err) {
00162 if (err == -1) { err = SockUtil::getErrno(); }
00163 #if !(defined _WINSOCK2_H || defined _WINSOCK_H)
00164 return (err == EAGAIN || err == EWOULDBLOCK || err == EINTR || err == EINPROGRESS);
00165 #else
00166 return (err == WSAEWOULDBLOCK || err == WSAEINPROGRESS || err == WSAEINTR);
00167 #endif
00168 }
00169 bool SockUtil::errorInterrupted(int err) {
00170 if (err == -1) { err = SockUtil::getErrno(); }
00171 #if !(defined _WINSOCK2_H || defined _WINSOCK_H)
00172 return (err == EINTR);
00173 #else
00174 return (err == WSAEINTR);
00175 #endif
00176 }
00177 bool SockUtil::errorBadF(int err) {
00178 if (err == -1) { err = SockUtil::getErrno(); }
00179 #if !(defined _WINSOCK2_H || defined _WINSOCK_H)
00180 return (err == EBADF);
00181 #else
00182 return (err == WSAEBADF);
00183 #endif
00184 }
00185 bool SockUtil::errorConnFail(int err) {
00186 if (err == -1) { err = SockUtil::getErrno(); }
00187 #if !(defined _WINSOCK2_H || defined _WINSOCK_H)
00188 return (err == ECONNABORTED || err == EPROTO);
00189 #else
00190 return (err == WSAECONNABORTED || err == WSAEPROTONOSUPPORT || err == WSAEPROTOTYPE || err == WSAENOPROTOOPT || err == WSAESOCKTNOSUPPORT);
00191 #endif
00192 }
00193 bool SockUtil::errorTransient(int err) {
00194 if (err == -1) { err = SockUtil::getErrno(); }
00195 #if !(defined _WINSOCK2_H || defined _WINSOCK_H)
00196 return (err == ENFILE || err == EMFILE || err == ENOBUFS || err == ENOMEM);
00197 #else
00198 return (err == WSAENOBUFS || err == WSAEMFILE || err == WSAEINTR);
00199 #endif
00200 }
00201 bool SockUtil::errorNotConnected(int err) {
00202 if (err == -1) { err = SockUtil::getErrno(); }
00203 #if !(defined _WINSOCK2_H || defined _WINSOCK_H)
00204 # ifdef EINVAL_IS_NOTCONN
00205 return (err == ENOTCONN || err == EINVAL);
00206 # else
00207 return (err == ENOTCONN);
00208 # endif
00209 #else
00210 return (err == WSAENOTCONN);
00211 #endif
00212 }