Beispiel #1
0
/****    SUPPORTING FUNCTIONS    ****/
static pmix_status_t parse_uri_file(char *filename,
                                    char **uri,
                                    char **nspace,
                                    pmix_rank_t *rank)
{
    FILE *fp;
    char *srvr, *p, *p2;
    pmix_lock_t lock;
    pmix_event_t ev;
    struct timeval tv;
    int retries;

    fp = fopen(filename, "r");
    if (NULL == fp) {
        /* if we cannot open the file, then the server must not
         * be configured to support tool connections, or this
         * user isn't authorized to access it - or it may just
         * not exist yet! Check for existence */
        if (0 != access(filename, R_OK)) {
            if (ENOENT == errno && 0 < mca_ptl_tcp_component.wait_to_connect) {
                /* the file does not exist, so give it
                 * a little time to see if the server
                 * is still starting up */
                retries = 0;
                do {
                    ++retries;
                    pmix_output_verbose(2, pmix_ptl_base_framework.framework_output,
                                        "WAITING FOR CONNECTION FILE");
                    PMIX_CONSTRUCT_LOCK(&lock);
                    tv.tv_sec = mca_ptl_tcp_component.wait_to_connect;
                    tv.tv_usec = 0;
                    pmix_event_evtimer_set(pmix_globals.evbase, &ev,
                                           timeout, &lock);
                    pmix_event_evtimer_add(&ev, &tv);
                    PMIX_WAIT_THREAD(&lock);
                    PMIX_DESTRUCT_LOCK(&lock);
                    fp = fopen(filename, "r");
                    if (NULL != fp) {
                        /* we found it! */
                        goto process;
                    }
                } while (retries < mca_ptl_tcp_component.max_retries);
                /* otherwise, mark it as unreachable */
            }
        }
        return PMIX_ERR_UNREACH;
    }

  process:
    /* get the URI */
    srvr = pmix_getline(fp);
    if (NULL == srvr) {
        PMIX_ERROR_LOG(PMIX_ERR_FILE_READ_FAILURE);
        fclose(fp);
        return PMIX_ERR_UNREACH;
    }
    /* see if this file contains the server's version */
    p2 = pmix_getline(fp);
    if (NULL == p2) {
        pmix_client_globals.myserver->proc_type = PMIX_PROC_SERVER | PMIX_PROC_V20;
        pmix_output_verbose(2, pmix_ptl_base_framework.framework_output,
                            "V20 SERVER DETECTED");
        pmix_client_globals.myserver->protocol = PMIX_PROTOCOL_V2;
    } else if (0 == strncmp(p2, "v2.1", strlen("v2.1")) ||
               0 == strncmp(p2, "2.1", strlen("2.1"))) {
        pmix_client_globals.myserver->proc_type = PMIX_PROC_SERVER | PMIX_PROC_V21;
        pmix_client_globals.myserver->protocol = PMIX_PROTOCOL_V2;
        pmix_output_verbose(2, pmix_ptl_base_framework.framework_output,
                            "V21 SERVER DETECTED");
    } else if (0 == strncmp(p2, "3", strlen("3")) ||
               0 == strncmp(p2, "v3", strlen("v3"))) {
        pmix_client_globals.myserver->proc_type = PMIX_PROC_SERVER | PMIX_PROC_V3;
        pmix_client_globals.myserver->protocol = PMIX_PROTOCOL_V2;
        pmix_output_verbose(2, pmix_ptl_base_framework.framework_output,
                            "V3 SERVER DETECTED");
    } else {
        pmix_output_verbose(2, pmix_ptl_base_framework.framework_output,
                            "UNKNOWN SERVER VERSION DETECTED: %s", p2);
    }
    if (NULL != p2) {
        free(p2);
    }

    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/rank */
    *nspace = strdup(srvr);
    *rank = strtoull(p2, NULL, 10);

    /* now parse the uri itself */
    *uri = strdup(p);
    free(srvr);

    return PMIX_SUCCESS;
}
Beispiel #2
0
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;
}