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
00034
00035
00036
00037
00038
00039
00040
00041 #ifndef WIN32
00042 #include <netdb.h>
00043 #include <arpa/inet.h>
00044 #include <unistd.h>
00045 #include <fcntl.h>
00046 #include <cstring>
00047 #include <cstdio>
00048 #include <cerrno>
00049 #else
00050 #include <winsock2.h>
00051 #include <ws2tcpip.h>
00052 #ifdef LEGACY_WIN32
00053 #include <wspiapi.h>
00054 #endif
00055 #endif
00056 #include "channel.h"
00057 #include "packet.h"
00058
00059 #ifdef WIN32
00060 #define socklen_t int
00061 #endif
00062
00063 #ifndef WIN32
00064 #define NET_ERROR errno
00065 #else
00066 #define NET_ERROR WSAGetLastError()
00067 #endif
00068
00069
00070 CChannel::CChannel():
00071 m_iIPversion(AF_INET),
00072 m_iSockAddrSize(sizeof(sockaddr_in)),
00073 m_iSocket(),
00074 m_iSndBufSize(65536),
00075 m_iRcvBufSize(65536)
00076 {
00077 }
00078
00079 CChannel::CChannel(int version):
00080 m_iIPversion(version),
00081 m_iSocket(),
00082 m_iSndBufSize(65536),
00083 m_iRcvBufSize(65536)
00084 {
00085 m_iSockAddrSize = (AF_INET == m_iIPversion) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
00086 }
00087
00088 CChannel::~CChannel()
00089 {
00090 }
00091
00092 void CChannel::open(const sockaddr* addr)
00093 {
00094
00095 m_iSocket = ::socket(m_iIPversion, SOCK_DGRAM, 0);
00096
00097 #ifdef WIN32
00098 if (INVALID_SOCKET == m_iSocket)
00099 #else
00100 if (m_iSocket < 0)
00101 #endif
00102 throw CUDTException(1, 0, NET_ERROR);
00103
00104 if (NULL != addr)
00105 {
00106 socklen_t namelen = m_iSockAddrSize;
00107
00108 if (0 != ::bind(m_iSocket, addr, namelen))
00109 throw CUDTException(1, 3, NET_ERROR);
00110 }
00111 else
00112 {
00113
00114 addrinfo hints;
00115 addrinfo* res;
00116
00117 memset(&hints, 0, sizeof(struct addrinfo));
00118
00119 hints.ai_flags = AI_PASSIVE;
00120 hints.ai_family = m_iIPversion;
00121 hints.ai_socktype = SOCK_DGRAM;
00122
00123 if (0 != ::getaddrinfo(NULL, "0", &hints, &res))
00124 throw CUDTException(1, 3, NET_ERROR);
00125
00126 if (0 != ::bind(m_iSocket, res->ai_addr, res->ai_addrlen))
00127 throw CUDTException(1, 3, NET_ERROR);
00128
00129 ::freeaddrinfo(res);
00130 }
00131
00132 setUDPSockOpt();
00133 }
00134
00135 void CChannel::open(UDPSOCKET udpsock)
00136 {
00137 m_iSocket = udpsock;
00138 setUDPSockOpt();
00139 }
00140
00141 void CChannel::setUDPSockOpt()
00142 {
00143 #if defined(BSD) || defined(OSX)
00144
00145 int maxsize = 64000;
00146 if (0 != ::setsockopt(m_iSocket, SOL_SOCKET, SO_RCVBUF, (char*)&m_iRcvBufSize, sizeof(int)))
00147 ::setsockopt(m_iSocket, SOL_SOCKET, SO_RCVBUF, (char*)&maxsize, sizeof(int));
00148 if (0 != ::setsockopt(m_iSocket, SOL_SOCKET, SO_SNDBUF, (char*)&m_iSndBufSize, sizeof(int)))
00149 ::setsockopt(m_iSocket, SOL_SOCKET, SO_SNDBUF, (char*)&maxsize, sizeof(int));
00150 #else
00151
00152 if ((0 != ::setsockopt(m_iSocket, SOL_SOCKET, SO_RCVBUF, (char*)&m_iRcvBufSize, sizeof(int))) ||
00153 (0 != ::setsockopt(m_iSocket, SOL_SOCKET, SO_SNDBUF, (char*)&m_iSndBufSize, sizeof(int))))
00154 throw CUDTException(1, 3, NET_ERROR);
00155 #endif
00156
00157 timeval tv;
00158 tv.tv_sec = 0;
00159 #if defined (BSD) || defined (OSX)
00160
00161
00162 tv.tv_usec = 10000;
00163 #else
00164 tv.tv_usec = 100;
00165 #endif
00166
00167 #ifdef UNIX
00168
00169
00170 int opts = ::fcntl(m_iSocket, F_GETFL);
00171 if (-1 == ::fcntl(m_iSocket, F_SETFL, opts | O_NONBLOCK))
00172 throw CUDTException(1, 3, NET_ERROR);
00173 #elif WIN32
00174 DWORD ot = 1;
00175 if (0 != ::setsockopt(m_iSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&ot, sizeof(DWORD)))
00176 throw CUDTException(1, 3, NET_ERROR);
00177 #else
00178
00179 if (0 != ::setsockopt(m_iSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(timeval)))
00180 throw CUDTException(1, 3, NET_ERROR);
00181 #endif
00182 }
00183
00184 void CChannel::close() const
00185 {
00186 #ifndef WIN32
00187 ::close(m_iSocket);
00188 #else
00189 ::closesocket(m_iSocket);
00190 #endif
00191 }
00192
00193 int CChannel::getSndBufSize()
00194 {
00195 socklen_t size = sizeof(socklen_t);
00196 ::getsockopt(m_iSocket, SOL_SOCKET, SO_SNDBUF, (char *)&m_iSndBufSize, &size);
00197 return m_iSndBufSize;
00198 }
00199
00200 int CChannel::getRcvBufSize()
00201 {
00202 socklen_t size = sizeof(socklen_t);
00203 ::getsockopt(m_iSocket, SOL_SOCKET, SO_RCVBUF, (char *)&m_iRcvBufSize, &size);
00204 return m_iRcvBufSize;
00205 }
00206
00207 void CChannel::setSndBufSize(int size)
00208 {
00209 m_iSndBufSize = size;
00210 }
00211
00212 void CChannel::setRcvBufSize(int size)
00213 {
00214 m_iRcvBufSize = size;
00215 }
00216
00217 void CChannel::getSockAddr(sockaddr* addr) const
00218 {
00219 socklen_t namelen = m_iSockAddrSize;
00220 ::getsockname(m_iSocket, addr, &namelen);
00221 }
00222
00223 void CChannel::getPeerAddr(sockaddr* addr) const
00224 {
00225 socklen_t namelen = m_iSockAddrSize;
00226 ::getpeername(m_iSocket, addr, &namelen);
00227 }
00228
00229 int CChannel::sendto(const sockaddr* addr, CPacket& packet) const
00230 {
00231
00232 if (packet.getFlag())
00233 for (int i = 0, n = packet.getLength() / 4; i < n; ++ i)
00234 *((uint32_t *)packet.m_pcData + i) = htonl(*((uint32_t *)packet.m_pcData + i));
00235
00236
00237
00238
00239 uint32_t* p = packet.m_nHeader;
00240 for (int j = 0; j < 4; ++ j)
00241 {
00242 *p = htonl(*p);
00243 ++ p;
00244 }
00245
00246 #ifndef WIN32
00247 msghdr mh;
00248 mh.msg_name = (sockaddr*)addr;
00249 mh.msg_namelen = m_iSockAddrSize;
00250 mh.msg_iov = (iovec*)packet.m_PacketVector;
00251 mh.msg_iovlen = 2;
00252 mh.msg_control = NULL;
00253 mh.msg_controllen = 0;
00254 mh.msg_flags = 0;
00255
00256 int res = ::sendmsg(m_iSocket, &mh, 0);
00257 #else
00258 DWORD size = CPacket::m_iPktHdrSize + packet.getLength();
00259 int addrsize = m_iSockAddrSize;
00260 int res = ::WSASendTo(m_iSocket, (LPWSABUF)packet.m_PacketVector, 2, &size, 0, addr, addrsize, NULL, NULL);
00261 res = (0 == res) ? size : -1;
00262 #endif
00263
00264
00265
00266
00267 p = packet.m_nHeader;
00268 for (int k = 0; k < 4; ++ k)
00269 {
00270 *p = ntohl(*p);
00271 ++ p;
00272 }
00273
00274 if (packet.getFlag())
00275 {
00276 for (int l = 0, n = packet.getLength() / 4; l < n; ++ l)
00277 *((uint32_t *)packet.m_pcData + l) = ntohl(*((uint32_t *)packet.m_pcData + l));
00278 }
00279
00280 return res;
00281 }
00282
00283 int CChannel::recvfrom(sockaddr* addr, CPacket& packet) const
00284 {
00285 #ifndef WIN32
00286 msghdr mh;
00287 mh.msg_name = addr;
00288 mh.msg_namelen = m_iSockAddrSize;
00289 mh.msg_iov = packet.m_PacketVector;
00290 mh.msg_iovlen = 2;
00291 mh.msg_control = NULL;
00292 mh.msg_controllen = 0;
00293 mh.msg_flags = 0;
00294
00295 #ifdef UNIX
00296 fd_set set;
00297 timeval tv;
00298 FD_ZERO(&set);
00299 FD_SET(m_iSocket, &set);
00300 tv.tv_sec = 0;
00301 tv.tv_usec = 10000;
00302 ::select(m_iSocket+1, &set, NULL, &set, &tv);
00303 #endif
00304
00305 int res = ::recvmsg(m_iSocket, &mh, 0);
00306 #else
00307 DWORD size = CPacket::m_iPktHdrSize + packet.getLength();
00308 DWORD flag = 0;
00309 int addrsize = m_iSockAddrSize;
00310
00311 int res = ::WSARecvFrom(m_iSocket, (LPWSABUF)packet.m_PacketVector, 2, &size, &flag, addr, &addrsize, NULL, NULL);
00312 res = (0 == res) ? size : -1;
00313 #endif
00314
00315 if (res <= 0)
00316 {
00317 packet.setLength(-1);
00318 return -1;
00319 }
00320
00321 packet.setLength(res - CPacket::m_iPktHdrSize);
00322
00323
00324
00325
00326 uint32_t* p = packet.m_nHeader;
00327 for (int i = 0; i < 4; ++ i)
00328 {
00329 *p = ntohl(*p);
00330 ++ p;
00331 }
00332
00333 if (packet.getFlag())
00334 {
00335 for (int j = 0, n = packet.getLength() / 4; j < n; ++ j)
00336 *((uint32_t *)packet.m_pcData + j) = ntohl(*((uint32_t *)packet.m_pcData + j));
00337 }
00338
00339 return packet.getLength();
00340 }