1/* 2 * Copyright 2016, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(D61_BSD) 11 */ 12 13#include <assert.h> 14#include <stdio.h> 15#include <stdlib.h> 16#include <string.h> 17#include <sel4/sel4.h> 18 19#include <refos-rpc/proc_client.h> 20#include <refos-rpc/proc_client_helper.h> 21#include <refos-rpc/serv_client.h> 22#include <refos-rpc/serv_client_helper.h> 23#include <refos-util/cspace.h> 24#include <refos-util/dprintf.h> 25 26/*! @brief Special helper function to handle the fact that the process server is connectionless. */ 27static bool 28serv_special_connectless_server(seL4_CPtr anon) { 29 return (anon == REFOS_NAMESERV_EP || anon == REFOS_PROCSERV_EP); 30} 31 32static serv_connection_t 33serv_connect_internal(char *serverPath, bool paramBuffer) 34{ 35 _svprintf("Connecting to server [%s]...\n", serverPath); 36 serv_connection_t sc; 37 memset(&sc, 0, sizeof(serv_connection_t)); 38 sc.error = EINVALID; 39 40 /* Resolve server path to find the server's anon cap. */ 41 _svprintf(" Querying nameserv to find anon cap for [%s]....\n", serverPath); 42 sc.serverMountPoint = nsv_resolve(serverPath); 43 if (!sc.serverMountPoint.success || ROS_ERRNO() != ESUCCESS) { 44 _svprintf(" WARNING: Server not found.\n"); 45 sc.error = ESERVERNOTFOUND; 46 goto exit1; 47 } 48 49 _svprintf(" Result path prefix [%s] anon 0x%x dspace [%s]....\n", 50 sc.serverMountPoint.nameservPathPrefix, sc.serverMountPoint.serverAnon, 51 sc.serverMountPoint.dspaceName); 52 if (serv_special_connectless_server(sc.serverMountPoint.serverAnon)) { 53 /* Connectionless server. */ 54 _svprintf(" Known connectionless server detected.\n"); 55 sc.connectionLess = true; 56 sc.serverSession = sc.serverMountPoint.serverAnon; 57 sc.error = ESUCCESS; 58 return sc; 59 } else { 60 /* Make connection request to server using the anon cap. */ 61 _svprintf(" Make connection request to server [%s] using the anon cap 0x%x...\n", 62 serverPath, sc.serverMountPoint.serverAnon); 63 sc.serverSession = serv_connect_direct(sc.serverMountPoint.serverAnon, REFOS_LIVENESS, 64 &sc.error); 65 } 66 if (!sc.serverSession || sc.error != ESUCCESS) { 67 _svprintf(" WARNING: Failed to anonymously connect to server.\n"); 68 goto exit2; 69 } 70 71 /* Try pinging the server. */ 72 int error = serv_ping(sc.serverSession); 73 if (error) { 74 _svprintf(" WARNING: Failed to ping file server.\n"); 75 sc.error = error; 76 goto exit3; 77 } 78 79 /* Set up the parameter buffer between client (ie. us) and server. */ 80 if (paramBuffer) { 81 sc.paramBuffer = data_open_map(REFOS_PROCSERV_EP, "anon", 0, 0, 82 PROCESS_PARAM_DEFAULTSIZE, -1); 83 if (sc.paramBuffer.err != ESUCCESS) { 84 _svprintf(" WARNING: Failed to create param buffer dspace.\n"); 85 sc.error = sc.paramBuffer.err; 86 goto exit3; 87 } 88 assert(sc.paramBuffer.window && sc.paramBuffer.dataspace); 89 assert(sc.paramBuffer.vaddr != NULL); 90 91 /* Set this parameter buffer on server. */ 92 error = serv_set_param_buffer(sc.serverSession, sc.paramBuffer.dataspace, 93 PROCESS_PARAM_DEFAULTSIZE); 94 if (error) { 95 _svprintf(" Failed to set remote server parameter buffer."); 96 sc.error = error; 97 goto exit4; 98 } 99 } else { 100 sc.paramBuffer.err = -1; 101 } 102 103 _svprintf("Successfully connected to server [%s]!\n", serverPath); 104 sc.error = ESUCCESS; 105 return sc; 106 107 /* Exit stack. */ 108exit4: 109 assert(sc.paramBuffer.err == ESUCCESS); 110 data_mapping_release(sc.paramBuffer); 111exit3: 112 assert(sc.serverSession); 113 if (!sc.connectionLess) { 114 serv_disconnect_direct(sc.serverSession); 115 seL4_CNode_Delete(REFOS_CSPACE, sc.serverSession, REFOS_CDEPTH); 116 csfree(sc.serverSession); 117 } 118exit2: 119 nsv_mountpoint_release(&sc.serverMountPoint); 120exit1: 121 assert(sc.error != ESUCCESS); 122 return sc; 123} 124 125serv_connection_t 126serv_connect(char *serverPath) 127{ 128 return serv_connect_internal(serverPath, true); 129} 130 131serv_connection_t 132serv_connect_no_pbuffer(char *serverPath) 133{ 134 return serv_connect_internal(serverPath, false); 135} 136 137void 138serv_disconnect(serv_connection_t *sc) 139{ 140 if (sc == NULL || sc->error != ESUCCESS) { 141 return; 142 } 143 144 /* Clean up the parameter buffer. */ 145 if (sc->paramBuffer.err == ESUCCESS && sc->paramBuffer.vaddr != NULL) { 146 data_mapping_release(sc->paramBuffer); 147 } 148 149 /* Disconnect session. */ 150 if (sc->serverSession && !sc->connectionLess) { 151 serv_disconnect_direct(sc->serverSession); 152 csfree_delete(sc->serverSession); 153 } 154 155 /* Release the mountpoint. */ 156 nsv_mountpoint_release(&sc->serverMountPoint); 157 memset(sc, 0, sizeof(serv_connection_t)); 158} 159