void DBusWatcher::HandleWatchAdd() { int fd; ssize_t res = TEMP_FAILURE_RETRY(read(mControlFdR.get(), &fd, sizeof(fd))); if (res < 0) { LOG("Cannot read DBus watch add descriptor data from socket!\n"); return; } unsigned int flags; res = TEMP_FAILURE_RETRY(read(mControlFdR.get(), &flags, sizeof(flags))); if (res < 0) { LOG("Cannot read DBus watch add flag data from socket!\n"); return; } DBusWatch* watch; res = TEMP_FAILURE_RETRY(read(mControlFdR.get(), &watch, sizeof(watch))); if (res < 0) { LOG("Cannot read DBus watch add watch data from socket!\n"); return; } struct pollfd p = { fd, // .fd DBusFlagsToUnixEvents(flags), // .events 0 // .revents }; if (mPollData.Contains(p, PollFdComparator())) { return; } mPollData.AppendElement(p); mWatchData.AppendElement(watch); }
void DBusWatcher::RemoveWatch(DBusWatch* aWatch) { static const char control = DBUS_EVENT_LOOP_REMOVE; ssize_t res = TEMP_FAILURE_RETRY(write(mControlFdW.get(), &control, sizeof(control))); if (res < 0) { LOG("Cannot write DBus remove watch control data to socket!\n"); return; } int fd = dbus_watch_get_unix_fd(aWatch); res = TEMP_FAILURE_RETRY(write(mControlFdW.get(), &fd, sizeof(fd))); if (res < 0) { LOG("Cannot write DBus remove watch descriptor data to socket!\n"); return; } unsigned int flags = dbus_watch_get_flags(aWatch); res = TEMP_FAILURE_RETRY(write(mControlFdW.get(), &flags, sizeof(flags))); if (res < 0) { LOG("Cannot write DBus remove watch flag data to socket!\n"); return; } }
nsresult KeyStoreConnector::CreateListenSocket(struct sockaddr* aAddress, socklen_t* aAddressLength, int& aListenFd) { ScopedClose fd; nsresult rv = CreateSocket(fd.rwget()); if (NS_FAILED(rv)) { return rv; } rv = SetSocketFlags(fd); if (NS_FAILED(rv)) { return rv; } if (aAddress && aAddressLength) { rv = CreateAddress(*aAddress, *aAddressLength); if (NS_FAILED(rv)) { return rv; } } // Allow access for wpa_supplicant (different user, different group) // // TODO: Improve this by setting specific user/group for // wpa_supplicant by calling |fchmod| and |fchown|. // chmod(KEYSTORE_SOCKET_PATH, S_IRUSR|S_IWUSR| S_IRGRP|S_IWGRP| S_IROTH|S_IWOTH); aListenFd = fd.forget(); return NS_OK; }
void DBusThread::CleanUp() { MOZ_ASSERT(!NS_IsMainThread()); dbus_connection_set_wakeup_main_function(mConnection, nullptr, nullptr, nullptr); dbus_bool_t success = dbus_connection_set_watch_functions(mConnection, nullptr, nullptr, nullptr, nullptr, nullptr); if (success != TRUE) { NS_WARNING("dbus_connection_set_watch_functions failed"); } #ifdef DEBUG LOG("Removing DBus Sockets\n"); #endif if (mControlFdW.get()) { mControlFdW.dispose(); } if (mControlFdR.get()) { mControlFdR.dispose(); } mPollData.Clear(); // DBusWatch pointers are maintained by DBus, so we won't leak by // clearing. mWatchData.Clear(); }
nsresult NfcConnector::CreateStreamSocket(struct sockaddr* aAddress, socklen_t* aAddressLength, int& aStreamFd) { ScopedClose fd; nsresult rv = CreateSocket(fd.rwget()); if (NS_FAILED(rv)) { return rv; } rv = SetSocketFlags(fd); if (NS_FAILED(rv)) { return rv; } if (aAddress && aAddressLength) { rv = CreateAddress(*aAddress, *aAddressLength); if (NS_FAILED(rv)) { return rv; } } aStreamFd = fd.forget(); return NS_OK; }
void DBusThread::EventLoop() { dbus_connection_set_watch_functions(mConnection, AddWatch, RemoveWatch, ToggleWatch, this, NULL); dbus_connection_set_wakeup_main_function(mConnection, DBusWakeup, this, NULL); #ifdef DEBUG LOG("DBus Event Loop Starting\n"); #endif while (1) { poll(mPollData.Elements(), mPollData.Length(), -1); for (uint32_t i = 0; i < mPollData.Length(); i++) { if (!mPollData[i].revents) { continue; } if (mPollData[i].fd == mControlFdR.get()) { char data; while (recv(mControlFdR.get(), &data, sizeof(char), MSG_DONTWAIT) != -1) { switch (data) { case DBUS_EVENT_LOOP_EXIT: #ifdef DEBUG LOG("DBus Event Loop Exiting\n"); #endif dbus_connection_set_watch_functions(mConnection, NULL, NULL, NULL, NULL, NULL); return; case DBUS_EVENT_LOOP_ADD: HandleWatchAdd(this); break; case DBUS_EVENT_LOOP_REMOVE: HandleWatchRemove(this); break; case DBUS_EVENT_LOOP_WAKEUP: // noop break; } } } else { short events = mPollData[i].revents; unsigned int flags = UnixEventsToDBusFlags(events); dbus_watch_handle(mWatchData[i], flags); mPollData[i].revents = 0; // Break at this point since we don't know if the operation // was destructive break; } } while (dbus_connection_dispatch(mConnection) == DBUS_DISPATCH_DATA_REMAINS) {} } }
bool DBusWatcher::SetUp() { MOZ_ASSERT(!NS_IsMainThread()); // If we already have a connection, exit if (mConnection) { return false; } // socketpair opens two sockets for the process to communicate on. // This is how android's implementation of the dbus event loop // communicates with itself in relation to IPC signals. These // sockets are contained sequentially in the same struct in the // android code, but we break them out into class members here. // Therefore we read into a local array and then copy. int sockets[2]; if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sockets) < 0) { return false; } mControlFdR.rwget() = sockets[0]; mControlFdW.rwget() = sockets[1]; pollfd* p = mPollData.AppendElement(); p->fd = mControlFdR.get(); p->events = POLLIN; p->revents = 0; // Due to the fact that mPollData and mWatchData have to match, we // push a null to the front of mWatchData since it has the control // fd in the first slot of mPollData. mWatchData.AppendElement(static_cast<DBusWatch*>(nullptr)); // If we can't establish a connection to dbus, nothing else will work nsresult rv = EstablishDBusConnection(); if (NS_FAILED(rv)) { NS_WARNING("Cannot create DBus Connection for DBus Thread!"); return false; } dbus_bool_t success = dbus_connection_set_watch_functions(mConnection, AddWatchFunction, RemoveWatchFunction, ToggleWatchFunction, this, nullptr); NS_ENSURE_TRUE(success == TRUE, false); dbus_connection_set_wakeup_main_function(mConnection, DBusWakeupFunction, this, nullptr); return true; }
void UnixSocketImpl::Connect() { MOZ_ASSERT(!NS_IsMainThread()); if (!mConnector) { NS_WARNING("No connector object available!"); return; } if (mFd.get() < 0) { mFd = mConnector->Create(); if (mFd.get() < 0) { return; } } int ret; if (!mConnector->CreateAddr(false, mAddrSize, mAddr, mAddress.get())) { NS_WARNING("Cannot create socket address!"); return; } ret = connect(mFd.get(), (struct sockaddr*)&mAddr, mAddrSize); if (ret) { #if DEBUG LOG("Socket connect errno=%d\n", errno); #endif mFd.reset(-1); nsRefPtr<OnSocketEventTask> t = new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR); NS_DispatchToMainThread(t); return; } if (!SetSocketFlags()) { return; } if (!mConnector->SetUp(mFd)) { NS_WARNING("Could not set up socket!"); return; } nsRefPtr<OnSocketEventTask> t = new OnSocketEventTask(this, OnSocketEventTask::CONNECT_SUCCESS); NS_DispatchToMainThread(t); SetUpIO(); }
bool NetlinkPoller::OpenSocket() { mSocket.rwget() = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); if (mSocket.get() < 0) return false; int sz = kBuffsize; if (setsockopt(mSocket.get(), SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) return false; // add FD_CLOEXEC flag int flags = fcntl(mSocket.get(), F_GETFD); if (flags == -1) { return false; } flags |= FD_CLOEXEC; if (fcntl(mSocket.get(), F_SETFD, flags) == -1) return false; // set non-blocking if (fcntl(mSocket.get(), F_SETFL, O_NONBLOCK) == -1) return false; struct sockaddr_nl saddr; bzero(&saddr, sizeof(saddr)); saddr.nl_family = AF_NETLINK; saddr.nl_groups = 1; saddr.nl_pid = gettid(); do { if (bind(mSocket.get(), (struct sockaddr *)&saddr, sizeof(saddr)) == 0) { break; } if (errno != EADDRINUSE) { return false; } if (saddr.nl_pid == 0) { return false; } // Once there was any other place in the same process assigning saddr.nl_pid by // gettid(), we can detect it and print warning message. printf_stderr("The netlink socket address saddr.nl_pid=%u is in use. Let the kernel re-assign.\n", saddr.nl_pid); saddr.nl_pid = 0; } while (true); if (!mIOLoop->WatchFileDescriptor(mSocket.get(), true, MessageLoopForIO::WATCH_READ, &mReadWatcher, this)) { return false; } return true; }
bool DBusThread::StopEventLoop() { if (!mThread) { return true; } char data = DBUS_EVENT_LOOP_EXIT; ssize_t wret = write(mControlFdW.get(), &data, sizeof(char)); if(wret < 0) { NS_ERROR("Cannot write exit flag to Dbus Thread!"); return false; } #ifdef DEBUG LOG("DBus Thread Joining\n"); #endif nsCOMPtr<nsIThread> tmpThread; mThread.swap(tmpThread); if(NS_FAILED(tmpThread->Shutdown())) { NS_WARNING("DBus thread shutdown failed!"); } #ifdef DEBUG LOG("DBus Thread Joined\n"); #endif TearDownData(); return true; }
bool DBusThread::TearDownData() { LOG("Removing DBus Sockets\n"); if (mControlFdW.get()) { mControlFdW.dispose(); } if (mControlFdR.get()) { mControlFdR.dispose(); } mPollData.Clear(); // DBusWatch pointers are maintained by DBus, so we won't leak by // clearing. mWatchData.Clear(); return true; }
void UnixSocketImpl::Connect() { if(mFd.get() < 0) { mFd = mConnector->Create(); if (mFd.get() < 0) { return; } } int ret; socklen_t addr_sz; struct sockaddr addr; mConnector->CreateAddr(false, addr_sz, &addr, mAddress.get()); ret = connect(mFd.get(), &addr, addr_sz); if (ret) { #if DEBUG LOG("Socket connect errno=%d\n", errno); #endif mFd.reset(-1); nsRefPtr<OnSocketEventTask> t = new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR); NS_DispatchToMainThread(t); return; } if (!mConnector->SetUp(mFd)) { NS_WARNING("Could not set up socket!"); return; } nsRefPtr<OnSocketEventTask> t = new OnSocketEventTask(this, OnSocketEventTask::CONNECT_SUCCESS); NS_DispatchToMainThread(t); // Due to the fact that we've dispatched our OnConnectSuccess message before // starting reading, we're guaranteed that any subsequent read tasks will // happen after the object has been notified of a successful connect. XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new StartImplReadingTask(this)); }
bool DBusThread::StartEventLoop() { // socketpair opens two sockets for the process to communicate on. // This is how android's implementation of the dbus event loop // communicates with itself in relation to IPC signals. These // sockets are contained sequentially in the same struct in the // android code, but we break them out into class members here. // Therefore we read into a local array and then copy. int sockets[2]; if (socketpair(AF_LOCAL, SOCK_STREAM, 0, (int*)(&sockets)) < 0) { TearDownData(); return false; } mControlFdR.rwget() = sockets[0]; mControlFdW.rwget() = sockets[1]; pollfd p; p.fd = mControlFdR.get(); p.events = POLLIN; mPollData.AppendElement(p); // Due to the fact that mPollData and mWatchData have to match, we // push a null to the front of mWatchData since it has the control // fd in the first slot of mPollData. mWatchData.AppendElement((DBusWatch*)NULL); if (!SetUpEventLoop()) { TearDownData(); return false; } if (NS_FAILED(NS_NewNamedThread("DBus Poll", getter_AddRefs(mThread), NS_NewNonOwningRunnableMethod(this, &DBusThread::EventLoop)))) { NS_WARNING("Cannot create DBus Thread!"); return false; } #ifdef DEBUG LOG("DBus Thread Starting\n"); #endif return true; }
bool DBusWatcher::AddWatch(DBusWatch* aWatch) { static const char control = DBUS_EVENT_LOOP_ADD; if (dbus_watch_get_enabled(aWatch) == FALSE) { return true; } // note that we can't just send the watch and inspect it later // because we may get a removeWatch call before this data is reacted // to by our eventloop and remove this watch.. reading the add first // and then inspecting the recently deceased watch would be bad. ssize_t res = TEMP_FAILURE_RETRY(write(mControlFdW.get(),&control, sizeof(control))); if (res < 0) { LOG("Cannot write DBus add watch control data to socket!\n"); return false; } int fd = dbus_watch_get_unix_fd(aWatch); res = TEMP_FAILURE_RETRY(write(mControlFdW.get(), &fd, sizeof(fd))); if (res < 0) { LOG("Cannot write DBus add watch descriptor data to socket!\n"); return false; } unsigned int flags = dbus_watch_get_flags(aWatch); res = TEMP_FAILURE_RETRY(write(mControlFdW.get(), &flags, sizeof(flags))); if (res < 0) { LOG("Cannot write DBus add watch flag data to socket!\n"); return false; } res = TEMP_FAILURE_RETRY(write(mControlFdW.get(), &aWatch, sizeof(aWatch))); if (res < 0) { LOG("Cannot write DBus add watch struct data to socket!\n"); return false; } return true; }
bool DBusWatcher::Stop() { static const char data = DBUS_EVENT_LOOP_EXIT; ssize_t res = TEMP_FAILURE_RETRY(write(mControlFdW.get(), &data, sizeof(data))); NS_ENSURE_TRUE(res == 1, false); return true; }
void DBusThread::WakeUp() { static const char control = DBUS_EVENT_LOOP_WAKEUP; struct pollfd fds = { mControlFdW.get(), POLLOUT, 0 }; int nfds = TEMP_FAILURE_RETRY(poll(&fds, 1, 0)); NS_ENSURE_TRUE_VOID(nfds == 1); NS_ENSURE_TRUE_VOID(fds.revents == POLLOUT); ssize_t rv = TEMP_FAILURE_RETRY(write(mControlFdW.get(), &control, sizeof(control))); if (rv < 0) { NS_WARNING("Cannot write wakeup bit to DBus controller!"); } }
void DBusWatcher::HandleWatchRemove() { int fd; ssize_t res = TEMP_FAILURE_RETRY(read(mControlFdR.get(), &fd, sizeof(fd))); if (res < 0) { LOG("Cannot read DBus watch remove descriptor data from socket!\n"); return; } unsigned int flags; res = TEMP_FAILURE_RETRY(read(mControlFdR.get(), &flags, sizeof(flags))); if (res < 0) { LOG("Cannot read DBus watch remove flag data from socket!\n"); return; } struct pollfd p = { fd, // .fd DBusFlagsToUnixEvents(flags), // .events 0 // .revents }; int index = mPollData.IndexOf(p, 0, PollFdComparator()); // There are times where removes can be requested for watches that // haven't been added (for example, whenever gecko comes up after // adapters have already been enabled), so check to make sure we're // using the watch in the first place if (index < 0) { LOG("DBus requested watch removal of non-existant socket, ignoring..."); return; } mPollData.RemoveElementAt(index); // DBusWatch pointers are maintained by DBus, so we won't leak by // removing. mWatchData.RemoveElementAt(index); }
bool NetlinkPoller::OpenSocket() { mSocket.rwget() = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); if (mSocket.get() < 0) return false; int sz = kBuffsize; if (setsockopt(mSocket.get(), SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) return false; // add FD_CLOEXEC flag int flags = fcntl(mSocket.get(), F_GETFD); if (flags == -1) { return false; } flags |= FD_CLOEXEC; if (fcntl(mSocket.get(), F_SETFD, flags) == -1) return false; // set non-blocking if (fcntl(mSocket.get(), F_SETFL, O_NONBLOCK) == -1) return false; struct sockaddr_nl saddr; bzero(&saddr, sizeof(saddr)); saddr.nl_family = AF_NETLINK; saddr.nl_groups = 1; saddr.nl_pid = getpid(); if (bind(mSocket.get(), (struct sockaddr *)&saddr, sizeof(saddr)) == -1) return false; if (!mIOLoop->WatchFileDescriptor(mSocket.get(), true, MessageLoopForIO::WATCH_READ, &mReadWatcher, this)) { return false; } return true; }
void NetlinkPoller::OnFileCanReadWithoutBlocking(int fd) { MOZ_ASSERT(fd == mSocket.get()); while (true) { int ret = read(fd, mBuffer, kBuffsize); if (ret == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { return; } if (errno == EINTR) { continue; } } if (ret <= 0) { // fatal error on netlink socket which should not happen _exit(1); } mNetlinkEvent.decode(reinterpret_cast<char*>(mBuffer), ret); mUeventObserverList.Broadcast(mNetlinkEvent); } }
void UnixSocketImpl::Accept() { MOZ_ASSERT(!NS_IsMainThread()); if (!mConnector) { NS_WARNING("No connector object available!"); return; } // This will set things we don't particularly care about, but it will hand // back the correct structure size which is what we do care about. if (!mConnector->CreateAddr(true, mAddrSize, mAddr, nullptr)) { NS_WARNING("Cannot create socket address!"); return; } if (mFd.get() < 0) { mFd = mConnector->Create(); if (mFd.get() < 0) { return; } if (!SetSocketFlags()) { return; } if (bind(mFd.get(), (struct sockaddr*)&mAddr, mAddrSize)) { #ifdef DEBUG LOG("...bind(%d) gave errno %d", mFd.get(), errno); #endif return; } if (listen(mFd.get(), 1)) { #ifdef DEBUG LOG("...listen(%d) gave errno %d", mFd.get(), errno); #endif return; } } SetUpIO(); }
void UnixSocketImpl::OnFileCanReadWithoutBlocking(int aFd) { MOZ_ASSERT(!NS_IsMainThread()); MOZ_ASSERT(!mShuttingDownOnIOThread); SocketConnectionStatus status = mConsumer->GetConnectionStatus(); if (status == SOCKET_CONNECTED) { // Read all of the incoming data. while (true) { uint8_t data[MAX_READ_SIZE]; ssize_t ret = read(aFd, data, MAX_READ_SIZE); if (ret <= 0) { if (ret == -1) { if (errno == EINTR) { continue; // retry system call when interrupted } if (errno == EAGAIN || errno == EWOULDBLOCK) { return; // no data available: return and re-poll } #ifdef DEBUG NS_WARNING("Cannot read from network"); #endif // else fall through to error handling on other errno's } // We're done with our descriptors. Ensure that spurious events don't // cause us to end up back here. mReadWatcher.StopWatchingFileDescriptor(); mWriteWatcher.StopWatchingFileDescriptor(); nsRefPtr<RequestClosingSocketTask> t = new RequestClosingSocketTask(this); NS_DispatchToMainThread(t); return; } UnixSocketRawData* incoming = new UnixSocketRawData(ret); memcpy(incoming->mData, data, ret); nsRefPtr<SocketReceiveTask> t = new SocketReceiveTask(this, incoming); NS_DispatchToMainThread(t); // If ret is less than MAX_READ_SIZE, there's no more data in the socket // for us to read now. if (ret < ssize_t(MAX_READ_SIZE)) { return; } } MOZ_NOT_REACHED("We returned early"); } if (status == SOCKET_LISTENING) { int client_fd = accept(mFd.get(), (struct sockaddr*)&mAddr, &mAddrSize); if (client_fd < 0) { return; } if (!mConnector->SetUp(client_fd)) { NS_WARNING("Could not set up socket!"); return; } mReadWatcher.StopWatchingFileDescriptor(); mWriteWatcher.StopWatchingFileDescriptor(); mFd.reset(client_fd); if (!SetSocketFlags()) { return; } mIOLoop = nullptr; nsRefPtr<OnSocketEventTask> t = new OnSocketEventTask(this, OnSocketEventTask::CONNECT_SUCCESS); NS_DispatchToMainThread(t); SetUpIO(); } }
void UnixSocketImpl::Accept() { socklen_t addr_sz; struct sockaddr addr; if (!mConnector) { NS_WARNING("No connector object available!"); return; } // This will set things we don't particularly care about, but it will hand // back the correct structure size which is what we do care about. mConnector->CreateAddr(true, addr_sz, &addr, nullptr); if(mFd.get() < 0) { mFd = mConnector->Create(); if (mFd.get() < 0) { return; } if (!SetNonblockFlags()) { return; } if (bind(mFd.get(), &addr, addr_sz)) { #ifdef DEBUG LOG("...bind(%d) gave errno %d", mFd.get(), errno); #endif return; } if (listen(mFd.get(), 1)) { #ifdef DEBUG LOG("...listen(%d) gave errno %d", mFd.get(), errno); #endif return; } } int client_fd; client_fd = accept(mFd.get(), &addr, &addr_sz); if (client_fd < 0) { EnqueueTask(SOCKET_RETRY_TIME_MS, new SocketAcceptTask(this)); return; } if (!mConnector->SetUp(client_fd)) { NS_WARNING("Could not set up socket!"); return; } mFd.reset(client_fd); nsRefPtr<OnSocketEventTask> t = new OnSocketEventTask(this, OnSocketEventTask::CONNECT_SUCCESS); NS_DispatchToMainThread(t); // Due to the fact that we've dispatched our OnConnectSuccess message before // starting reading, we're guaranteed that any subsequent read tasks will // happen after the object has been notified of a successful connect. XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new StartImplReadingTask(this)); }
void UnixSocketImpl::Accept() { MOZ_ASSERT(!NS_IsMainThread()); mTask = nullptr; if (!mConnector) { NS_WARNING("No connector object available!"); return; } // This will set things we don't particularly care about, but it will hand // back the correct structure size which is what we do care about. if (!mConnector->CreateAddr(true, mAddrSize, mAddr, nullptr)) { NS_WARNING("Cannot create socket address!"); return; } if (mFd.get() < 0) { mFd = mConnector->Create(); if (mFd.get() < 0) { return; } if (!SetNonblockFlags()) { return; } if (bind(mFd.get(), (struct sockaddr*)&mAddr, mAddrSize)) { #ifdef DEBUG LOG("...bind(%d) gave errno %d", mFd.get(), errno); #endif return; } if (listen(mFd.get(), 1)) { #ifdef DEBUG LOG("...listen(%d) gave errno %d", mFd.get(), errno); #endif return; } } int client_fd; client_fd = accept(mFd.get(), (struct sockaddr*)&mAddr, &mAddrSize); if (client_fd < 0) { EnqueueTask(SOCKET_RETRY_TIME_MS, new SocketAcceptTask(this)); return; } if (!mConnector->SetUp(client_fd)) { NS_WARNING("Could not set up socket!"); return; } mFd.reset(client_fd); nsRefPtr<OnSocketEventTask> t = new OnSocketEventTask(this, OnSocketEventTask::CONNECT_SUCCESS); NS_DispatchToMainThread(t); SetUpIO(); }
void UnixSocketImpl::Connect() { MOZ_ASSERT(!NS_IsMainThread()); if (!mConnector) { NS_WARNING("No connector object available!"); return; } if(mFd.get() < 0) { mFd = mConnector->Create(); if (mFd.get() < 0) { return; } } int ret; if (!mConnector->CreateAddr(false, mAddrSize, mAddr, mAddress.get())) { NS_WARNING("Cannot create socket address!"); return; } // Select non-blocking IO. if (!SetNonblockFlags()) { nsRefPtr<OnSocketEventTask> t = new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR); NS_DispatchToMainThread(t); return; } ret = connect(mFd.get(), (struct sockaddr*)&mAddr, mAddrSize); if (ret) { if (errno == EINPROGRESS) { // Select blocking IO again, since we've now at least queue'd the connect // as nonblock. int current_opts = fcntl(mFd.get(), F_GETFL, 0); if (-1 == current_opts) { NS_WARNING("Cannot get socket opts!"); nsRefPtr<OnSocketEventTask> t = new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR); NS_DispatchToMainThread(t); return; } if (-1 == fcntl(mFd.get(), F_SETFL, current_opts & ~O_NONBLOCK)) { NS_WARNING("Cannot set socket opts to blocking!"); nsRefPtr<OnSocketEventTask> t = new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR); NS_DispatchToMainThread(t); return; } // Set up a write watch to make sure we receive the connect signal MessageLoopForIO::current()->WatchFileDescriptor( mFd.get(), false, MessageLoopForIO::WATCH_WRITE, &mWriteWatcher, this); #ifdef DEBUG LOG("UnixSocket Connection delayed!"); #endif return; } #if DEBUG LOG("Socket connect errno=%d\n", errno); #endif mFd.reset(-1); nsRefPtr<OnSocketEventTask> t = new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR); NS_DispatchToMainThread(t); return; } if (!mConnector->SetUp(mFd)) { NS_WARNING("Could not set up socket!"); return; } nsRefPtr<OnSocketEventTask> t = new OnSocketEventTask(this, OnSocketEventTask::CONNECT_SUCCESS); NS_DispatchToMainThread(t); SetUpIO(); }
void UnixSocketImpl::OnFileCanWriteWithoutBlocking(int aFd) { MOZ_ASSERT(!NS_IsMainThread()); MOZ_ASSERT(!mShuttingDownOnIOThread); SocketConnectionStatus status = mConsumer->GetConnectionStatus(); if (status == SOCKET_CONNECTED) { // Try to write the bytes of mCurrentRilRawData. If all were written, continue. // // Otherwise, save the byte position of the next byte to write // within mCurrentRilRawData, and request another write when the // system won't block. // while (true) { UnixSocketRawData* data; if (mOutgoingQ.IsEmpty()) { return; } data = mOutgoingQ.ElementAt(0); const uint8_t *toWrite; toWrite = data->mData; while (data->mCurrentWriteOffset < data->mSize) { ssize_t write_amount = data->mSize - data->mCurrentWriteOffset; ssize_t written; written = write (aFd, toWrite + data->mCurrentWriteOffset, write_amount); if (written > 0) { data->mCurrentWriteOffset += written; } if (written != write_amount) { break; } } if (data->mCurrentWriteOffset != data->mSize) { MessageLoopForIO::current()->WatchFileDescriptor( aFd, false, MessageLoopForIO::WATCH_WRITE, &mWriteWatcher, this); return; } mOutgoingQ.RemoveElementAt(0); delete data; } } else if (status == SOCKET_CONNECTING) { int error, ret; socklen_t len = sizeof(error); ret = getsockopt(mFd.get(), SOL_SOCKET, SO_ERROR, &error, &len); if (ret || error) { NS_WARNING("getsockopt failure on async socket connect!"); nsRefPtr<OnSocketEventTask> t = new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR); NS_DispatchToMainThread(t); return; } if (!mConnector->SetUp(mFd)) { NS_WARNING("Could not set up socket!"); nsRefPtr<OnSocketEventTask> t = new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR); NS_DispatchToMainThread(t); return; } nsRefPtr<OnSocketEventTask> t = new OnSocketEventTask(this, OnSocketEventTask::CONNECT_SUCCESS); NS_DispatchToMainThread(t); SetUpIO(); } }
bool DBusWatcher::Poll() { int res = TEMP_FAILURE_RETRY(poll(mPollData.Elements(), mPollData.Length(), -1)); NS_ENSURE_TRUE(res > 0, false); bool continueThread = true; nsTArray<pollfd>::size_type i = 0; while (i < mPollData.Length()) { if (mPollData[i].revents == POLLIN) { if (mPollData[i].fd == mControlFdR.get()) { char data; res = TEMP_FAILURE_RETRY(read(mControlFdR.get(), &data, sizeof(data))); NS_ENSURE_TRUE(res > 0, false); switch (data) { case DBUS_EVENT_LOOP_EXIT: continueThread = false; break; case DBUS_EVENT_LOOP_ADD: HandleWatchAdd(); break; case DBUS_EVENT_LOOP_REMOVE: HandleWatchRemove(); // don't increment i, or we'll skip one element continue; case DBUS_EVENT_LOOP_WAKEUP: NS_ProcessPendingEvents(NS_GetCurrentThread(), PR_INTERVAL_NO_TIMEOUT); break; default: #if DEBUG nsCString warning("unknown command "); warning.AppendInt(data); NS_WARNING(warning.get()); #endif break; } } else { short events = mPollData[i].revents; mPollData[i].revents = 0; dbus_watch_handle(mWatchData[i], UnixEventsToDBusFlags(events)); DBusDispatchStatus dbusDispatchStatus; do { dbusDispatchStatus = dbus_connection_dispatch(GetConnection()); } while (dbusDispatchStatus == DBUS_DISPATCH_DATA_REMAINS); // Break at this point since we don't know if the operation // was destructive break; } } ++i; } return continueThread; }