| Index: webrtc/base/macasyncsocket.cc
|
| diff --git a/webrtc/base/macasyncsocket.cc b/webrtc/base/macasyncsocket.cc
|
| deleted file mode 100644
|
| index 9f38c2937ca5388fdbe21df2dfd9dd2ab2d8b32a..0000000000000000000000000000000000000000
|
| --- a/webrtc/base/macasyncsocket.cc
|
| +++ /dev/null
|
| @@ -1,485 +0,0 @@
|
| -/*
|
| - * Copyright 2010 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.
|
| - */
|
| -//
|
| -// MacAsyncSocket is a kind of AsyncSocket. It does not support the SOCK_DGRAM
|
| -// type (yet). It works asynchronously, which means that users of this socket
|
| -// should connect to the various events declared in asyncsocket.h to receive
|
| -// notifications about this socket. It uses CFSockets for signals, but prefers
|
| -// the basic bsd socket operations rather than their CFSocket wrappers when
|
| -// possible.
|
| -
|
| -#include <CoreFoundation/CoreFoundation.h>
|
| -#include <fcntl.h>
|
| -
|
| -#include "webrtc/base/macasyncsocket.h"
|
| -
|
| -#include "webrtc/base/logging.h"
|
| -#include "webrtc/base/macsocketserver.h"
|
| -
|
| -namespace rtc {
|
| -
|
| -static const int kCallbackFlags = kCFSocketReadCallBack |
|
| - kCFSocketConnectCallBack |
|
| - kCFSocketWriteCallBack;
|
| -
|
| -MacAsyncSocket::MacAsyncSocket(MacBaseSocketServer* ss, int family)
|
| - : ss_(ss),
|
| - socket_(NULL),
|
| - native_socket_(INVALID_SOCKET),
|
| - source_(NULL),
|
| - current_callbacks_(0),
|
| - disabled_(false),
|
| - error_(0),
|
| - state_(CS_CLOSED),
|
| - resolver_(NULL) {
|
| - Initialize(family);
|
| -}
|
| -
|
| -MacAsyncSocket::~MacAsyncSocket() {
|
| - Close();
|
| -}
|
| -
|
| -// Returns the address to which the socket is bound. If the socket is not
|
| -// bound, then the any-address is returned.
|
| -SocketAddress MacAsyncSocket::GetLocalAddress() const {
|
| - SocketAddress address;
|
| -
|
| - // The CFSocket doesn't pick up on implicit binds from the connect call.
|
| - // Calling bind in before connect explicitly causes errors, so just query
|
| - // the underlying bsd socket.
|
| - sockaddr_storage addr;
|
| - socklen_t addrlen = sizeof(addr);
|
| - int result = ::getsockname(native_socket_,
|
| - reinterpret_cast<sockaddr*>(&addr), &addrlen);
|
| - if (result >= 0) {
|
| - SocketAddressFromSockAddrStorage(addr, &address);
|
| - }
|
| - return address;
|
| -}
|
| -
|
| -// Returns the address to which the socket is connected. If the socket is not
|
| -// connected, then the any-address is returned.
|
| -SocketAddress MacAsyncSocket::GetRemoteAddress() const {
|
| - SocketAddress address;
|
| -
|
| - // Use native_socket for consistency with GetLocalAddress.
|
| - sockaddr_storage addr;
|
| - socklen_t addrlen = sizeof(addr);
|
| - int result = ::getpeername(native_socket_,
|
| - reinterpret_cast<sockaddr*>(&addr), &addrlen);
|
| - if (result >= 0) {
|
| - SocketAddressFromSockAddrStorage(addr, &address);
|
| - }
|
| - return address;
|
| -}
|
| -
|
| -// Bind the socket to a local address.
|
| -int MacAsyncSocket::Bind(const SocketAddress& address) {
|
| - sockaddr_storage saddr = {0};
|
| - size_t len = address.ToSockAddrStorage(&saddr);
|
| - int err = ::bind(native_socket_, reinterpret_cast<sockaddr*>(&saddr), len);
|
| - if (err == SOCKET_ERROR) error_ = errno;
|
| - return err;
|
| -}
|
| -
|
| -void MacAsyncSocket::OnResolveResult(SignalThread* thread) {
|
| - if (thread != resolver_) {
|
| - return;
|
| - }
|
| - int error = resolver_->GetError();
|
| - if (error == 0) {
|
| - error = DoConnect(resolver_->address());
|
| - } else {
|
| - Close();
|
| - }
|
| - if (error) {
|
| - error_ = error;
|
| - SignalCloseEvent(this, error_);
|
| - }
|
| -}
|
| -
|
| -// Connect to a remote address.
|
| -int MacAsyncSocket::Connect(const SocketAddress& addr) {
|
| - // TODO(djw): Consolidate all the connect->resolve->doconnect implementations.
|
| - if (state_ != CS_CLOSED) {
|
| - SetError(EALREADY);
|
| - return SOCKET_ERROR;
|
| - }
|
| - if (addr.IsUnresolvedIP()) {
|
| - LOG(LS_VERBOSE) << "Resolving addr in MacAsyncSocket::Connect";
|
| - resolver_ = new AsyncResolver();
|
| - resolver_->SignalWorkDone.connect(this,
|
| - &MacAsyncSocket::OnResolveResult);
|
| - resolver_->Start(addr);
|
| - state_ = CS_CONNECTING;
|
| - return 0;
|
| - }
|
| - return DoConnect(addr);
|
| -}
|
| -
|
| -int MacAsyncSocket::DoConnect(const SocketAddress& addr) {
|
| - if (!valid()) {
|
| - Initialize(addr.family());
|
| - if (!valid())
|
| - return SOCKET_ERROR;
|
| - }
|
| -
|
| - sockaddr_storage saddr;
|
| - size_t len = addr.ToSockAddrStorage(&saddr);
|
| - int result = ::connect(native_socket_, reinterpret_cast<sockaddr*>(&saddr),
|
| - len);
|
| -
|
| - if (result != SOCKET_ERROR) {
|
| - state_ = CS_CONNECTED;
|
| - } else {
|
| - error_ = errno;
|
| - if (error_ == EINPROGRESS) {
|
| - state_ = CS_CONNECTING;
|
| - result = 0;
|
| - }
|
| - }
|
| - return result;
|
| -}
|
| -
|
| -// Send to the remote end we're connected to.
|
| -int MacAsyncSocket::Send(const void* buffer, size_t length) {
|
| - if (!valid()) {
|
| - return SOCKET_ERROR;
|
| - }
|
| -
|
| - int sent = ::send(native_socket_, buffer, length, 0);
|
| -
|
| - if (sent == SOCKET_ERROR) {
|
| - error_ = errno;
|
| -
|
| - if (IsBlocking()) {
|
| - // Reenable the writable callback (once), since we are flow controlled.
|
| - CFSocketEnableCallBacks(socket_, kCallbackFlags);
|
| - current_callbacks_ = kCallbackFlags;
|
| - }
|
| - }
|
| - return sent;
|
| -}
|
| -
|
| -// Send to the given address. We may or may not be connected to anyone.
|
| -int MacAsyncSocket::SendTo(const void* buffer, size_t length,
|
| - const SocketAddress& address) {
|
| - if (!valid()) {
|
| - return SOCKET_ERROR;
|
| - }
|
| -
|
| - sockaddr_storage saddr;
|
| - size_t len = address.ToSockAddrStorage(&saddr);
|
| - int sent = ::sendto(native_socket_, buffer, length, 0,
|
| - reinterpret_cast<sockaddr*>(&saddr), len);
|
| -
|
| - if (sent == SOCKET_ERROR) {
|
| - error_ = errno;
|
| - }
|
| -
|
| - return sent;
|
| -}
|
| -
|
| -// Read data received from the remote end we're connected to.
|
| -int MacAsyncSocket::Recv(void* buffer, size_t length, int64_t* timestamp) {
|
| - if (timestamp) {
|
| - *timestamp = -1;
|
| - }
|
| - int received = ::recv(native_socket_, reinterpret_cast<char*>(buffer),
|
| - length, 0);
|
| - if (received == SOCKET_ERROR) error_ = errno;
|
| -
|
| - // Recv should only be called when there is data to read
|
| - ASSERT((received != 0) || (length == 0));
|
| - return received;
|
| -}
|
| -
|
| -// Read data received from any remote party
|
| -int MacAsyncSocket::RecvFrom(void* buffer,
|
| - size_t length,
|
| - SocketAddress* out_addr,
|
| - int64_t* timestamp) {
|
| - if (timestamp) {
|
| - *timestamp = -1;
|
| - }
|
| - sockaddr_storage saddr;
|
| - socklen_t addr_len = sizeof(saddr);
|
| - int received = ::recvfrom(native_socket_, reinterpret_cast<char*>(buffer),
|
| - length, 0, reinterpret_cast<sockaddr*>(&saddr),
|
| - &addr_len);
|
| - if (received >= 0 && out_addr != NULL) {
|
| - SocketAddressFromSockAddrStorage(saddr, out_addr);
|
| - } else if (received == SOCKET_ERROR) {
|
| - error_ = errno;
|
| - }
|
| - return received;
|
| -}
|
| -
|
| -int MacAsyncSocket::Listen(int backlog) {
|
| - if (!valid()) {
|
| - return SOCKET_ERROR;
|
| - }
|
| -
|
| - int res = ::listen(native_socket_, backlog);
|
| - if (res != SOCKET_ERROR)
|
| - state_ = CS_CONNECTING;
|
| - else
|
| - error_ = errno;
|
| -
|
| - return res;
|
| -}
|
| -
|
| -MacAsyncSocket* MacAsyncSocket::Accept(SocketAddress* out_addr) {
|
| - sockaddr_storage saddr;
|
| - socklen_t addr_len = sizeof(saddr);
|
| -
|
| - int socket_fd = ::accept(native_socket_, reinterpret_cast<sockaddr*>(&saddr),
|
| - &addr_len);
|
| - if (socket_fd == INVALID_SOCKET) {
|
| - error_ = errno;
|
| - return NULL;
|
| - }
|
| -
|
| - MacAsyncSocket* s = new MacAsyncSocket(ss_, saddr.ss_family, socket_fd);
|
| - if (s && s->valid()) {
|
| - s->state_ = CS_CONNECTED;
|
| - if (out_addr)
|
| - SocketAddressFromSockAddrStorage(saddr, out_addr);
|
| - } else {
|
| - delete s;
|
| - s = NULL;
|
| - }
|
| - return s;
|
| -}
|
| -
|
| -int MacAsyncSocket::Close() {
|
| - if (source_ != NULL) {
|
| - CFRunLoopSourceInvalidate(source_);
|
| - CFRelease(source_);
|
| - if (ss_) ss_->UnregisterSocket(this);
|
| - source_ = NULL;
|
| - }
|
| -
|
| - if (socket_ != NULL) {
|
| - CFSocketInvalidate(socket_);
|
| - CFRelease(socket_);
|
| - socket_ = NULL;
|
| - }
|
| -
|
| - if (resolver_) {
|
| - resolver_->Destroy(false);
|
| - resolver_ = NULL;
|
| - }
|
| -
|
| - native_socket_ = INVALID_SOCKET; // invalidates the socket
|
| - error_ = 0;
|
| - state_ = CS_CLOSED;
|
| - return 0;
|
| -}
|
| -
|
| -int MacAsyncSocket::EstimateMTU(uint16_t* mtu) {
|
| - ASSERT(false && "NYI");
|
| - return -1;
|
| -}
|
| -
|
| -int MacAsyncSocket::GetError() const {
|
| - return error_;
|
| -}
|
| -
|
| -void MacAsyncSocket::SetError(int error) {
|
| - error_ = error;
|
| -}
|
| -
|
| -Socket::ConnState MacAsyncSocket::GetState() const {
|
| - return state_;
|
| -}
|
| -
|
| -int MacAsyncSocket::GetOption(Option opt, int* value) {
|
| - ASSERT(false && "NYI");
|
| - return -1;
|
| -}
|
| -
|
| -int MacAsyncSocket::SetOption(Option opt, int value) {
|
| - ASSERT(false && "NYI");
|
| - return -1;
|
| -}
|
| -
|
| -void MacAsyncSocket::EnableCallbacks() {
|
| - if (valid()) {
|
| - disabled_ = false;
|
| - CFSocketEnableCallBacks(socket_, current_callbacks_);
|
| - }
|
| -}
|
| -
|
| -void MacAsyncSocket::DisableCallbacks() {
|
| - if (valid()) {
|
| - disabled_ = true;
|
| - CFSocketDisableCallBacks(socket_, kCallbackFlags);
|
| - }
|
| -}
|
| -
|
| -MacAsyncSocket::MacAsyncSocket(MacBaseSocketServer* ss, int family,
|
| - int native_socket)
|
| - : ss_(ss),
|
| - socket_(NULL),
|
| - native_socket_(native_socket),
|
| - source_(NULL),
|
| - current_callbacks_(0),
|
| - disabled_(false),
|
| - error_(0),
|
| - state_(CS_CLOSED),
|
| - resolver_(NULL) {
|
| - Initialize(family);
|
| -}
|
| -
|
| -// Create a new socket, wrapping the native socket if provided or creating one
|
| -// otherwise. In case of any failure, consume the native socket. We assume the
|
| -// wrapped socket is in the closed state. If this is not the case you must
|
| -// update the state_ field for this socket yourself.
|
| -void MacAsyncSocket::Initialize(int family) {
|
| - CFSocketContext ctx = { 0 };
|
| - ctx.info = this;
|
| -
|
| - // First create the CFSocket
|
| - CFSocketRef cf_socket = NULL;
|
| - bool res = false;
|
| - if (native_socket_ == INVALID_SOCKET) {
|
| - cf_socket = CFSocketCreate(kCFAllocatorDefault,
|
| - family, SOCK_STREAM, IPPROTO_TCP,
|
| - kCallbackFlags, MacAsyncSocketCallBack, &ctx);
|
| - } else {
|
| - cf_socket = CFSocketCreateWithNative(kCFAllocatorDefault,
|
| - native_socket_, kCallbackFlags,
|
| - MacAsyncSocketCallBack, &ctx);
|
| - }
|
| -
|
| - if (cf_socket) {
|
| - res = true;
|
| - socket_ = cf_socket;
|
| - native_socket_ = CFSocketGetNative(cf_socket);
|
| - current_callbacks_ = kCallbackFlags;
|
| - }
|
| -
|
| - if (res) {
|
| - // Make the underlying socket asynchronous
|
| - res = (-1 != ::fcntl(native_socket_, F_SETFL,
|
| - ::fcntl(native_socket_, F_GETFL, 0) | O_NONBLOCK));
|
| - }
|
| -
|
| - if (res) {
|
| - // Add this socket to the run loop, at priority 1 so that it will be
|
| - // queued behind any pending signals.
|
| - source_ = CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket_, 1);
|
| - res = (source_ != NULL);
|
| - if (!res) errno = EINVAL;
|
| - }
|
| -
|
| - if (res) {
|
| - if (ss_) ss_->RegisterSocket(this);
|
| - CFRunLoopAddSource(CFRunLoopGetCurrent(), source_, kCFRunLoopCommonModes);
|
| - }
|
| -
|
| - if (!res) {
|
| - int error = errno;
|
| - Close(); // Clears error_.
|
| - error_ = error;
|
| - }
|
| -}
|
| -
|
| -// Call CFRelease on the result when done using it
|
| -CFDataRef MacAsyncSocket::CopyCFAddress(const SocketAddress& address) {
|
| - sockaddr_storage saddr;
|
| - size_t len = address.ToSockAddrStorage(&saddr);
|
| -
|
| - const UInt8* bytes = reinterpret_cast<UInt8*>(&saddr);
|
| -
|
| - CFDataRef cf_address = CFDataCreate(kCFAllocatorDefault,
|
| - bytes, len);
|
| -
|
| - ASSERT(cf_address != NULL);
|
| - return cf_address;
|
| -}
|
| -
|
| -void MacAsyncSocket::MacAsyncSocketCallBack(CFSocketRef s,
|
| - CFSocketCallBackType callbackType,
|
| - CFDataRef address,
|
| - const void* data,
|
| - void* info) {
|
| - MacAsyncSocket* this_socket =
|
| - reinterpret_cast<MacAsyncSocket*>(info);
|
| - ASSERT(this_socket != NULL && this_socket->socket_ == s);
|
| -
|
| - // Don't signal any socket messages if the socketserver is not listening on
|
| - // them. When we are reenabled they will be requeued and will fire again.
|
| - if (this_socket->disabled_)
|
| - return;
|
| -
|
| - switch (callbackType) {
|
| - case kCFSocketReadCallBack:
|
| - // This callback is invoked in one of 3 situations:
|
| - // 1. A new connection is waiting to be accepted.
|
| - // 2. The remote end closed the connection (a recv will return 0).
|
| - // 3. Data is available to read.
|
| - // 4. The connection closed unhappily (recv will return -1).
|
| - if (this_socket->state_ == CS_CONNECTING) {
|
| - // Case 1.
|
| - this_socket->SignalReadEvent(this_socket);
|
| - } else {
|
| - char ch, amt;
|
| - amt = ::recv(this_socket->native_socket_, &ch, 1, MSG_PEEK);
|
| - if (amt == 0) {
|
| - // Case 2.
|
| - this_socket->state_ = CS_CLOSED;
|
| -
|
| - // Disable additional callbacks or we will signal close twice.
|
| - CFSocketDisableCallBacks(this_socket->socket_, kCFSocketReadCallBack);
|
| - this_socket->current_callbacks_ &= ~kCFSocketReadCallBack;
|
| - this_socket->SignalCloseEvent(this_socket, 0);
|
| - } else if (amt > 0) {
|
| - // Case 3.
|
| - this_socket->SignalReadEvent(this_socket);
|
| - } else {
|
| - // Case 4.
|
| - int error = errno;
|
| - if (error == EAGAIN) {
|
| - // Observed in practice. Let's hope it's a spurious or out of date
|
| - // signal, since we just eat it.
|
| - } else {
|
| - this_socket->error_ = error;
|
| - this_socket->SignalCloseEvent(this_socket, error);
|
| - }
|
| - }
|
| - }
|
| - break;
|
| -
|
| - case kCFSocketConnectCallBack:
|
| - if (data != NULL) {
|
| - // An error occured in the background while connecting
|
| - this_socket->error_ = errno;
|
| - this_socket->state_ = CS_CLOSED;
|
| - this_socket->SignalCloseEvent(this_socket, this_socket->error_);
|
| - } else {
|
| - this_socket->state_ = CS_CONNECTED;
|
| - this_socket->SignalConnectEvent(this_socket);
|
| - }
|
| - break;
|
| -
|
| - case kCFSocketWriteCallBack:
|
| - // Update our callback tracking. Write doesn't reenable, so it's off now.
|
| - this_socket->current_callbacks_ &= ~kCFSocketWriteCallBack;
|
| - this_socket->SignalWriteEvent(this_socket);
|
| - break;
|
| -
|
| - default:
|
| - ASSERT(false && "Invalid callback type for socket");
|
| - }
|
| -}
|
| -
|
| -} // namespace rtc
|
|
|