| 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 | 
|---|