static serv_connection_t serv_connect_internal(char *serverPath, bool paramBuffer) { _svprintf("Connecting to server [%s]...\n", serverPath); serv_connection_t sc; memset(&sc, 0, sizeof(serv_connection_t)); sc.error = EINVALID; /* Resolve server path to find the server's anon cap. */ _svprintf(" Querying nameserv to find anon cap for [%s]....\n", serverPath); printf(" Querying nameserv to find anon cap for [%s]....\n", serverPath); sc.serverMountPoint = nsv_resolve(serverPath); if (!sc.serverMountPoint.success || ROS_ERRNO() != ESUCCESS) { _svprintf(" WARNING: Server not found.\n"); printf(" WARNING: Server not found.\n"); sc.error = ESERVERNOTFOUND; goto exit1; } _svprintf(" Result path prefix [%s] anon 0x%x dspace [%s]....\n", sc.serverMountPoint.nameservPathPrefix, sc.serverMountPoint.serverAnon, sc.serverMountPoint.dspaceName); printf(" Result path prefix [%s] anon 0x%x dspace [%s]....\n", sc.serverMountPoint.nameservPathPrefix, sc.serverMountPoint.serverAnon, sc.serverMountPoint.dspaceName); if (serv_special_connectless_server(sc.serverMountPoint.serverAnon)) { /* Connectionless server. */ _svprintf(" Known connectionless server detected.\n"); printf(" Known connectionless server detected.\n"); sc.connectionLess = true; sc.serverSession = sc.serverMountPoint.serverAnon; sc.error = ESUCCESS; return sc; } else { /* Make connection request to server using the anon cap. */ _svprintf(" Make connection request to server [%s] using the anon cap 0x%x...\n", serverPath, sc.serverMountPoint.serverAnon); printf(" Make connection request to server [%s] using the anon cap 0x%x...\n", serverPath, sc.serverMountPoint.serverAnon); sc.serverSession = serv_connect_direct(sc.serverMountPoint.serverAnon, REFOS_LIVENESS, &sc.error); } if (!sc.serverSession || sc.error != ESUCCESS) { _svprintf(" WARNING: Failed to anonymously connect to server.\n"); printf(" WARNING: Failed to anonymously connect to server.\n"); goto exit2; } /* Try pinging the server. */ int error = serv_ping(sc.serverSession); if (error) { _svprintf(" WARNING: Failed to ping file server.\n"); printf(" WARNING: Failed to ping file server.\n"); sc.error = error; goto exit3; } /* Set up the parameter buffer between client (ie. us) and server. */ if (paramBuffer) { sc.paramBuffer = data_open_map(REFOS_PROCSERV_EP, "anon", 0, 0, PROCESS_PARAM_DEFAULTSIZE, -1); if (sc.paramBuffer.err != ESUCCESS) { _svprintf(" WARNING: Failed to create param buffer dspace.\n"); printf(" WARNING: Failed to create param buffer dspace.\n"); sc.error = sc.paramBuffer.err; goto exit3; } assert(sc.paramBuffer.window && sc.paramBuffer.dataspace); assert(sc.paramBuffer.vaddr != NULL); /* Set this parameter buffer on server. */ error = serv_set_param_buffer(sc.serverSession, sc.paramBuffer.dataspace, PROCESS_PARAM_DEFAULTSIZE); if (error) { _svprintf(" Failed to set remote server parameter buffer."); printf(" Failed to set remote server parameter buffer."); sc.error = error; goto exit4; } } else { sc.paramBuffer.err = -1; } _svprintf("Successfully connected to server [%s]!\n", serverPath); printf("Successfully connected to server [%s]!\n", serverPath); sc.error = ESUCCESS; return sc; /* Exit stack. */ exit4: assert(sc.paramBuffer.err == ESUCCESS); data_mapping_release(sc.paramBuffer); exit3: assert(sc.serverSession); if (!sc.connectionLess) { serv_disconnect_direct(sc.serverSession); seL4_CNode_Delete(REFOS_CSPACE, sc.serverSession, REFOS_CDEPTH); csfree(sc.serverSession); } exit2: nsv_mountpoint_release(&sc.serverMountPoint); exit1: assert(sc.error != ESUCCESS); return sc; }
int srv_common_init(srv_common_t *s, srv_common_config_t config) { assert(s); dprintf("Initialising %s common server state...\n", config.serverName); memset(s, 0, sizeof(srv_common_t)); s->config = config; /* Create sync anon EP. */ dprintf(" creating %s anon endpoint...\n", config.serverName); s->anonEP = proc_new_endpoint(); if (!s->anonEP) { ROS_ERROR("srv_common_init could not create endpoint for %s.", config.serverName); return ENOMEM; } /* Create async EP. */ dprintf(" creating %s async endpoint...\n", config.serverName); s->notifyAsyncEP = proc_new_async_endpoint(); if (!s->notifyAsyncEP) { ROS_ERROR("srv_common_init could not create async endpoint."); return ENOMEM; } /* Mint badged async EP. */ dprintf(" creating async death and/or fault notification badged EP...\n"); s->notifyClientFaultDeathAsyncEP = srv_mint(config.faultDeathNotifyBadge, s->notifyAsyncEP); if (!s->notifyClientFaultDeathAsyncEP) { ROS_ERROR("srv_common_init could not create minted async endpoint."); return EINVALID; } /* Bind the notification AEP. */ dprintf(" binding notification AEP...\n"); int error = seL4_TCB_BindNotification(REFOS_THREAD_TCB, s->notifyAsyncEP); if (error != seL4_NoError) { ROS_ERROR("srv_common_init could not bind async endpoint."); return EINVALID; } /* Register ourselves under our mountpoint name. */ if (config.mountPointPath != NULL) { dprintf(" registering under the mountpoint [%s]...\n", config.mountPointPath); error = nsv_register(config.nameServEP, config.mountPointPath, s->anonEP); if (error != ESUCCESS) { ROS_ERROR("srv_common_init could not register anon ep."); return error; } } /* Initialise client table. */ if (config.maxClients > 0) { dprintf(" initialising client table for %s...\n", config.serverName); client_table_init(&s->clientTable, config.maxClients, config.clientBadgeBase, config.clientMagic, s->anonEP); dprintf(" initialising client table default handlers for %s...\n", config.serverName); s->ctable_connect_direct_handler = srv_ctable_connect_direct_handler; s->ctable_set_param_buffer_handler = srv_ctable_set_param_buffer_handler; s->ctable_disconnect_direct_handler = srv_ctable_disconnect_direct_handler; } /* Set up our server --> process server notification buffer. */ if (config.notificationBufferSize > 0) { /* Open and map the notification buffer on our side. */ dprintf(" initialising notification buffer for %s...\n", config.serverName); s->notifyBuffer = data_open_map(REFOS_PROCSERV_EP, "anon", 0, 0, config.notificationBufferSize, -1); if (s->notifyBuffer.err != ESUCCESS) { ROS_ERROR("srv_common_init failed to open & map anon dspace for notifications."); return s->notifyBuffer.err; } /* Share and set the notification buffer on the procserv side. */ assert(s->notifyBuffer.dataspace); error = proc_notification_buffer(s->notifyBuffer.dataspace); if (error != ESUCCESS) { ROS_ERROR("srv_common_init failed to set notification buffer."); return error; } s->notifyBufferStart = 0; } /* Set up our server --> process server parameter buffer. */ if (config.paramBufferSize > 0) { dprintf(" initialising procserv param buffer for %s...\n", config.serverName); s->procServParamBuffer = data_open_map(REFOS_PROCSERV_EP, "anon", 0, 0, config.paramBufferSize, -1); if (s->procServParamBuffer.err != ESUCCESS) { ROS_ERROR("srv_common_init failed to open & map anon dspace for param buffer."); return s->procServParamBuffer.err; } error = proc_set_parambuffer(s->procServParamBuffer.dataspace, config.paramBufferSize); if (error != ESUCCESS) { ROS_ERROR("srv_common_init failed to set procserv param buffer."); return error; } } s->magic = SRV_MAGIC; return ESUCCESS; }