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
00042
00043 #include <sys/types.h>
00044 #ifdef WIN32
00045 #include <windows.h>
00046 #ifndef IP_ADD_MEMBERSHIP // VS.Net defines this within winsock2.h
00047 #include <WS2TCPIP.h>
00048 #endif
00049 #include <io.h>
00050 #else
00051 #include <sys/socket.h>
00052 #include <netinet/in.h>
00053 #include <netinet/tcp.h>
00054 #include <arpa/inet.h>
00055 #include <netdb.h>
00056 #include <unistd.h>
00057 #include <fcntl.h>
00058 #include <sys/time.h>
00059 #endif
00060 #include <errno.h>
00061 #include <stdio.h>
00062 #include <math.h>
00063 #include <map>
00064 #include <OSGBase.h>
00065 #include <OSGBaseFunctions.h>
00066 #include <OSGSocketAddress.h>
00067 #include <OSGDgramSocket.h>
00068 #include <OSGNetworkMessage.h>
00069
00070 OSG_USING_NAMESPACE
00071
00093
00094
00095
00100 DgramSocket::DgramSocket():
00101 Socket()
00102 {
00103 }
00104
00107 DgramSocket::DgramSocket(const DgramSocket &source):
00108 Socket(source)
00109 {
00110 }
00111
00112
00113
00114
00119 void DgramSocket::open()
00120 {
00121 _sd = socket(AF_INET, SOCK_DGRAM, 0);
00122 if(_sd<0)
00123 {
00124 throw SocketError("socket()");
00125 }
00126
00127 int on = 1;
00128 if(::setsockopt(_sd,
00129 SOL_SOCKET, SO_BROADCAST,
00130 (SocketOptT*)&on, sizeof(on)) < 0)
00131 {
00132 throw SocketError("setsockopt(,SOL_SOCKET,SO_BROADCAST)");
00133 }
00134
00135 setTTL(2);
00136 }
00137
00140 void DgramSocket::close(void)
00141 {
00142 #ifdef WIN32
00143 ::closesocket(_sd);
00144 #else
00145 ::close(_sd);
00146 #endif
00147 }
00148
00149
00150
00151
00157 int DgramSocket::recvFrom(void *buf,int size,SocketAddress &from)
00158 {
00159 int len;
00160 SocketLenT addrLen=from.getSockAddrSize();
00161
00162 #ifndef WIN32
00163 do
00164 {
00165 #endif
00166 len=recvfrom(_sd,
00167 (char*)buf,
00168 size,
00169 0,
00170 from.getSockAddr(),
00171 &addrLen);
00172 #ifndef WIN32
00173 }
00174 while(len < 0 && errno == EAGAIN);
00175 #endif
00176
00177 if(len < 0)
00178 {
00179 #if defined WIN32
00180 if(getError() == WSAECONNRESET)
00181 {
00182 throw SocketConnReset("recvfrom");
00183 }
00184 if(getError() == WSAEMSGSIZE)
00185 {
00186 len=size;
00187 }
00188 else
00189 #endif
00190 throw SocketError("recvfrom()");
00191 }
00192 return len;
00193 }
00194
00202 int DgramSocket::peekFrom(void *buf,int size,SocketAddress &from)
00203 {
00204 int len;
00205 SocketLenT addrLen=from.getSockAddrSize();
00206
00207 len=recvfrom(_sd,
00208 (char*)buf,
00209 size,
00210 MSG_PEEK,
00211 from.getSockAddr(),
00212 &addrLen);
00213 if(len == -1)
00214 {
00215 #if defined WIN32
00216 if(getError() == WSAECONNRESET)
00217 {
00218 throw SocketConnReset("recvfrom");
00219 }
00220 if(getError() == WSAEMSGSIZE)
00221 {
00222 len=size;
00223 }
00224 else
00225 #endif
00226 throw SocketError("recvfrom()");
00227 }
00228 return len;
00229 }
00230
00235 int DgramSocket::recvFrom(NetworkMessage &msg,SocketAddress &from)
00236 {
00237 NetworkMessage::Header hdr;
00238 peek(&hdr,sizeof(hdr));
00239 msg.setSize(osgntohl(hdr.size));
00240 return recvFrom(msg.getBuffer(),msg.getSize(),from);
00241 }
00242
00247 int DgramSocket::sendTo(const void *buf,int size,const SocketAddress &to)
00248 {
00249 int len;
00250
00251
00252 len=sendto(_sd,
00253 (const char*)buf,size,
00254 #if defined(WIN32) && defined(MSG_NOSIGNAL)
00255 MSG_NOSIGNAL,
00256 #else
00257 0,
00258 #endif
00259 to.getSockAddr(),
00260 to.getSockAddrSize());
00261 #ifdef _sgi
00262
00263
00264 while(len == -1 && errno == ENOBUFS)
00265 {
00266 usleep(100);
00267 len=sendto(_sd,
00268 (const char*)buf,size,
00269 0,
00270 to.getSockAddr(),
00271 to.getSockAddrSize());
00272 }
00273 #endif
00274
00275 if(len == -1)
00276 {
00277 throw SocketError("sendto()");
00278 }
00279 return len;
00280 }
00281
00286 int DgramSocket::sendTo(NetworkMessage &msg,const SocketAddress &to)
00287 {
00288 NetworkMessage::Header &hdr=msg.getHeader();
00289 hdr.size=osghtonl(msg.getSize());
00290 return sendTo(msg.getBuffer(),msg.getSize(),to);
00291 }
00292
00293
00294
00295
00299 void DgramSocket::join(const SocketAddress &group,const SocketAddress &interf)
00300 {
00301 struct ip_mreq joinAddr;
00302 int rc;
00303
00304
00305 joinAddr.imr_multiaddr.s_addr =
00306 ((sockaddr_in*)group.getSockAddr())->sin_addr.s_addr;
00307
00308
00309 joinAddr.imr_interface =
00310 ((struct sockaddr_in*)interf.getSockAddr())->sin_addr;
00311 rc=setsockopt(_sd,
00312 IPPROTO_IP,
00313 IP_ADD_MEMBERSHIP,
00314 (SocketOptT*)&joinAddr,
00315 sizeof(joinAddr));
00316 if(rc < 0)
00317 {
00318 throw SocketError("setsockopt(IPPROTO_IP,IP_ADD_MEMBERSHIP)");
00319 }
00320 }
00321
00324 void DgramSocket::leave(const SocketAddress &group,const SocketAddress &interf)
00325 {
00326 struct ip_mreq joinAddr;
00327 int rc;
00328
00329
00330 joinAddr.imr_multiaddr.s_addr =
00331 ((sockaddr_in*)group.getSockAddr())->sin_addr.s_addr;
00332
00333 joinAddr.imr_interface =
00334 ((sockaddr_in*)interf.getSockAddr())->sin_addr;
00335 rc=setsockopt(_sd,
00336 IPPROTO_IP,
00337 IP_DROP_MEMBERSHIP,
00338 (SocketOptT*)&joinAddr,
00339 sizeof(joinAddr));
00340 if(rc < 0)
00341 {
00342 throw SocketError("setsockopt(IPPROTO_IP,IP_DROP_MEMBERSHIP)");
00343 }
00344 }
00345
00350 void DgramSocket::setTTL(unsigned char ttl)
00351 {
00352 int rc=setsockopt(_sd, IPPROTO_IP,IP_MULTICAST_TTL,
00353 (SocketOptT*)&ttl,sizeof(ttl));
00354 if(rc < 0)
00355 {
00356 throw SocketError("setsockopt(IPPROTO_IP,IP_MULTICAST_TTL)");
00357 }
00358 }
00359
00363 void DgramSocket::setMCastInterface(const SocketAddress &interf)
00364 {
00365 int rc=setsockopt(_sd,
00366 IPPROTO_IP,
00367 IP_MULTICAST_IF,
00368 (SocketOptT*)interf.getSockAddr(),
00369 interf.getSockAddrSize());
00370 if(rc < 0)
00371 {
00372 throw SocketError("setsockopt(IPPROTO_IP,IP_MULTICAST_IF)");
00373 }
00374
00375 }
00376
00377
00378
00379
00382 const DgramSocket & DgramSocket::operator =(const DgramSocket &source)
00383 {
00384 _sd=source._sd;
00385 return *this;
00386 }
00387
00388
00389
00390
00391 #ifdef __sgi
00392 #pragma set woff 1174
00393 #endif
00394
00395 #ifdef OSG_LINUX_ICC
00396 #pragma warning( disable : 177 )
00397 #endif
00398
00399 namespace
00400 {
00401 static Char8 cvsid_cpp [] = "@(#)$Id: $";
00402 static Char8 cvsid_hpp [] = OSG_DGRAMSOCKET_HEADER_CVSID;
00403 }