147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/* 247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * Copyright 2010 The WebRTC Project Authors. All rights reserved. 347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * 447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * Use of this source code is governed by a BSD-style license 547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * that can be found in the LICENSE file in the root of the source 647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * tree. An additional intellectual property rights grant can be found 747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * in the file PATENTS. All contributing project authors may 847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * be found in the AUTHORS file in the root of the source tree. 947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org */ 1047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// 1147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// MacAsyncSocket is a kind of AsyncSocket. It does not support the SOCK_DGRAM 1247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// type (yet). It works asynchronously, which means that users of this socket 1347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// should connect to the various events declared in asyncsocket.h to receive 1447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// notifications about this socket. It uses CFSockets for signals, but prefers 1547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// the basic bsd socket operations rather than their CFSocket wrappers when 1647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// possible. 1747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <CoreFoundation/CoreFoundation.h> 1947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <fcntl.h> 2047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 2147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/macasyncsocket.h" 2247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 2347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/logging.h" 2447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/macsocketserver.h" 2547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 2647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgnamespace rtc { 2747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 2847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic const int kCallbackFlags = kCFSocketReadCallBack | 2947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org kCFSocketConnectCallBack | 3047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org kCFSocketWriteCallBack; 3147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 3247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgMacAsyncSocket::MacAsyncSocket(MacBaseSocketServer* ss, int family) 3347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org : ss_(ss), 3447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org socket_(NULL), 3547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org native_socket_(INVALID_SOCKET), 3647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org source_(NULL), 3747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org current_callbacks_(0), 3847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org disabled_(false), 3947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org error_(0), 4047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org state_(CS_CLOSED), 4147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org resolver_(NULL) { 4247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Initialize(family); 4347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 4447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 4547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgMacAsyncSocket::~MacAsyncSocket() { 4647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Close(); 4747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 4847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 4947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Returns the address to which the socket is bound. If the socket is not 5047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// bound, then the any-address is returned. 5147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSocketAddress MacAsyncSocket::GetLocalAddress() const { 5247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SocketAddress address; 5347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 5447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // The CFSocket doesn't pick up on implicit binds from the connect call. 5547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Calling bind in before connect explicitly causes errors, so just query 5647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // the underlying bsd socket. 5747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org sockaddr_storage addr; 5847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org socklen_t addrlen = sizeof(addr); 5947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int result = ::getsockname(native_socket_, 6047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org reinterpret_cast<sockaddr*>(&addr), &addrlen); 6147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (result >= 0) { 6247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SocketAddressFromSockAddrStorage(addr, &address); 6347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 6447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return address; 6547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 6647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 6747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Returns the address to which the socket is connected. If the socket is not 6847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// connected, then the any-address is returned. 6947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSocketAddress MacAsyncSocket::GetRemoteAddress() const { 7047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SocketAddress address; 7147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 7247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Use native_socket for consistency with GetLocalAddress. 7347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org sockaddr_storage addr; 7447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org socklen_t addrlen = sizeof(addr); 7547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int result = ::getpeername(native_socket_, 7647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org reinterpret_cast<sockaddr*>(&addr), &addrlen); 7747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (result >= 0) { 7847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SocketAddressFromSockAddrStorage(addr, &address); 7947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 8047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return address; 8147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 8247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 8347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Bind the socket to a local address. 8447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint MacAsyncSocket::Bind(const SocketAddress& address) { 8547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org sockaddr_storage saddr = {0}; 8647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org size_t len = address.ToSockAddrStorage(&saddr); 8747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int err = ::bind(native_socket_, reinterpret_cast<sockaddr*>(&saddr), len); 8847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (err == SOCKET_ERROR) error_ = errno; 8947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return err; 9047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 9147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 9247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid MacAsyncSocket::OnResolveResult(SignalThread* thread) { 9347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (thread != resolver_) { 9447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return; 9547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 9647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int error = resolver_->GetError(); 9747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (error == 0) { 9847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org error = DoConnect(resolver_->address()); 9947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 10047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Close(); 10147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 10247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (error) { 10347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org error_ = error; 10447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SignalCloseEvent(this, error_); 10547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 10647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 10747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 10847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Connect to a remote address. 10947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint MacAsyncSocket::Connect(const SocketAddress& addr) { 11047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // TODO(djw): Consolidate all the connect->resolve->doconnect implementations. 11147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (state_ != CS_CLOSED) { 11247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SetError(EALREADY); 11347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SOCKET_ERROR; 11447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 11547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (addr.IsUnresolved()) { 11647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_VERBOSE) << "Resolving addr in MacAsyncSocket::Connect"; 11747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org resolver_ = new AsyncResolver(); 11847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org resolver_->SignalWorkDone.connect(this, 11947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org &MacAsyncSocket::OnResolveResult); 12047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org resolver_->Start(addr); 12147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org state_ = CS_CONNECTING; 12247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return 0; 12347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 12447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return DoConnect(addr); 12547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 12647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 12747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint MacAsyncSocket::DoConnect(const SocketAddress& addr) { 12847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!valid()) { 12947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Initialize(addr.family()); 13047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!valid()) 13147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SOCKET_ERROR; 13247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 13347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 13447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org sockaddr_storage saddr; 13547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org size_t len = addr.ToSockAddrStorage(&saddr); 13647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int result = ::connect(native_socket_, reinterpret_cast<sockaddr*>(&saddr), 13747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org len); 13847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 13947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (result != SOCKET_ERROR) { 14047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org state_ = CS_CONNECTED; 14147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 14247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org error_ = errno; 14347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (error_ == EINPROGRESS) { 14447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org state_ = CS_CONNECTING; 14547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org result = 0; 14647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 14747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 14847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return result; 14947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 15047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 15147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Send to the remote end we're connected to. 15247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint MacAsyncSocket::Send(const void* buffer, size_t length) { 15347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!valid()) { 15447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SOCKET_ERROR; 15547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 15647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 15747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int sent = ::send(native_socket_, buffer, length, 0); 15847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 15947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (sent == SOCKET_ERROR) { 16047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org error_ = errno; 16147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 16247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (IsBlocking()) { 16347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Reenable the writable callback (once), since we are flow controlled. 16447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CFSocketEnableCallBacks(socket_, kCallbackFlags); 16547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org current_callbacks_ = kCallbackFlags; 16647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 16747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 16847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return sent; 16947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 17047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 17147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Send to the given address. We may or may not be connected to anyone. 17247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint MacAsyncSocket::SendTo(const void* buffer, size_t length, 17347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const SocketAddress& address) { 17447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!valid()) { 17547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SOCKET_ERROR; 17647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 17747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 17847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org sockaddr_storage saddr; 17947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org size_t len = address.ToSockAddrStorage(&saddr); 18047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int sent = ::sendto(native_socket_, buffer, length, 0, 18147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org reinterpret_cast<sockaddr*>(&saddr), len); 18247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 18347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (sent == SOCKET_ERROR) { 18447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org error_ = errno; 18547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 18647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 18747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return sent; 18847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 18947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 19047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Read data received from the remote end we're connected to. 19147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint MacAsyncSocket::Recv(void* buffer, size_t length) { 19247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int received = ::recv(native_socket_, reinterpret_cast<char*>(buffer), 19347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org length, 0); 19447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (received == SOCKET_ERROR) error_ = errno; 19547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 19647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Recv should only be called when there is data to read 19747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT((received != 0) || (length == 0)); 19847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return received; 19947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 20047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 20147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Read data received from any remote party 20247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint MacAsyncSocket::RecvFrom(void* buffer, size_t length, 20347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SocketAddress* out_addr) { 20447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org sockaddr_storage saddr; 20547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org socklen_t addr_len = sizeof(saddr); 20647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int received = ::recvfrom(native_socket_, reinterpret_cast<char*>(buffer), 20747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org length, 0, reinterpret_cast<sockaddr*>(&saddr), 20847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org &addr_len); 20947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (received >= 0 && out_addr != NULL) { 21047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SocketAddressFromSockAddrStorage(saddr, out_addr); 21147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else if (received == SOCKET_ERROR) { 21247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org error_ = errno; 21347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 21447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return received; 21547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 21647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 21747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint MacAsyncSocket::Listen(int backlog) { 21847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!valid()) { 21947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SOCKET_ERROR; 22047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 22147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 22247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int res = ::listen(native_socket_, backlog); 22347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (res != SOCKET_ERROR) 22447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org state_ = CS_CONNECTING; 22547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org else 22647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org error_ = errno; 22747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 22847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return res; 22947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 23047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 23147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgMacAsyncSocket* MacAsyncSocket::Accept(SocketAddress* out_addr) { 23247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org sockaddr_storage saddr; 23347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org socklen_t addr_len = sizeof(saddr); 23447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 23547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int socket_fd = ::accept(native_socket_, reinterpret_cast<sockaddr*>(&saddr), 23647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org &addr_len); 23747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (socket_fd == INVALID_SOCKET) { 23847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org error_ = errno; 23947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return NULL; 24047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 24147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 24247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org MacAsyncSocket* s = new MacAsyncSocket(ss_, saddr.ss_family, socket_fd); 24347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (s && s->valid()) { 24447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org s->state_ = CS_CONNECTED; 24547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (out_addr) 24647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SocketAddressFromSockAddrStorage(saddr, out_addr); 24747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 24847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org delete s; 24947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org s = NULL; 25047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 25147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return s; 25247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 25347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 25447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint MacAsyncSocket::Close() { 25547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (source_ != NULL) { 25647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CFRunLoopSourceInvalidate(source_); 25747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CFRelease(source_); 25847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (ss_) ss_->UnregisterSocket(this); 25947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org source_ = NULL; 26047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 26147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 26247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (socket_ != NULL) { 26347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CFSocketInvalidate(socket_); 26447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CFRelease(socket_); 26547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org socket_ = NULL; 26647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 26747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 26847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (resolver_) { 26947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org resolver_->Destroy(false); 27047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org resolver_ = NULL; 27147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 27247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 27347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org native_socket_ = INVALID_SOCKET; // invalidates the socket 27447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org error_ = 0; 27547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org state_ = CS_CLOSED; 27647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return 0; 27747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 27847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 27947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint MacAsyncSocket::EstimateMTU(uint16* mtu) { 28047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(false && "NYI"); 28147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 28247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 28347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 28447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint MacAsyncSocket::GetError() const { 28547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return error_; 28647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 28747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 28847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid MacAsyncSocket::SetError(int error) { 28947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org error_ = error; 29047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 29147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 29247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSocket::ConnState MacAsyncSocket::GetState() const { 29347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return state_; 29447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 29547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 29647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint MacAsyncSocket::GetOption(Option opt, int* value) { 29747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(false && "NYI"); 29847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 29947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 30047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 30147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint MacAsyncSocket::SetOption(Option opt, int value) { 30247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(false && "NYI"); 30347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 30447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 30547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 30647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid MacAsyncSocket::EnableCallbacks() { 30747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (valid()) { 30847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org disabled_ = false; 30947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CFSocketEnableCallBacks(socket_, current_callbacks_); 31047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 31147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 31247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 31347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid MacAsyncSocket::DisableCallbacks() { 31447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (valid()) { 31547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org disabled_ = true; 31647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CFSocketDisableCallBacks(socket_, kCallbackFlags); 31747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 31847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 31947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 32047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgMacAsyncSocket::MacAsyncSocket(MacBaseSocketServer* ss, int family, 32147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int native_socket) 32247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org : ss_(ss), 32347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org socket_(NULL), 32447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org native_socket_(native_socket), 32547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org source_(NULL), 32647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org current_callbacks_(0), 32747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org disabled_(false), 32847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org error_(0), 32947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org state_(CS_CLOSED), 33047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org resolver_(NULL) { 33147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Initialize(family); 33247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 33347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 33447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Create a new socket, wrapping the native socket if provided or creating one 33547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// otherwise. In case of any failure, consume the native socket. We assume the 33647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// wrapped socket is in the closed state. If this is not the case you must 33747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// update the state_ field for this socket yourself. 33847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid MacAsyncSocket::Initialize(int family) { 33947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CFSocketContext ctx = { 0 }; 34047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ctx.info = this; 34147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 34247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // First create the CFSocket 34347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CFSocketRef cf_socket = NULL; 34447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org bool res = false; 34547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (native_socket_ == INVALID_SOCKET) { 34647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org cf_socket = CFSocketCreate(kCFAllocatorDefault, 34747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org family, SOCK_STREAM, IPPROTO_TCP, 34847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org kCallbackFlags, MacAsyncSocketCallBack, &ctx); 34947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 35047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org cf_socket = CFSocketCreateWithNative(kCFAllocatorDefault, 35147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org native_socket_, kCallbackFlags, 35247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org MacAsyncSocketCallBack, &ctx); 35347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 35447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 35547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (cf_socket) { 35647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org res = true; 35747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org socket_ = cf_socket; 35847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org native_socket_ = CFSocketGetNative(cf_socket); 35947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org current_callbacks_ = kCallbackFlags; 36047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 36147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 36247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (res) { 36347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Make the underlying socket asynchronous 36447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org res = (-1 != ::fcntl(native_socket_, F_SETFL, 36547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ::fcntl(native_socket_, F_GETFL, 0) | O_NONBLOCK)); 36647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 36747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 36847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (res) { 36947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Add this socket to the run loop, at priority 1 so that it will be 37047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // queued behind any pending signals. 37147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org source_ = CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket_, 1); 37247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org res = (source_ != NULL); 37347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!res) errno = EINVAL; 37447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 37547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 37647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (res) { 37747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (ss_) ss_->RegisterSocket(this); 37847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CFRunLoopAddSource(CFRunLoopGetCurrent(), source_, kCFRunLoopCommonModes); 37947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 38047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 38147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!res) { 38247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int error = errno; 38347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Close(); // Clears error_. 38447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org error_ = error; 38547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 38647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 38747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 38847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Call CFRelease on the result when done using it 38947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgCFDataRef MacAsyncSocket::CopyCFAddress(const SocketAddress& address) { 39047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org sockaddr_storage saddr; 39147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org size_t len = address.ToSockAddrStorage(&saddr); 39247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 39347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const UInt8* bytes = reinterpret_cast<UInt8*>(&saddr); 39447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 39547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CFDataRef cf_address = CFDataCreate(kCFAllocatorDefault, 39647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org bytes, len); 39747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 39847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(cf_address != NULL); 39947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return cf_address; 40047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 40147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 40247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid MacAsyncSocket::MacAsyncSocketCallBack(CFSocketRef s, 40347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CFSocketCallBackType callbackType, 40447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CFDataRef address, 40547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const void* data, 40647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org void* info) { 40747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org MacAsyncSocket* this_socket = 40847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org reinterpret_cast<MacAsyncSocket*>(info); 40947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(this_socket != NULL && this_socket->socket_ == s); 41047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 41147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Don't signal any socket messages if the socketserver is not listening on 41247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // them. When we are reenabled they will be requeued and will fire again. 41347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (this_socket->disabled_) 41447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return; 41547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 41647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org switch (callbackType) { 41747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case kCFSocketReadCallBack: 41847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // This callback is invoked in one of 3 situations: 41947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // 1. A new connection is waiting to be accepted. 42047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // 2. The remote end closed the connection (a recv will return 0). 42147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // 3. Data is available to read. 42247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // 4. The connection closed unhappily (recv will return -1). 42347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (this_socket->state_ == CS_CONNECTING) { 42447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Case 1. 42547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org this_socket->SignalReadEvent(this_socket); 42647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 42747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org char ch, amt; 42847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org amt = ::recv(this_socket->native_socket_, &ch, 1, MSG_PEEK); 42947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (amt == 0) { 43047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Case 2. 43147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org this_socket->state_ = CS_CLOSED; 43247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 43347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Disable additional callbacks or we will signal close twice. 43447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CFSocketDisableCallBacks(this_socket->socket_, kCFSocketReadCallBack); 43547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org this_socket->current_callbacks_ &= ~kCFSocketReadCallBack; 43647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org this_socket->SignalCloseEvent(this_socket, 0); 43747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else if (amt > 0) { 43847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Case 3. 43947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org this_socket->SignalReadEvent(this_socket); 44047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 44147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Case 4. 44247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int error = errno; 44347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (error == EAGAIN) { 44447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Observed in practice. Let's hope it's a spurious or out of date 44547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // signal, since we just eat it. 44647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 44747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org this_socket->error_ = error; 44847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org this_socket->SignalCloseEvent(this_socket, error); 44947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 45047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 45147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 45247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 45347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 45447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case kCFSocketConnectCallBack: 45547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (data != NULL) { 45647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // An error occured in the background while connecting 45747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org this_socket->error_ = errno; 45847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org this_socket->state_ = CS_CLOSED; 45947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org this_socket->SignalCloseEvent(this_socket, this_socket->error_); 46047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 46147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org this_socket->state_ = CS_CONNECTED; 46247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org this_socket->SignalConnectEvent(this_socket); 46347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 46447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 46547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 46647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case kCFSocketWriteCallBack: 46747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Update our callback tracking. Write doesn't reenable, so it's off now. 46847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org this_socket->current_callbacks_ &= ~kCFSocketWriteCallBack; 46947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org this_socket->SignalWriteEvent(this_socket); 47047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 47147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 47247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org default: 47347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(false && "Invalid callback type for socket"); 47447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 47547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 47647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 47747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} // namespace rtc 478