Ejemplo n.º 1
0
/* called when all listening endpoints have been shutdown, so no further
   events will be received on them - at this point it's safe to destroy
   things */
static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) {
  /* delete ALL the things */
  gpr_mu_lock(&s->mu);

  GPR_ASSERT(s->shutdown);

  if (s->head) {
    grpc_udp_listener *sp;
    for (sp = s->head; sp; sp = sp->next) {
      grpc_unlink_if_unix_domain_socket(&sp->addr);

      GRPC_CLOSURE_INIT(&sp->destroyed_closure, destroyed_port, s,
                        grpc_schedule_on_exec_ctx);
      if (!sp->orphan_notified) {
        /* Call the orphan_cb to signal that the FD is about to be closed and
         * should no longer be used. Because at this point, all listening ports
         * have been shutdown already, no need to shutdown again.*/
        GRPC_CLOSURE_INIT(&sp->orphan_fd_closure, dummy_cb, sp->emfd,
                          grpc_schedule_on_exec_ctx);
        GPR_ASSERT(sp->orphan_cb);
        sp->orphan_cb(exec_ctx, sp->emfd, &sp->orphan_fd_closure,
                      sp->server->user_data);
      }
      grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL,
                     false /* already_closed */, "udp_listener_shutdown");
    }
    gpr_mu_unlock(&s->mu);
  } else {
    gpr_mu_unlock(&s->mu);
    finish_shutdown(exec_ctx, s);
  }
}
Ejemplo n.º 2
0
/* called when all listening endpoints have been shutdown, so no further
   events will be received on them - at this point it's safe to destroy
   things */
static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) {
  /* delete ALL the things */
  gpr_mu_lock(&s->mu);

  GPR_ASSERT(s->shutdown);

  if (s->head) {
    grpc_udp_listener *sp;
    for (sp = s->head; sp; sp = sp->next) {
      grpc_unlink_if_unix_domain_socket(&sp->addr);

      grpc_closure_init(&sp->destroyed_closure, destroyed_port, s,
                        grpc_schedule_on_exec_ctx);

      /* Call the orphan_cb to signal that the FD is about to be closed and
       * should no longer be used. */
      GPR_ASSERT(sp->orphan_cb);
      sp->orphan_cb(exec_ctx, sp->emfd, sp->server->user_data);

      grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL,
                     "udp_listener_shutdown");
    }
    gpr_mu_unlock(&s->mu);
  } else {
    gpr_mu_unlock(&s->mu);
    finish_shutdown(exec_ctx, s);
  }
}
Ejemplo n.º 3
0
/* called when all listening endpoints have been shutdown, so no further
   events will be received on them - at this point it's safe to destroy
   things */
static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
    /* delete ALL the things */
    gpr_mu_lock(&s->mu);

    if (!s->shutdown) {
        gpr_mu_unlock(&s->mu);
        return;
    }

    if (s->head) {
        grpc_tcp_listener *sp;
        for (sp = s->head; sp; sp = sp->next) {
            grpc_unlink_if_unix_domain_socket(&sp->addr.sockaddr);
            sp->destroyed_closure.cb = destroyed_port;
            sp->destroyed_closure.cb_arg = s;
            grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL,
                           "tcp_listener_shutdown");
        }
        gpr_mu_unlock(&s->mu);
    } else {
        gpr_mu_unlock(&s->mu);
        finish_shutdown(exec_ctx, s);
    }
}
Ejemplo n.º 4
0
int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
                             size_t addr_len) {
    grpc_tcp_listener *sp;
    grpc_tcp_listener *sp2 = NULL;
    int fd;
    grpc_dualstack_mode dsmode;
    struct sockaddr_in6 addr6_v4mapped;
    struct sockaddr_in wild4;
    struct sockaddr_in6 wild6;
    struct sockaddr_in addr4_copy;
    struct sockaddr *allocated_addr = NULL;
    struct sockaddr_storage sockname_temp;
    socklen_t sockname_len;
    int port;
    unsigned port_index = 0;
    unsigned fd_index = 0;
    if (s->tail != NULL) {
        port_index = s->tail->port_index + 1;
    }
    grpc_unlink_if_unix_domain_socket((struct sockaddr *)addr);

    /* Check if this is a wildcard port, and if so, try to keep the port the same
       as some previously created listener. */
    if (grpc_sockaddr_get_port(addr) == 0) {
        for (sp = s->head; sp; sp = sp->next) {
            sockname_len = sizeof(sockname_temp);
            if (0 == getsockname(sp->fd, (struct sockaddr *)&sockname_temp,
                                 &sockname_len)) {
                port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
                if (port > 0) {
                    allocated_addr = malloc(addr_len);
                    memcpy(allocated_addr, addr, addr_len);
                    grpc_sockaddr_set_port(allocated_addr, port);
                    addr = allocated_addr;
                    break;
                }
            }
        }
    }

    sp = NULL;

    if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
        addr = (const struct sockaddr *)&addr6_v4mapped;
        addr_len = sizeof(addr6_v4mapped);
    }

    /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
    if (grpc_sockaddr_is_wildcard(addr, &port)) {
        grpc_sockaddr_make_wildcards(port, &wild4, &wild6);

        /* Try listening on IPv6 first. */
        addr = (struct sockaddr *)&wild6;
        addr_len = sizeof(wild6);
        fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
        sp = add_socket_to_server(s, fd, addr, addr_len, port_index, fd_index);
        if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
            goto done;
        }
        if (sp != NULL) {
            ++fd_index;
        }
        /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */
        if (port == 0 && sp != NULL) {
            grpc_sockaddr_set_port((struct sockaddr *)&wild4, sp->port);
        }
        addr = (struct sockaddr *)&wild4;
        addr_len = sizeof(wild4);
    }

    fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
    if (fd < 0) {
        gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno));
    } else {
        if (dsmode == GRPC_DSMODE_IPV4 &&
                grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
            addr = (struct sockaddr *)&addr4_copy;
            addr_len = sizeof(addr4_copy);
        }
        sp2 = sp;
        sp = add_socket_to_server(s, fd, addr, addr_len, port_index, fd_index);
        if (sp2 != NULL && sp != NULL) {
            sp2->sibling = sp;
            sp->is_sibling = 1;
        }
    }

done:
    gpr_free(allocated_addr);
    if (sp != NULL) {
        return sp->port;
    } else {
        return -1;
    }
}
Ejemplo n.º 5
0
grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
                                     size_t addr_len, int *out_port) {
  grpc_tcp_listener *sp;
  grpc_tcp_listener *sp2 = NULL;
  int fd;
  grpc_dualstack_mode dsmode;
  struct sockaddr_in6 addr6_v4mapped;
  struct sockaddr_in wild4;
  struct sockaddr_in6 wild6;
  struct sockaddr_in addr4_copy;
  struct sockaddr *allocated_addr = NULL;
  struct sockaddr_storage sockname_temp;
  socklen_t sockname_len;
  int port;
  unsigned port_index = 0;
  unsigned fd_index = 0;
  grpc_error *errs[2] = {GRPC_ERROR_NONE, GRPC_ERROR_NONE};
  if (s->tail != NULL) {
    port_index = s->tail->port_index + 1;
  }
  grpc_unlink_if_unix_domain_socket((struct sockaddr *)addr);

  /* Check if this is a wildcard port, and if so, try to keep the port the same
     as some previously created listener. */
  if (grpc_sockaddr_get_port(addr) == 0) {
    for (sp = s->head; sp; sp = sp->next) {
      sockname_len = sizeof(sockname_temp);
      if (0 == getsockname(sp->fd, (struct sockaddr *)&sockname_temp,
                           &sockname_len)) {
        port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
        if (port > 0) {
          allocated_addr = gpr_malloc(addr_len);
          memcpy(allocated_addr, addr, addr_len);
          grpc_sockaddr_set_port(allocated_addr, port);
          addr = allocated_addr;
          break;
        }
      }
    }
  }

  sp = NULL;

  if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
    addr = (const struct sockaddr *)&addr6_v4mapped;
    addr_len = sizeof(addr6_v4mapped);
  }

  /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
  if (grpc_sockaddr_is_wildcard(addr, &port)) {
    grpc_sockaddr_make_wildcards(port, &wild4, &wild6);

    /* Try listening on IPv6 first. */
    addr = (struct sockaddr *)&wild6;
    addr_len = sizeof(wild6);
    errs[0] = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode, &fd);
    if (errs[0] == GRPC_ERROR_NONE) {
      errs[0] = add_socket_to_server(s, fd, addr, addr_len, port_index,
                                     fd_index, &sp);
      if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
        goto done;
      }
      if (sp != NULL) {
        ++fd_index;
      }
      /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */
      if (port == 0 && sp != NULL) {
        grpc_sockaddr_set_port((struct sockaddr *)&wild4, sp->port);
      }
    }
    addr = (struct sockaddr *)&wild4;
    addr_len = sizeof(wild4);
  }

  errs[1] = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode, &fd);
  if (errs[1] == GRPC_ERROR_NONE) {
    if (dsmode == GRPC_DSMODE_IPV4 &&
        grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
      addr = (struct sockaddr *)&addr4_copy;
      addr_len = sizeof(addr4_copy);
    }
    sp2 = sp;
    errs[1] =
        add_socket_to_server(s, fd, addr, addr_len, port_index, fd_index, &sp);
    if (sp2 != NULL && sp != NULL) {
      sp2->sibling = sp;
      sp->is_sibling = 1;
    }
  }

done:
  gpr_free(allocated_addr);
  if (sp != NULL) {
    *out_port = sp->port;
    GRPC_ERROR_UNREF(errs[0]);
    GRPC_ERROR_UNREF(errs[1]);
    return GRPC_ERROR_NONE;
  } else {
    *out_port = -1;
    char *addr_str = grpc_sockaddr_to_uri(addr);
    grpc_error *err = grpc_error_set_str(
        GRPC_ERROR_CREATE_REFERENCING("Failed to add port to server", errs,
                                      GPR_ARRAY_SIZE(errs)),
        GRPC_ERROR_STR_TARGET_ADDRESS, addr_str);
    GRPC_ERROR_UNREF(errs[0]);
    GRPC_ERROR_UNREF(errs[1]);
    gpr_free(addr_str);
    return err;
  }
}