Bumping manifests a=b2g-bump
[gecko.git] / ipc / unixfd / UnixSocketWatcher.cpp
blob25904d5aa56029ab6fbbdbd85ba77829fb76d2ff
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()
17 void UnixSocketWatcher::Close()
19 MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
21 mConnectionStatus = SOCKET_IS_DISCONNECTED;
22 UnixFdWatcher::Close();
25 nsresult
26 UnixSocketWatcher::Connect(const struct sockaddr* aAddr, socklen_t aAddrLen)
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);
40 return NS_ERROR_FAILURE;
43 mConnectionStatus = SOCKET_IS_CONNECTED;
44 OnConnected();
46 return NS_OK;
49 nsresult
50 UnixSocketWatcher::Listen(const struct sockaddr* aAddr, socklen_t aAddrLen)
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;
60 if (listen(GetFd(), 1) < 0) {
61 OnError("listen", errno);
62 return NS_ERROR_FAILURE;
64 mConnectionStatus = SOCKET_IS_LISTENING;
65 OnListening();
67 return NS_OK;
70 UnixSocketWatcher::UnixSocketWatcher(MessageLoop* aIOLoop)
71 : UnixFdWatcher(aIOLoop)
72 , mConnectionStatus(SOCKET_IS_DISCONNECTED)
76 UnixSocketWatcher::UnixSocketWatcher(MessageLoop* aIOLoop, int aFd,
77 ConnectionStatus aConnectionStatus)
78 : UnixFdWatcher(aIOLoop, aFd)
79 , mConnectionStatus(aConnectionStatus)
83 void
84 UnixSocketWatcher::SetSocket(int aFd, ConnectionStatus aConnectionStatus)
86 MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
88 SetFd(aFd);
89 mConnectionStatus = aConnectionStatus;
92 void
93 UnixSocketWatcher::OnFileCanReadWithoutBlocking(int aFd)
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);
110 } else {
111 NS_NOTREACHED("invalid connection state for reading");
115 void
116 UnixSocketWatcher::OnFileCanWriteWithoutBlocking(int aFd)
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();
135 } else {
136 NS_NOTREACHED("invalid connection state for writing");