ipc/unixfd/UnixSocketWatcher.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/ipc/unixfd/UnixSocketWatcher.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,141 @@
     1.4 +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
     1.5 +/* vim: set ts=2 et sw=2 tw=80: */
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#include <fcntl.h>
    1.11 +#include "UnixSocketWatcher.h"
    1.12 +
    1.13 +namespace mozilla {
    1.14 +namespace ipc {
    1.15 +
    1.16 +UnixSocketWatcher::~UnixSocketWatcher()
    1.17 +{
    1.18 +}
    1.19 +
    1.20 +void UnixSocketWatcher::Close()
    1.21 +{
    1.22 +  MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
    1.23 +
    1.24 +  mConnectionStatus = SOCKET_IS_DISCONNECTED;
    1.25 +  UnixFdWatcher::Close();
    1.26 +}
    1.27 +
    1.28 +nsresult
    1.29 +UnixSocketWatcher::Connect(const struct sockaddr* aAddr, socklen_t aAddrLen)
    1.30 +{
    1.31 +  MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
    1.32 +  MOZ_ASSERT(IsOpen());
    1.33 +  MOZ_ASSERT(aAddr || !aAddrLen);
    1.34 +
    1.35 +  if (connect(GetFd(), aAddr, aAddrLen) < 0) {
    1.36 +    if (errno == EINPROGRESS) {
    1.37 +      mConnectionStatus = SOCKET_IS_CONNECTING;
    1.38 +      // Set up a write watch to receive the connect signal
    1.39 +      AddWatchers(WRITE_WATCHER, false);
    1.40 +    } else {
    1.41 +      OnError("connect", errno);
    1.42 +    }
    1.43 +    return NS_ERROR_FAILURE;
    1.44 +  }
    1.45 +
    1.46 +  mConnectionStatus = SOCKET_IS_CONNECTED;
    1.47 +  OnConnected();
    1.48 +
    1.49 +  return NS_OK;
    1.50 +}
    1.51 +
    1.52 +nsresult
    1.53 +UnixSocketWatcher::Listen(const struct sockaddr* aAddr, socklen_t aAddrLen)
    1.54 +{
    1.55 +  MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
    1.56 +  MOZ_ASSERT(IsOpen());
    1.57 +  MOZ_ASSERT(aAddr || !aAddrLen);
    1.58 +
    1.59 +  if (bind(GetFd(), aAddr, aAddrLen) < 0) {
    1.60 +    OnError("bind", errno);
    1.61 +    return NS_ERROR_FAILURE;
    1.62 +  }
    1.63 +  if (listen(GetFd(), 1) < 0) {
    1.64 +    OnError("listen", errno);
    1.65 +    return NS_ERROR_FAILURE;
    1.66 +  }
    1.67 +  mConnectionStatus = SOCKET_IS_LISTENING;
    1.68 +  OnListening();
    1.69 +
    1.70 +  return NS_OK;
    1.71 +}
    1.72 +
    1.73 +UnixSocketWatcher::UnixSocketWatcher(MessageLoop* aIOLoop)
    1.74 +: UnixFdWatcher(aIOLoop)
    1.75 +, mConnectionStatus(SOCKET_IS_DISCONNECTED)
    1.76 +{
    1.77 +}
    1.78 +
    1.79 +UnixSocketWatcher::UnixSocketWatcher(MessageLoop* aIOLoop, int aFd,
    1.80 +                                     ConnectionStatus aConnectionStatus)
    1.81 +: UnixFdWatcher(aIOLoop, aFd)
    1.82 +, mConnectionStatus(aConnectionStatus)
    1.83 +{
    1.84 +}
    1.85 +
    1.86 +void
    1.87 +UnixSocketWatcher::SetSocket(int aFd, ConnectionStatus aConnectionStatus)
    1.88 +{
    1.89 +  MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
    1.90 +
    1.91 +  SetFd(aFd);
    1.92 +  mConnectionStatus = aConnectionStatus;
    1.93 +}
    1.94 +
    1.95 +void
    1.96 +UnixSocketWatcher::OnFileCanReadWithoutBlocking(int aFd)
    1.97 +{
    1.98 +  MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
    1.99 +  MOZ_ASSERT(aFd == GetFd());
   1.100 +
   1.101 +  if (mConnectionStatus == SOCKET_IS_CONNECTED) {
   1.102 +    OnSocketCanReceiveWithoutBlocking();
   1.103 +  } else if (mConnectionStatus == SOCKET_IS_LISTENING) {
   1.104 +    sockaddr_any addr;
   1.105 +    socklen_t addrLen = sizeof(addr);
   1.106 +    int fd = TEMP_FAILURE_RETRY(accept(GetFd(),
   1.107 +      reinterpret_cast<struct sockaddr*>(&addr), &addrLen));
   1.108 +    if (fd < 0) {
   1.109 +      OnError("accept", errno);
   1.110 +    } else {
   1.111 +      OnAccepted(fd, &addr, addrLen);
   1.112 +    }
   1.113 +  } else {
   1.114 +    NS_NOTREACHED("invalid connection state for reading");
   1.115 +  }
   1.116 +}
   1.117 +
   1.118 +void
   1.119 +UnixSocketWatcher::OnFileCanWriteWithoutBlocking(int aFd)
   1.120 +{
   1.121 +  MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
   1.122 +  MOZ_ASSERT(aFd == GetFd());
   1.123 +
   1.124 +  if (mConnectionStatus == SOCKET_IS_CONNECTED) {
   1.125 +    OnSocketCanSendWithoutBlocking();
   1.126 +  } else if (mConnectionStatus == SOCKET_IS_CONNECTING) {
   1.127 +    RemoveWatchers(WRITE_WATCHER);
   1.128 +    int error = 0;
   1.129 +    socklen_t len = sizeof(error);
   1.130 +    if (getsockopt(GetFd(), SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
   1.131 +      OnError("getsockopt", errno);
   1.132 +    } else if (error) {
   1.133 +      OnError("connect", error);
   1.134 +    } else {
   1.135 +      mConnectionStatus = SOCKET_IS_CONNECTED;
   1.136 +      OnConnected();
   1.137 +    }
   1.138 +  } else {
   1.139 +    NS_NOTREACHED("invalid connection state for writing");
   1.140 +  }
   1.141 +}
   1.142 +
   1.143 +}
   1.144 +}

mercurial