diff options
Diffstat (limited to 'src/udpsocket.cpp')
| -rw-r--r-- | src/udpsocket.cpp | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/src/udpsocket.cpp b/src/udpsocket.cpp new file mode 100644 index 0000000..91e04c1 --- /dev/null +++ b/src/udpsocket.cpp | |||
| @@ -0,0 +1,240 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2007-2011 Xagasoft, All rights reserved. | ||
| 3 | * | ||
| 4 | * This file is part of the libbu++ library and is released under the | ||
| 5 | * terms of the license contained in the file LICENSE. | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include "bu/udpsocket.h" | ||
| 9 | |||
| 10 | #include "bu/sio.h" | ||
| 11 | using namespace Bu; | ||
| 12 | #include <fcntl.h> | ||
| 13 | |||
| 14 | #include <errno.h> | ||
| 15 | #include <arpa/inet.h> | ||
| 16 | #include <sys/socket.h> | ||
| 17 | #include <netinet/in.h> | ||
| 18 | #include <sys/utsname.h> | ||
| 19 | |||
| 20 | namespace Bu { subExceptionDef( UdpSocketException ) } | ||
| 21 | |||
| 22 | #define saTarget ( *((struct sockaddr_in *)paTarget) ) | ||
| 23 | |||
| 24 | Bu::UdpSocket::UdpSocket( int iUdpSocket ) : | ||
| 25 | iUdpSocket( iUdpSocket ), | ||
| 26 | paTarget( NULL ), | ||
| 27 | bBound( false ) | ||
| 28 | { | ||
| 29 | } | ||
| 30 | |||
| 31 | Bu::UdpSocket::UdpSocket( const Bu::String &sAddr, int iPort, int iFlags ) : | ||
| 32 | iUdpSocket( 0 ), | ||
| 33 | paTarget( NULL ), | ||
| 34 | bBound( false ) | ||
| 35 | { | ||
| 36 | iUdpSocket = socket( PF_INET, SOCK_DGRAM, 0 ); | ||
| 37 | if( iUdpSocket < 0 ) | ||
| 38 | { | ||
| 39 | throw UdpSocketException("Couldn't open udp socket: %s", | ||
| 40 | strerror( errno ) | ||
| 41 | ); | ||
| 42 | } | ||
| 43 | |||
| 44 | if( (iFlags&Broadcast) ) | ||
| 45 | { | ||
| 46 | int broadcast = 1; | ||
| 47 | if( (setsockopt( iUdpSocket, SOL_SOCKET, SO_BROADCAST, | ||
| 48 | &broadcast, sizeof(broadcast) )) == -1) | ||
| 49 | { | ||
| 50 | throw UdpSocketException("Couldn't set udp socket to broadcast: %s", | ||
| 51 | strerror( errno ) | ||
| 52 | ); | ||
| 53 | } | ||
| 54 | } | ||
| 55 | |||
| 56 | paTarget = new struct sockaddr_in; | ||
| 57 | saTarget.sin_family = AF_INET; | ||
| 58 | saTarget.sin_port = htons( iPort ); | ||
| 59 | saTarget.sin_addr.s_addr = inet_addr( sAddr.getStr() ); // INADDR_ANY; | ||
| 60 | memset( saTarget.sin_zero, '\0', sizeof(saTarget.sin_zero) ); | ||
| 61 | |||
| 62 | if( (iFlags&Read) ) | ||
| 63 | { | ||
| 64 | if( bind( iUdpSocket, (struct sockaddr*)paTarget, sizeof(struct sockaddr_in) ) | ||
| 65 | == -1 ) | ||
| 66 | { | ||
| 67 | throw UdpSocketException("Couldn't bind port to udp socket: %s", | ||
| 68 | strerror( errno ) | ||
| 69 | ); | ||
| 70 | } | ||
| 71 | bBound = true; | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 75 | Bu::UdpSocket::~UdpSocket() | ||
| 76 | { | ||
| 77 | close(); | ||
| 78 | delete (struct sockaddr_in *)paTarget; | ||
| 79 | paTarget = NULL; | ||
| 80 | } | ||
| 81 | |||
| 82 | Bu::String Bu::UdpSocket::addrToStr( const addr &a ) | ||
| 83 | { | ||
| 84 | Bu::String sOut; | ||
| 85 | sOut.format("%d.%d.%d.%d", | ||
| 86 | (a&0xff), | ||
| 87 | (a&0xff00)>>8, | ||
| 88 | (a&0xff0000)>>16, | ||
| 89 | (a&0xff000000)>>24 | ||
| 90 | ); | ||
| 91 | |||
| 92 | return sOut; | ||
| 93 | } | ||
| 94 | |||
| 95 | void Bu::UdpSocket::close() | ||
| 96 | { | ||
| 97 | ::close( iUdpSocket ); | ||
| 98 | } | ||
| 99 | |||
| 100 | Bu::size Bu::UdpSocket::read( void *pBuf, Bu::size nBytes ) | ||
| 101 | { | ||
| 102 | return recv( iUdpSocket, pBuf, nBytes, 0 ); | ||
| 103 | } | ||
| 104 | |||
| 105 | Bu::size Bu::UdpSocket::read( void *pBuf, Bu::size nBytes, | ||
| 106 | Bu::UdpSocket::addr &aHost, int &iPort ) | ||
| 107 | { | ||
| 108 | sockaddr_in name; | ||
| 109 | size_t size = sizeof(name); | ||
| 110 | Bu::size ret = recvfrom( iUdpSocket, pBuf, nBytes, 0, | ||
| 111 | (struct sockaddr *)&name, &size ); | ||
| 112 | aHost = name.sin_addr.s_addr; | ||
| 113 | iPort = ntohs(name.sin_port); | ||
| 114 | return ret; | ||
| 115 | } | ||
| 116 | |||
| 117 | Bu::size Bu::UdpSocket::write( const void *pBuf, Bu::size nBytes ) | ||
| 118 | { | ||
| 119 | if( bBound ) | ||
| 120 | { | ||
| 121 | return sendto( iUdpSocket, pBuf, nBytes, 0, NULL, 0 ); | ||
| 122 | } | ||
| 123 | else | ||
| 124 | { | ||
| 125 | return sendto( iUdpSocket, pBuf, nBytes, 0, | ||
| 126 | (struct sockaddr*)paTarget, sizeof(struct sockaddr_in) ); | ||
| 127 | } | ||
| 128 | } | ||
| 129 | |||
| 130 | Bu::size Bu::UdpSocket::tell() | ||
| 131 | { | ||
| 132 | throw Bu::UnsupportedException(); | ||
| 133 | } | ||
| 134 | |||
| 135 | void Bu::UdpSocket::seek( Bu::size ) | ||
| 136 | { | ||
| 137 | throw Bu::UnsupportedException(); | ||
| 138 | } | ||
| 139 | |||
| 140 | void Bu::UdpSocket::setPos( Bu::size ) | ||
| 141 | { | ||
| 142 | throw Bu::UnsupportedException(); | ||
| 143 | } | ||
| 144 | |||
| 145 | void Bu::UdpSocket::setPosEnd( Bu::size ) | ||
| 146 | { | ||
| 147 | throw Bu::UnsupportedException(); | ||
| 148 | } | ||
| 149 | |||
| 150 | bool Bu::UdpSocket::isEos() | ||
| 151 | { | ||
| 152 | return false; | ||
| 153 | } | ||
| 154 | |||
| 155 | bool Bu::UdpSocket::isOpen() | ||
| 156 | { | ||
| 157 | return true; | ||
| 158 | } | ||
| 159 | |||
| 160 | void Bu::UdpSocket::flush() | ||
| 161 | { | ||
| 162 | } | ||
| 163 | |||
| 164 | bool Bu::UdpSocket::canRead() | ||
| 165 | { | ||
| 166 | return bBound; | ||
| 167 | } | ||
| 168 | |||
| 169 | bool Bu::UdpSocket::canWrite() | ||
| 170 | { | ||
| 171 | return true; | ||
| 172 | } | ||
| 173 | |||
| 174 | bool Bu::UdpSocket::isReadable() | ||
| 175 | { | ||
| 176 | return bBound; | ||
| 177 | } | ||
| 178 | |||
| 179 | bool Bu::UdpSocket::isWritable() | ||
| 180 | { | ||
| 181 | return true; | ||
| 182 | } | ||
| 183 | |||
| 184 | bool Bu::UdpSocket::isSeekable() | ||
| 185 | { | ||
| 186 | return false; | ||
| 187 | } | ||
| 188 | |||
| 189 | bool Bu::UdpSocket::isBlocking() | ||
| 190 | { | ||
| 191 | return true; | ||
| 192 | } | ||
| 193 | |||
| 194 | void Bu::UdpSocket::setBlocking( bool bBlocking ) | ||
| 195 | { | ||
| 196 | #ifndef WIN32 | ||
| 197 | if( bBlocking ) | ||
| 198 | { | ||
| 199 | fcntl( iUdpSocket, F_SETFL, fcntl( iUdpSocket, F_GETFL, 0 ) & (~O_NONBLOCK) ); | ||
| 200 | } | ||
| 201 | else | ||
| 202 | { | ||
| 203 | fcntl( iUdpSocket, F_SETFL, fcntl( iUdpSocket, F_GETFL, 0 ) | O_NONBLOCK ); | ||
| 204 | } | ||
| 205 | #else | ||
| 206 | u_long iMode; | ||
| 207 | if( bBlocking ) | ||
| 208 | iMode = 0; | ||
| 209 | else | ||
| 210 | iMode = 1; | ||
| 211 | //------------------------- | ||
| 212 | // Set the socket I/O mode: In this case FIONBIO | ||
| 213 | // enables or disables the blocking mode for the | ||
| 214 | // socket based on the numerical value of iMode. | ||
| 215 | // If iMode = 0, blocking is enabled; | ||
| 216 | // If iMode != 0, non-blocking mode is enabled. | ||
| 217 | bu_ioctlsocket(iUdpSocket, FIONBIO, &iMode); | ||
| 218 | #endif | ||
| 219 | } | ||
| 220 | |||
| 221 | void Bu::UdpSocket::setSize( Bu::size ) | ||
| 222 | { | ||
| 223 | throw Bu::UnsupportedException(); | ||
| 224 | } | ||
| 225 | |||
| 226 | Bu::size Bu::UdpSocket::getSize() const | ||
| 227 | { | ||
| 228 | throw Bu::UnsupportedException(); | ||
| 229 | } | ||
| 230 | |||
| 231 | Bu::size Bu::UdpSocket::getBlockSize() const | ||
| 232 | { | ||
| 233 | return 1500; | ||
| 234 | } | ||
| 235 | |||
| 236 | Bu::String Bu::UdpSocket::getLocation() const | ||
| 237 | { | ||
| 238 | throw Bu::UnsupportedException(); | ||
| 239 | } | ||
| 240 | |||
