ipc/unixfd/UnixSocketWatcher.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial