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(); }
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)); }
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(); } }
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::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::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::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(); } }