Пример #1
0
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();
}
Пример #2
0
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));
}
Пример #3
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();
  }

}
Пример #4
0
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();
}
Пример #5
0
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();
}
Пример #6
0
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));
}
Пример #7
0
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();
  }
}