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/. */
6
7 #include <fcntl.h>
8 #include "UnixSocketWatcher.h"
9
10 namespace mozilla {
11 namespace ipc {
12
~UnixSocketWatcher()13 UnixSocketWatcher::~UnixSocketWatcher()
14 {
15 }
16
Close()17 void UnixSocketWatcher::Close()
18 {
19 MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
20
21 mConnectionStatus = SOCKET_IS_DISCONNECTED;
22 UnixFdWatcher::Close();
23 }
24
25 nsresult
Connect(const struct sockaddr * aAddr,socklen_t aAddrLen)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);
31
32 if (TEMP_FAILURE_RETRY(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 return NS_OK;
38 }
39 OnError("connect", errno);
40 return NS_ERROR_FAILURE;
41 }
42
43 mConnectionStatus = SOCKET_IS_CONNECTED;
44 OnConnected();
45
46 return NS_OK;
47 }
48
49 nsresult
Listen(const struct sockaddr * aAddr,socklen_t aAddrLen)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);
55
56 if (mConnectionStatus == SOCKET_IS_DISCONNECTED) {
57 // We init the socket descriptor when we listen for the first time.
58 if (bind(GetFd(), aAddr, aAddrLen) < 0) {
59 OnError("bind", errno);
60 return NS_ERROR_FAILURE;
61 }
62 if (listen(GetFd(), 1) < 0) {
63 OnError("listen", errno);
64 return NS_ERROR_FAILURE;
65 }
66 }
67 mConnectionStatus = SOCKET_IS_LISTENING;
68 OnListening();
69
70 return NS_OK;
71 }
72
UnixSocketWatcher(MessageLoop * aIOLoop)73 UnixSocketWatcher::UnixSocketWatcher(MessageLoop* aIOLoop)
74 : UnixFdWatcher(aIOLoop)
75 , mConnectionStatus(SOCKET_IS_DISCONNECTED)
76 {
77 }
78
UnixSocketWatcher(MessageLoop * aIOLoop,int aFd,ConnectionStatus aConnectionStatus)79 UnixSocketWatcher::UnixSocketWatcher(MessageLoop* aIOLoop, int aFd,
80 ConnectionStatus aConnectionStatus)
81 : UnixFdWatcher(aIOLoop, aFd)
82 , mConnectionStatus(aConnectionStatus)
83 {
84 }
85
86 void
SetSocket(int aFd,ConnectionStatus aConnectionStatus)87 UnixSocketWatcher::SetSocket(int aFd, ConnectionStatus aConnectionStatus)
88 {
89 MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
90
91 SetFd(aFd);
92 mConnectionStatus = aConnectionStatus;
93 }
94
95 void
OnFileCanReadWithoutBlocking(int aFd)96 UnixSocketWatcher::OnFileCanReadWithoutBlocking(int aFd)
97 {
98 MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
99 MOZ_ASSERT(aFd == GetFd());
100
101 if (mConnectionStatus == SOCKET_IS_CONNECTED) {
102 OnSocketCanReceiveWithoutBlocking();
103 } else if (mConnectionStatus == SOCKET_IS_LISTENING) {
104 OnSocketCanAcceptWithoutBlocking();
105 } else {
106 NS_NOTREACHED("invalid connection state for reading");
107 }
108 }
109
110 void
OnFileCanWriteWithoutBlocking(int aFd)111 UnixSocketWatcher::OnFileCanWriteWithoutBlocking(int aFd)
112 {
113 MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
114 MOZ_ASSERT(aFd == GetFd());
115
116 if (mConnectionStatus == SOCKET_IS_CONNECTED) {
117 OnSocketCanSendWithoutBlocking();
118 } else if (mConnectionStatus == SOCKET_IS_CONNECTING) {
119 RemoveWatchers(WRITE_WATCHER);
120 int error = 0;
121 socklen_t len = sizeof(error);
122 if (getsockopt(GetFd(), SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
123 OnError("getsockopt", errno);
124 } else if (error) {
125 OnError("connect", error);
126 } else {
127 mConnectionStatus = SOCKET_IS_CONNECTED;
128 OnConnected();
129 }
130 } else {
131 NS_NOTREACHED("invalid connection state for writing");
132 }
133 }
134
135 }
136 }
137