static pmix_status_t connect_to_peer(struct pmix_peer_t *peer, pmix_info_t *info, size_t ninfo) { struct sockaddr_un *address; char *evar, **uri; pmix_status_t rc; int sd; pmix_socklen_t len; bool retried = false; pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "[%s:%d] connect to server", __FILE__, __LINE__); /* if we are not a client, there is nothing we can do */ if (!PMIX_PROC_IS_CLIENT(pmix_globals.mypeer)) { return PMIX_ERR_NOT_SUPPORTED; } /* if we don't have a path to the daemon rendezvous point, * then we need to return an error */ if (NULL != (evar = getenv("PMIX_SERVER_URI2USOCK"))) { /* this is a v2.1+ server */ pmix_globals.mypeer->nptr->compat.bfrops = pmix_bfrops_base_assign_module("v21"); if (NULL == pmix_globals.mypeer->nptr->compat.bfrops) { return PMIX_ERR_INIT; } } else if (NULL != (evar = getenv("PMIX_SERVER_URI"))) { /* this is a pre-v2.1 server - must use the v12 bfrops module */ pmix_globals.mypeer->nptr->compat.bfrops = pmix_bfrops_base_assign_module("v12"); if (NULL == pmix_globals.mypeer->nptr->compat.bfrops) { return PMIX_ERR_INIT; } } else { /* let the caller know that the server isn't available */ return PMIX_ERR_SERVER_NOT_AVAIL; } /* the server will be using the same bfrops as us */ pmix_client_globals.myserver->nptr->compat.bfrops = pmix_globals.mypeer->nptr->compat.bfrops; /* mark that we are using the V1 protocol */ pmix_globals.mypeer->protocol = PMIX_PROTOCOL_V1; uri = pmix_argv_split(evar, ':'); if (3 != pmix_argv_count(uri)) { pmix_argv_free(uri); PMIX_ERROR_LOG(PMIX_ERROR); return PMIX_ERROR; } /* set the server nspace */ if (NULL == pmix_client_globals.myserver->info) { pmix_client_globals.myserver->info = PMIX_NEW(pmix_rank_info_t); } if (NULL == pmix_client_globals.myserver->nptr) { pmix_client_globals.myserver->nptr = PMIX_NEW(pmix_namespace_t); } if (NULL == pmix_client_globals.myserver->nptr->nspace) { pmix_client_globals.myserver->nptr->nspace = strdup(uri[0]); } if (NULL == pmix_client_globals.myserver->info->pname.nspace) { pmix_client_globals.myserver->info->pname.nspace = strdup(uri[0]); } /* set the server rank */ pmix_client_globals.myserver->info->pname.rank = strtoull(uri[1], NULL, 10); /* setup the path to the daemon rendezvous point */ memset(&mca_ptl_usock_component.connection, 0, sizeof(struct sockaddr_storage)); address = (struct sockaddr_un*)&mca_ptl_usock_component.connection; address->sun_family = AF_UNIX; snprintf(address->sun_path, sizeof(address->sun_path)-1, "%s", uri[2]); /* if the rendezvous file doesn't exist, that's an error */ if (0 != access(uri[2], R_OK)) { pmix_argv_free(uri); PMIX_ERROR_LOG(PMIX_ERR_NOT_FOUND); return PMIX_ERR_NOT_FOUND; } pmix_argv_free(uri); retry: /* establish the connection */ len = sizeof(struct sockaddr_un); if (PMIX_SUCCESS != (rc = pmix_ptl_base_connect(&mca_ptl_usock_component.connection, len, &sd))) { PMIX_ERROR_LOG(rc); return rc; } pmix_client_globals.myserver->sd = sd; /* send our identity and any authentication credentials to the server */ if (PMIX_SUCCESS != (rc = send_connect_ack(sd))) { CLOSE_THE_SOCKET(sd); return rc; } /* do whatever handshake is required */ if (PMIX_SUCCESS != (rc = recv_connect_ack(sd))) { CLOSE_THE_SOCKET(sd); if (PMIX_ERR_TEMP_UNAVAILABLE == rc) { /* give it two tries */ if (!retried) { retried = true; goto retry; } } return rc; } pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "sock_peer_try_connect: Connection across to server succeeded"); /* mark the connection as made */ pmix_globals.connected = true; pmix_ptl_base_set_nonblocking(sd); /* setup recv event */ pmix_event_assign(&pmix_client_globals.myserver->recv_event, pmix_globals.evbase, pmix_client_globals.myserver->sd, EV_READ | EV_PERSIST, pmix_usock_recv_handler, pmix_client_globals.myserver); pmix_event_add(&pmix_client_globals.myserver->recv_event, 0); pmix_client_globals.myserver->recv_ev_active = true; PMIX_POST_OBJECT(pmix_client_globals.myserver); pmix_event_add(&pmix_client_globals.myserver->recv_event, 0); /* setup send event */ pmix_event_assign(&pmix_client_globals.myserver->send_event, pmix_globals.evbase, pmix_client_globals.myserver->sd, EV_WRITE|EV_PERSIST, pmix_usock_send_handler, pmix_client_globals.myserver); pmix_client_globals.myserver->send_ev_active = false; return PMIX_SUCCESS; }
static pmix_status_t connect_to_peer(struct pmix_peer_t *peer, pmix_info_t *info, size_t ninfo) { char *evar, **uri; char *filename, *host; FILE *fp; char *srvr, *p, *p2; struct sockaddr_in *in; struct sockaddr_in6 *in6; pmix_socklen_t len; int sd, rc; pmix_output_verbose(2, pmix_globals.debug_output, "ptl:tcp: connecting to server"); /* see if the connection info is in the info array - if * so, then that overrides all other options */ /* if I am a client, then we need to look for the appropriate * connection info in the environment */ if (PMIX_PROC_CLIENT == pmix_globals.proc_type) { if (NULL == (evar = getenv("PMIX_SERVER_URI2"))) { /* not us */ return PMIX_ERR_NOT_SUPPORTED; } /* the URI consists of elements: * - server nspace.rank * - ptl rendezvous URI */ uri = pmix_argv_split(evar, ';'); if (2 != pmix_argv_count(uri)) { PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM); pmix_argv_free(uri); return PMIX_ERR_NOT_SUPPORTED; } /* set the server nspace */ p = uri[0]; if (NULL == (p2 = strchr(p, '.'))) { PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM); pmix_argv_free(uri); return PMIX_ERR_NOT_SUPPORTED; } *p2 = '\0'; ++p2; pmix_client_globals.myserver.info = PMIX_NEW(pmix_rank_info_t); pmix_client_globals.myserver.info->nptr = PMIX_NEW(pmix_nspace_t); (void)strncpy(pmix_client_globals.myserver.info->nptr->nspace, p, PMIX_MAX_NSLEN); /* set the server rank */ pmix_client_globals.myserver.info->rank = strtoull(p2, NULL, 10); /* save the URI, but do not overwrite what we may have received from * the info-key directives */ if (NULL == mca_ptl_tcp_component.super.uri) { mca_ptl_tcp_component.super.uri = strdup(uri[1]); } pmix_argv_free(uri); } else if (PMIX_PROC_TOOL == pmix_globals.proc_type) { /* if we already have a URI, then look no further */ if (NULL == mca_ptl_tcp_component.super.uri) { /* we have to discover the connection info, * if possible. Start by looking for the connection * info in the expected place - if the server supports * tool connections via TCP, then there will be a * "contact.txt" file under the system tmpdir */ filename = pmix_os_path(false, mca_ptl_tcp_component.tmpdir, "pmix-contact.txt", NULL); if (NULL == filename) { return PMIX_ERR_NOMEM; } fp = fopen(filename, "r"); if (NULL == fp) { /* if we cannot open the file, then the server must not * be configured to support tool connections - so abort */ free(filename); return PMIX_ERR_UNREACH; } free(filename); /* get the URI */ srvr = pmix_getline(fp); if (NULL == srvr) { PMIX_ERROR_LOG(PMIX_ERR_FILE_READ_FAILURE); fclose(fp); return PMIX_ERR_UNREACH; } fclose(fp); /* up to the first ';' is the server nspace/rank */ if (NULL == (p = strchr(srvr, ';'))) { /* malformed */ free(srvr); return PMIX_ERR_UNREACH; } *p = '\0'; ++p; // move past the semicolon /* the nspace is the section up to the '.' */ if (NULL == (p2 = strchr(srvr, '.'))) { /* malformed */ free(srvr); return PMIX_ERR_UNREACH; } *p2 = '\0'; ++p2; /* set the server nspace */ pmix_client_globals.myserver.info = PMIX_NEW(pmix_rank_info_t); pmix_client_globals.myserver.info->nptr = PMIX_NEW(pmix_nspace_t); (void)strncpy(pmix_client_globals.myserver.info->nptr->nspace, srvr, PMIX_MAX_NSLEN); pmix_client_globals.myserver.info->rank = strtoull(p2, NULL, 10); /* now parse the uti itself */ mca_ptl_tcp_component.super.uri = strdup(p); free(srvr); } } /* mark that we are the active module for this server */ pmix_client_globals.myserver.compat.ptl = &pmix_ptl_tcp_module; /* setup the path to the daemon rendezvous point */ memset(&mca_ptl_tcp_component.connection, 0, sizeof(struct sockaddr_storage)); if (0 == strncmp(mca_ptl_tcp_component.super.uri, "tcp4", 4)) { /* separate the IP address from the port */ p = strdup(mca_ptl_tcp_component.super.uri); if (NULL == p) { return PMIX_ERR_NOMEM; } p2 = strchr(&p[7], ':'); if (NULL == p2) { free(p); return PMIX_ERR_BAD_PARAM; } *p2 = '\0'; ++p2; host = &p[7]; /* load the address */ in = (struct sockaddr_in*)&mca_ptl_tcp_component.connection; in->sin_family = AF_INET; in->sin_addr.s_addr = inet_addr(host); if (in->sin_addr.s_addr == INADDR_NONE) { free(p); return PMIX_ERR_BAD_PARAM; } in->sin_port = htons(atoi(p2)); len = sizeof(struct sockaddr_in); } else { /* separate the IP address from the port */ p = strdup(mca_ptl_tcp_component.super.uri); if (NULL == p) { return PMIX_ERR_NOMEM; } p2 = strchr(&p[7], ':'); if (NULL == p2) { free(p); return PMIX_ERR_BAD_PARAM; } *p2 = '\0'; if (']' == p[strlen(p)-1]) { p[strlen(p)-1] = '\0'; } if ('[' == p[7]) { host = &p[8]; } else { host = &p[7]; } /* load the address */ in6 = (struct sockaddr_in6*)&mca_ptl_tcp_component.connection; in6->sin6_family = AF_INET6; if (0 == inet_pton(AF_INET6, host, (void*)&in6->sin6_addr)) { pmix_output (0, "ptl_tcp_parse_uri: Could not convert %s\n", host); free(p); return PMIX_ERR_BAD_PARAM; } in6->sin6_port = htons(atoi(p2)); len = sizeof(struct sockaddr_in6); } free(p); /* establish the connection */ if (PMIX_SUCCESS != (rc = pmix_ptl_base_connect(&mca_ptl_tcp_component.connection, len, &sd))) { PMIX_ERROR_LOG(rc); return rc; } pmix_client_globals.myserver.sd = sd; /* send our identity and any authentication credentials to the server */ if (PMIX_SUCCESS != (rc = send_connect_ack(sd))) { PMIX_ERROR_LOG(rc); CLOSE_THE_SOCKET(sd); return rc; } /* do whatever handshake is required */ if (PMIX_SUCCESS != (rc = recv_connect_ack(sd))) { PMIX_ERROR_LOG(rc); CLOSE_THE_SOCKET(sd); return rc; } pmix_output_verbose(2, pmix_globals.debug_output, "sock_peer_try_connect: Connection across to server succeeded"); /* mark the connection as made */ pmix_globals.connected = true; pmix_ptl_base_set_nonblocking(sd); /* setup recv event */ pmix_event_assign(&pmix_client_globals.myserver.recv_event, pmix_globals.evbase, pmix_client_globals.myserver.sd, EV_READ | EV_PERSIST, pmix_ptl_base_recv_handler, &pmix_client_globals.myserver); pmix_event_add(&pmix_client_globals.myserver.recv_event, 0); pmix_client_globals.myserver.recv_ev_active = true; /* setup send event */ pmix_event_assign(&pmix_client_globals.myserver.send_event, pmix_globals.evbase, pmix_client_globals.myserver.sd, EV_WRITE|EV_PERSIST, pmix_ptl_base_send_handler, &pmix_client_globals.myserver); pmix_client_globals.myserver.send_ev_active = false; return PMIX_SUCCESS; }
static pmix_status_t try_connect(int *sd) { char *p, *p2, *host; struct sockaddr_in *in; struct sockaddr_in6 *in6; size_t len; pmix_status_t rc; bool retried = false; pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "pmix:tcp try connect to %s", mca_ptl_tcp_component.super.uri); /* mark that we are the active module for this server */ pmix_client_globals.myserver->nptr->compat.ptl = &pmix_ptl_tcp_module; /* setup the path to the daemon rendezvous point */ memset(&mca_ptl_tcp_component.connection, 0, sizeof(struct sockaddr_storage)); if (0 == strncmp(mca_ptl_tcp_component.super.uri, "tcp4", 4)) { /* need to skip the tcp4: part */ p = strdup(&mca_ptl_tcp_component.super.uri[7]); if (NULL == p) { PMIX_ERROR_LOG(PMIX_ERR_NOMEM); return PMIX_ERR_NOMEM; } /* separate the IP address from the port */ p2 = strchr(p, ':'); if (NULL == p2) { free(p); PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM); return PMIX_ERR_BAD_PARAM; } *p2 = '\0'; p2++; host = p; /* load the address */ in = (struct sockaddr_in*)&mca_ptl_tcp_component.connection; in->sin_family = AF_INET; in->sin_addr.s_addr = inet_addr(host); if (in->sin_addr.s_addr == INADDR_NONE) { free(p); PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM); return PMIX_ERR_BAD_PARAM; } in->sin_port = htons(atoi(p2)); len = sizeof(struct sockaddr_in); } else { /* need to skip the tcp6: part */ p = strdup(&mca_ptl_tcp_component.super.uri[7]); if (NULL == p) { PMIX_ERROR_LOG(PMIX_ERR_NOMEM); return PMIX_ERR_NOMEM; } p2 = strchr(p, ':'); if (NULL == p2) { free(p); PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM); return PMIX_ERR_BAD_PARAM; } *p2 = '\0'; if (']' == p[strlen(p)-1]) { p[strlen(p)-1] = '\0'; } if ('[' == p[0]) { host = &p[1]; } else { host = &p[0]; } /* load the address */ in6 = (struct sockaddr_in6*)&mca_ptl_tcp_component.connection; in6->sin6_family = AF_INET6; if (0 == inet_pton(AF_INET6, host, (void*)&in6->sin6_addr)) { pmix_output (0, "ptl_tcp_parse_uri: Could not convert %s\n", host); free(p); PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM); return PMIX_ERR_BAD_PARAM; } in6->sin6_port = htons(atoi(p2)); len = sizeof(struct sockaddr_in6); } free(p); retry: /* establish the connection */ if (PMIX_SUCCESS != (rc = pmix_ptl_base_connect(&mca_ptl_tcp_component.connection, len, sd))) { /* do not error log - might just be a stale connection point */ return rc; } /* send our identity and any authentication credentials to the server */ if (PMIX_SUCCESS != (rc = send_connect_ack(*sd))) { PMIX_ERROR_LOG(rc); CLOSE_THE_SOCKET(*sd); return rc; } /* do whatever handshake is required */ if (PMIX_SUCCESS != (rc = recv_connect_ack(*sd))) { CLOSE_THE_SOCKET(*sd); if (PMIX_ERR_TEMP_UNAVAILABLE == rc) { /* give it two tries */ if (!retried) { retried = true; goto retry; } } PMIX_ERROR_LOG(rc); return rc; } return PMIX_SUCCESS; }
static pmix_status_t connect_to_peer(struct pmix_peer_t *peer, pmix_info_t *info, size_t ninfo) { struct sockaddr_un *address; char *evar, **uri; pmix_status_t rc; int sd; pmix_socklen_t len; /* if we are not a client, there is nothing we can do */ if (!PMIX_PROC_IS_CLIENT) { return PMIX_ERR_NOT_SUPPORTED; } /* if we don't have a path to the daemon rendezvous point, * then we need to return an error */ if (NULL == (evar = getenv("PMIX_SERVER_URI"))) { /* let the caller know that the server isn't available */ return PMIX_ERR_SERVER_NOT_AVAIL; } uri = pmix_argv_split(evar, ':'); if (3 != pmix_argv_count(uri)) { pmix_argv_free(uri); return PMIX_ERROR; } /* set the server nspace */ if (NULL == pmix_client_globals.myserver->info) { pmix_client_globals.myserver->info = PMIX_NEW(pmix_rank_info_t); } if (NULL == pmix_client_globals.myserver->nptr) { pmix_client_globals.myserver->nptr = PMIX_NEW(pmix_nspace_t); } if (NULL == pmix_client_globals.myserver->nptr->nspace) { pmix_client_globals.myserver->nptr->nspace = strdup(uri[0]); } if (NULL == pmix_client_globals.myserver->info->pname.nspace) { pmix_client_globals.myserver->info->pname.nspace = strdup(uri[0]); } /* set the server rank */ pmix_client_globals.myserver->info->pname.rank = strtoull(uri[1], NULL, 10); /* setup the path to the daemon rendezvous point */ memset(&mca_ptl_usock_component.connection, 0, sizeof(struct sockaddr_storage)); address = (struct sockaddr_un*)&mca_ptl_usock_component.connection; address->sun_family = AF_UNIX; snprintf(address->sun_path, sizeof(address->sun_path)-1, "%s", uri[2]); /* if the rendezvous file doesn't exist, that's an error */ if (0 != access(uri[2], R_OK)) { pmix_argv_free(uri); return PMIX_ERR_NOT_FOUND; } pmix_argv_free(uri); /* establish the connection */ len = sizeof(struct sockaddr_un); if (PMIX_SUCCESS != (rc = pmix_ptl_base_connect(&mca_ptl_usock_component.connection, len, &sd))) { PMIX_ERROR_LOG(rc); return rc; } pmix_client_globals.myserver->sd = sd; /* send our identity and any authentication credentials to the server */ if (PMIX_SUCCESS != (rc = send_connect_ack(sd))) { CLOSE_THE_SOCKET(sd); return rc; } /* do whatever handshake is required */ if (PMIX_SUCCESS != (rc = recv_connect_ack(sd))) { CLOSE_THE_SOCKET(sd); return rc; } pmix_output_verbose(2, pmix_globals.debug_output, "sock_peer_try_connect: Connection across to server succeeded"); /* mark the connection as made */ pmix_globals.connected = true; pmix_ptl_base_set_nonblocking(sd); /* setup recv event */ pmix_event_assign(&pmix_client_globals.myserver->recv_event, pmix_globals.evbase, pmix_client_globals.myserver->sd, EV_READ | EV_PERSIST, pmix_ptl_base_recv_handler, &pmix_client_globals.myserver); pmix_event_add(&pmix_client_globals.myserver->recv_event, 0); pmix_client_globals.myserver->recv_ev_active = true; /* setup send event */ pmix_event_assign(&pmix_client_globals.myserver->send_event, pmix_globals.evbase, pmix_client_globals.myserver->sd, EV_WRITE|EV_PERSIST, pmix_ptl_base_send_handler, &pmix_client_globals.myserver); pmix_client_globals.myserver->send_ev_active = false; return PMIX_SUCCESS; }