| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | |
| 3 * | |
| 4 * Use of this source code is governed by a BSD-style license | |
| 5 * that can be found in the LICENSE file in the root of the source | |
| 6 * tree. An additional intellectual property rights grant can be found | |
| 7 * in the file PATENTS. All contributing project authors may | |
| 8 * be found in the AUTHORS file in the root of the source tree. | |
| 9 */ | |
| 10 | |
| 11 #include "webrtc/test/channel_transport/udp_socket_posix.h" | |
| 12 | |
| 13 #include <errno.h> | |
| 14 #include <fcntl.h> | |
| 15 #include <netdb.h> | |
| 16 #include <stdio.h> | |
| 17 #include <string.h> | |
| 18 #include <sys/ioctl.h> | |
| 19 #include <sys/types.h> | |
| 20 #include <time.h> | |
| 21 #include <unistd.h> | |
| 22 | |
| 23 #include "webrtc/system_wrappers/include/trace.h" | |
| 24 #include "webrtc/test/channel_transport/udp_socket_manager_wrapper.h" | |
| 25 #include "webrtc/test/channel_transport/udp_socket_wrapper.h" | |
| 26 | |
| 27 namespace webrtc { | |
| 28 namespace test { | |
| 29 UdpSocketPosix::UdpSocketPosix(const int32_t id, UdpSocketManager* mgr, | |
| 30 bool ipV6Enable) | |
| 31 : _id(id), | |
| 32 _closeBlockingCompletedCond(true, false), | |
| 33 _readyForDeletionCond(true, false) | |
| 34 { | |
| 35 WEBRTC_TRACE(kTraceMemory, kTraceTransport, id, | |
| 36 "UdpSocketPosix::UdpSocketPosix()"); | |
| 37 | |
| 38 _wantsIncoming = false; | |
| 39 _mgr = mgr; | |
| 40 | |
| 41 _obj = NULL; | |
| 42 _incomingCb = NULL; | |
| 43 _readyForDeletion = false; | |
| 44 _closeBlockingActive = false; | |
| 45 _closeBlockingCompleted = false; | |
| 46 if(ipV6Enable) | |
| 47 { | |
| 48 _socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); | |
| 49 } | |
| 50 else { | |
| 51 _socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); | |
| 52 } | |
| 53 | |
| 54 // Set socket to nonblocking mode. | |
| 55 int enable_non_blocking = 1; | |
| 56 if(ioctl(_socket, FIONBIO, &enable_non_blocking) == -1) | |
| 57 { | |
| 58 WEBRTC_TRACE(kTraceWarning, kTraceTransport, id, | |
| 59 "Failed to make socket nonblocking"); | |
| 60 } | |
| 61 // Enable close on fork for file descriptor so that it will not block until | |
| 62 // forked process terminates. | |
| 63 if(fcntl(_socket, F_SETFD, FD_CLOEXEC) == -1) | |
| 64 { | |
| 65 WEBRTC_TRACE(kTraceWarning, kTraceTransport, id, | |
| 66 "Failed to set FD_CLOEXEC for socket"); | |
| 67 } | |
| 68 } | |
| 69 | |
| 70 UdpSocketPosix::~UdpSocketPosix() | |
| 71 { | |
| 72 if(_socket != INVALID_SOCKET) | |
| 73 { | |
| 74 close(_socket); | |
| 75 _socket = INVALID_SOCKET; | |
| 76 } | |
| 77 } | |
| 78 | |
| 79 bool UdpSocketPosix::SetCallback(CallbackObj obj, IncomingSocketCallback cb) | |
| 80 { | |
| 81 _obj = obj; | |
| 82 _incomingCb = cb; | |
| 83 | |
| 84 WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id, | |
| 85 "UdpSocketPosix(%p)::SetCallback", this); | |
| 86 | |
| 87 if (_mgr->AddSocket(this)) | |
| 88 { | |
| 89 WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id, | |
| 90 "UdpSocketPosix(%p)::SetCallback socket added to manager", | |
| 91 this); | |
| 92 return true; // socket is now ready for action | |
| 93 } | |
| 94 | |
| 95 WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id, | |
| 96 "UdpSocketPosix(%p)::SetCallback error adding me to mgr", | |
| 97 this); | |
| 98 return false; | |
| 99 } | |
| 100 | |
| 101 bool UdpSocketPosix::SetSockopt(int32_t level, int32_t optname, | |
| 102 const int8_t* optval, int32_t optlen) | |
| 103 { | |
| 104 if(0 == setsockopt(_socket, level, optname, optval, optlen )) | |
| 105 { | |
| 106 return true; | |
| 107 } | |
| 108 | |
| 109 WEBRTC_TRACE(kTraceError, kTraceTransport, _id, | |
| 110 "UdpSocketPosix::SetSockopt(), error:%d", errno); | |
| 111 return false; | |
| 112 } | |
| 113 | |
| 114 int32_t UdpSocketPosix::SetTOS(int32_t serviceType) | |
| 115 { | |
| 116 if (SetSockopt(IPPROTO_IP, IP_TOS ,(int8_t*)&serviceType ,4) != 0) | |
| 117 { | |
| 118 return -1; | |
| 119 } | |
| 120 return 0; | |
| 121 } | |
| 122 | |
| 123 bool UdpSocketPosix::Bind(const SocketAddress& name) | |
| 124 { | |
| 125 int size = sizeof(sockaddr); | |
| 126 if (0 == bind(_socket, reinterpret_cast<const sockaddr*>(&name),size)) | |
| 127 { | |
| 128 return true; | |
| 129 } | |
| 130 WEBRTC_TRACE(kTraceError, kTraceTransport, _id, | |
| 131 "UdpSocketPosix::Bind() error: %d", errno); | |
| 132 return false; | |
| 133 } | |
| 134 | |
| 135 int32_t UdpSocketPosix::SendTo(const int8_t* buf, size_t len, | |
| 136 const SocketAddress& to) | |
| 137 { | |
| 138 int size = sizeof(sockaddr); | |
| 139 int retVal = sendto(_socket,buf, len, 0, | |
| 140 reinterpret_cast<const sockaddr*>(&to), size); | |
| 141 if(retVal == SOCKET_ERROR) | |
| 142 { | |
| 143 WEBRTC_TRACE(kTraceError, kTraceTransport, _id, | |
| 144 "UdpSocketPosix::SendTo() error: %d", errno); | |
| 145 } | |
| 146 | |
| 147 return retVal; | |
| 148 } | |
| 149 | |
| 150 SOCKET UdpSocketPosix::GetFd() { return _socket; } | |
| 151 | |
| 152 bool UdpSocketPosix::ValidHandle() | |
| 153 { | |
| 154 return _socket != INVALID_SOCKET; | |
| 155 } | |
| 156 | |
| 157 bool UdpSocketPosix::SetQos(int32_t /*serviceType*/, | |
| 158 int32_t /*tokenRate*/, | |
| 159 int32_t /*bucketSize*/, | |
| 160 int32_t /*peekBandwith*/, | |
| 161 int32_t /*minPolicedSize*/, | |
| 162 int32_t /*maxSduSize*/, | |
| 163 const SocketAddress& /*stRemName*/, | |
| 164 int32_t /*overrideDSCP*/) { | |
| 165 return false; | |
| 166 } | |
| 167 | |
| 168 void UdpSocketPosix::HasIncoming() | |
| 169 { | |
| 170 // replace 2048 with a mcro define and figure out | |
| 171 // where 2048 comes from | |
| 172 int8_t buf[2048]; | |
| 173 int retval; | |
| 174 SocketAddress from; | |
| 175 #if defined(WEBRTC_MAC) | |
| 176 sockaddr sockaddrfrom; | |
| 177 memset(&from, 0, sizeof(from)); | |
| 178 memset(&sockaddrfrom, 0, sizeof(sockaddrfrom)); | |
| 179 socklen_t fromlen = sizeof(sockaddrfrom); | |
| 180 #else | |
| 181 memset(&from, 0, sizeof(from)); | |
| 182 socklen_t fromlen = sizeof(from); | |
| 183 #endif | |
| 184 | |
| 185 #if defined(WEBRTC_MAC) | |
| 186 retval = recvfrom(_socket,buf, sizeof(buf), 0, | |
| 187 reinterpret_cast<sockaddr*>(&sockaddrfrom), &fromlen); | |
| 188 memcpy(&from, &sockaddrfrom, fromlen); | |
| 189 from._sockaddr_storage.sin_family = sockaddrfrom.sa_family; | |
| 190 #else | |
| 191 retval = recvfrom(_socket,buf, sizeof(buf), 0, | |
| 192 reinterpret_cast<sockaddr*>(&from), &fromlen); | |
| 193 #endif | |
| 194 | |
| 195 switch(retval) | |
| 196 { | |
| 197 case 0: | |
| 198 // The peer has performed an orderly shutdown. | |
| 199 break; | |
| 200 case SOCKET_ERROR: | |
| 201 break; | |
| 202 default: | |
| 203 if (_wantsIncoming && _incomingCb) | |
| 204 { | |
| 205 _incomingCb(_obj, buf, retval, &from); | |
| 206 } | |
| 207 break; | |
| 208 } | |
| 209 } | |
| 210 | |
| 211 bool UdpSocketPosix::WantsIncoming() { return _wantsIncoming; } | |
| 212 | |
| 213 void UdpSocketPosix::CloseBlocking() | |
| 214 { | |
| 215 rtc::CritScope lock(&_cs); | |
| 216 _closeBlockingActive = true; | |
| 217 if(!CleanUp()) | |
| 218 { | |
| 219 _closeBlockingActive = false; | |
| 220 return; | |
| 221 } | |
| 222 | |
| 223 if(!_readyForDeletion) | |
| 224 { | |
| 225 _cs.Leave(); | |
| 226 _readyForDeletionCond.Wait(rtc::Event::kForever); | |
| 227 _cs.Enter(); | |
| 228 } | |
| 229 _closeBlockingCompleted = true; | |
| 230 _closeBlockingCompletedCond.Set(); | |
| 231 } | |
| 232 | |
| 233 void UdpSocketPosix::ReadyForDeletion() | |
| 234 { | |
| 235 rtc::CritScope lock(&_cs); | |
| 236 if(!_closeBlockingActive) | |
| 237 { | |
| 238 return; | |
| 239 } | |
| 240 | |
| 241 close(_socket); | |
| 242 _socket = INVALID_SOCKET; | |
| 243 _readyForDeletion = true; | |
| 244 _readyForDeletionCond.Set(); | |
| 245 if(!_closeBlockingCompleted) | |
| 246 { | |
| 247 _cs.Leave(); | |
| 248 _closeBlockingCompletedCond.Wait(rtc::Event::kForever); | |
| 249 _cs.Enter(); | |
| 250 } | |
| 251 } | |
| 252 | |
| 253 bool UdpSocketPosix::CleanUp() | |
| 254 { | |
| 255 _wantsIncoming = false; | |
| 256 | |
| 257 if (_socket == INVALID_SOCKET) | |
| 258 { | |
| 259 return false; | |
| 260 } | |
| 261 | |
| 262 WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id, | |
| 263 "calling UdpSocketManager::RemoveSocket()..."); | |
| 264 _mgr->RemoveSocket(this); | |
| 265 // After this, the socket should may be or will be as deleted. Return | |
| 266 // immediately. | |
| 267 return true; | |
| 268 } | |
| 269 | |
| 270 } // namespace test | |
| 271 } // namespace webrtc | |
| OLD | NEW |