1/** \file 2 * \brief Example rpc application using call/response stubs 3 */ 4 5/* 6 * Copyright (c) 2010, ETH Zurich. 7 * All rights reserved. 8 * 9 * This file is distributed under the terms in the attached LICENSE file. 10 * If you do not find this file, copies can be found by writing to: 11 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 12 */ 13 14#include <stdio.h> 15#include <string.h> 16 17#include <barrelfish/barrelfish.h> 18#include <barrelfish/nameservice_client.h> 19 20#include <if/xmplrpc_defs.h> 21 22const char *service_name = "xmplrpc_msg_service"; 23 24/* --------------------- Client ------------------------------ */ 25 26static void rx_myrpc_response(struct xmplrpc_binding *b, const char *s) 27{ 28 debug_printf("client: rx_myrpc_response called: %s\n", s); 29 30 // no need to free s 31} 32 33 34static void send_myrpc_call_cb(void *a) 35{ 36 debug_printf("client: myrpc_call sent successfully\n"); 37} 38 39static void send_myrpc_call(void *a) 40{ 41 errval_t err; 42 43 debug_printf("client: sending mycall\n"); 44 45 struct xmplrpc_binding *b = (struct xmplrpc_binding *)a; 46 47 struct event_closure txcont = MKCONT(send_myrpc_call_cb, b); 48 49 err = xmplrpc_myrpc_call__tx(b, txcont, 42); 50 51 if (err_is_fail(err)) { 52 if (err_no(err) == FLOUNDER_ERR_TX_BUSY) { 53 debug_printf("client: re-sending mycall\n"); 54 struct waitset *ws = get_default_waitset(); 55 txcont = MKCONT(send_myrpc_call, b); 56 err = b->register_send(b, ws, txcont); 57 if (err_is_fail(err)) { 58 // note that only one continuation may be registered at a time 59 DEBUG_ERR(err, "register_send on binding failed!"); 60 } 61 } else { 62 DEBUG_ERR(err, "error sending mycall message\n"); 63 } 64 } 65} 66 67struct xmplrpc_rx_vtbl c_rx_vtbl = { 68 .myrpc_response = rx_myrpc_response, 69}; 70 71static void bind_cb(void *st, errval_t err, struct xmplrpc_binding *b) 72{ 73 if (err_is_fail(err)) { 74 USER_PANIC_ERR(err, "bind failed"); 75 } 76 77 b->rx_vtbl = c_rx_vtbl; 78 79 send_myrpc_call(b); 80} 81 82 83static void start_client(void) 84{ 85 errval_t err; 86 iref_t iref; 87 88 err = nameservice_blocking_lookup(service_name, &iref); 89 if (err_is_fail(err)) { 90 USER_PANIC_ERR(err, "nameservice_blocking_lookup failed"); 91 } 92 93 err = xmplrpc_bind(iref, 94 bind_cb, 95 NULL /* state for bind_cb */, 96 get_default_waitset(), 97 IDC_BIND_FLAGS_DEFAULT); 98 if (err_is_fail(err)) { 99 USER_PANIC_ERR(err, "bind failed"); 100 } 101} 102 103/* --------------------- Server ------------------------------ */ 104 105struct server_state { 106 struct xmplrpc_binding *b; 107 char *s; 108}; 109 110static void free_st(struct server_state* st) 111{ 112 if (st->s != NULL) free(st->s); 113 free(st); 114} 115 116static void send_myrpc_response_cb(void *a) 117{ 118 struct server_state *st = (struct server_state*)a; 119 120 debug_printf("server: myresponse sent succesfully\n"); 121 122 free_st(st); 123} 124 125static void send_myrpc_response(void *a) 126{ 127 errval_t err; 128 struct server_state *st = (struct server_state*)a; 129 130 debug_printf("server: sending myresponse\n"); 131 132 struct event_closure txcont = MKCONT(send_myrpc_response_cb, st); 133 err = xmplrpc_myrpc_response__tx(st->b, txcont, st->s); 134 135 if (err_is_fail(err)) { 136 if (err_no(err) == FLOUNDER_ERR_TX_BUSY) { 137 debug_printf("server: re-sending myresponse\n"); 138 struct waitset *ws = get_default_waitset(); 139 txcont = MKCONT(send_myrpc_response, st); 140 err = st->b->register_send(st->b, ws, txcont); 141 if (err_is_fail(err)) { 142 // note that only one continuation may be registered at a time 143 DEBUG_ERR(err, "register_send on binding failed!"); 144 free_st(st); 145 } 146 } else { 147 DEBUG_ERR(err, "error sending mycall message\n"); 148 free_st(st); 149 } 150 } 151} 152 153static void rx_myrpc_call(struct xmplrpc_binding *b, int i) 154{ 155 debug_printf("server: received myrpc_call: %d\n", i); 156 157 // prepare and send reply 158 159 struct server_state *st = malloc(sizeof(struct server_state)); 160 if (st == NULL) { 161 USER_PANIC("cannot reply, out of memory"); 162 } 163 164 st->b = b; 165 st->s = malloc(20); 166 if (st->s != NULL) { 167 snprintf(st->s, 20, "!%d!", i); 168 } 169 170 send_myrpc_response(st); 171} 172 173static struct xmplrpc_rx_vtbl s_rx_vtbl = { 174 .myrpc_call = rx_myrpc_call, 175}; 176 177static errval_t connect_cb(void *st, struct xmplrpc_binding *b) 178{ 179 b->rx_vtbl = s_rx_vtbl; 180 181 return SYS_ERR_OK; 182} 183 184static void export_cb(void *st, errval_t err, iref_t iref) 185{ 186 if (err_is_fail(err)) { 187 USER_PANIC_ERR(err, "export failed"); 188 } 189 190 err = nameservice_register(service_name, iref); 191 if (err_is_fail(err)) { 192 USER_PANIC_ERR(err, "nameservice_register failed"); 193 } 194} 195 196static void start_server(void) 197{ 198 errval_t err; 199 200 err = xmplrpc_export(NULL /* state pointer for connect/export callbacks */, 201 export_cb, connect_cb, 202 get_default_waitset(), 203 IDC_EXPORT_FLAGS_DEFAULT); 204 if (err_is_fail(err)) { 205 USER_PANIC_ERR(err, "export failed"); 206 } 207} 208 209 210 211/* --------------------- Main ------------------------------ */ 212 213int main(int argc, char *argv[]) 214{ 215 errval_t err; 216 217 if ((argc >= 2) && (strcmp(argv[1], "client") == 0)) { 218 start_client(); 219 } else if ((argc >= 2) && (strcmp(argv[1], "server") == 0)) { 220 start_server(); 221 } else { 222 printf("usage: %s client|server\n", argv[0]); 223 return EXIT_FAILURE; 224 } 225 226 struct waitset *ws = get_default_waitset(); 227 while (1) { 228 err = event_dispatch(ws); 229 if (err_is_fail(err)) { 230 DEBUG_ERR(err, "in event_dispatch"); 231 break; 232 } 233 } 234 235 return EXIT_FAILURE; 236} 237