sync_socket_posix.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sync_socket.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/ioctl.h> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/socket.h> 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h> 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_SOLARIS) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/filio.h> 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// To avoid users sending negative message lengths to Send/Receive 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we clamp message lengths, which are size_t, to no more than INT_MAX. 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kMaxMessageLength = static_cast<size_t>(INT_MAX); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const SyncSocket::Handle SyncSocket::kInvalidHandle = -1; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncSocket::SyncSocket() : handle_(kInvalidHandle) {} 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncSocket::~SyncSocket() { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Close(); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SyncSocket::CreatePair(SyncSocket* socket_a, SyncSocket* socket_b) { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(socket_a != socket_b); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(socket_a->handle_ == kInvalidHandle); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(socket_b->handle_ == kInvalidHandle); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nosigpipe = 1; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // defined(OS_MACOSX) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Handle handles[2] = { kInvalidHandle, kInvalidHandle }; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (socketpair(AF_UNIX, SOCK_STREAM, 0, handles) != 0) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto cleanup; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // On OSX an attempt to read or write to a closed socket may generate a 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SIGPIPE rather than returning -1. setsockopt will shut this off. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (0 != setsockopt(handles[0], SOL_SOCKET, SO_NOSIGPIPE, 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &nosigpipe, sizeof nosigpipe) || 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0 != setsockopt(handles[1], SOL_SOCKET, SO_NOSIGPIPE, 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &nosigpipe, sizeof nosigpipe)) { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto cleanup; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Copy the handles out for successful return. 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket_a->handle_ = handles[0]; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket_b->handle_ = handles[1]; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cleanup: 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (handles[0] != kInvalidHandle) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HANDLE_EINTR(close(handles[0])) < 0) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DPLOG(ERROR) << "close"; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (handles[1] != kInvalidHandle) { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HANDLE_EINTR(close(handles[1])) < 0) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DPLOG(ERROR) << "close"; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SyncSocket::Close() { 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (handle_ == kInvalidHandle) { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int retval = HANDLE_EINTR(close(handle_)); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (retval < 0) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DPLOG(ERROR) << "close"; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handle_ = kInvalidHandle; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (retval == 0); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SyncSocket::Send(const void* buffer, size_t length) { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(length, kMaxMessageLength); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* charbuffer = static_cast<const char*>(buffer); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int len = file_util::WriteFileDescriptor(handle_, charbuffer, length); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (len == -1) ? 0 : static_cast<size_t>(len); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SyncSocket::Receive(void* buffer, size_t length) { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(length, kMaxMessageLength); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* charbuffer = static_cast<char*>(buffer); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (file_util::ReadFromFD(handle_, charbuffer, length)) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return length; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SyncSocket::Peek() { 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int number_chars; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (-1 == ioctl(handle_, FIONREAD, &number_chars)) { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there is an error in ioctl, signal that the channel would block. 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (size_t) number_chars; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CancelableSyncSocket::CancelableSyncSocket() {} 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CancelableSyncSocket::CancelableSyncSocket(Handle handle) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : SyncSocket(handle) { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CancelableSyncSocket::Shutdown() { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HANDLE_EINTR(shutdown(handle(), SHUT_RDWR)) >= 0; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t CancelableSyncSocket::Send(const void* buffer, size_t length) { 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) long flags = 0; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flags = fcntl(handle_, F_GETFL, NULL); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (flags != -1 && (flags & O_NONBLOCK) == 0) { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set the socket to non-blocking mode for sending if its original mode 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is blocking. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fcntl(handle_, F_SETFL, flags | O_NONBLOCK); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t len = SyncSocket::Send(buffer, length); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (flags != -1 && (flags & O_NONBLOCK) == 0) { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Restore the original flags. 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fcntl(handle_, F_SETFL, flags); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return len; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CancelableSyncSocket::CreatePair(CancelableSyncSocket* socket_a, 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelableSyncSocket* socket_b) { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SyncSocket::CreatePair(socket_a, socket_b); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 155