213 lines
4.0 KiB
C
213 lines
4.0 KiB
C
#include <transport.h>
|
|
#include <errno.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
struct client
|
|
{
|
|
bool connected, received;
|
|
const char *expected;
|
|
struct transport_handle h;
|
|
|
|
struct io
|
|
{
|
|
FILE *in, *out;
|
|
} io;
|
|
};
|
|
|
|
struct server
|
|
{
|
|
struct transport_handle h;
|
|
struct io io;
|
|
const char *expected;
|
|
bool received;
|
|
};
|
|
|
|
static int io_write(const void *const buf, const size_t n,
|
|
const struct io *const io)
|
|
{
|
|
FILE *const f = io->out;
|
|
const size_t w = fwrite(buf, 1, n, f);
|
|
|
|
return ferror(f) ? -1 : w;
|
|
}
|
|
|
|
static int io_read(void *const buf, const size_t n,
|
|
const struct io *const io)
|
|
{
|
|
FILE *const f = io->in;
|
|
const size_t w = fread(buf, 1, n, f);
|
|
|
|
return ferror(f) ? -1 : w;
|
|
}
|
|
|
|
static int client_write(const void *const buf, const size_t n, void *const arg)
|
|
{
|
|
struct client *const c = arg;
|
|
|
|
return io_write(buf, n, &c->io);
|
|
}
|
|
|
|
static int client_read(void *const buf, const size_t n, void *const arg)
|
|
{
|
|
struct client *const c = arg;
|
|
|
|
return io_read(buf, n, &c->io);
|
|
}
|
|
|
|
static void client_received(const struct transport_event *const ev,
|
|
void *const arg)
|
|
{
|
|
struct client *const c = arg;
|
|
|
|
if (ev->common.type == TRANSPORT_EVENT_TYPE_CONNECT)
|
|
c->connected = true;
|
|
else if (ev->common.type == TRANSPORT_EVENT_TYPE_DATA)
|
|
{
|
|
const struct transport_event_data *const d = &ev->u.data;
|
|
|
|
if (!strncmp(d->buf, c->expected, d->n))
|
|
c->received = true;
|
|
}
|
|
}
|
|
|
|
static int server_write(const void *const buf, const size_t n, void *const arg)
|
|
{
|
|
struct server *const s = arg;
|
|
|
|
return io_write(buf, n, &s->io);
|
|
}
|
|
|
|
static int server_read(void *const buf, const size_t n, void *const arg)
|
|
{
|
|
struct server *const s = arg;
|
|
|
|
return io_read(buf, n, &s->io);
|
|
}
|
|
|
|
static void server_received(const struct transport_event *const ev,
|
|
void *const arg)
|
|
{
|
|
struct server *const s = arg;
|
|
|
|
if (ev->common.type == TRANSPORT_EVENT_TYPE_DATA)
|
|
{
|
|
const struct transport_event_data *const d = &ev->u.data;
|
|
|
|
if (!strncmp(d->buf, s->expected, d->n))
|
|
s->received = true;
|
|
}
|
|
}
|
|
|
|
static int loop(struct server *const s, struct client *const c)
|
|
{
|
|
if (transport_update(&s->h)
|
|
|| !freopen("client", "w+b", s->io.in))
|
|
return -1;
|
|
|
|
rewind(s->io.out);
|
|
|
|
if (transport_update(&c->h)
|
|
|| !freopen("server", "w+b", c->io.in))
|
|
return -1;
|
|
|
|
rewind(c->io.out);
|
|
return 0;
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
int ret = EXIT_FAILURE;
|
|
FILE *const cf = fopen("client", "w+b"),
|
|
*const sf = fopen("server", "w+b");
|
|
|
|
if (!cf)
|
|
{
|
|
perror("fopen(3) client");
|
|
goto end;
|
|
}
|
|
else if (!sf)
|
|
{
|
|
perror("fopen(3) server");
|
|
goto end;
|
|
}
|
|
|
|
struct client c =
|
|
{
|
|
.h =
|
|
{
|
|
.cfg =
|
|
{
|
|
.arg = &c,
|
|
.read = client_read,
|
|
.write = client_write,
|
|
.received = client_received
|
|
}
|
|
},
|
|
|
|
.io =
|
|
{
|
|
.in = sf,
|
|
.out = cf
|
|
},
|
|
|
|
.expected = "hi there!"
|
|
};
|
|
|
|
struct server s =
|
|
{
|
|
.h =
|
|
{
|
|
.cfg =
|
|
{
|
|
.arg = &s,
|
|
.read = server_read,
|
|
.write = server_write,
|
|
.received = server_received,
|
|
}
|
|
},
|
|
|
|
.io =
|
|
{
|
|
.in = cf,
|
|
.out = sf
|
|
},
|
|
|
|
.expected = "hello"
|
|
};
|
|
|
|
if (transport_connect(&c.h))
|
|
goto end;
|
|
|
|
while (!c.connected)
|
|
if (loop(&s, &c))
|
|
goto end;
|
|
|
|
if (transport_send(&c.h, s.expected, strlen(s.expected)))
|
|
goto end;
|
|
|
|
while (!s.received)
|
|
if (loop(&s, &c))
|
|
goto end;
|
|
|
|
if (transport_send(&s.h, c.expected, strlen(c.expected)))
|
|
goto end;
|
|
|
|
while (!c.received)
|
|
if (loop(&s, &c))
|
|
goto end;
|
|
|
|
ret = EXIT_SUCCESS;
|
|
|
|
end:
|
|
if (cf)
|
|
fclose(cf);
|
|
|
|
if (sf)
|
|
fclose(sf);
|
|
|
|
return ret;
|
|
}
|