1/** \file
2 *  \brief Example application using THC 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, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
12 */
13
14#include <stdio.h>
15#include <string.h>
16
17#include <barrelfish/barrelfish.h>
18
19#include <thc/thc.h>
20
21#include <if/xmplthc_defs.h>
22#include <if/xmplthc_thc.h>
23
24const char *service_name = "xmplthc_binding_service";
25
26/* --------------------- Client ------------------------------ */
27
28static void run_client(struct xmplthc_thc_client_binding_t *cl)
29{
30    int i = 42;
31
32    char s[512];
33
34    // regular message
35    cl->send.mymsg(cl, i);
36    debug_printf("client: sent msg: %d\n", i);
37
38    // call/response
39    cl->send.mycall(cl, i);
40    debug_printf("client: sent mycall: %d\n", i);
41    cl->recv.myresponse(cl, s);
42    debug_printf("client: received myresponse: '%s'\n", s);
43
44    // rpc as call/response
45    cl->send.myrpc(cl, i);
46    debug_printf("client: sent myrpc call msg: %d\n", i);
47    cl->recv.myrpc(cl, s);
48    debug_printf("client: received myrpc response msg: '%s'\n", s);
49
50    // rpc
51    cl->call_seq.myrpc(cl, i, s);
52    debug_printf("client: returned from myrpc(%d, '%s')\n", i, s);
53
54    debug_printf("finished client\n");
55}
56
57
58static void start_client(void)
59{
60    errval_t err;
61
62    struct xmplthc_binding *b;
63    struct xmplthc_thc_client_binding_t *cl;
64
65    err = xmplthc_thc_connect_by_name(service_name,
66                                      get_default_waitset(),
67                                      IDC_BIND_FLAGS_DEFAULT,
68                                      &b);
69    if (err_is_fail(err)) {
70        USER_PANIC_ERR(err, "could not bind (thc)");
71    }
72
73    cl = malloc(sizeof(struct xmplthc_thc_client_binding_t));
74    assert(cl != NULL);
75
76    err = xmplthc_thc_init_client(cl, b, b);
77    if (err_is_fail(err)) {
78        USER_PANIC_ERR(err, "could not init client (thc)");
79    }
80
81    run_client(cl);
82}
83
84
85/* --------------------- Server ------------------------------ */
86
87static void rx_xmplthc_myrpc(struct xmplthc_thc_service_binding_t *sv,
88                             int i)
89{
90    debug_printf("server: received xmplthc_myrpc_call: %d\n", i);
91
92    // send reply
93    char *s = malloc(20);
94    if (s != NULL) {
95        snprintf(s, 20, "!%d!", i);
96    }
97    sv->send.myrpc(sv, s);
98}
99
100
101
102static void rx_xmplthc_mycall(struct xmplthc_thc_service_binding_t *sv,
103                              int i)
104{
105    debug_printf("server: received xmplthc_mycall: %d\n", i);
106
107    // send reply
108    char *s = malloc(20);
109    if (s != NULL) {
110        snprintf(s, 20, "!%d!", i);
111    }
112    sv->send.myresponse(sv, s);
113}
114
115
116static void rx_xmplthc_mymsg(struct xmplthc_thc_service_binding_t *sv,
117                           int i)
118{
119    debug_printf("server: received xmplthc_msg: %d\n", i);
120}
121
122static void run_server(struct xmplthc_thc_service_binding_t *sv)
123{
124    xmplthc_service_msg_t msg;
125    bool loop = true;
126
127    // this is the bitmap of messages we are interested in receiving
128    struct xmplthc_service_selector selector = {
129        .mymsg = 1,
130        .mycall = 1,
131        .myrpc = 1,
132    };
133
134    while (loop) {
135
136        // receive any message
137        sv->recv_any(sv, &msg, selector);
138
139        // dispatch it
140        switch(msg.msg) {
141        case xmplthc_mymsg:
142            rx_xmplthc_mymsg(sv, msg.args.mymsg.i);
143            break;
144        case xmplthc_mycall:
145            rx_xmplthc_mycall(sv, msg.args.mycall.i);
146            break;
147        case xmplthc_myrpc:
148            rx_xmplthc_myrpc(sv, msg.args.myrpc.in.i);
149            break;
150        default:
151            debug_printf("unexpected message: %d\n", msg.msg);
152            loop = false;
153            break;
154        }
155    }
156}
157
158
159
160static void start_server(void)
161{
162
163    errval_t err;
164
165    struct xmplthc_thc_export_info e_info;
166    struct xmplthc_thc_service_binding_t *sv;
167    struct xmplthc_binding *b;
168    iref_t iref;
169
170    err = xmplthc_thc_export(&e_info, service_name,
171                             get_default_waitset(),
172                             IDC_EXPORT_FLAGS_DEFAULT,
173                             &iref);
174    if (err_is_fail(err)) {
175        USER_PANIC_ERR(err, "thc export failed");
176    }
177
178    err = xmplthc_thc_accept(&e_info, &b);
179    if (err_is_fail(err)) {
180        USER_PANIC_ERR(err, "thc accept failed");
181    }
182
183    sv = malloc(sizeof(struct xmplthc_thc_service_binding_t));
184    assert(sv != NULL);
185
186    err = xmplthc_thc_init_service(sv, b, b);
187    if (err_is_fail(err)) {
188        USER_PANIC_ERR(err, "thc init failed");
189    }
190
191    run_server(sv);
192}
193
194
195
196/* --------------------- Main ------------------------------ */
197int main(int argc, char *argv[])
198{
199    if ((argc >= 2) && (strcmp(argv[1], "client") == 0)) {
200        start_client();
201    } else if ((argc >= 2) && (strcmp(argv[1], "server") == 0)) {
202        start_server();
203    } else {
204        printf("usage: %s client|server\n", argv[0]);
205        return EXIT_FAILURE;
206    }
207
208    return EXIT_SUCCESS;
209}
210