Here is a simple synchronous server for the protocol defined in
The example.mx File. Note that this server does not use advanced features such as asynchronous operation.
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
#include <minirpc/minirpc.h>
#include "example_server.h"
#define die(s, args...) do {fprintf(stderr, s"\n", ##args); abort();} while (0)
struct conn_data {
struct mrpc_connection *conn;
char *remote;
unsigned chosen;
int count;
};
mrpc_status_t do_choose(void *conn_data, struct mrpc_message *msg,
example_color_choice *in)
{
struct conn_data *data=conn_data;
unsigned i;
unsigned new=0;
for (i=0; i<in->acceptable.acceptable_len; i++)
new |= 1 << in->acceptable.acceptable_val[i];
data->chosen=new;
data->count=i;
return MINIRPC_OK;
}
mrpc_status_t do_get(void *conn_data, struct mrpc_message *msg,
example_count *out)
{
struct conn_data *data=conn_data;
*out=data->count;
return MINIRPC_OK;
}
static const struct example_server_operations ops = {
.choose_color = do_choose,
.get_num_colors = do_get,
.crayon_selected = NULL,
};
void *do_accept(void *set_data, struct mrpc_connection *conn,
struct sockaddr *from, socklen_t from_len)
{
struct conn_data *data;
char buf[256];
if (getnameinfo(from, from_len, buf, sizeof(buf), NULL, 0, 0)) {
mrpc_conn_close(conn);
return NULL;
}
example_server_set_operations(conn, &ops);
data=malloc(sizeof(*data));
memset(data, 0, sizeof(*data));
data->conn=conn;
data->remote=strndup(buf, sizeof(buf));
fprintf(stderr, "New connection from %s\n", data->remote);
return data;
}
void do_disconnect(void *conn_data, enum mrpc_disc_reason reason)
{
struct conn_data *data=conn_data;
const char *reason_str;
if (conn_data == NULL)
return;
switch (reason) {
case MRPC_DISC_USER:
reason_str="by application";
break;
case MRPC_DISC_CLOSED:
reason_str="by remote end";
break;
case MRPC_DISC_IOERR:
reason_str="due to I/O error";
break;
default:
reason_str="for unknown reason";
}
fprintf(stderr, "Connection to %s closed %s\n", data->remote,
reason_str);
free(data->remote);
free(data);
}
int main(int argc, char **argv)
{
struct mrpc_conn_set *set;
char *port;
int ret;
if (argc != 2) {
fprintf(stderr, "Usage: %s port\n", argv[0]);
exit(1);
}
port=argv[1];
if (mrpc_conn_set_create(&set, example_server, NULL))
die("Couldn't create connection set");
if (mrpc_set_accept_func(set, do_accept))
die("Couldn't set accept function");
if (mrpc_set_disconnect_func(set, do_disconnect))
die("Couldn't set disconnect function");
ret=mrpc_listen(set, AF_UNSPEC, NULL, &port);
if (ret)
die("Couldn't create listening socket: %s", strerror(ret));
mrpc_dispatcher_add(set);
mrpc_dispatch_loop(set);
return 0;
}