ipc/unixfd/UnixSocketWatcher.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
     2 /* vim: set ts=2 et sw=2 tw=80: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include <fcntl.h>
     8 #include "UnixSocketWatcher.h"
    10 namespace mozilla {
    11 namespace ipc {
    13 UnixSocketWatcher::~UnixSocketWatcher()
    14 {
    15 }
    17 void UnixSocketWatcher::Close()
    18 {
    19   MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
    21   mConnectionStatus = SOCKET_IS_DISCONNECTED;
    22   UnixFdWatcher::Close();
    23 }
    25 nsresult
    26 UnixSocketWatcher::Connect(const struct sockaddr* aAddr, socklen_t aAddrLen)
    27 {
    28   MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
    29   MOZ_ASSERT(IsOpen());
    30   MOZ_ASSERT(aAddr || !aAddrLen);
    32   if (connect(GetFd(), aAddr, aAddrLen) < 0) {
    33     if (errno == EINPROGRESS) {
    34       mConnectionStatus = SOCKET_IS_CONNECTING;
    35       // Set up a write watch to receive the connect signal
    36       AddWatchers(WRITE_WATCHER, false);
    37     } else {
    38       OnError("connect", errno);
    39     }
    40     return NS_ERROR_FAILURE;
    41   }
    43   mConnectionStatus = SOCKET_IS_CONNECTED;
    44   OnConnected();
    46   return NS_OK;
    47 }
    49 nsresult
    50 UnixSocketWatcher::Listen(const struct sockaddr* aAddr, socklen_t aAddrLen)
    51 {
    52   MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
    53   MOZ_ASSERT(IsOpen());
    54   MOZ_ASSERT(aAddr || !aAddrLen);
    56   if (bind(GetFd(), aAddr, aAddrLen) < 0) {
    57     OnError("bind", errno);
    58     return NS_ERROR_FAILURE;
    59   }
    60   if (listen(GetFd(), 1) < 0) {
    61     OnError("listen", errno);
    62     return NS_ERROR_FAILURE;
    63   }
    64   mConnectionStatus = SOCKET_IS_LISTENING;
    65   OnListening();
    67   return NS_OK;
    68 }
    70 UnixSocketWatcher::UnixSocketWatcher(MessageLoop* aIOLoop)
    71 : UnixFdWatcher(aIOLoop)
    72 , mConnectionStatus(SOCKET_IS_DISCONNECTED)
    73 {
    74 }
    76 UnixSocketWatcher::UnixSocketWatcher(MessageLoop* aIOLoop, int aFd,
    77                                      ConnectionStatus aConnectionStatus)
    78 : UnixFdWatcher(aIOLoop, aFd)
    79 , mConnectionStatus(aConnectionStatus)
    80 {
    81 }
    83 void
    84 UnixSocketWatcher::SetSocket(int aFd, ConnectionStatus aConnectionStatus)
    85 {
    86   MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
    88   SetFd(aFd);
    89   mConnectionStatus = aConnectionStatus;
    90 }
    92 void
    93 UnixSocketWatcher::OnFileCanReadWithoutBlocking(int aFd)
    94 {
    95   MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
    96   MOZ_ASSERT(aFd == GetFd());
    98   if (mConnectionStatus == SOCKET_IS_CONNECTED) {
    99     OnSocketCanReceiveWithoutBlocking();
   100   } else if (mConnectionStatus == SOCKET_IS_LISTENING) {
   101     sockaddr_any addr;
   102     socklen_t addrLen = sizeof(addr);
   103     int fd = TEMP_FAILURE_RETRY(accept(GetFd(),
   104       reinterpret_cast<struct sockaddr*>(&addr), &addrLen));
   105     if (fd < 0) {
   106       OnError("accept", errno);
   107     } else {
   108       OnAccepted(fd, &addr, addrLen);
   109     }
   110   } else {
   111     NS_NOTREACHED("invalid connection state for reading");
   112   }
   113 }
   115 void
   116 UnixSocketWatcher::OnFileCanWriteWithoutBlocking(int aFd)
   117 {
   118   MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
   119   MOZ_ASSERT(aFd == GetFd());
   121   if (mConnectionStatus == SOCKET_IS_CONNECTED) {
   122     OnSocketCanSendWithoutBlocking();
   123   } else if (mConnectionStatus == SOCKET_IS_CONNECTING) {
   124     RemoveWatchers(WRITE_WATCHER);
   125     int error = 0;
   126     socklen_t len = sizeof(error);
   127     if (getsockopt(GetFd(), SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
   128       OnError("getsockopt", errno);
   129     } else if (error) {
   130       OnError("connect", error);
   131     } else {
   132       mConnectionStatus = SOCKET_IS_CONNECTED;
   133       OnConnected();
   134     }
   135   } else {
   136     NS_NOTREACHED("invalid connection state for writing");
   137   }
   138 }
   140 }
   141 }

mercurial