Example #1
0
char *grpc_sockaddr_to_uri(const struct sockaddr *addr) {
  char *temp;
  char *result;
  struct sockaddr_in addr_normalized;

  if (grpc_sockaddr_is_v4mapped(addr, &addr_normalized)) {
    addr = (const struct sockaddr *)&addr_normalized;
  }

  switch (addr->sa_family) {
    case AF_INET:
      grpc_sockaddr_to_string(&temp, addr, 0);
      gpr_asprintf(&result, "ipv4:%s", temp);
      gpr_free(temp);
      return result;
    case AF_INET6:
      grpc_sockaddr_to_string(&temp, addr, 0);
      gpr_asprintf(&result, "ipv6:%s", temp);
      gpr_free(temp);
      return result;
#ifdef GPR_POSIX_SOCKET
    case AF_UNIX:
      gpr_asprintf(&result, "unix:%s", ((struct sockaddr_un *)addr)->sun_path);
      return result;
#endif
  }

  return NULL;
}
Example #2
0
static grpc_error *handle_addrinfo_result(int status, struct addrinfo *result,
                                          grpc_resolved_addresses **addresses) {
  struct addrinfo *resp;
  size_t i;
  if (status != 0) {
    grpc_error *error;
    *addresses = NULL;
    error = GRPC_ERROR_CREATE("getaddrinfo failed");
    error =
        grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, uv_strerror(status));
    return error;
  }
  (*addresses) = gpr_malloc(sizeof(grpc_resolved_addresses));
  (*addresses)->naddrs = 0;
  for (resp = result; resp != NULL; resp = resp->ai_next) {
    (*addresses)->naddrs++;
  }
  (*addresses)->addrs =
      gpr_malloc(sizeof(grpc_resolved_address) * (*addresses)->naddrs);
  i = 0;
  for (resp = result; resp != NULL; resp = resp->ai_next) {
    memcpy(&(*addresses)->addrs[i].addr, resp->ai_addr, resp->ai_addrlen);
    (*addresses)->addrs[i].len = resp->ai_addrlen;
    i++;
  }

  {
    for (i = 0; i < (*addresses)->naddrs; i++) {
      char *buf;
      grpc_sockaddr_to_string(&buf, &(*addresses)->addrs[i], 0);
      gpr_free(buf);
    }
  }
  return GRPC_ERROR_NONE;
}
Example #3
0
static int add_socket_to_server(grpc_tcp_server *s, int fd,
                                const struct sockaddr *addr, size_t addr_len) {
  server_port *sp;
  int port;
  char *addr_str;
  char *name;

  port = prepare_socket(fd, addr, addr_len);
  if (port >= 0) {
    grpc_sockaddr_to_string(&addr_str, (struct sockaddr *)&addr, 1);
    gpr_asprintf(&name, "tcp-server-listener:%s", addr_str);
    gpr_mu_lock(&s->mu);
    GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server");
    /* append it to the list under a lock */
    if (s->nports == s->port_capacity) {
      s->port_capacity *= 2;
      s->ports = gpr_realloc(s->ports, sizeof(server_port) * s->port_capacity);
    }
    sp = &s->ports[s->nports++];
    sp->server = s;
    sp->fd = fd;
    sp->emfd = grpc_fd_create(fd, name);
    memcpy(sp->addr.untyped, addr, addr_len);
    sp->addr_len = addr_len;
    GPR_ASSERT(sp->emfd);
    gpr_mu_unlock(&s->mu);
    gpr_free(addr_str);
    gpr_free(name);
  }

  return port;
}
static grpc_tcp_listener *add_socket_to_server(grpc_tcp_server *s, int fd,
        const struct sockaddr *addr,
        size_t addr_len) {
    grpc_tcp_listener *sp = NULL;
    int port;
    char *addr_str;
    char *name;

    port = prepare_socket(fd, addr, addr_len);
    if (port >= 0) {
        grpc_sockaddr_to_string(&addr_str, (struct sockaddr *)&addr, 1);
        gpr_asprintf(&name, "tcp-server-listener:%s", addr_str);
        gpr_mu_lock(&s->mu);
        s->nports++;
        GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server");
        sp = gpr_malloc(sizeof(grpc_tcp_listener));
        sp->next = s->head;
        s->head = sp;
        sp->server = s;
        sp->fd = fd;
        sp->emfd = grpc_fd_create(fd, name);
        memcpy(sp->addr.untyped, addr, addr_len);
        sp->addr_len = addr_len;
        sp->port = port;
        sp->is_sibling = 0;
        sp->sibling = NULL;
        gpr_ref_init(&sp->refs, 1);
        GPR_ASSERT(sp->emfd);
        gpr_mu_unlock(&s->mu);
        gpr_free(addr_str);
        gpr_free(name);
    }

    return sp;
}
Example #5
0
static grpc_error *error_for_fd(int fd, const grpc_resolved_address *addr) {
  if (fd >= 0) return GRPC_ERROR_NONE;
  char *addr_str;
  grpc_sockaddr_to_string(&addr_str, addr, 0);
  grpc_error *err = grpc_error_set_str(GRPC_OS_ERROR(errno, "socket"),
                                       GRPC_ERROR_STR_TARGET_ADDRESS,
                                       grpc_slice_from_copied_string(addr_str));
  gpr_free(addr_str);
  return err;
}
Example #6
0
static void test_addr_init_str(test_addr *addr) {
  char *str = NULL;
  if (grpc_sockaddr_to_string(&str, &addr->addr, 0) != -1) {
    size_t str_len;
    memcpy(addr->str, str, (str_len = strnlen(str, sizeof(addr->str) - 1)));
    addr->str[str_len] = '\0';
    gpr_free(str);
  } else {
    addr->str[0] = '\0';
  }
}
Example #7
0
static void expect_sockaddr_str(const char *expected, void *addr,
                                int normalize) {
  int result;
  char *str;
  gpr_log(GPR_INFO, "  expect_sockaddr_str(%s)", expected);
  result = grpc_sockaddr_to_string(&str, (struct sockaddr *)addr, normalize);
  GPR_ASSERT(str != NULL);
  GPR_ASSERT(result >= 0);
  GPR_ASSERT((size_t)result == strlen(str));
  GPR_ASSERT(strcmp(expected, str) == 0);
  gpr_free(str);
}
Example #8
0
/* event manager callback when reads are ready */
static void on_read(void *arg, int success) {
  server_port *sp = arg;

  if (!success) {
    goto error;
  }

  /* loop until accept4 returns EAGAIN, and then re-arm notification */
  for (;;) {
    struct sockaddr_storage addr;
    socklen_t addrlen = sizeof(addr);
    char *addr_str;
    char *name;
    /* Note: If we ever decide to return this address to the user, remember to
             strip off the ::ffff:0.0.0.0/96 prefix first. */
    int fd = grpc_accept4(sp->fd, (struct sockaddr *)&addr, &addrlen, 1, 1);
    if (fd < 0) {
      switch (errno) {
        case EINTR:
          continue;
        case EAGAIN:
          grpc_fd_notify_on_read(sp->emfd, &sp->read_closure);
          return;
        default:
          gpr_log(GPR_ERROR, "Failed accept4: %s", strerror(errno));
          goto error;
      }
    }

    grpc_set_socket_no_sigpipe_if_possible(fd);

    grpc_sockaddr_to_string(&addr_str, (struct sockaddr *)&addr, 1);
    gpr_asprintf(&name, "tcp-server-connection:%s", addr_str);

    sp->server->cb(sp->server->cb_arg,
                   grpc_tcp_create(grpc_fd_create(fd, name),
                                   GRPC_TCP_DEFAULT_READ_SLICE_SIZE));

    gpr_free(addr_str);
    gpr_free(name);
  }

  abort();

error:
  gpr_mu_lock(&sp->server->mu);
  if (0 == --sp->server->active_ports) {
    gpr_cv_broadcast(&sp->server->cv);
  }
  gpr_mu_unlock(&sp->server->mu);
}
Example #9
0
char *grpc_sockaddr_to_uri(const struct sockaddr *addr) {
  char *temp;
  char *result;
  struct sockaddr_in addr_normalized;

  if (grpc_sockaddr_is_v4mapped(addr, &addr_normalized)) {
    addr = (const struct sockaddr *)&addr_normalized;
  }

  switch (addr->sa_family) {
    case AF_INET:
      grpc_sockaddr_to_string(&temp, addr, 0);
      gpr_asprintf(&result, "ipv4:%s", temp);
      gpr_free(temp);
      return result;
    case AF_INET6:
      grpc_sockaddr_to_string(&temp, addr, 0);
      gpr_asprintf(&result, "ipv6:%s", temp);
      gpr_free(temp);
      return result;
    default:
      return grpc_sockaddr_to_uri_unix_if_possible(addr);
  }
}
Example #10
0
/* Prepare a recently-created socket for listening. */
static int prepare_socket(int fd, const struct sockaddr *addr,
                          size_t addr_len) {
  struct sockaddr_storage sockname_temp;
  socklen_t sockname_len;
  int get_local_ip;
  int rc;

  if (fd < 0) {
    goto error;
  }

  if (!grpc_set_socket_nonblocking(fd, 1) || !grpc_set_socket_cloexec(fd, 1)) {
    gpr_log(GPR_ERROR, "Unable to configure socket %d: %s", fd,
            strerror(errno));
  }

  get_local_ip = 1;
  rc = setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &get_local_ip,
                  sizeof(get_local_ip));
  if (rc == 0 && addr->sa_family == AF_INET6) {
#if !TARGET_OS_IPHONE
    rc = setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &get_local_ip,
                    sizeof(get_local_ip));
#endif
  }

  GPR_ASSERT(addr_len < ~(socklen_t)0);
  if (bind(fd, addr, (socklen_t)addr_len) < 0) {
    char *addr_str;
    grpc_sockaddr_to_string(&addr_str, addr, 0);
    gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str, strerror(errno));
    gpr_free(addr_str);
    goto error;
  }

  sockname_len = sizeof(sockname_temp);
  if (getsockname(fd, (struct sockaddr *)&sockname_temp, &sockname_len) < 0) {
    goto error;
  }

  return grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);

error:
  if (fd >= 0) {
    close(fd);
  }
  return -1;
}
Example #11
0
/* Insert count new listeners after listener. Every new listener will have the
   same listen address as listener (SO_REUSEPORT must be enabled). Every new
   listener is a sibling of listener. */
static grpc_error *clone_port(grpc_tcp_listener *listener, unsigned count) {
  grpc_tcp_listener *sp = NULL;
  char *addr_str;
  char *name;
  grpc_error *err;

  for (grpc_tcp_listener *l = listener->next; l && l->is_sibling; l = l->next) {
    l->fd_index += count;
  }

  for (unsigned i = 0; i < count; i++) {
    int fd = -1;
    int port = -1;
    grpc_dualstack_mode dsmode;
    err = grpc_create_dualstack_socket(&listener->addr, SOCK_STREAM, 0, &dsmode,
                                       &fd);
    if (err != GRPC_ERROR_NONE) return err;
    err = prepare_socket(fd, &listener->addr, true, &port);
    if (err != GRPC_ERROR_NONE) return err;
    listener->server->nports++;
    grpc_sockaddr_to_string(&addr_str, &listener->addr, 1);
    gpr_asprintf(&name, "tcp-server-listener:%s/clone-%d", addr_str, i);
    sp = gpr_malloc(sizeof(grpc_tcp_listener));
    sp->next = listener->next;
    listener->next = sp;
    /* sp (the new listener) is a sibling of 'listener' (the original
       listener). */
    sp->is_sibling = 1;
    sp->sibling = listener->sibling;
    listener->sibling = sp;
    sp->server = listener->server;
    sp->fd = fd;
    sp->emfd = grpc_fd_create(fd, name);
    memcpy(&sp->addr, &listener->addr, sizeof(grpc_resolved_address));
    sp->port = port;
    sp->port_index = listener->port_index;
    sp->fd_index = listener->fd_index + count - i;
    GPR_ASSERT(sp->emfd);
    while (listener->server->tail->next != NULL) {
      listener->server->tail = listener->server->tail->next;
    }
    gpr_free(addr_str);
    gpr_free(name);
  }

  return GRPC_ERROR_NONE;
}
Example #12
0
/* Prepare (bind) a recently-created socket for listening. */
static int prepare_socket(SOCKET sock, const struct sockaddr *addr,
                          int addr_len) {
  struct sockaddr_storage sockname_temp;
  socklen_t sockname_len;

  if (sock == INVALID_SOCKET) goto error;

  if (!grpc_tcp_prepare_socket(sock)) {
    char *utf8_message = gpr_format_message(WSAGetLastError());
    gpr_log(GPR_ERROR, "Unable to prepare socket: %s", utf8_message);
    gpr_free(utf8_message);
    goto error;
  }

  if (bind(sock, addr, addr_len) == SOCKET_ERROR) {
    char *addr_str;
    char *utf8_message = gpr_format_message(WSAGetLastError());
    grpc_sockaddr_to_string(&addr_str, addr, 0);
    gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str, utf8_message);
    gpr_free(utf8_message);
    gpr_free(addr_str);
    goto error;
  }

  if (listen(sock, SOMAXCONN) == SOCKET_ERROR) {
    char *utf8_message = gpr_format_message(WSAGetLastError());
    gpr_log(GPR_ERROR, "listen: %s", utf8_message);
    gpr_free(utf8_message);
    goto error;
  }

  sockname_len = sizeof(sockname_temp);
  if (getsockname(sock, (struct sockaddr *)&sockname_temp, &sockname_len) ==
      SOCKET_ERROR) {
    char *utf8_message = gpr_format_message(WSAGetLastError());
    gpr_log(GPR_ERROR, "getsockname: %s", utf8_message);
    gpr_free(utf8_message);
    goto error;
  }

  return grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);

error:
  if (sock != INVALID_SOCKET) closesocket(sock);
  return -1;
}
/* Prepare a recently-created socket for listening. */
static int prepare_socket(int fd, const struct sockaddr *addr,
                          size_t addr_len) {
    struct sockaddr_storage sockname_temp;
    socklen_t sockname_len;

    if (fd < 0) {
        goto error;
    }

    if (!grpc_set_socket_nonblocking(fd, 1) || !grpc_set_socket_cloexec(fd, 1) ||
            (addr->sa_family != AF_UNIX && (!grpc_set_socket_low_latency(fd, 1) ||
                                            !grpc_set_socket_reuse_addr(fd, 1))) ||
            !grpc_set_socket_no_sigpipe_if_possible(fd)) {
        gpr_log(GPR_ERROR, "Unable to configure socket %d: %s", fd,
                strerror(errno));
        goto error;
    }

    GPR_ASSERT(addr_len < ~(socklen_t)0);
    if (bind(fd, addr, (socklen_t)addr_len) < 0) {
        char *addr_str;
        grpc_sockaddr_to_string(&addr_str, addr, 0);
        gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str, strerror(errno));
        gpr_free(addr_str);
        goto error;
    }

    if (listen(fd, get_max_accept_queue_size()) < 0) {
        gpr_log(GPR_ERROR, "listen: %s", strerror(errno));
        goto error;
    }

    sockname_len = sizeof(sockname_temp);
    if (getsockname(fd, (struct sockaddr *)&sockname_temp, &sockname_len) < 0) {
        goto error;
    }

    return grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);

error:
    if (fd >= 0) {
        close(fd);
    }
    return -1;
}
Example #14
0
static grpc_error *add_socket_to_server(grpc_tcp_server *s, int fd,
                                        const struct sockaddr *addr,
                                        size_t addr_len, unsigned port_index,
                                        unsigned fd_index,
                                        grpc_tcp_listener **listener) {
  grpc_tcp_listener *sp = NULL;
  int port = -1;
  char *addr_str;
  char *name;

  grpc_error *err = prepare_socket(fd, addr, addr_len, s->so_reuseport, &port);
  if (err == GRPC_ERROR_NONE) {
    GPR_ASSERT(port > 0);
    grpc_sockaddr_to_string(&addr_str, (struct sockaddr *)&addr, 1);
    gpr_asprintf(&name, "tcp-server-listener:%s", addr_str);
    gpr_mu_lock(&s->mu);
    s->nports++;
    GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server");
    sp = gpr_malloc(sizeof(grpc_tcp_listener));
    sp->next = NULL;
    if (s->head == NULL) {
      s->head = sp;
    } else {
      s->tail->next = sp;
    }
    s->tail = sp;
    sp->server = s;
    sp->fd = fd;
    sp->emfd = grpc_fd_create(fd, name);
    memcpy(sp->addr.untyped, addr, addr_len);
    sp->addr_len = addr_len;
    sp->port = port;
    sp->port_index = port_index;
    sp->fd_index = fd_index;
    sp->is_sibling = 0;
    sp->sibling = NULL;
    GPR_ASSERT(sp->emfd);
    gpr_mu_unlock(&s->mu);
    gpr_free(addr_str);
    gpr_free(name);
  }

  *listener = sp;
  return err;
}
Example #15
0
static int add_socket_to_server(grpc_udp_server *s, int fd,
                                const grpc_resolved_address *addr,
                                grpc_udp_server_read_cb read_cb,
                                grpc_udp_server_write_cb write_cb,
                                grpc_udp_server_orphan_cb orphan_cb) {
  grpc_udp_listener *sp;
  int port;
  char *addr_str;
  char *name;

  port = prepare_socket(s->socket_factory, fd, addr);
  if (port >= 0) {
    grpc_sockaddr_to_string(&addr_str, addr, 1);
    gpr_asprintf(&name, "udp-server-listener:%s", addr_str);
    gpr_free(addr_str);
    gpr_mu_lock(&s->mu);
    s->nports++;
    sp = gpr_malloc(sizeof(grpc_udp_listener));
    sp->next = NULL;
    if (s->head == NULL) {
      s->head = sp;
    } else {
      s->tail->next = sp;
    }
    s->tail = sp;
    sp->server = s;
    sp->fd = fd;
    sp->emfd = grpc_fd_create(fd, name);
    memcpy(&sp->addr, addr, sizeof(grpc_resolved_address));
    sp->read_cb = read_cb;
    sp->write_cb = write_cb;
    sp->orphan_cb = orphan_cb;
    sp->orphan_notified = false;
    GPR_ASSERT(sp->emfd);
    gpr_mu_unlock(&s->mu);
    gpr_free(name);
  }

  return port;
}
static grpc_error *blocking_resolve_address_impl(
    const char *name, const char *default_port,
    grpc_resolved_addresses **addresses) {
  struct addrinfo hints;
  struct addrinfo *result = NULL, *resp;
  char *host;
  char *port;
  int s;
  size_t i;
  grpc_error *error = GRPC_ERROR_NONE;

  /* parse name, splitting it into host and port parts */
  gpr_split_host_port(name, &host, &port);
  if (host == NULL) {
    char *msg;
    gpr_asprintf(&msg, "unparseable host:port: '%s'", name);
    error = GRPC_ERROR_CREATE(msg);
    gpr_free(msg);
    goto done;
  }
  if (port == NULL) {
    if (default_port == NULL) {
      char *msg;
      gpr_asprintf(&msg, "no port in name '%s'", name);
      error = GRPC_ERROR_CREATE(msg);
      gpr_free(msg);
      goto done;
    }
    port = gpr_strdup(default_port);
  }

  /* Call getaddrinfo */
  memset(&hints, 0, sizeof(hints));
  hints.ai_family = AF_UNSPEC;     /* ipv4 or ipv6 */
  hints.ai_socktype = SOCK_STREAM; /* stream socket */
  hints.ai_flags = AI_PASSIVE;     /* for wildcard IP address */

  GRPC_SCHEDULING_START_BLOCKING_REGION;
  s = getaddrinfo(host, port, &hints, &result);
  GRPC_SCHEDULING_END_BLOCKING_REGION;
  if (s != 0) {
    error = GRPC_WSA_ERROR(WSAGetLastError(), "getaddrinfo");
    goto done;
  }

  /* Success path: set addrs non-NULL, fill it in */
  (*addresses) = gpr_malloc(sizeof(grpc_resolved_addresses));
  (*addresses)->naddrs = 0;
  for (resp = result; resp != NULL; resp = resp->ai_next) {
    (*addresses)->naddrs++;
  }
  (*addresses)->addrs =
      gpr_malloc(sizeof(grpc_resolved_address) * (*addresses)->naddrs);
  i = 0;
  for (resp = result; resp != NULL; resp = resp->ai_next) {
    memcpy(&(*addresses)->addrs[i].addr, resp->ai_addr, resp->ai_addrlen);
    (*addresses)->addrs[i].len = resp->ai_addrlen;
    i++;
  }

  {
    for (i = 0; i < (*addresses)->naddrs; i++) {
      char *buf;
      grpc_sockaddr_to_string(
          &buf, (struct sockaddr *)&(*addresses)->addrs[i].addr, 0);
      gpr_free(buf);
    }
  }

done:
  gpr_free(host);
  gpr_free(port);
  if (result) {
    freeaddrinfo(result);
  }
  return error;
}
Example #17
0
/* event manager callback when reads are ready */
static void on_read(void *arg, int success) {
  server_port *sp = arg;
  grpc_fd *fdobj;
  size_t i;

  if (!success) {
    goto error;
  }

  /* loop until accept4 returns EAGAIN, and then re-arm notification */
  for (;;) {
    struct sockaddr_storage addr;
    socklen_t addrlen = sizeof(addr);
    char *addr_str;
    char *name;
    /* Note: If we ever decide to return this address to the user, remember to
             strip off the ::ffff:0.0.0.0/96 prefix first. */
    int fd = grpc_accept4(sp->fd, (struct sockaddr *)&addr, &addrlen, 1, 1);
    if (fd < 0) {
      switch (errno) {
        case EINTR:
          continue;
        case EAGAIN:
          grpc_fd_notify_on_read(sp->emfd, &sp->read_closure);
          return;
        default:
          gpr_log(GPR_ERROR, "Failed accept4: %s", strerror(errno));
          goto error;
      }
    }

    grpc_set_socket_no_sigpipe_if_possible(fd);

    grpc_sockaddr_to_string(&addr_str, (struct sockaddr *)&addr, 1);
    gpr_asprintf(&name, "tcp-server-connection:%s", addr_str);

    fdobj = grpc_fd_create(fd, name);
    /* TODO(ctiller): revise this when we have server-side sharding
       of channels -- we certainly should not be automatically adding every
       incoming channel to every pollset owned by the server */
    for (i = 0; i < sp->server->pollset_count; i++) {
      grpc_pollset_add_fd(sp->server->pollsets[i], fdobj);
    }
    sp->server->cb(sp->server->cb_arg,
                   grpc_tcp_create(fdobj, GRPC_TCP_DEFAULT_READ_SLICE_SIZE));

    gpr_free(name);
    gpr_free(addr_str);
  }

  abort();

error:
  gpr_mu_lock(&sp->server->mu);
  if (0 == --sp->server->active_ports) {
    gpr_mu_unlock(&sp->server->mu);
    deactivated_all_ports(sp->server);
  } else {
    gpr_mu_unlock(&sp->server->mu);
  }
}
Example #18
0
/* Prepare a recently-created socket for listening. */
static int prepare_socket(grpc_socket_factory *socket_factory, int fd,
                          const grpc_resolved_address *addr) {
  grpc_resolved_address sockname_temp;
  struct sockaddr *addr_ptr = (struct sockaddr *)addr->addr;
  /* Set send/receive socket buffers to 1 MB */
  int buffer_size_bytes = 1024 * 1024;

  if (fd < 0) {
    goto error;
  }

  if (grpc_set_socket_nonblocking(fd, 1) != GRPC_ERROR_NONE) {
    gpr_log(GPR_ERROR, "Unable to set nonblocking %d: %s", fd, strerror(errno));
    goto error;
  }
  if (grpc_set_socket_cloexec(fd, 1) != GRPC_ERROR_NONE) {
    gpr_log(GPR_ERROR, "Unable to set cloexec %d: %s", fd, strerror(errno));
    goto error;
  }

  if (grpc_set_socket_ip_pktinfo_if_possible(fd) != GRPC_ERROR_NONE) {
    gpr_log(GPR_ERROR, "Unable to set ip_pktinfo.");
    goto error;
  } else if (addr_ptr->sa_family == AF_INET6) {
    if (grpc_set_socket_ipv6_recvpktinfo_if_possible(fd) != GRPC_ERROR_NONE) {
      gpr_log(GPR_ERROR, "Unable to set ipv6_recvpktinfo.");
      goto error;
    }
  }

  GPR_ASSERT(addr->len < ~(socklen_t)0);
  if (bind_socket(socket_factory, fd, addr) < 0) {
    char *addr_str;
    grpc_sockaddr_to_string(&addr_str, addr, 0);
    gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str, strerror(errno));
    gpr_free(addr_str);
    goto error;
  }

  sockname_temp.len = sizeof(struct sockaddr_storage);

  if (getsockname(fd, (struct sockaddr *)sockname_temp.addr,
                  (socklen_t *)&sockname_temp.len) < 0) {
    goto error;
  }

  if (grpc_set_socket_sndbuf(fd, buffer_size_bytes) != GRPC_ERROR_NONE) {
    gpr_log(GPR_ERROR, "Failed to set send buffer size to %d bytes",
            buffer_size_bytes);
    goto error;
  }

  if (grpc_set_socket_rcvbuf(fd, buffer_size_bytes) != GRPC_ERROR_NONE) {
    gpr_log(GPR_ERROR, "Failed to set receive buffer size to %d bytes",
            buffer_size_bytes);
    goto error;
  }

  return grpc_sockaddr_get_port(&sockname_temp);

error:
  if (fd >= 0) {
    close(fd);
  }
  return -1;
}
Example #19
0
grpc_resolved_addresses *grpc_blocking_resolve_address(
    const char *name, const char *default_port) {
  struct addrinfo hints;
  struct addrinfo *result = NULL, *resp;
  char *host;
  char *port;
  int s;
  size_t i;
  grpc_resolved_addresses *addrs = NULL;

  /* parse name, splitting it into host and port parts */
  gpr_split_host_port(name, &host, &port);
  if (host == NULL) {
    gpr_log(GPR_ERROR, "unparseable host:port: '%s'", name);
    goto done;
  }
  if (port == NULL) {
    if (default_port == NULL) {
      gpr_log(GPR_ERROR, "no port in name '%s'", name);
      goto done;
    }
    port = gpr_strdup(default_port);
  }

  /* Call getaddrinfo */
  memset(&hints, 0, sizeof(hints));
  hints.ai_family = AF_UNSPEC;     /* ipv4 or ipv6 */
  hints.ai_socktype = SOCK_STREAM; /* stream socket */
  hints.ai_flags = AI_PASSIVE;     /* for wildcard IP address */

  GRPC_SCHEDULING_START_BLOCKING_REGION;
  s = getaddrinfo(host, port, &hints, &result);
  GRPC_SCHEDULING_END_BLOCKING_REGION;
  if (s != 0) {
    gpr_log(GPR_ERROR, "getaddrinfo: %s", gai_strerror(s));
    goto done;
  }

  /* Success path: set addrs non-NULL, fill it in */
  addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
  addrs->naddrs = 0;
  for (resp = result; resp != NULL; resp = resp->ai_next) {
    addrs->naddrs++;
  }
  addrs->addrs = gpr_malloc(sizeof(grpc_resolved_address) * addrs->naddrs);
  i = 0;
  for (resp = result; resp != NULL; resp = resp->ai_next) {
    memcpy(&addrs->addrs[i].addr, resp->ai_addr, resp->ai_addrlen);
    addrs->addrs[i].len = resp->ai_addrlen;
    i++;
  }

  {
    for (i = 0; i < addrs->naddrs; i++) {
      char *buf;
      grpc_sockaddr_to_string(&buf, (struct sockaddr *)&addrs->addrs[i].addr,
                              0);
      gpr_free(buf);
    }
  }

done:
  gpr_free(host);
  gpr_free(port);
  if (result) {
    freeaddrinfo(result);
  }
  return addrs;
}
grpc_error *grpc_tcp_server_add_all_local_addrs(grpc_tcp_server *s,
                                                unsigned port_index,
                                                int requested_port,
                                                int *out_port) {
  struct ifaddrs *ifa = NULL;
  struct ifaddrs *ifa_it;
  unsigned fd_index = 0;
  grpc_tcp_listener *sp = NULL;
  grpc_error *err = GRPC_ERROR_NONE;
  if (requested_port == 0) {
    /* Note: There could be a race where some local addrs can listen on the
       selected port and some can't. The sane way to handle this would be to
       retry by recreating the whole grpc_tcp_server. Backing out individual
       listeners and orphaning the FDs looks like too much trouble. */
    if ((err = get_unused_port(&requested_port)) != GRPC_ERROR_NONE) {
      return err;
    } else if (requested_port <= 0) {
      return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad get_unused_port()");
    }
    gpr_log(GPR_DEBUG, "Picked unused port %d", requested_port);
  }
  if (getifaddrs(&ifa) != 0 || ifa == NULL) {
    return GRPC_OS_ERROR(errno, "getifaddrs");
  }
  for (ifa_it = ifa; ifa_it != NULL; ifa_it = ifa_it->ifa_next) {
    grpc_resolved_address addr;
    char *addr_str = NULL;
    grpc_dualstack_mode dsmode;
    grpc_tcp_listener *new_sp = NULL;
    const char *ifa_name = (ifa_it->ifa_name ? ifa_it->ifa_name : "<unknown>");
    if (ifa_it->ifa_addr == NULL) {
      continue;
    } else if (ifa_it->ifa_addr->sa_family == AF_INET) {
      addr.len = sizeof(struct sockaddr_in);
    } else if (ifa_it->ifa_addr->sa_family == AF_INET6) {
      addr.len = sizeof(struct sockaddr_in6);
    } else {
      continue;
    }
    memcpy(addr.addr, ifa_it->ifa_addr, addr.len);
    if (!grpc_sockaddr_set_port(&addr, requested_port)) {
      /* Should never happen, because we check sa_family above. */
      err = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to set port");
      break;
    }
    if (grpc_sockaddr_to_string(&addr_str, &addr, 0) < 0) {
      addr_str = gpr_strdup("<error>");
    }
    gpr_log(GPR_DEBUG,
            "Adding local addr from interface %s flags 0x%x to server: %s",
            ifa_name, ifa_it->ifa_flags, addr_str);
    /* We could have multiple interfaces with the same address (e.g., bonding),
       so look for duplicates. */
    if (find_listener_with_addr(s, &addr) != NULL) {
      gpr_log(GPR_DEBUG, "Skipping duplicate addr %s on interface %s", addr_str,
              ifa_name);
      gpr_free(addr_str);
      continue;
    }
    if ((err = grpc_tcp_server_add_addr(s, &addr, port_index, fd_index, &dsmode,
                                        &new_sp)) != GRPC_ERROR_NONE) {
      char *err_str = NULL;
      grpc_error *root_err;
      if (gpr_asprintf(&err_str, "Failed to add listener: %s", addr_str) < 0) {
        err_str = gpr_strdup("Failed to add listener");
      }
      root_err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(err_str);
      gpr_free(err_str);
      gpr_free(addr_str);
      err = grpc_error_add_child(root_err, err);
      break;
    } else {
      GPR_ASSERT(requested_port == new_sp->port);
      ++fd_index;
      if (sp != NULL) {
        new_sp->is_sibling = 1;
        sp->sibling = new_sp;
      }
      sp = new_sp;
    }
    gpr_free(addr_str);
  }
  freeifaddrs(ifa);
  if (err != GRPC_ERROR_NONE) {
    return err;
  } else if (sp == NULL) {
    return GRPC_ERROR_CREATE_FROM_STATIC_STRING("No local addresses");
  } else {
    *out_port = sp->port;
    return GRPC_ERROR_NONE;
  }
}