Note: We no longer publish the latest version of our code here. We primarily use a kumc-bmi github organization. The heron ETL repository, in particular, is not public. Peers in the informatics community should see MultiSiteDev for details on requesting access.

source: webrtc/webrtc/test/channel_transport/udp_socket_posix.cc @ 0:4bda6873e34c

pub_scrub_3792 tip
Last change on this file since 0:4bda6873e34c was 0:4bda6873e34c, checked in by Michael Prittie <mprittie@…>, 6 years ago

Scrubbed password for publication.

File size: 7.7 KB
Line 
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/interface/trace.h"
24#include "webrtc/test/channel_transport/udp_socket_manager_wrapper.h"
25#include "webrtc/test/channel_transport/udp_socket_wrapper.h"
26
27namespace webrtc {
28namespace test {
29UdpSocketPosix::UdpSocketPosix(const int32_t id, UdpSocketManager* mgr,
30                               bool ipV6Enable)
31{
32    WEBRTC_TRACE(kTraceMemory, kTraceTransport, id,
33                 "UdpSocketPosix::UdpSocketPosix()");
34
35    _wantsIncoming = false;
36    _error = 0;
37    _mgr = mgr;
38
39    _id = id;
40    _obj = NULL;
41    _incomingCb = NULL;
42    _readyForDeletionCond = ConditionVariableWrapper::CreateConditionVariable();
43    _closeBlockingCompletedCond =
44        ConditionVariableWrapper::CreateConditionVariable();
45    _cs = CriticalSectionWrapper::CreateCriticalSection();
46    _readyForDeletion = false;
47    _closeBlockingActive = false;
48    _closeBlockingCompleted= false;
49    if(ipV6Enable)
50    {
51        _socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
52    }
53    else {
54        _socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
55    }
56
57    // Set socket to nonblocking mode.
58    int enable_non_blocking = 1;
59    if(ioctl(_socket, FIONBIO, &enable_non_blocking) == -1)
60    {
61        WEBRTC_TRACE(kTraceWarning, kTraceTransport, id,
62                     "Failed to make socket nonblocking");
63    }
64    // Enable close on fork for file descriptor so that it will not block until
65    // forked process terminates.
66    if(fcntl(_socket, F_SETFD, FD_CLOEXEC) == -1)
67    {
68        WEBRTC_TRACE(kTraceWarning, kTraceTransport, id,
69                     "Failed to set FD_CLOEXEC for socket");
70    }
71}
72
73UdpSocketPosix::~UdpSocketPosix()
74{
75    if(_socket != INVALID_SOCKET)
76    {
77        close(_socket);
78        _socket = INVALID_SOCKET;
79    }
80    if(_readyForDeletionCond)
81    {
82        delete _readyForDeletionCond;
83    }
84
85    if(_closeBlockingCompletedCond)
86    {
87        delete _closeBlockingCompletedCond;
88    }
89
90    if(_cs)
91    {
92        delete _cs;
93    }
94}
95
96int32_t UdpSocketPosix::ChangeUniqueId(const int32_t id)
97{
98    _id = id;
99    return 0;
100}
101
102bool UdpSocketPosix::SetCallback(CallbackObj obj, IncomingSocketCallback cb)
103{
104    _obj = obj;
105    _incomingCb = cb;
106
107    WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
108                 "UdpSocketPosix(%p)::SetCallback", this);
109
110    if (_mgr->AddSocket(this))
111      {
112        WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
113                     "UdpSocketPosix(%p)::SetCallback socket added to manager",
114                     this);
115        return true;   // socket is now ready for action
116      }
117
118    WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
119                 "UdpSocketPosix(%p)::SetCallback error adding me to mgr",
120                 this);
121    return false;
122}
123
124bool UdpSocketPosix::SetSockopt(int32_t level, int32_t optname,
125                                const int8_t* optval, int32_t optlen)
126{
127   if(0 == setsockopt(_socket, level, optname, optval, optlen ))
128   {
129       return true;
130   }
131
132   _error = errno;
133   WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
134                "UdpSocketPosix::SetSockopt(), error:%d", _error);
135   return false;
136}
137
138int32_t UdpSocketPosix::SetTOS(int32_t serviceType)
139{
140    if (SetSockopt(IPPROTO_IP, IP_TOS ,(int8_t*)&serviceType ,4) != 0)
141    {
142        return -1;
143    }
144    return 0;
145}
146
147bool UdpSocketPosix::Bind(const SocketAddress& name)
148{
149    int size = sizeof(sockaddr);
150    if (0 == bind(_socket, reinterpret_cast<const sockaddr*>(&name),size))
151    {
152        return true;
153    }
154    _error = errno;
155    WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
156                 "UdpSocketPosix::Bind() error: %d",_error);
157    return false;
158}
159
160int32_t UdpSocketPosix::SendTo(const int8_t* buf, int32_t len,
161                               const SocketAddress& to)
162{
163    int size = sizeof(sockaddr);
164    int retVal = sendto(_socket,buf, len, 0,
165                        reinterpret_cast<const sockaddr*>(&to), size);
166    if(retVal == SOCKET_ERROR)
167    {
168        _error = errno;
169        WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
170                     "UdpSocketPosix::SendTo() error: %d", _error);
171    }
172
173    return retVal;
174}
175
176SOCKET UdpSocketPosix::GetFd() { return _socket; }
177int32_t UdpSocketPosix::GetError() { return _error; }
178
179bool UdpSocketPosix::ValidHandle()
180{
181    return _socket != INVALID_SOCKET;
182}
183
184bool UdpSocketPosix::SetQos(int32_t /*serviceType*/,
185                            int32_t /*tokenRate*/,
186                            int32_t /*bucketSize*/,
187                            int32_t /*peekBandwith*/,
188                            int32_t /*minPolicedSize*/,
189                            int32_t /*maxSduSize*/,
190                            const SocketAddress& /*stRemName*/,
191                            int32_t /*overrideDSCP*/) {
192  return false;
193}
194
195void UdpSocketPosix::HasIncoming()
196{
197    // replace 2048 with a mcro define and figure out
198    // where 2048 comes from
199    int8_t buf[2048];
200    int retval;
201    SocketAddress from;
202#if defined(WEBRTC_MAC)
203    sockaddr sockaddrfrom;
204    memset(&from, 0, sizeof(from));
205    memset(&sockaddrfrom, 0, sizeof(sockaddrfrom));
206    socklen_t fromlen = sizeof(sockaddrfrom);
207#else
208    memset(&from, 0, sizeof(from));
209    socklen_t fromlen = sizeof(from);
210#endif
211
212#if defined(WEBRTC_MAC)
213        retval = recvfrom(_socket,buf, sizeof(buf), 0,
214                          reinterpret_cast<sockaddr*>(&sockaddrfrom), &fromlen);
215        memcpy(&from, &sockaddrfrom, fromlen);
216        from._sockaddr_storage.sin_family = sockaddrfrom.sa_family;
217#else
218        retval = recvfrom(_socket,buf, sizeof(buf), 0,
219                          reinterpret_cast<sockaddr*>(&from), &fromlen);
220#endif
221
222    switch(retval)
223    {
224    case 0:
225        // The peer has performed an orderly shutdown.
226        break;
227    case SOCKET_ERROR:
228        break;
229    default:
230        if (_wantsIncoming && _incomingCb)
231        {
232          _incomingCb(_obj, buf, retval, &from);
233        }
234        break;
235    }
236}
237
238bool UdpSocketPosix::WantsIncoming() { return _wantsIncoming; }
239
240void UdpSocketPosix::CloseBlocking()
241{
242    _cs->Enter();
243    _closeBlockingActive = true;
244    if(!CleanUp())
245    {
246        _closeBlockingActive = false;
247        _cs->Leave();
248        return;
249    }
250
251    while(!_readyForDeletion)
252    {
253        _readyForDeletionCond->SleepCS(*_cs);
254    }
255    _closeBlockingCompleted = true;
256    _closeBlockingCompletedCond->Wake();
257    _cs->Leave();
258}
259
260void UdpSocketPosix::ReadyForDeletion()
261{
262    _cs->Enter();
263    if(!_closeBlockingActive)
264    {
265        _cs->Leave();
266        return;
267    }
268    close(_socket);
269    _socket = INVALID_SOCKET;
270    _readyForDeletion = true;
271    _readyForDeletionCond->Wake();
272    while(!_closeBlockingCompleted)
273    {
274        _closeBlockingCompletedCond->SleepCS(*_cs);
275    }
276    _cs->Leave();
277}
278
279bool UdpSocketPosix::CleanUp()
280{
281    _wantsIncoming = false;
282
283    if (_socket == INVALID_SOCKET)
284    {
285        return false;
286    }
287
288    WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
289                 "calling UdpSocketManager::RemoveSocket()...");
290    _mgr->RemoveSocket(this);
291    // After this, the socket should may be or will be as deleted. Return
292    // immediately.
293    return true;
294}
295
296}  // namespace test
297}  // namespace webrtc
Note: See TracBrowser for help on using the repository browser.