| Index: webrtc/test/channel_transport/udp_socket_posix.cc
|
| diff --git a/webrtc/test/channel_transport/udp_socket_posix.cc b/webrtc/test/channel_transport/udp_socket_posix.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..8ed5825dbcc1588a2b6092fdf9b736ee239f6184
|
| --- /dev/null
|
| +++ b/webrtc/test/channel_transport/udp_socket_posix.cc
|
| @@ -0,0 +1,271 @@
|
| +/*
|
| + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
| + *
|
| + * Use of this source code is governed by a BSD-style license
|
| + * that can be found in the LICENSE file in the root of the source
|
| + * tree. An additional intellectual property rights grant can be found
|
| + * in the file PATENTS. All contributing project authors may
|
| + * be found in the AUTHORS file in the root of the source tree.
|
| + */
|
| +
|
| +#include "webrtc/test/channel_transport/udp_socket_posix.h"
|
| +
|
| +#include <errno.h>
|
| +#include <fcntl.h>
|
| +#include <netdb.h>
|
| +#include <stdio.h>
|
| +#include <string.h>
|
| +#include <sys/ioctl.h>
|
| +#include <sys/types.h>
|
| +#include <time.h>
|
| +#include <unistd.h>
|
| +
|
| +#include "webrtc/system_wrappers/include/trace.h"
|
| +#include "webrtc/test/channel_transport/udp_socket_manager_wrapper.h"
|
| +#include "webrtc/test/channel_transport/udp_socket_wrapper.h"
|
| +
|
| +namespace webrtc {
|
| +namespace test {
|
| +UdpSocketPosix::UdpSocketPosix(const int32_t id, UdpSocketManager* mgr,
|
| + bool ipV6Enable)
|
| + : _id(id),
|
| + _closeBlockingCompletedCond(true, false),
|
| + _readyForDeletionCond(true, false)
|
| +{
|
| + WEBRTC_TRACE(kTraceMemory, kTraceTransport, id,
|
| + "UdpSocketPosix::UdpSocketPosix()");
|
| +
|
| + _wantsIncoming = false;
|
| + _mgr = mgr;
|
| +
|
| + _obj = NULL;
|
| + _incomingCb = NULL;
|
| + _readyForDeletion = false;
|
| + _closeBlockingActive = false;
|
| + _closeBlockingCompleted = false;
|
| + if(ipV6Enable)
|
| + {
|
| + _socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
| + }
|
| + else {
|
| + _socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
| + }
|
| +
|
| + // Set socket to nonblocking mode.
|
| + int enable_non_blocking = 1;
|
| + if(ioctl(_socket, FIONBIO, &enable_non_blocking) == -1)
|
| + {
|
| + WEBRTC_TRACE(kTraceWarning, kTraceTransport, id,
|
| + "Failed to make socket nonblocking");
|
| + }
|
| + // Enable close on fork for file descriptor so that it will not block until
|
| + // forked process terminates.
|
| + if(fcntl(_socket, F_SETFD, FD_CLOEXEC) == -1)
|
| + {
|
| + WEBRTC_TRACE(kTraceWarning, kTraceTransport, id,
|
| + "Failed to set FD_CLOEXEC for socket");
|
| + }
|
| +}
|
| +
|
| +UdpSocketPosix::~UdpSocketPosix()
|
| +{
|
| + if(_socket != INVALID_SOCKET)
|
| + {
|
| + close(_socket);
|
| + _socket = INVALID_SOCKET;
|
| + }
|
| +}
|
| +
|
| +bool UdpSocketPosix::SetCallback(CallbackObj obj, IncomingSocketCallback cb)
|
| +{
|
| + _obj = obj;
|
| + _incomingCb = cb;
|
| +
|
| + WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
|
| + "UdpSocketPosix(%p)::SetCallback", this);
|
| +
|
| + if (_mgr->AddSocket(this))
|
| + {
|
| + WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
|
| + "UdpSocketPosix(%p)::SetCallback socket added to manager",
|
| + this);
|
| + return true; // socket is now ready for action
|
| + }
|
| +
|
| + WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
|
| + "UdpSocketPosix(%p)::SetCallback error adding me to mgr",
|
| + this);
|
| + return false;
|
| +}
|
| +
|
| +bool UdpSocketPosix::SetSockopt(int32_t level, int32_t optname,
|
| + const int8_t* optval, int32_t optlen)
|
| +{
|
| + if(0 == setsockopt(_socket, level, optname, optval, optlen ))
|
| + {
|
| + return true;
|
| + }
|
| +
|
| + WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
|
| + "UdpSocketPosix::SetSockopt(), error:%d", errno);
|
| + return false;
|
| +}
|
| +
|
| +int32_t UdpSocketPosix::SetTOS(int32_t serviceType)
|
| +{
|
| + if (SetSockopt(IPPROTO_IP, IP_TOS ,(int8_t*)&serviceType ,4) != 0)
|
| + {
|
| + return -1;
|
| + }
|
| + return 0;
|
| +}
|
| +
|
| +bool UdpSocketPosix::Bind(const SocketAddress& name)
|
| +{
|
| + int size = sizeof(sockaddr);
|
| + if (0 == bind(_socket, reinterpret_cast<const sockaddr*>(&name),size))
|
| + {
|
| + return true;
|
| + }
|
| + WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
|
| + "UdpSocketPosix::Bind() error: %d", errno);
|
| + return false;
|
| +}
|
| +
|
| +int32_t UdpSocketPosix::SendTo(const int8_t* buf, size_t len,
|
| + const SocketAddress& to)
|
| +{
|
| + int size = sizeof(sockaddr);
|
| + int retVal = sendto(_socket,buf, len, 0,
|
| + reinterpret_cast<const sockaddr*>(&to), size);
|
| + if(retVal == SOCKET_ERROR)
|
| + {
|
| + WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
|
| + "UdpSocketPosix::SendTo() error: %d", errno);
|
| + }
|
| +
|
| + return retVal;
|
| +}
|
| +
|
| +SOCKET UdpSocketPosix::GetFd() { return _socket; }
|
| +
|
| +bool UdpSocketPosix::ValidHandle()
|
| +{
|
| + return _socket != INVALID_SOCKET;
|
| +}
|
| +
|
| +bool UdpSocketPosix::SetQos(int32_t /*serviceType*/,
|
| + int32_t /*tokenRate*/,
|
| + int32_t /*bucketSize*/,
|
| + int32_t /*peekBandwith*/,
|
| + int32_t /*minPolicedSize*/,
|
| + int32_t /*maxSduSize*/,
|
| + const SocketAddress& /*stRemName*/,
|
| + int32_t /*overrideDSCP*/) {
|
| + return false;
|
| +}
|
| +
|
| +void UdpSocketPosix::HasIncoming()
|
| +{
|
| + // replace 2048 with a mcro define and figure out
|
| + // where 2048 comes from
|
| + int8_t buf[2048];
|
| + int retval;
|
| + SocketAddress from;
|
| +#if defined(WEBRTC_MAC)
|
| + sockaddr sockaddrfrom;
|
| + memset(&from, 0, sizeof(from));
|
| + memset(&sockaddrfrom, 0, sizeof(sockaddrfrom));
|
| + socklen_t fromlen = sizeof(sockaddrfrom);
|
| +#else
|
| + memset(&from, 0, sizeof(from));
|
| + socklen_t fromlen = sizeof(from);
|
| +#endif
|
| +
|
| +#if defined(WEBRTC_MAC)
|
| + retval = recvfrom(_socket,buf, sizeof(buf), 0,
|
| + reinterpret_cast<sockaddr*>(&sockaddrfrom), &fromlen);
|
| + memcpy(&from, &sockaddrfrom, fromlen);
|
| + from._sockaddr_storage.sin_family = sockaddrfrom.sa_family;
|
| +#else
|
| + retval = recvfrom(_socket,buf, sizeof(buf), 0,
|
| + reinterpret_cast<sockaddr*>(&from), &fromlen);
|
| +#endif
|
| +
|
| + switch(retval)
|
| + {
|
| + case 0:
|
| + // The peer has performed an orderly shutdown.
|
| + break;
|
| + case SOCKET_ERROR:
|
| + break;
|
| + default:
|
| + if (_wantsIncoming && _incomingCb)
|
| + {
|
| + _incomingCb(_obj, buf, retval, &from);
|
| + }
|
| + break;
|
| + }
|
| +}
|
| +
|
| +bool UdpSocketPosix::WantsIncoming() { return _wantsIncoming; }
|
| +
|
| +void UdpSocketPosix::CloseBlocking()
|
| +{
|
| + rtc::CritScope lock(&_cs);
|
| + _closeBlockingActive = true;
|
| + if(!CleanUp())
|
| + {
|
| + _closeBlockingActive = false;
|
| + return;
|
| + }
|
| +
|
| + if(!_readyForDeletion)
|
| + {
|
| + _cs.Leave();
|
| + _readyForDeletionCond.Wait(rtc::Event::kForever);
|
| + _cs.Enter();
|
| + }
|
| + _closeBlockingCompleted = true;
|
| + _closeBlockingCompletedCond.Set();
|
| +}
|
| +
|
| +void UdpSocketPosix::ReadyForDeletion()
|
| +{
|
| + rtc::CritScope lock(&_cs);
|
| + if(!_closeBlockingActive)
|
| + {
|
| + return;
|
| + }
|
| +
|
| + close(_socket);
|
| + _socket = INVALID_SOCKET;
|
| + _readyForDeletion = true;
|
| + _readyForDeletionCond.Set();
|
| + if(!_closeBlockingCompleted)
|
| + {
|
| + _cs.Leave();
|
| + _closeBlockingCompletedCond.Wait(rtc::Event::kForever);
|
| + _cs.Enter();
|
| + }
|
| +}
|
| +
|
| +bool UdpSocketPosix::CleanUp()
|
| +{
|
| + _wantsIncoming = false;
|
| +
|
| + if (_socket == INVALID_SOCKET)
|
| + {
|
| + return false;
|
| + }
|
| +
|
| + WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
|
| + "calling UdpSocketManager::RemoveSocket()...");
|
| + _mgr->RemoveSocket(this);
|
| + // After this, the socket should may be or will be as deleted. Return
|
| + // immediately.
|
| + return true;
|
| +}
|
| +
|
| +} // namespace test
|
| +} // namespace webrtc
|
|
|