1/** \file
2 *  \brief Example application using THC stubs and language features
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_lang_service";
25
26/* --------------------- Client ------------------------------ */
27
28static void run_client(struct xmplthc_thc_client_binding_t *cl, int id)
29{
30    int i = 42 + id;
31    char *s = NULL;
32
33    while (true) {
34        cl->call_seq.myrpc(cl, i, &s);
35        free(s);
36    }
37
38}
39
40
41static void start_client(char *arg)
42{
43    errval_t err;
44
45    struct xmplthc_binding *b;
46    struct xmplthc_thc_client_binding_t *cl;
47
48    err = xmplthc_thc_connect_by_name(service_name,
49                                      get_default_waitset(),
50                                      IDC_BIND_FLAGS_DEFAULT,
51                                      &b);
52    if (err_is_fail(err)) {
53        USER_PANIC_ERR(err, "could not bind (thc)");
54    }
55
56    cl = malloc(sizeof(struct xmplthc_thc_client_binding_t));
57    assert(cl != NULL);
58
59    err = xmplthc_thc_init_client(cl, b, b);
60    if (err_is_fail(err)) {
61        USER_PANIC_ERR(err, "could not init client (thc)");
62    }
63
64    run_client(cl, atoi(arg));
65}
66
67
68/* --------------------- Server ------------------------------ */
69
70static void rx_xmplthc_myrpc(struct xmplthc_thc_service_binding_t *sv,
71                             int i)
72{
73    debug_printf("received xmplthc_myrpc_call: %d\n", i);
74
75    // send reply
76    char *s = malloc(20);
77    if (s != NULL) {
78        snprintf(s, 20, "!%d!", i);
79    }
80    sv->send.myrpc(sv, s);
81}
82
83
84
85
86static void run_server(struct xmplthc_thc_service_binding_t *sv)
87{
88    xmplthc_service_msg_t msg;
89    bool loop = true;
90
91    // this is the bitmap of messages we are interested in receiving
92    struct xmplthc_service_selector selector = {
93        .mymsg = 0,
94        .mycall = 0,
95        .myrpc = 1,
96    };
97
98    while (loop) {
99        // receive any message
100        sv->recv_any(sv, &msg, selector);
101
102        // dispatch it
103        switch(msg.msg) {
104        case xmplthc_myrpc:
105            rx_xmplthc_myrpc(sv, msg.args.myrpc.in.i);
106            break;
107        default:
108            debug_printf("unexpected message: %d\n", msg.msg);
109            loop = false;
110            break;
111        }
112    }
113
114}
115
116
117
118static void start_server(void)
119{
120
121    errval_t err;
122
123    struct xmplthc_thc_export_info e_info;
124    struct xmplthc_thc_service_binding_t *sv;
125    struct xmplthc_binding *b;
126    iref_t iref;
127
128    err = xmplthc_thc_export(&e_info, service_name,
129                             get_default_waitset(),
130                             IDC_EXPORT_FLAGS_DEFAULT,
131                             &iref);
132    if (err_is_fail(err)) {
133        USER_PANIC_ERR(err, "thc export failed");
134    }
135
136    do {
137
138        while (true) {
139
140            debug_printf("server: waiting for another connection\n");
141
142            err = xmplthc_thc_accept(&e_info, &b);
143            if (err_is_fail(err)) {
144                USER_PANIC_ERR(err, "thc accept failed");
145            }
146
147            sv = malloc(sizeof(struct xmplthc_thc_service_binding_t));
148            assert(sv != NULL);
149
150            err = xmplthc_thc_init_service(sv, b, b);
151            if (err_is_fail(err)) {
152                USER_PANIC_ERR(err, "thc init failed");
153            }
154
155            async run_server(sv);
156        }
157
158    } finish;
159}
160
161
162
163/* --------------------- Main ------------------------------ */
164
165int thcmain(int argc, char *argv[])
166{
167    if ((argc >= 2) && (strcmp(argv[1], "client") == 0)) {
168        start_client(argv[2]);
169    } else if ((argc >= 2) && (strcmp(argv[1], "server") == 0)) {
170        start_server();
171    } else {
172        printf("usage: %s client|server\n", argv[0]);
173        return EXIT_FAILURE;
174    }
175
176    return EXIT_SUCCESS;
177}
178