This source file includes following definitions.
- component_open
- component_close
- component_query
- setup_listener
- listener_cb
- connection_handler
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 
  24 
  25 
  26 
  27 
  28 
  29 
  30 
  31 
  32 #include <src/include/pmix_config.h>
  33 #include <pmix_common.h>
  34 
  35 #ifdef HAVE_FCNTL_H
  36 #include <fcntl.h>
  37 #endif
  38 #ifdef HAVE_UNISTD_H
  39 #include <unistd.h>
  40 #endif
  41 #ifdef HAVE_SYS_SOCKET_H
  42 #include <sys/socket.h>
  43 #endif
  44 #ifdef HAVE_SYS_UN_H
  45 #include <sys/un.h>
  46 #endif
  47 #ifdef HAVE_SYS_UIO_H
  48 #include <sys/uio.h>
  49 #endif
  50 #ifdef HAVE_SYS_TYPES_H
  51 #include <sys/types.h>
  52 #endif
  53 #ifdef HAVE_SYS_STAT_H
  54 #include <sys/stat.h>
  55 #endif
  56 #include <errno.h>
  57 
  58 #include "src/util/argv.h"
  59 #include "src/util/error.h"
  60 #include "src/util/fd.h"
  61 #include "src/util/show_help.h"
  62 #include "src/util/strnlen.h"
  63 #include "src/mca/bfrops/base/base.h"
  64 #include "src/mca/gds/base/base.h"
  65 #include "src/mca/psec/base/base.h"
  66 #include "src/server/pmix_server_ops.h"
  67 
  68 #include "src/mca/ptl/base/base.h"
  69 #include "src/mca/ptl/usock/ptl_usock.h"
  70 
  71 static pmix_status_t component_open(void);
  72 static pmix_status_t component_close(void);
  73 static int component_query(pmix_mca_base_module_t **module, int *priority);
  74 static pmix_status_t setup_listener(pmix_info_t info[], size_t ninfo,
  75                                     bool *need_listener);
  76 
  77 
  78 
  79 
  80 
  81 PMIX_EXPORT pmix_ptl_usock_component_t mca_ptl_usock_component = {
  82     .super = {
  83         .base = {
  84             PMIX_PTL_BASE_VERSION_1_0_0,
  85 
  86             
  87             .pmix_mca_component_name = "usock",
  88             PMIX_MCA_BASE_MAKE_VERSION(component,
  89                                        PMIX_MAJOR_VERSION,
  90                                        PMIX_MINOR_VERSION,
  91                                        PMIX_RELEASE_VERSION),
  92 
  93             
  94             .pmix_mca_open_component = component_open,
  95             .pmix_mca_close_component = component_close,
  96             .pmix_mca_query_component = component_query
  97         },
  98         .priority = 15,
  99         .uri = NULL,
 100         .setup_listener = setup_listener
 101     },
 102     .tmpdir = NULL,
 103     .filename = NULL
 104 };
 105 
 106 static void connection_handler(int sd, short args, void *cbdata);
 107 static void listener_cb(int incoming_sd, void *cbdata);
 108 
 109 pmix_status_t component_open(void)
 110 {
 111     char *tdir;
 112 
 113     memset(&mca_ptl_usock_component.connection, 0, sizeof(mca_ptl_usock_component.connection));
 114 
 115     
 116 
 117     if (NULL == (tdir = getenv("PMIX_SYSTEM_TMPDIR"))) {
 118         if (NULL == (tdir = getenv("TMPDIR"))) {
 119             if (NULL == (tdir = getenv("TEMP"))) {
 120                 if (NULL == (tdir = getenv("TMP"))) {
 121                     tdir = "/tmp";
 122                 }
 123             }
 124         }
 125     }
 126     if (NULL != tdir) {
 127         mca_ptl_usock_component.tmpdir = strdup(tdir);
 128     }
 129 
 130     return PMIX_SUCCESS;
 131 }
 132 
 133 
 134 pmix_status_t component_close(void)
 135 {
 136     if (NULL != mca_ptl_usock_component.tmpdir) {
 137         free(mca_ptl_usock_component.tmpdir);
 138     }
 139     if (NULL != mca_ptl_usock_component.super.uri) {
 140         free(mca_ptl_usock_component.super.uri);
 141     }
 142     if (NULL != mca_ptl_usock_component.filename) {
 143         
 144         unlink(mca_ptl_usock_component.filename);
 145         free(mca_ptl_usock_component.filename);
 146     }
 147 
 148     return PMIX_SUCCESS;
 149 }
 150 
 151 static int component_query(pmix_mca_base_module_t **module, int *priority)
 152 {
 153     *module = (pmix_mca_base_module_t*)&pmix_ptl_usock_module;
 154     return PMIX_SUCCESS;
 155 }
 156 
 157 
 158 
 159 
 160 
 161 
 162 
 163 
 164 
 165 
 166 static pmix_status_t setup_listener(pmix_info_t info[], size_t ninfo,
 167                                     bool *need_listener)
 168 {
 169     int flags;
 170     size_t n;
 171     pmix_listener_t *lt;
 172     pmix_status_t rc;
 173     socklen_t addrlen;
 174     struct sockaddr_un *address;
 175     bool disabled = false;
 176     char *pmix_pid;
 177     pid_t mypid;
 178 
 179     pmix_output_verbose(2, pmix_ptl_base_framework.framework_output,
 180                         "ptl:usock setup_listener");
 181 
 182     
 183     if (!PMIX_PROC_IS_SERVER(pmix_globals.mypeer)) {
 184         return PMIX_ERR_NOT_SUPPORTED;
 185     }
 186 
 187     
 188     if (NULL != info) {
 189         for (n=0; n < ninfo; n++) {
 190             if (0 == strcmp(info[n].key, PMIX_USOCK_DISABLE)) {
 191                 disabled = PMIX_INFO_TRUE(&info[n]);;
 192                 break;
 193             }
 194         }
 195     }
 196 
 197     
 198     if (disabled) {
 199         pmix_output_verbose(2, pmix_ptl_base_framework.framework_output,
 200                             "ptl:usock not available");
 201         return PMIX_ERR_NOT_AVAILABLE;
 202     }
 203 
 204     pmix_output_verbose(2, pmix_ptl_base_framework.framework_output,
 205                         "ptl:usock setting up listener");
 206 
 207     addrlen = sizeof(struct sockaddr_un);
 208     address = (struct sockaddr_un*)&mca_ptl_usock_component.connection;
 209     address->sun_family = AF_UNIX;
 210 
 211     
 212     lt = PMIX_NEW(pmix_listener_t);
 213 
 214     
 215 
 216     mypid = getpid();
 217     if (0 > asprintf(&pmix_pid, "%s/pmix-%d", mca_ptl_usock_component.tmpdir, mypid)) {
 218         PMIX_RELEASE(lt);
 219         return PMIX_ERR_NOMEM;
 220     }
 221     if ((strlen(pmix_pid) + 1) > sizeof(address->sun_path)-1) {
 222         pmix_show_help("help-pmix-server.txt", "rnd-path-too-long", true,
 223                        mca_ptl_usock_component.tmpdir, pmix_pid);
 224         free(pmix_pid);
 225         PMIX_RELEASE(lt);
 226         return PMIX_ERR_INVALID_LENGTH;
 227     }
 228     snprintf(address->sun_path, sizeof(address->sun_path)-1, "%s", pmix_pid);
 229     free(pmix_pid);
 230     
 231     lt->varname = strdup("PMIX_SERVER_URI:PMIX_SERVER_URI2USOCK");
 232     if (0 > asprintf(<->uri, "%s:%lu:%s", pmix_globals.myid.nspace,
 233                     (unsigned long)pmix_globals.myid.rank, address->sun_path)) {
 234         PMIX_RELEASE(lt);
 235         return PMIX_ERR_NOMEM;
 236     }
 237     
 238     mca_ptl_usock_component.filename = strdup(address->sun_path);
 239 
 240     lt->protocol = PMIX_PROTOCOL_V1;
 241     lt->ptl = (struct pmix_ptl_module_t*)&pmix_ptl_usock_module;
 242     lt->cbfunc = connection_handler;
 243     pmix_list_append(&pmix_ptl_globals.listeners, <->super);
 244 
 245     
 246     lt->socket = socket(PF_UNIX, SOCK_STREAM, 0);
 247     if (lt->socket < 0) {
 248         printf("%s:%d socket() failed\n", __FILE__, __LINE__);
 249         goto sockerror;
 250     }
 251     
 252 
 253     if (pmix_fd_set_cloexec(lt->socket) != PMIX_SUCCESS) {
 254         CLOSE_THE_SOCKET(lt->socket);
 255         goto sockerror;
 256     }
 257 
 258     if (bind(lt->socket, (struct sockaddr*)address, addrlen) < 0) {
 259         printf("%s:%d bind() failed\n", __FILE__, __LINE__);
 260         CLOSE_THE_SOCKET(lt->socket);
 261         goto sockerror;
 262     }
 263     
 264     if (lt->owner_given) {
 265         if (0 != chown(address->sun_path, lt->owner, -1)) {
 266             pmix_output(0, "CANNOT CHOWN socket %s: %s", address->sun_path, strerror (errno));
 267             CLOSE_THE_SOCKET(lt->socket);
 268             goto sockerror;
 269         }
 270     }
 271     if (lt->group_given) {
 272         if (0 != chown(address->sun_path, -1, lt->group)) {
 273             pmix_output(0, "CANNOT CHOWN socket %s: %s", address->sun_path, strerror (errno));
 274             CLOSE_THE_SOCKET(lt->socket);
 275             goto sockerror;
 276         }
 277     }
 278     
 279     if (0 != chmod(address->sun_path, lt->mode)) {
 280         pmix_output(0, "CANNOT CHMOD socket %s: %s", address->sun_path, strerror (errno));
 281         CLOSE_THE_SOCKET(lt->socket);
 282         goto sockerror;
 283     }
 284 
 285     
 286     if (listen(lt->socket, SOMAXCONN) < 0) {
 287         printf("%s:%d listen() failed\n", __FILE__, __LINE__);
 288         CLOSE_THE_SOCKET(lt->socket);
 289         goto sockerror;
 290     }
 291 
 292     
 293     if ((flags = fcntl(lt->socket, F_GETFL, 0)) < 0) {
 294         printf("%s:%d fcntl(F_GETFL) failed\n", __FILE__, __LINE__);
 295         CLOSE_THE_SOCKET(lt->socket);
 296         goto sockerror;
 297     }
 298     flags |= O_NONBLOCK;
 299     if (fcntl(lt->socket, F_SETFL, flags) < 0) {
 300         printf("%s:%d fcntl(F_SETFL) failed\n", __FILE__, __LINE__);
 301         CLOSE_THE_SOCKET(lt->socket);
 302         goto sockerror;
 303     }
 304 
 305     
 306     rc = PMIX_ERR_NOT_SUPPORTED;
 307     if (NULL != pmix_host_server.listener) {
 308         rc = pmix_host_server.listener(lt->socket, listener_cb, (void*)lt);
 309     }
 310 
 311     if (PMIX_SUCCESS != rc) {
 312         *need_listener = true;
 313     }
 314 
 315     return PMIX_SUCCESS;
 316 
 317   sockerror:
 318       pmix_list_remove_item(&pmix_ptl_globals.listeners, <->super);
 319       PMIX_RELEASE(lt);
 320       return PMIX_ERROR;
 321 }
 322 
 323 static void listener_cb(int incoming_sd, void *cbdata)
 324 {
 325     pmix_pending_connection_t *pending_connection;
 326 
 327     
 328     pmix_output_verbose(8, pmix_ptl_base_framework.framework_output,
 329                         "listen_cb: pushing new connection %d into evbase",
 330                         incoming_sd);
 331     pending_connection = PMIX_NEW(pmix_pending_connection_t);
 332     pending_connection->sd = incoming_sd;
 333     pmix_event_assign(&pending_connection->ev, pmix_globals.evbase, -1,
 334                       EV_WRITE, connection_handler, pending_connection);
 335     pmix_event_active(&pending_connection->ev, EV_WRITE, 1);
 336 }
 337 
 338 static void connection_handler(int sd, short args, void *cbdata)
 339 {
 340     pmix_pending_connection_t *pnd = (pmix_pending_connection_t*)cbdata;
 341     char *msg, *ptr, *nspace, *version, *sec, *bfrops, *gds;
 342     pmix_status_t rc;
 343     unsigned int rank;
 344     pmix_usock_hdr_t hdr;
 345     pmix_namespace_t *nptr, *tmp;
 346     pmix_rank_info_t *info;
 347     pmix_peer_t *psave = NULL;
 348     bool found;
 349     pmix_proc_t proc;
 350     size_t len;
 351     pmix_bfrop_buffer_type_t bftype;
 352     char **vers;
 353     int major, minor, rel;
 354     unsigned int msglen;
 355     pmix_info_t ginfo;
 356     pmix_byte_object_t cred;
 357 
 358     
 359     PMIX_ACQUIRE_OBJECT(pnd);
 360 
 361     pmix_output_verbose(2, pmix_ptl_base_framework.framework_output,
 362                         "USOCK CONNECTION FROM PEER ON SOCKET %d", pnd->sd);
 363 
 364     
 365     memset(&hdr, 0, sizeof(pmix_usock_hdr_t));
 366 
 367     
 368     if (PMIX_SUCCESS != (rc = pmix_ptl_base_recv_blocking(pnd->sd, (char*)&hdr, sizeof(pmix_usock_hdr_t)))) {
 369         CLOSE_THE_SOCKET(pnd->sd);
 370         PMIX_RELEASE(pnd);
 371         return;
 372     }
 373 
 374     
 375 
 376 
 377     if (PMIX_MAX_CRED_SIZE < hdr.nbytes) {
 378         CLOSE_THE_SOCKET(pnd->sd);
 379         PMIX_RELEASE(pnd);
 380         return;
 381     }
 382     if (NULL == (msg = (char*)malloc(hdr.nbytes))) {
 383         CLOSE_THE_SOCKET(pnd->sd);
 384         PMIX_RELEASE(pnd);
 385         return;
 386     }
 387     if (PMIX_SUCCESS != pmix_ptl_base_recv_blocking(pnd->sd, msg, hdr.nbytes)) {
 388         
 389         pmix_output_verbose(2, pmix_ptl_base_framework.framework_output,
 390                             "unable to complete recv of connect-ack with client ON SOCKET %d", pnd->sd);
 391         free(msg);
 392         CLOSE_THE_SOCKET(pnd->sd);
 393         PMIX_RELEASE(pnd);
 394         return;
 395     }
 396     len = hdr.nbytes;
 397     ptr = msg;
 398 
 399     
 400     PMIX_STRNLEN(msglen, ptr, len);
 401     if (msglen < len) {
 402         nspace = ptr;
 403         ptr += strlen(nspace) + 1;
 404         len -= strlen(nspace) + 1;
 405     } else {
 406         free(msg);
 407         CLOSE_THE_SOCKET(pnd->sd);
 408         PMIX_RELEASE(pnd);
 409         return;
 410     }
 411 
 412     
 413     PMIX_STRNLEN(msglen, ptr, len);
 414     if (msglen <= len) {
 415         memcpy(&rank, ptr, sizeof(int));
 416         ptr += sizeof(int);
 417         len -= sizeof(int);
 418     } else {
 419         free(msg);
 420         CLOSE_THE_SOCKET(pnd->sd);
 421         PMIX_RELEASE(pnd);
 422         return;
 423     }
 424 
 425     
 426     PMIX_STRNLEN(msglen, ptr, len);
 427     if (msglen < len) {
 428         version = ptr;
 429         ptr += strlen(version) + 1;
 430         len -= strlen(version) + 1;
 431     } else {
 432         free(msg);
 433         CLOSE_THE_SOCKET(pnd->sd);
 434         PMIX_RELEASE(pnd);
 435         return;
 436     }
 437 
 438     
 439 
 440     vers = pmix_argv_split(version, '.');
 441     major = strtol(vers[0], NULL, 10);
 442     minor = strtol(vers[1], NULL, 10);
 443     rel = strtol(vers[2], NULL, 10);
 444     pmix_argv_free(vers);
 445     if (1 == major && (2 != minor || 5 > rel)) {
 446         pmix_output_verbose(2, pmix_ptl_base_framework.framework_output,
 447                             "connection request from client of unsupported version %s", version);
 448         free(msg);
 449         CLOSE_THE_SOCKET(pnd->sd);
 450         PMIX_RELEASE(pnd);
 451         return;
 452     }
 453 
 454     
 455     if (1 == major) {
 456         
 457         PMIX_STRNLEN(msglen, ptr, len);
 458         if (msglen < len) {
 459             cred.bytes = ptr;
 460             cred.size = strlen(ptr);
 461             ptr += cred.size + 1;
 462             len -= cred.size + 1;
 463         } else {
 464             free(msg);
 465             CLOSE_THE_SOCKET(pnd->sd);
 466             PMIX_RELEASE(pnd);
 467             return;
 468         }
 469     } else {
 470         
 471         if (sizeof(size_t) < len) {
 472             memcpy(&cred.size, ptr, sizeof(size_t));
 473             ptr += sizeof(size_t);
 474             len -= sizeof(size_t);
 475         } else {
 476             free(msg);
 477             CLOSE_THE_SOCKET(pnd->sd);
 478             PMIX_RELEASE(pnd);
 479             return;
 480         }
 481         if (0 < cred.size) {
 482             cred.bytes = ptr;
 483             ptr += cred.size;
 484             len -= cred.size;
 485         } else {
 486             
 487 
 488             cred.bytes = NULL;
 489         }
 490     }
 491 
 492     
 493     PMIX_STRNLEN(msglen, ptr, len);
 494     if (msglen < len) {
 495         sec = ptr;
 496         ptr += strlen(sec) + 1;
 497         len -= strlen(sec) + 1;
 498     } else {
 499         free(msg);
 500         CLOSE_THE_SOCKET(pnd->sd);
 501         PMIX_RELEASE(pnd);
 502         return;
 503     }
 504 
 505     
 506     PMIX_STRNLEN(msglen, ptr, len);
 507     if (msglen < len) {
 508         bfrops = ptr;
 509         ptr += strlen(bfrops) + 1;
 510         len -= strlen(bfrops) + 1;
 511     } else {
 512         free(msg);
 513         CLOSE_THE_SOCKET(pnd->sd);
 514         PMIX_RELEASE(pnd);
 515         return;
 516     }
 517 
 518     
 519     if (0 < len) {
 520         bftype = ptr[0];
 521         ptr += 1;
 522         len -= 1;
 523     } else {
 524         free(msg);
 525         CLOSE_THE_SOCKET(pnd->sd);
 526         PMIX_RELEASE(pnd);
 527         return;
 528     }
 529 
 530     
 531     PMIX_STRNLEN(msglen, ptr, len);
 532     if (msglen < len) {
 533         gds = ptr;
 534         ptr += strlen(gds) + 1;
 535         len -= strlen(gds) + 1;
 536     } else {
 537         free(msg);
 538         CLOSE_THE_SOCKET(pnd->sd);
 539         PMIX_RELEASE(pnd);
 540         return;
 541     }
 542 
 543     pmix_output_verbose(2, pmix_ptl_base_framework.framework_output,
 544                         "connect-ack recvd from peer %s:%d:%s on socket %d",
 545                         nspace, rank, version, pnd->sd);
 546 
 547     
 548     nptr = NULL;
 549     PMIX_LIST_FOREACH(tmp, &pmix_server_globals.nspaces, pmix_namespace_t) {
 550         if (0 == strcmp(tmp->nspace, nspace)) {
 551             nptr = tmp;
 552             break;
 553         }
 554     }
 555     if (NULL == nptr) {
 556         
 557         free(msg);
 558         
 559         rc = PMIX_ERR_NOT_FOUND;
 560         goto error;
 561     }
 562 
 563     
 564     info = NULL;
 565     found = false;
 566     PMIX_LIST_FOREACH(info, &nptr->ranks, pmix_rank_info_t) {
 567         if (info->pname.rank == rank) {
 568             found = true;
 569             break;
 570         }
 571     }
 572     if (!found) {
 573         
 574         free(msg);
 575         
 576         rc = PMIX_ERR_NOT_FOUND;
 577         goto error;
 578     }
 579     
 580 
 581 
 582     psave = PMIX_NEW(pmix_peer_t);
 583     if (NULL == psave) {
 584         free(msg);
 585         rc = PMIX_ERR_NOMEM;
 586         goto error;
 587     }
 588     
 589     if (1 == major) {
 590         psave->proc_type = PMIX_PROC_CLIENT | PMIX_PROC_V1;
 591     } else if (2 == major && 0 == minor) {
 592         psave->proc_type = PMIX_PROC_CLIENT | PMIX_PROC_V20;
 593     } else if (2 == major && 1 == minor) {
 594         psave->proc_type = PMIX_PROC_CLIENT | PMIX_PROC_V21;
 595     } else if (3 == major) {
 596         psave->proc_type = PMIX_PROC_CLIENT | PMIX_PROC_V3;
 597     } else {
 598         
 599         pmix_output_verbose(2, pmix_ptl_base_framework.framework_output,
 600                             "connection request from client of unrecognized version %s", version);
 601         free(msg);
 602         PMIX_RELEASE(psave);
 603         CLOSE_THE_SOCKET(pnd->sd);
 604         PMIX_RELEASE(pnd);
 605         return;
 606     }
 607     
 608     psave->protocol = pnd->protocol;
 609     
 610     PMIX_RETAIN(nptr);
 611     psave->nptr = nptr;
 612     PMIX_RETAIN(info);
 613     psave->info = info;
 614     
 615     psave->epilog.uid = info->uid;
 616     psave->epilog.gid = info->gid;
 617     nptr->epilog.uid = info->uid;
 618     nptr->epilog.gid = info->gid;
 619     info->proc_cnt++; 
 620     psave->sd = pnd->sd;
 621     if (0 > (psave->index = pmix_pointer_array_add(&pmix_server_globals.clients, psave))) {
 622         free(msg);
 623         info->proc_cnt--;
 624         PMIX_RELEASE(info);
 625         PMIX_RELEASE(psave);
 626         
 627         CLOSE_THE_SOCKET(pnd->sd);
 628         PMIX_RELEASE(pnd);
 629         return;
 630     }
 631     info->peerid = psave->index;
 632 
 633     
 634     nptr->compat.psec = pmix_psec_base_assign_module(sec);
 635     if (NULL == nptr->compat.psec) {
 636         free(msg);
 637         info->proc_cnt--;
 638         PMIX_RELEASE(info);
 639         pmix_pointer_array_set_item(&pmix_server_globals.clients, psave->index, NULL);
 640         PMIX_RELEASE(psave);
 641         
 642         goto error;
 643     }
 644 
 645     
 646     nptr->compat.bfrops = pmix_bfrops_base_assign_module(bfrops);
 647     if (NULL == nptr->compat.bfrops) {
 648         free(msg);
 649         info->proc_cnt--;
 650         PMIX_RELEASE(info);
 651         pmix_pointer_array_set_item(&pmix_server_globals.clients, psave->index, NULL);
 652         PMIX_RELEASE(psave);
 653        
 654         goto error;
 655     }
 656     
 657     nptr->compat.type = bftype;
 658 
 659     
 660     if (NULL != gds) {
 661         PMIX_INFO_LOAD(&ginfo, PMIX_GDS_MODULE, gds, PMIX_STRING);
 662         nptr->compat.gds = pmix_gds_base_assign_module(&ginfo, 1);
 663         PMIX_INFO_DESTRUCT(&ginfo);
 664     } else {
 665         nptr->compat.gds = pmix_gds_base_assign_module(NULL, 0);
 666     }
 667     if (NULL == nptr->compat.gds) {
 668         free(msg);
 669         info->proc_cnt--;
 670         pmix_pointer_array_set_item(&pmix_server_globals.clients, psave->index, NULL);
 671         PMIX_RELEASE(psave);
 672         
 673         goto error;
 674     }
 675 
 676     
 677 
 678     if (!nptr->version_stored) {
 679         PMIX_INFO_LOAD(&ginfo, PMIX_BFROPS_MODULE, nptr->compat.bfrops->version, PMIX_STRING);
 680         PMIX_GDS_CACHE_JOB_INFO(rc, pmix_globals.mypeer, nptr, &ginfo, 1);
 681         PMIX_INFO_DESTRUCT(&ginfo);
 682         nptr->version_stored = true;
 683     }
 684 
 685     
 686 
 687 
 688     nptr->compat.ptl = &pmix_ptl_usock_module;
 689 
 690     
 691     PMIX_PSEC_VALIDATE_CONNECTION(rc, psave, NULL, 0, NULL, 0, &cred);
 692     
 693     free(msg);
 694 
 695     if (PMIX_SUCCESS != rc) {
 696         pmix_output_verbose(2, pmix_ptl_base_framework.framework_output,
 697                             "validation of client credentials failed: %s",
 698                             PMIx_Error_string(rc));
 699         info->proc_cnt--;
 700         PMIX_RELEASE(info);
 701         pmix_pointer_array_set_item(&pmix_server_globals.clients, psave->index, NULL);
 702         PMIX_RELEASE(psave);
 703         
 704         CLOSE_THE_SOCKET(pnd->sd);
 705         PMIX_RELEASE(pnd);
 706         return;
 707     }
 708 
 709     
 710     if (PMIX_SUCCESS != (rc = pmix_ptl_base_send_blocking(pnd->sd, (char*)&psave->index, sizeof(int)))) {
 711         PMIX_ERROR_LOG(rc);
 712         info->proc_cnt--;
 713         PMIX_RELEASE(info);
 714         pmix_pointer_array_set_item(&pmix_server_globals.clients, psave->index, NULL);
 715         PMIX_RELEASE(psave);
 716         CLOSE_THE_SOCKET(pnd->sd);
 717         PMIX_RELEASE(pnd);
 718         return;
 719     }
 720 
 721     pmix_output_verbose(2, pmix_ptl_base_framework.framework_output,
 722                         "connect-ack from client completed");
 723 
 724     
 725     if (NULL != pmix_host_server.client_connected) {
 726         pmix_strncpy(proc.nspace, psave->info->pname.nspace, PMIX_MAX_NSLEN);
 727         proc.rank = psave->info->pname.rank;
 728         rc = pmix_host_server.client_connected(&proc, psave->info->server_object, NULL, NULL);
 729         if (PMIX_SUCCESS != rc && PMIX_OPERATION_SUCCEEDED != rc) {
 730             PMIX_ERROR_LOG(rc);
 731             info->proc_cnt--;
 732             PMIX_RELEASE(info);
 733             pmix_pointer_array_set_item(&pmix_server_globals.clients, psave->index, NULL);
 734             PMIX_RELEASE(psave);
 735             CLOSE_THE_SOCKET(pnd->sd);
 736         }
 737     }
 738 
 739     
 740     pmix_event_assign(&psave->recv_event, pmix_globals.evbase, pnd->sd,
 741                       EV_READ|EV_PERSIST, pmix_usock_recv_handler, psave);
 742     pmix_event_add(&psave->recv_event, NULL);
 743     psave->recv_ev_active = true;
 744     pmix_event_assign(&psave->send_event, pmix_globals.evbase, pnd->sd,
 745                       EV_WRITE|EV_PERSIST, pmix_usock_send_handler, psave);
 746     pmix_output_verbose(2, pmix_ptl_base_framework.framework_output,
 747                         "pmix:server client %s:%u has connected on socket %d",
 748                         psave->info->pname.nspace, psave->info->pname.rank, psave->sd);
 749 
 750     PMIX_RELEASE(pnd);
 751     return;
 752 
 753   error:
 754     
 755     if (PMIX_SUCCESS != pmix_ptl_base_send_blocking(pnd->sd, (char*)&rc, sizeof(int))) {
 756         PMIX_ERROR_LOG(rc);
 757     }
 758     CLOSE_THE_SOCKET(pnd->sd);
 759     PMIX_RELEASE(pnd);
 760     return;
 761 }