Example #1
0
/* Callback from ares when socket operation is started */
static void uv__ares_sockstate_cb(void* data, ares_socket_t sock,
    int read, int write) {
  uv_loop_t* loop = data;
  uv_ares_task_t* h;

  assert((uv_loop_t*)loop->timer.data == loop);

  h = uv_find_ares_handle(loop, sock);

  if (read || write) {
    if (!h) {
      /* New socket */

      /* If this is the first socket then start the timer. */
      if (!uv_is_active((uv_handle_t*)&loop->timer)) {
        assert(uv_ares_handles_empty(loop));
        uv__ares_timer_start(loop);
      }

      h = uv__ares_task_create(loop, sock);
      uv_add_ares_handle(loop, h);
    }

    if (read) {
      ev_io_start(loop->ev, &h->read_watcher);
    } else {
      ev_io_stop(loop->ev, &h->read_watcher);
    }

    if (write) {
      ev_io_start(loop->ev, &h->write_watcher);
    } else {
      ev_io_stop(loop->ev, &h->write_watcher);
    }

  } else {
    /*
     * read == 0 and write == 0 this is c-ares's way of notifying us that
     * the socket is now closed. We must free the data associated with
     * socket.
     */
    assert(h && "When an ares socket is closed we should have a handle for it");

    ev_io_stop(loop->ev, &h->read_watcher);
    ev_io_stop(loop->ev, &h->write_watcher);

    uv_remove_ares_handle(h);
    free(h);

    if (uv_ares_handles_empty(loop)) {
      uv__ares_timer_stop(loop);
    }
  }
}
Example #2
0
/* Callback from ares when socket operation is started */
static void uv__ares_sockstate_cb(void* data, ares_socket_t sock,
    int read, int write) {
  uv_ares_task_t* h = uv_find_ares_handle(sock);

  if (read || write) {
    if (!h) {
      /* New socket */

      /* If this is the first socket then start the timer. */
      if (!ev_is_active(&ares_data.timer)) {
        assert(uv_ares_handles_empty());
        ev_timer_again(EV_DEFAULT_UC_ &ares_data.timer);
      }

      h = uv__ares_task_create(sock);
      uv_add_ares_handle(h);
    }

    if (read) {
      ev_io_start(EV_DEFAULT_UC_ &h->read_watcher);
    } else {
      ev_io_stop(EV_DEFAULT_UC_ &h->read_watcher);
    }

    if (write) {
      ev_io_start(EV_DEFAULT_UC_ &h->write_watcher);
    } else {
      ev_io_stop(EV_DEFAULT_UC_ &h->write_watcher);
    }

  } else {
    /*
     * read == 0 and write == 0 this is c-ares's way of notifying us that
     * the socket is now closed. We must free the data associated with
     * socket.
     */
    assert(h && "When an ares socket is closed we should have a handle for it");

    ev_io_stop(EV_DEFAULT_UC_ &h->read_watcher);
    ev_io_stop(EV_DEFAULT_UC_ &h->write_watcher);

    uv_remove_ares_handle(h);
    free(h);

    if (uv_ares_handles_empty()) {
      ev_timer_stop(EV_DEFAULT_UC_ &ares_data.timer);
    }
  }
}
Example #3
0
/* callback from ares when socket operation is started */
static void uv_ares_sockstate_cb(void *data, ares_socket_t sock, int read,
    int write) {
  /* look to see if we have a handle for this socket in our list */
  uv_loop_t* loop = (uv_loop_t*) data;
  uv_ares_task_t* uv_handle_ares = uv_find_ares_handle(loop, sock);

  if (read == 0 && write == 0) {
    /* if read and write are 0, cleanup existing data */
    /* The code assumes that c-ares does a callback with read = 0 and */
    /* write = 0 when the socket is closed. After we receive this we stop */
    /* monitoring the socket. */
    if (uv_handle_ares != NULL) {
      uv_req_t* uv_ares_req;

      uv_handle_ares->h_close_event = CreateEvent(NULL, FALSE, FALSE, NULL);
      /* remove Wait */
      if (uv_handle_ares->h_wait) {
        UnregisterWaitEx(uv_handle_ares->h_wait,
                         uv_handle_ares->h_close_event);
        uv_handle_ares->h_wait = NULL;
      }

      /* detach socket from the event */
      WSAEventSelect(sock, NULL, 0);
      if (uv_handle_ares->h_event != WSA_INVALID_EVENT) {
        WSACloseEvent(uv_handle_ares->h_event);
        uv_handle_ares->h_event = WSA_INVALID_EVENT;
      }
      /* remove handle from list */
      uv_remove_ares_handle(uv_handle_ares);

      /* Post request to cleanup the Task */
      uv_ares_req = &uv_handle_ares->ares_req;
      uv_req_init(loop, uv_ares_req);
      uv_ares_req->type = UV_ARES_CLEANUP_REQ;
      uv_ares_req->data = uv_handle_ares;

      /* post ares done with socket - finish cleanup when all threads done. */
      POST_COMPLETION_FOR_REQ(loop, uv_ares_req);
    } else {
      assert(0);
      uv_fatal_error(ERROR_INVALID_DATA, "ares_SockStateCB");
    }
  } else {
    if (uv_handle_ares == NULL) {
      /* setup new handle */
      /* The code assumes that c-ares will call us when it has an open socket.
        We need to call into c-ares when there is something to read,
        or when it becomes writable. */
      uv_handle_ares = (uv_ares_task_t*)malloc(sizeof(uv_ares_task_t));
      if (uv_handle_ares == NULL) {
        uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
      }
      uv_handle_ares->type = UV_ARES_TASK;
      uv_handle_ares->close_cb = NULL;
      uv_handle_ares->loop = loop;
      uv_handle_ares->data = loop;
      uv_handle_ares->sock = sock;
      uv_handle_ares->h_wait = NULL;
      uv_handle_ares->flags = 0;

      /* create an event to wait on socket signal */
      uv_handle_ares->h_event = WSACreateEvent();
      if (uv_handle_ares->h_event == WSA_INVALID_EVENT) {
        uv_fatal_error(WSAGetLastError(), "WSACreateEvent");
      }

      /* tie event to socket */
      if (SOCKET_ERROR == WSAEventSelect(sock,
                                         uv_handle_ares->h_event,
                                         FD_READ | FD_WRITE | FD_CONNECT)) {
        uv_fatal_error(WSAGetLastError(), "WSAEventSelect");
      }

      /* add handle to list */
      uv_add_ares_handle(loop, uv_handle_ares);
      uv_ref(loop);

      /*
       * we have a single polling timer for all ares sockets.
       * This is preferred to using ares_timeout. See ares_timeout.c warning.
       * if timer is not running start it, and keep socket count
       */
      if (loop->ares_active_sockets == 0) {
        uv_timer_init(loop, &loop->ares_polling_timer);
        uv_timer_start(&loop->ares_polling_timer, uv_ares_poll, 1000L, 1000L);
      }
      loop->ares_active_sockets++;

      /* specify thread pool function to call when event is signaled */
      if (RegisterWaitForSingleObject(&uv_handle_ares->h_wait,
                                  uv_handle_ares->h_event,
                                  uv_ares_socksignal_tp,
                                  (void*)uv_handle_ares,
                                  INFINITE,
                                  WT_EXECUTEINWAITTHREAD) == 0) {
        uv_fatal_error(GetLastError(), "RegisterWaitForSingleObject");
      }
    } else {
      /* found existing handle.  */
      assert(uv_handle_ares->type == UV_ARES_TASK);
      assert(uv_handle_ares->data != NULL);
      assert(uv_handle_ares->h_event != WSA_INVALID_EVENT);
    }
  }
}