#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <pthread.h>
#include <unistd.h>
#include "../honey_badger_bindings.h"
void *quic_accept_process(void *arg)
{
struct
{
struct QuicNetworkOpaque *net;
struct QuicPeerConnectionsOpaque *peer_connections;
size_t node_index;
} *params = arg;
char *returned_addr;
NetworkErrorCode e = quic_accept(params->net, params->peer_connections, &returned_addr);
if (e != NetworkSuccess)
{
printf("Error accepting connection for node %zu, error code: %d\n", params->node_index, e);
pthread_exit(NULL);
}
else
{
printf("Node %zu accepted connection from %s\n", params->node_index, returned_addr);
free_quic_addr(returned_addr);
}
return NULL;
}
void *quic_recv_process(void *arg)
{
struct
{
struct QuicPeerConnectionsOpaque *peer_connections;
char *addr;
size_t node_index;
} *params = arg;
struct ByteSlice msg;
NetworkErrorCode e = quic_receive_from_sync(params->peer_connections, params->addr, &msg);
if (e != NetworkSuccess)
{
printf("Error recv from %s, error code: %d\n", params->addr, e);
pthread_exit(NULL);
}
printf("Node %zu Received from %s: %s\n", params->node_index, params->addr, msg.pointer);
free_bytes_slice(msg);
return NULL;
}
void quic_test()
{
init_tls();
struct QuicPeerConnectionsOpaque *peer_connection1;
struct QuicPeerConnectionsOpaque *peer_connection2;
struct QuicPeerConnectionsOpaque *peer_connection3;
struct QuicNetworkOpaque *quic_node1 = new_quic_network(&peer_connection1);
struct QuicNetworkOpaque *quic_node2 = new_quic_network(&peer_connection2);
struct QuicNetworkOpaque *quic_node3 = new_quic_network(&peer_connection3);
char addr1[] = "127.0.0.1:9090";
char addr2[] = "127.0.0.1:9091";
char addr3[] = "127.0.0.1:9092";
NetworkErrorCode e = quic_listen(quic_node1, addr1);
if (e != NetworkSuccess)
{
printf("Error starting net1, error code: %d\n", e);
exit(1);
}
e = quic_listen(quic_node2, addr2);
if (e != NetworkSuccess)
{
printf("Error starting net2, error code: %d\n", e);
exit(1);
}
e = quic_listen(quic_node3, addr3);
if (e != NetworkSuccess)
{
printf("Error starting net2, error code: %d\n", e);
exit(1);
}
pthread_t acc_thread2, acc_thread3;
struct QuicAcceptArgs
{
struct QuicNetworkOpaque *quic_node;
struct QuicPeerConnectionsOpaque *peer_connections;
size_t node_index;
};
struct QuicAcceptArgs acc_args2 = {
.quic_node = quic_node2,
.peer_connections = peer_connection2,
.node_index = 2,
};
struct QuicAcceptArgs acc_args3 = {
.quic_node = quic_node3,
.peer_connections = peer_connection3,
.node_index = 3,
};
pthread_create(&acc_thread2, NULL, quic_accept_process, (void *)&acc_args2);
pthread_create(&acc_thread3, NULL, quic_accept_process, (void *)&acc_args3);
e = quic_connect(quic_node1, peer_connection1, addr2);
if (e != NetworkSuccess)
{
printf("Error connecting to addr: %s, error code: %d\n", addr2, e);
exit(1);
}
printf("Node1 connected to addr: %s\n", addr2);
e = quic_connect(quic_node1, peer_connection1, addr3);
if (e != NetworkSuccess)
{
printf("Error connecting to addr: %s, error code: %d\n", addr3, e);
exit(1);
}
printf("Node1 connected to addr: %s\n", addr3);
pthread_join(acc_thread2, NULL);
pthread_join(acc_thread3, NULL);
pthread_t recv_thread2, recv_thread3;
struct QuicRecvArgs
{
struct QuicPeerConnectionsOpaque *peer_connections;
char *addr;
size_t node_index;
};
struct QuicRecvArgs recv_args2 = {
.peer_connections = peer_connection1,
.addr = addr3,
.node_index = 1};
struct QuicRecvArgs recv_args3 = {
.peer_connections = peer_connection2,
.addr = addr1,
.node_index = 2};
pthread_create(&recv_thread2, NULL, quic_recv_process, (void *)&recv_args2);
pthread_create(&recv_thread3, NULL, quic_recv_process, (void *)&recv_args3);
char myString[] = "Hello from node1";
struct ByteSlice msg;
msg.pointer = (uint8_t *)myString;
msg.len = strlen(myString) + 1;
quic_send(peer_connection1, addr2, msg);
char myString2[] = "Hello from node3";
struct ByteSlice msg2;
msg2.pointer = (uint8_t *)myString2;
msg2.len = strlen(myString2) + 1;
quic_send(peer_connection3, addr1, msg2);
pthread_join(recv_thread2, NULL);
pthread_join(recv_thread3, NULL);
free_quic_peer_connections(peer_connection1);
free_quic_peer_connections(peer_connection2);
free_quic_peer_connections(peer_connection3);
NetworkOpaque *hb_net1 = quic_into_hb_network(&quic_node1);
NetworkOpaque *hb_net2 = quic_into_hb_network(&quic_node2);
NetworkOpaque *hb_net3 = quic_into_hb_network(&quic_node3);
assert(quic_node1 == NULL);
assert(quic_node2 == NULL);
assert(quic_node3 == NULL);
free_network(hb_net1);
free_network(hb_net2);
free_network(hb_net3);
}
int main()
{
quic_test();
return 0;
}