void
UnixSocketImpl::OnFileCanWriteWithoutBlocking(int aFd)
{
  MOZ_ASSERT(!NS_IsMainThread());
  MOZ_ASSERT(!mShuttingDownOnIOThread);

  // 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.
  //
  MOZ_ASSERT(aFd >= 0);
  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;
  }
}
Beispiel #2
0
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();
  }

}