コード例 #1
0
ファイル: net.c プロジェクト: xuezaijiongtu/fossa
/*
 * Callback for the async resolver on ns_connect_opt() call.
 * Main task of this function is to trigger NS_CONNECT event with
 *    either failure (and dealloc the connection)
 *    or success (and proceed with connect()
 */
static void resolve_cb(struct ns_dns_message *msg, void *data) {
  struct ns_connection *nc = (struct ns_connection *) data;
  int i;
  int failure = -1;

  if (msg != NULL) {
    /*
     * Take the first DNS A answer and run...
     */
    for (i = 0; i < msg->num_answers; i++) {
      if (msg->answers[i].rtype == NS_DNS_A_RECORD) {
        static struct ns_add_sock_opts opts;
        /*
         * Async resolver guarantees that there is at least one answer.
         * TODO(lsm): handle IPv6 answers too
         */
        ns_dns_parse_record_data(msg, &msg->answers[i], &nc->sa.sin.sin_addr,
                                 4);
        /* Make ns_finish_connect() trigger NS_CONNECT on failure */
        nc->flags |= NSF_CONNECTING;
        ns_finish_connect(nc, nc->flags & NSF_UDP ? SOCK_DGRAM : SOCK_STREAM,
                          &nc->sa, opts);
        return;
      }
    }
  }

  /*
   * If we get there was no NS_DNS_A_RECORD in the answer
   */
  ns_call(nc, NS_CONNECT, &failure);
  ns_destroy_conn(nc);
}
コード例 #2
0
ファイル: net.c プロジェクト: xuezaijiongtu/fossa
static void ns_close_conn(struct ns_connection *conn) {
  DBG(("%p %lu", conn, conn->flags));
  if (!(conn->flags & NSF_CONNECTING)) {
    ns_call(conn, NS_CLOSE, NULL);
  }
  ns_remove_conn(conn);
  ns_destroy_conn(conn);
}
コード例 #3
0
ファイル: net.c プロジェクト: xuezaijiongtu/fossa
struct ns_connection *ns_connect_opt(struct ns_mgr *mgr, const char *address,
                                     ns_event_handler_t callback,
                                     struct ns_connect_opts opts) {
  struct ns_connection *nc = NULL;
  int proto, rc;
  struct ns_add_sock_opts add_sock_opts;
  char host[NS_MAX_HOST_LEN];

  NS_COPY_COMMON_CONNECTION_OPTIONS(&add_sock_opts, &opts);

  if ((nc = ns_create_connection(mgr, callback, add_sock_opts)) == NULL) {
    return NULL;
  } else if ((rc = ns_parse_address(address, &nc->sa, &proto, host,
                                    sizeof(host))) < 0) {
    /* Address is malformed */
    NS_SET_PTRPTR(opts.error_string, "cannot parse address");
    ns_destroy_conn(nc);
    return NULL;
  }
  nc->flags |= opts.flags & _NS_ALLOWED_CONNECT_FLAGS_MASK;
  nc->flags |= (proto == SOCK_DGRAM) ? NSF_UDP : 0;
  nc->user_data = opts.user_data;

  if (rc == 0) {
#ifndef NS_DISABLE_RESOLVER
    /*
     * DNS resolution is required for host.
     * ns_parse_address() fills port in nc->sa, which we pass to resolve_cb()
     */
    if (ns_resolve_async(nc->mgr, host, NS_DNS_A_RECORD, resolve_cb, nc) != 0) {
      NS_SET_PTRPTR(opts.error_string, "cannot schedule DNS lookup");
      ns_destroy_conn(nc);
      return NULL;
    }

    return nc;
#else
    NS_SET_PTRPTR(opts.error_string, "Resolver is disabled");
    ns_destroy_conn(nc);
    return NULL;
#endif
  } else {
    /* Address is parsed and resolved to IP. proceed with connect() */
    return ns_finish_connect(nc, proto, &nc->sa, add_sock_opts);
  }
}
コード例 #4
0
ファイル: net.c プロジェクト: xuezaijiongtu/fossa
/*
 * Schedules an async connect for a resolved address and proto.
 * Called from two places: `ns_connect_opt()` and from async resolver.
 * When called from the async resolver, it must trigger `NS_CONNECT` event
 * with a failure flag to indicate connection failure.
 */
NS_INTERNAL struct ns_connection *ns_finish_connect(struct ns_connection *nc,
                                                    int proto,
                                                    union socket_address *sa,
                                                    struct ns_add_sock_opts o) {
  sock_t sock = INVALID_SOCKET;
  int rc;

  DBG(("%p %s://%s:%hu", nc, proto == SOCK_DGRAM ? "udp" : "tcp",
       inet_ntoa(nc->sa.sin.sin_addr), ntohs(nc->sa.sin.sin_port)));

  if ((sock = socket(AF_INET, proto, 0)) == INVALID_SOCKET) {
    int failure = errno;
    NS_SET_PTRPTR(o.error_string, "cannot create socket");
    if (nc->flags & NSF_CONNECTING) {
      ns_call(nc, NS_CONNECT, &failure);
    }
    ns_destroy_conn(nc);
    return NULL;
  }

  ns_set_non_blocking_mode(sock);
  rc = (proto == SOCK_DGRAM) ? 0 : connect(sock, &sa->sa, sizeof(sa->sin));

  if (rc != 0 && ns_is_error(rc)) {
    NS_SET_PTRPTR(o.error_string, "cannot connect to socket");
    if (nc->flags & NSF_CONNECTING) {
      ns_call(nc, NS_CONNECT, &rc);
    }
    ns_destroy_conn(nc);
    close(sock);
    return NULL;
  }

  /* Fire NS_CONNECT on next poll. */
  nc->flags |= NSF_CONNECTING;

  /* No ns_destroy_conn() call after this! */
  ns_set_sock(nc, sock);
  return nc;
}
コード例 #5
0
ファイル: skeleton.c プロジェクト: hosseinian-malay/fossa
static void ns_close_conn(struct ns_connection *conn) {
  DBG(("%p %lu", conn, conn->flags));
  ns_call(conn, NS_CLOSE, NULL);
  ns_remove_conn(conn);
  ns_destroy_conn(conn);
}