Changeset - 1f2d007ac1cc
examples/0_three_forward/amy.exe
Show inline comments
 
deleted file
 
binary diff not shown
examples/0_three_forward/bob.exe
Show inline comments
 
deleted file
 
binary diff not shown
examples/1_load_pdl/amy.exe
Show inline comments
 
deleted file
 
binary diff not shown
examples/1_load_pdl/bob.exe
Show inline comments
 
deleted file
 
binary diff not shown
examples/1_socketlike/amy.c
Show inline comments
 
file renamed from examples/0_three_forward/amy.c to examples/1_socketlike/amy.c
examples/1_socketlike/bob.c
Show inline comments
 
file renamed from examples/0_three_forward/bob.c to examples/1_socketlike/bob.c
examples/1_socketlike/make.sh
Show inline comments
 
file renamed from examples/0_three_forward/make.sh to examples/1_socketlike/make.sh
examples/2_atomic_swap/amy.exe
Show inline comments
 
deleted file
 
binary diff not shown
examples/2_atomic_swap/bob.c
Show inline comments
 
deleted file
examples/2_atomic_swap/bob.exe
Show inline comments
 
deleted file
 
binary diff not shown
examples/2_dynamic_pdl/amy.c
Show inline comments
 
file renamed from examples/1_load_pdl/amy.c to examples/2_dynamic_pdl/amy.c
 
#include <stdio.h>
 
#include <stdlib.h>
 
#include <string.h>
 
#include "../../reowolf.h"
 
#include "../utility.c"
 

	
 
int main() { // AMY
 
	char * pdl = buffer_pdl("forward.pdl");
 
	char * pdl = buffer_pdl("eg_protocols.pdl");
 
	
 
	char msg_buf[128];
 
	memset(msg_buf, 0, 128);
 
	
 
	printf("input a message to send:");
 

	
 
	check("fgets", fgets(msg_buf, 128-1, stdin) == NULL);
 
	int msg_len = strlen(msg_buf);
 
	msg_buf[msg_len-1] = 0;
 
	printf("will send msg `%s`\n", msg_buf);
 
	
 
	Connector* c = connector_new();
 
	printf("configuring...\n");
 
	check("config ", connector_configure(c, pdl, "forward"));
 
	check("bind 0 ", connector_bind_native(c, 0));
 
	check("bind 1 ", connector_bind_passive(c, 1, "127.0.0.1:7000"));
 
	printf("connecting...\n");
 
	check("connect", connector_connect(c, 5000));
 
	
 
	int i;
 
	for (i = 0; i < 3; i++) {
 
		check("put ", connector_put(c, 0, msg_buf, msg_len));
 
		check("sync", connector_sync(c, 1000));
 
		printf("Sent one message!\n");
 
	}
 
	
 
	printf("destroying...\n");
 
	connector_destroy(c);
 
	printf("exiting...\n");
 
	free(pdl);
 
	return 0;
 
}
 
\ No newline at end of file
examples/2_dynamic_pdl/bob.c
Show inline comments
 
file renamed from examples/1_load_pdl/bob.c to examples/2_dynamic_pdl/bob.c
 
#include <stdio.h>
 
#include "../../reowolf.h"
 
#include "../utility.c"
 

	
 
int main() { // BOB!
 
	char * pdl = buffer_pdl("forward.pdl");
 
	char * pdl = buffer_pdl("eg_protocols.pdl");
 
	
 
	// BOB
 
	Connector* c = connector_new();
 
	printf("configuring...\n");
 
	check("config ", connector_configure(c, pdl, "forward"));
 
	check("bind 0 ", connector_bind_active(c, 0, "127.0.0.1:7000"));
 
	check("bind 1 ", connector_bind_native(c, 1));
 
	printf("connecting...\n");
 
	check("connect", connector_connect(c, 5000));
 
	
 
	int i;
 
	for (i = 0; i < 3; i++) {
 
		check("get ", connector_get(c, 0));
 
		check("sync", connector_sync(c, 1000));
 

	
 
		int msg_len;
 
		const unsigned char * msg;
 
		check("read", connector_gotten(c, 0, &msg, &msg_len));
 

	
 
		printf("Received one message `%s`!\n", msg);
 
	}
 
	
 
	printf("destroying...\n");
 
	connector_destroy(c);
 
	printf("exiting...\n");
 
	free(pdl);
 
	return 0;
 
}
 
\ No newline at end of file
examples/2_dynamic_pdl/make.sh
Show inline comments
 
file renamed from examples/1_load_pdl/make.sh to examples/2_dynamic_pdl/make.sh
examples/3_nondeterminism/amy.c
Show inline comments
 
new file 100644
 
#include <stdio.h>
 
#include <stdlib.h>
 
#include <string.h>
 
#include "../../reowolf.h"
 
#include "../utility.c"
 

	
 
int main() { // AMY
 
	char * pdl = buffer_pdl("eg_protocols.pdl");
 
	
 
	Connector* c = connector_new();
 
	printf("configuring...\n");
 

	
 
	check("config ", connector_configure(c, pdl, "sync"));
 
	check("bind 0 ", connector_bind_native(c, 0));
 
	check("bind 1 ", connector_bind_passive(c, 1, "127.0.0.1:7000"));
 
	printf("connecting...\n");
 
	check("connect", connector_connect(c, 5000));
 

	
 
	int send_next = 0;
 
	char msg_buf[32];
 
	int code;
 
	int i;
 
	for (i = 0; 1; i++) {
 
		itoa(send_next, msg_buf, 10);
 
		
 
		printf("\nround %d. Will send msg `%s` next", i, msg_buf);
 
		
 
		
 
		// batch 0: no messages sent
 
		check("next_batch ", connector_next_batch(c));
 
		
 
		// batch 1: put 0
 
		check("put ", connector_put(c, 0, msg_buf, strlen(msg_buf) + 1));
 
		code = connector_sync(c, 3000);
 
		
 
		if (code == 0) printf("Sent no message!");
 
		else if (code == 1) {
 
			printf("Sent message `%s`!", msg_buf);
 
			send_next++;
 
		} else {
 
			printf(
 
				"Connector error! %d (%s)\nBreaking loop!\n",
 
				code, connector_error_peek()
 
			);
 
			break;
 
		}
 
	}
 
	
 
	printf("destroying...\n");
 
	connector_destroy(c);
 
	printf("exiting...\n");
 
	free(pdl);
 
	return 0;
 
}
 
\ No newline at end of file
examples/3_nondeterminism/bob.c
Show inline comments
 
new file 100644
 
#include <stdio.h>
 
#include <time.h>
 
#include "../../reowolf.h"
 
#include "../utility.c"
 

	
 
int main() { // BOB!
 
	char * pdl = buffer_pdl("eg_protocols.pdl");
 
	Connector* c = connector_new();
 

	
 
	printf("configuring...\n");
 
	check("config ", connector_configure(c, pdl, "sync"));
 

	
 
	check("bind 0 ", connector_bind_active(c, 0, "127.0.0.1:7000"));
 
	check("bind 1 ", connector_bind_native(c, 1));
 

	
 
	printf("connecting...\n");
 
	check("connect", connector_connect(c, 5000));
 

	
 
	int msg_len;
 
	const unsigned char * msg;
 

	
 
	int i;
 
	srand(time(NULL));
 
	for (i = 0; i < 10; i++) {
 
		printf("\nround %d...\n", i);
 
		int random = rand() % 2;
 
		if (random == 0) {
 
			printf("I don't want a message!\n");
 
			check("sync", connector_sync(c, 1000));
 
		} else {
 
			printf("I want a message!\n");
 
			check("get ", connector_get(c, 0));
 
			check("sync", connector_sync(c, 1000));
 
			check("read msg", connector_gotten(c, 0, &msg, &msg_len));
 
			printf("Got message: `%.*s`\n", msg_len, msg);
 
		}
 
	}
 
	
 
	printf("destroying...\n");
 
	connector_destroy(c);
 
	printf("exiting...\n");
 
	free(pdl);
 
	return 0;
 
}
 
\ No newline at end of file
examples/3_nondeterminism/make.sh
Show inline comments
 
file renamed from examples/2_atomic_swap/make.sh to examples/3_nondeterminism/make.sh
examples/4_atomicity/amy.c
Show inline comments
 
file renamed from examples/2_atomic_swap/amy.c to examples/4_atomicity/amy.c
 
#include <stdio.h>
 
#include <stdlib.h>
 
#include <string.h>
 
#include "../../reowolf.h"
 
#include "../utility.c"
 

	
 
int main() { // AMY
 
	char * pdl = buffer_pdl("swap.pdl");
 
	char * pdl = buffer_pdl("eg_protocols.pdl");
 
	
 
	Connector* c = connector_new();
 
	printf("configuring...\n");
 

	
 
	check("config ", connector_configure(c, pdl, "forward_two"));
 
	check("config ", connector_configure(c, pdl, "sync_two"));
 
	check("bind 0 ", connector_bind_native(c, 0));
 
	check("bind 1 ", connector_bind_native(c, 1));
 
	check("bind 2 ", connector_bind_passive(c, 2, "127.0.0.1:7000"));
 
	check("bind 3 ", connector_bind_passive(c, 3, "127.0.0.1:7001"));
 
	printf("connecting...\n");
 
	check("connect", connector_connect(c, 5000));
 

	
 
	int i;
 
	for (i = 0; i < 3; i++) {
 
	int code;
 
	while (1) {
 
		printf("\nround %d\n", i);
 
		
 
		// batch 0: no messages sent
 
		check("next_batch ", connector_next_batch(c));
 
		
 
		// batch 1: put 0 and put 1
 
		check("put ", connector_put(c, 0, "one", 3));
 
		check("put ", connector_put(c, 1, "two", 3));
 
		check("sync", connector_sync(c, 1000));
 
		code = connector_sync(c, 3000);
 
		
 
		printf("Sent both messages!\n");
 
		if (code == 0) printf("Sent neither message!");
 
		else if (code == 1) printf("Sent both messages!");
 
		else {
 
			printf(
 
				"Connector error! %d (%s)\nBreaking loop!\n",
 
				code, connector_error_peek()
 
			);
 
			break;
 
		}
 
	}
 
	
 
	printf("destroying...\n");
 
	connector_destroy(c);
 
	printf("exiting...\n");
 
	free(pdl);
 
	return 0;
 
}
 
\ No newline at end of file
examples/4_atomicity/bob.c
Show inline comments
 
new file 100644
 
#include <stdio.h>
 
#include "../../reowolf.h"
 
#include "../utility.c"
 

	
 
int main() { // BOB!
 
	char * pdl = buffer_pdl("eg_protocols.pdl");
 
	Connector* c = connector_new();
 

	
 
	printf("configuring...\n");
 
	check("config ", connector_configure(c, pdl, "sync_two"));
 

	
 
	check("bind 0 ", connector_bind_active(c, 0, "127.0.0.1:7000"));
 
	check("bind 1 ", connector_bind_active(c, 1, "127.0.0.1:7001"));
 
	check("bind 2 ", connector_bind_native(c, 2));
 
	check("bind 3 ", connector_bind_native(c, 3));
 

	
 
	printf("connecting...\n");
 
	check("connect", connector_connect(c, 5000));
 

	
 
	int msg_len;
 
	const unsigned char * msg;
 

	
 
	int i;
 
	
 
	// rounds 0..=2: get both messages
 
	for (i = 0; i <= 2; i++) {
 
		printf("\nround %d\n", i);
 
		
 
		check("get ", connector_get(c, 0));
 
		check("get ", connector_get(c, 1));
 
		check("sync", connector_sync(c, 1000));
 
		
 
		check("read one", connector_gotten(c, 0, &msg, &msg_len));
 
		printf("Got message one: `%.*s`\n", msg_len, msg);
 
		
 
		check("read two", connector_gotten(c, 1, &msg, &msg_len));
 
		printf("Got message two: `%.*s`\n", msg_len, msg);
 
	}
 
	// rounds 3..=5: get neither message
 
	for (i = 3; i <= 5; i++) {
 
		printf("\nround %d\n", i);
 
		
 
		//check("get ", connector_get(c, 0));
 
		//check("get ", connector_get(c, 1));
 
		check("sync", connector_sync(c, 3000));
 
		
 
		//check("read one", connector_gotten(c, 0, &msg, &msg_len));
 
		//printf("Got message one: `%.*s`\n", msg_len, msg);
 
		
 
		//check("read two", connector_gotten(c, 1, &msg, &msg_len));
 
		//printf("Got message two: `%.*s`\n", msg_len, msg);
 
	}
 
	// round 6: attempt to get just one message
 
	for (i = 6; i <= 6; i++) {
 
		printf("\nround %d\n", i);
 
		
 
		check("get ", connector_get(c, 0));
 
		//check("get ", connector_get(c, 1));
 
		check("sync", connector_sync(c, 3000));
 
		
 
		//check("read one", connector_gotten(c, 0, &msg, &msg_len));
 
		//printf("Got message one: `%.*s`\n", msg_len, msg);
 
		
 
		check("read two", connector_gotten(c, 1, &msg, &msg_len));
 
		printf("Got message two: `%.*s`\n", msg_len, msg);
 
	}
 
	
 
	printf("destroying...\n");
 
	connector_destroy(c);
 
	printf("exiting...\n");
 
	free(pdl);
 
	return 0;
 
}
 
\ No newline at end of file
examples/4_atomicity/make.sh
Show inline comments
 
new file 100644
 
#!/bin/sh
 

	
 
LIB_PATH="../"
 
gcc -L $LIB_PATH -lreowolf_rs -Wl,-R$LIB_PATH amy.c -o amy
 
gcc -L $LIB_PATH -lreowolf_rs -Wl,-R$LIB_PATH bob.c -o bob
examples/5_recovery/amy.c
Show inline comments
 
new file 100644
 
#include <stdio.h>
 
#include <stdlib.h>
 
#include <string.h>
 
#include "../../reowolf.h"
 
#include "../utility.c"
 

	
 
int main() { // AMY
 
	char * pdl = buffer_pdl("eg_protocols.pdl");
 
	
 
	Connector* c = connector_new();
 
	printf("configuring...\n");
 

	
 
	check("config ", connector_configure(c, pdl, "sync"));
 
	check("bind 0 ", connector_bind_native(c, 0));
 
	check("bind 1 ", connector_bind_passive(c, 1, "127.0.0.1:7000"));
 
	printf("connecting...\n");
 
	check("connect", connector_connect(c, 5000));
 
	
 
	int i;
 
	int code;
 
	while (1) {
 
		printf("\nround %d. I will offer the message \"hello\".\n", i);
 
		connector_next_batch(c);
 
		check("put ", connector_put(c, 0, "hello", 5));
 
		code = connector_sync(c, 3000);
 
		
 
		if (code == 0) printf("OK! No message was sent!");
 
		else if (code == 1) printf("OK! My message was received!");
 
		else if (code == -1) printf("!!! UH OH! The round rolled back! Let's try again");
 
		else {
 
			printf(
 
				"Something went wrong!\n",
 
				code, connector_error_peek()
 
			);
 
			break;
 
		}
 
	}
 
	
 
	printf("destroying...\n");
 
	connector_destroy(c);
 
	printf("exiting...\n");
 
	free(pdl);
 
	return 0;
 
}
 
\ No newline at end of file
examples/5_recovery/amy.exe
Show inline comments
 
new file 100644
 
binary diff not shown
examples/5_recovery/bob.c
Show inline comments
 
new file 100644
 
#include <stdio.h>
 
#include "../../reowolf.h"
 
#include "../utility.c"
 

	
 
int main() { // BOB!
 

	
 
	char * pdl = buffer_pdl("eg_protocols.pdl");
 
	Connector* c = connector_new();
 

	
 
	printf("configuring...\n");
 
	check("config ", connector_configure(c, pdl, "recovery_bob"));
 
	check("bind 0 ", connector_bind_active(c, 0, "127.0.0.1:7000"));
 
	check("bind 1 ", connector_bind_native(c, 1));
 

	
 
	printf("connecting...\n");
 
	check("connect", connector_connect(c, 5000));
 

	
 
	int msg_len;
 
	const unsigned char * msg;
 

	
 
	int i;
 
	char msg_buf[1];
 
	int code;
 
	char answer;
 
	
 
	for (i = 0; true; i++) {
 
		printf("\nround %d...\n", i);
 
		printf("Should I receive a message? (y/n): ");
 
		scanf(" %c", &answer);
 
		if (answer == 'y') {
 
			printf("OK! Let's receive a message!\n");
 
			connector_get(c, 0);
 
		} else if (answer == 'n') {
 
			printf("OK! Let's NOT receive a message!\n");
 
		} else {
 
			printf("Expected (y/n) input!");
 
			continue;
 
		}
 
		
 
		code = connector_sync(c, 1000);
 
			
 
		// lets see how it went
 
		if (code == 0) {
 
			printf("Success!\n");
 
			if (answer == 'y') {
 
				check("read ", connector_gotten(c, 0, &msg, &msg_len));
 
				printf("Got message: `%.*s`\n", msg_len, msg);
 
			}
 
		} else if (code == -1) {
 
			printf("!!! UH OH! The round rolled back! Let's try again\n");
 
		} else {
 
			printf(
 
				"Something went wrong!\n",
 
				code, connector_error_peek()
 
			);
 
			break;
 
		}
 
	}
 
	
 
	printf("destroying...\n");
 
	connector_destroy(c);
 
	printf("exiting...\n");
 
	free(pdl);
 
	return 0;
 
}
 
\ No newline at end of file
examples/5_recovery/bob.exe
Show inline comments
 
new file 100644
 
binary diff not shown
examples/5_recovery/make.sh
Show inline comments
 
new file 100644
 
#!/bin/sh
 

	
 
LIB_PATH="../"
 
gcc -L $LIB_PATH -lreowolf_rs -Wl,-R$LIB_PATH amy.c -o amy
 
gcc -L $LIB_PATH -lreowolf_rs -Wl,-R$LIB_PATH bob.c -o bob
examples/6_constraint_solve/THIS IS TODO.txt
Show inline comments
 
new file 100644
examples/6_constraint_solve/main.c
Show inline comments
 
new file 100644
 
#include <stdio.h>
 
#include <stdlib.h>
 
#include <string.h>
 
#include <time.h>
 
#include "../../reowolf.h"
 
#include "../utility.c"
 

	
 
int main(int arg_c, char * argv[]) {
 
	int index;
 
	if (arg_c != 2) {
 
		printf("Expected one arg: which peer I am in 0..4");
 
		return 1;
 
	}
 
	index = atoi(argv[1]);
 
	printf("I am peer %d\n", index);
 
	
 
	const char* addrs[] = {
 
		"127.0.0.1:7000",
 
		"127.0.0.1:7001",
 
		"127.0.0.1:7002",
 
		"127.0.0.1:7003",
 
		"127.0.0.1:7004",
 
		"127.0.0.1:7005",
 
	};
 

	
 
	char * pdl = buffer_pdl("eg_protocols.pdl");
 
	
 
	Connector* c = connector_new();
 
	printf("configuring...\n");
 

	
 
	check("config ", connector_configure(c, pdl, "xor_three"));
 
	int i, j;
 
	int addr_index = 0;
 
	int port = 0;
 
	for (i = 0; i < 4; i++) {
 
		for (j = i+1; j < 4; j++) {
 
			if (i==index) {
 
				printf("ports %d and %d are for a passive channel to peer %d over addr %s\n", port, port+1, j, addrs[addr_index]);
 
				check("bind an ", connector_bind_native(c, port));
 
				port++;
 
				check("bind a  ", connector_bind_active(c, port, addrs[addr_index]));
 
				port++;
 
			} else if (j==index) {
 
				printf("ports %d and %d are for an active channel to peer %d over addr %s\n", port, port+1, i, addrs[addr_index]);
 
				check("bind p  ", connector_bind_passive(c, port, addrs[addr_index]));
 
				port++;
 
				check("bind pn ", connector_bind_native(c, port));
 
				port++;
 
			}
 
			addr_index++;
 
		}
 
	}
 
	check("connect", connector_connect(c, 5000));
 
	
 
	for (i = 0; i < 4; i++) {
 
		if (i == index) continue;
 
		// another batch
 
		for (j = 0; j < 4; j++) {
 
			
 
		}
 
	}
 
	connector_sync();
 
	
 
	printf("destroying...\n");
 
	connector_destroy(c);
 
	printf("exiting...\n");
 
	free(pdl);
 
	return 0;
 
}
 
\ No newline at end of file
examples/6_constraint_solve/main.exe
Show inline comments
 
new file 100644
 
binary diff not shown
examples/6_constraint_solve/make.sh
Show inline comments
 
new file 100644
 
#!/bin/sh
 

	
 
LIB_PATH="../"
 
gcc -L $LIB_PATH -lreowolf_rs -Wl,-R$LIB_PATH main.c -o main
examples/eg_protocols.pdl
Show inline comments
 
new file 100644
 
primitive forward(in i, out o) {
 
	while(true) synchronous {
 
		put(o, get(i));
 
	}
 
}
 
primitive sync(in i, out o) {
 
	while(true) synchronous {
 
		if(fires(i)) {
 
			put(o, get(i));
 
		}
 
	}
 
}
 

	
 
primitive sync_two(in ia, in ib, out oa, out ob) {
 
	while(true) synchronous {
 
		if (fires(ia)) {
 
			put(oa, get(ia));
 
			put(ob, get(ib));
 
		}
 
	}
 
}
 

	
 
composite recovery_bob(in i, out o) {
 
	new sync(i, o);
 
}
 

	
 
primitive xor_three(in ai, out ao, in bi, out bo, in ci, out co) {
 
	synchronous {
 
		if      (fires(ai)) put(ao, get(ai));
 
		else if (fires(bi)) put(bo, get(bi));
 
		else                put(co, get(ci)); 
 
	}
 
}
 
\ No newline at end of file
examples/forward.pdl
Show inline comments
 
deleted file
examples/utility.c
Show inline comments
 
#include <stdio.h>
 
#include <stdlib.h>
 
#include <errno.h>
 

	
 
void check(const char* phase, int err) {
 
	if (err) {
 
		printf("ERR %d in phase `%s`. Err was `%s`\nEXITING!\n",
 
			err, phase, connector_error_peek());
 
		exit(1);
 
	}
 
}
 

	
 
// allocates a buffer!
 
char * buffer_pdl(char * filename) {
 
	FILE *f = fopen("forward.pdl", "rb");
 
	FILE *f = fopen(filename, "rb");
 
	if (f == NULL) {
 
		printf("Opening pdl file returned errno %d!\n", errno);
 
		exit(1);
 
	}
 
	fseek(f, 0, SEEK_END);
 
	long fsize = ftell(f);
 
	fseek(f, 0, SEEK_SET);
 
	char *pdl = malloc(fsize + 1);
 
	fread(pdl, 1, fsize, f);
 
	fclose(f);
 
	pdl[fsize] = 0;
 
	return pdl;
 
}
 
\ No newline at end of file
reowolf.h
Show inline comments
 
/* CBindgen generated */
 

	
 
#ifndef REOWOLF_HEADER_DEFINED
 
#define REOWOLF_HEADER_DEFINED
 

	
 
#include <stdarg.h>
 
#include <stdbool.h>
 
#include <stdint.h>
 
#include <stdlib.h>
 

	
 
typedef struct Connector Connector;
 

	
 
typedef uint32_t ControllerId;
 

	
 
/**
 
 * Provides a binding annotation for the port with the given index with "active":
 
 * (The port will conenct to a "passive" port at the given address during connect())
 
 * Returns:
 
 * - 0 for success
 
 * - 1 if the port was already bound and was left unchanged
 
 * # Safety
 
 * TODO
 
 */
 
int connector_bind_active(Connector *connector, unsigned int proto_port_index, const char *address);
 

	
 
/**
 
 * Provides a binding annotation for the port with the given index with "native":
 
 * (The port is exposed for reading and writing from the application)
 
 * Returns:
 
 * # Safety
 
 * TODO
 
 */
 
int connector_bind_native(Connector *connector, uintptr_t proto_port_index);
 

	
 
/**
 
 * Provides a binding annotation for the port with the given index with "native":
 
 * (The port is exposed for reading and writing from the application)
 
 * Returns:
 
 * # Safety
 
 * TODO
 
 */
 
int connector_bind_passive(Connector *connector,
 
                           unsigned int proto_port_index,
 
                           const char *address);
 

	
 
/**
 
 * Configures the given Reowolf connector with a protocol description in PDL.
 
 * Returns:
 
 * # Safety
 
 * TODO
 
 */
 
int connector_configure(Connector *connector, char *pdl, char *main);
 

	
 
/**
 
 * Provides a binding annotation for the port with the given index with "active":
 
 * (The port will conenct to a "passive" port at the given address during connect())
 
 * Returns:
 
 * - 0 SUCCESS: connected successfully
 
 * - TODO error codes
 
 * # Safety
 
 * TODO
 
 */
 
int connector_connect(Connector *connector, uint64_t timeout_millis);
 

	
 
/**
 
 * Destroys the given connector, freeing its underlying resources.
 
 * # Safety
 
 * TODO
 
 */
 
void connector_destroy(Connector *connector);
 

	
 
/**
 
 * # Safety
 
 * TODO
 
 */
 
int connector_dump_log(Connector *connector);
 

	
 
/**
 
 * Resets the error message buffer.
 
 * Returns:
 
 * - 0 if an error was cleared
 
 * - 1 if there was no error to clear
 
 * # Safety
 
 * TODO
 
 */
 
int connector_error_clear(void);
 

	
 
/**
 
 * Returns a pointer into the error buffer for reading as a null-terminated string
 
 * Returns null if there is no error in the buffer.
 
 * # Safety
 
 * TODO
 
 */
 
const char *connector_error_peek(void);
 

	
 
/**
 
 * Prepares to synchronously put a message at the given port, writing it to the given buffer.
 
 * - 0 SUCCESS
 
 * - 1 this port has the wrong direction
 
 * - 2 this port is already marked to get
 
 * # Safety
 
 * TODO
 
 */
 
int connector_get(Connector *connector, unsigned int proto_port_index);
 

	
 
/**
 
 * # Safety
 
 * TODO
 
 */
 
int connector_gotten(Connector *connector,
 
                     unsigned int proto_port_index,
 
                     const unsigned char **buf_ptr_outptr,
 
                     unsigned int *len_outptr);
 

	
 
/**
 
 * Creates and returns Reowolf Connector structure allocated on the heap.
 
 */
 
Connector *connector_new(void);
 

	
 
/**
 
 * # Safety
 
 * TODO
 
 */
 
int connector_next_batch(Connector *connector);
 

	
 
/**
 
 * Prepares to synchronously put a message at the given port, reading it from the given buffer.
 
 * # Safety
 
 * TODO
 
 */
 
int connector_put(Connector *connector,
 
                  unsigned int proto_port_index,
 
                  unsigned char *buf_ptr,
 
                  unsigned int msg_len);
 

	
 
/**
 
 * # Safety
 
 * TODO
 
 */
 
int connector_sync(Connector *connector, uint64_t timeout_millis);
 

	
 
/**
 
 * Creates and returns Reowolf Connector structure allocated on the heap.
 
 */
 
Connector *connector_with_controller_id(ControllerId controller_id);
 

	
 
/**
 
 * # Safety
 
 * TODO
 
 */
 
int port_close(Connector *connector, unsigned int _proto_port_index);
 

	
 
#endif /* REOWOLF_HEADER_DEFINED */
src/runtime/connector.rs
Show inline comments
 
use crate::common::*;
 
use crate::runtime::{errors::*, *};
 

	
 
pub fn random_controller_id() -> ControllerId {
 
    type Bytes8 = [u8; std::mem::size_of::<ControllerId>()];
 
    let mut bytes = Bytes8::default();
 
    getrandom::getrandom(&mut bytes).unwrap();
 
    unsafe { std::mem::transmute::<Bytes8, ControllerId>(bytes) }
 
}
 

	
 
impl Default for Unconfigured {
 
    fn default() -> Self {
 
        let controller_id = random_controller_id();
 
        Self { controller_id }
 
    }
 
}
 
impl Default for Connector {
 
    fn default() -> Self {
 
        Self::Unconfigured(Unconfigured::default())
 
    }
 
}
 
impl Connector {
 
    /// Configure the Connector with the given Pdl description.
 
    pub fn configure(&mut self, pdl: &[u8], main_component: &[u8]) -> Result<(), ConfigErr> {
 
        use ConfigErr::*;
 
        let controller_id = match self {
 
            Connector::Configured(_) => return Err(AlreadyConfigured),
 
            Connector::Connected(_) => return Err(AlreadyConnected),
 
            Connector::Unconfigured(Unconfigured { controller_id }) => *controller_id,
 
        };
 
        let protocol_description = Arc::new(ProtocolD::parse(pdl).map_err(ParseErr)?);
 
        let polarities = protocol_description.component_polarities(main_component)?;
 
        let configured = Configured {
 
            controller_id,
 
            protocol_description,
 
            bindings: Default::default(),
 
            polarities,
 
            main_component: main_component.to_vec(),
 
        };
 
        *self = Connector::Configured(configured);
 
        Ok(())
 
    }
 

	
 
    /// Bind the (configured) connector's port corresponding to the
 
    pub fn bind_port(
 
        &mut self,
 
        proto_port_index: usize,
 
        binding: PortBinding,
 
    ) -> Result<(), PortBindErr> {
 
        use PortBindErr::*;
 
        match self {
 
            Connector::Unconfigured { .. } => Err(NotConfigured),
 
            Connector::Connected(_) => Err(AlreadyConnected),
 
            Connector::Configured(configured) => {
 
                if configured.polarities.len() <= proto_port_index {
 
                    return Err(IndexOutOfBounds);
 
                }
 
                configured.bindings.insert(proto_port_index, binding);
 
                Ok(())
 
            }
 
        }
 
    }
 
    pub fn connect(&mut self, timeout: Duration) -> Result<(), ConnectErr> {
 
        let deadline = Instant::now() + timeout;
 
        use ConnectErr::*;
 
        let configured = match self {
 
            Connector::Unconfigured { .. } => return Err(NotConfigured),
 
            Connector::Connected(_) => return Err(AlreadyConnected),
 
            Connector::Configured(configured) => configured,
 
        };
 
        // 1. Unwrap bindings or err
 
        let bound_proto_interface: Vec<(_, _)> = configured
 
            .polarities
 
            .iter()
 
            .copied()
 
            .enumerate()
 
            .map(|(native_index, polarity)| {
 
                let binding = configured
 
                    .bindings
 
                    .get(&native_index)
 
                    .copied()
 
                    .ok_or(PortNotBound { native_index })?;
 
                Ok((binding, polarity))
 
            })
 
            .collect::<Result<Vec<(_, _)>, ConnectErr>>()?;
 
        let (controller, native_interface) = Controller::connect(
 
            configured.controller_id,
 
            &configured.main_component,
 
            configured.protocol_description.clone(),
 
            &bound_proto_interface[..],
 
            deadline,
 
        )?;
 
        *self = Connector::Connected(Connected {
 
            native_interface,
 
            sync_batches: vec![Default::default()],
 
            controller,
 
        });
 
        Ok(())
 
    }
 
    pub fn get_mut_logger(&mut self) -> Option<&mut String> {
 
        match self {
 
            Connector::Connected(connected) => Some(&mut connected.controller.inner.logger),
 
            _ => None,
 
        }
 
    }
 

	
 
    pub fn put(&mut self, native_port_index: usize, payload: Payload) -> Result<(), PortOpErr> {
 
        use PortOpErr::*;
 
        let connected = match self {
 
            Connector::Connected(connected) => connected,
 
            _ => return Err(NotConnected),
 
        };
 
        let (ekey, native_polarity) =
 
            *connected.native_interface.get(native_port_index).ok_or(IndexOutOfBounds)?;
 
        if native_polarity != Putter {
 
            return Err(WrongPolarity);
 
        }
 
        let sync_batch = connected.sync_batches.iter_mut().last().expect("no sync batch!");
 
        if sync_batch.puts.contains_key(&ekey) {
 
            return Err(DuplicateOperation);
 
        }
 
        sync_batch.puts.insert(ekey, payload);
 
        Ok(())
 
    }
 

	
 
    pub fn get(&mut self, native_port_index: usize) -> Result<(), PortOpErr> {
 
        use PortOpErr::*;
 
        let connected = match self {
 
            Connector::Connected(connected) => connected,
 
            _ => return Err(NotConnected),
 
        };
 
        let (ekey, native_polarity) =
 
            *connected.native_interface.get(native_port_index).ok_or(IndexOutOfBounds)?;
 
        if native_polarity != Getter {
 
            return Err(WrongPolarity);
 
        }
 
        let sync_batch = connected.sync_batches.iter_mut().last().expect("no sync batch!");
 
        if sync_batch.gets.contains(&ekey) {
 
            return Err(DuplicateOperation);
 
        }
 
        sync_batch.gets.insert(ekey);
 
        Ok(())
 
    }
 
    pub fn next_batch(&mut self) -> Result<usize, ()> {
 
        let connected = match self {
 
            Connector::Connected(connected) => connected,
 
            _ => return Err(()),
 
        };
 
        connected.sync_batches.push(SyncBatch::default());
 
        Ok(connected.sync_batches.len() - 1)
 
        Ok(connected.sync_batches.len() - 2)
 
    }
 

	
 
    pub fn sync(&mut self, timeout: Duration) -> Result<usize, SyncErr> {
 
        let deadline = Instant::now() + timeout;
 
        use SyncErr::*;
 
        let connected = match self {
 
            Connector::Connected(connected) => connected,
 
            _ => return Err(NotConnected),
 
        };
 

	
 
        // do the synchronous round!
 
        let res =
 
            connected.controller.sync_round(Some(deadline), Some(connected.sync_batches.drain(..)));
 
        connected.sync_batches.push(SyncBatch::default());
 
        res?;
 
        Ok(connected.controller.inner.mono_n.result.as_mut().expect("qqqs").0)
 
    }
 

	
 
    pub fn read_gotten(&self, native_port_index: usize) -> Result<&[u8], ReadGottenErr> {
 
        use ReadGottenErr::*;
 
        let connected = match self {
 
            Connector::Connected(connected) => connected,
 
            _ => return Err(NotConnected),
 
        };
 
        let &(key, polarity) =
 
            connected.native_interface.get(native_port_index).ok_or(IndexOutOfBounds)?;
 
        if polarity != Getter {
 
            return Err(WrongPolarity);
 
        }
 
        let result = connected.controller.inner.mono_n.result.as_ref().ok_or(NoPreviousRound)?;
 
        let payload = result.1.get(&key).ok_or(DidNotGet)?;
 
        Ok(payload)
 
    }
 
}
src/runtime/ffi.rs
Show inline comments
 
@@ -89,276 +89,286 @@ pub extern "C" fn connector_error_clear() -> c_int {
 
            0
 
        } else {
 
            1
 
        }
 
    })
 
}
 

	
 
/// Creates and returns Reowolf Connector structure allocated on the heap.
 
#[no_mangle]
 
pub extern "C" fn connector_new() -> *mut Connector {
 
    Box::into_raw(Box::new(Connector::default()))
 
}
 

	
 
/// Creates and returns Reowolf Connector structure allocated on the heap.
 
#[no_mangle]
 
pub extern "C" fn connector_with_controller_id(controller_id: ControllerId) -> *mut Connector {
 
    Box::into_raw(Box::new(Connector::Unconfigured(Unconfigured { controller_id })))
 
}
 

	
 
/// Configures the given Reowolf connector with a protocol description in PDL.
 
/// Returns:
 
/// # Safety
 
/// TODO
 
#[no_mangle]
 
pub unsafe extern "C" fn connector_configure(
 
    connector: *mut Connector,
 
    pdl: *mut c_char,
 
    main: *mut c_char,
 
) -> c_int {
 
    let mut b = Box::from_raw(connector); // unsafe!
 
    let ret = as_rust_bytes(pdl, |pdl_bytes| {
 
        as_rust_bytes(main, |main_bytes| match b.configure(pdl_bytes, main_bytes) {
 
            Ok(()) => 0,
 
            Err(e) => {
 
                overwrite_last_error(format!("{:?}", e).as_bytes());
 
                -1
 
            }
 
        })
 
    });
 
    Box::into_raw(b); // don't drop!
 
    ret
 
}
 

	
 
/// Provides a binding annotation for the port with the given index with "native":
 
/// (The port is exposed for reading and writing from the application)
 
/// Returns:
 
/// # Safety
 
/// TODO
 
#[no_mangle]
 
pub unsafe extern "C" fn connector_bind_native(
 
    connector: *mut Connector,
 
    proto_port_index: usize,
 
) -> c_int {
 
    // use PortBindErr::*;
 
    let mut b = Box::from_raw(connector); // unsafe!
 
    let ret = match b.bind_port(proto_port_index, PortBinding::Native) {
 
        Ok(()) => 0,
 
        Err(e) => {
 
            overwrite_last_error(format!("{:?}", e).as_bytes());
 
            -1
 
        }
 
    };
 
    Box::into_raw(b); // don't drop!
 
    ret
 
}
 

	
 
/// Provides a binding annotation for the port with the given index with "native":
 
/// (The port is exposed for reading and writing from the application)
 
/// Returns:
 
/// # Safety
 
/// TODO
 
#[no_mangle]
 
pub unsafe extern "C" fn connector_bind_passive(
 
    connector: *mut Connector,
 
    proto_port_index: c_uint,
 
    address: *const c_char,
 
) -> c_int {
 
    if let Some(addr) = try_parse_addr(address) {
 
        // use PortBindErr::*;
 
        let mut b = Box::from_raw(connector); // unsafe!
 
        let ret =
 
            match b.bind_port(proto_port_index.try_into().unwrap(), PortBinding::Passive(addr)) {
 
                Ok(()) => 0,
 
                Err(e) => {
 
                    overwrite_last_error(format!("{:?}", e).as_bytes());
 
                    -1
 
                }
 
            };
 
        Box::into_raw(b); // don't drop!
 
        ret
 
    } else {
 
        overwrite_last_error(b"Failed to parse input as ip address!");
 
        -1
 
    }
 
}
 

	
 
/// Provides a binding annotation for the port with the given index with "active":
 
/// (The port will conenct to a "passive" port at the given address during connect())
 
/// Returns:
 
/// - 0 for success
 
/// - 1 if the port was already bound and was left unchanged
 
/// # Safety
 
/// TODO
 
#[no_mangle]
 
pub unsafe extern "C" fn connector_bind_active(
 
    connector: *mut Connector,
 
    proto_port_index: c_uint,
 
    address: *const c_char,
 
) -> c_int {
 
    if let Some(addr) = try_parse_addr(address) {
 
        // use PortBindErr::*;
 
        let mut b = Box::from_raw(connector); // unsafe!
 
        let ret = match b.bind_port(proto_port_index.try_into().unwrap(), PortBinding::Active(addr))
 
        {
 
            Ok(()) => 0,
 
            Err(e) => {
 
                overwrite_last_error(format!("{:?}", e).as_bytes());
 
                -1
 
            }
 
        };
 
        Box::into_raw(b); // don't drop!
 
        ret
 
    } else {
 
        overwrite_last_error(b"Failed to parse input as ip address!");
 
        -1
 
    }
 
}
 

	
 
/// Provides a binding annotation for the port with the given index with "active":
 
/// (The port will conenct to a "passive" port at the given address during connect())
 
/// Returns:
 
/// - 0 SUCCESS: connected successfully
 
/// - TODO error codes
 
/// # Safety
 
/// TODO
 
#[no_mangle]
 
pub unsafe extern "C" fn connector_connect(
 
    connector: *mut Connector,
 
    timeout_millis: u64,
 
) -> c_int {
 
    let mut b = Box::from_raw(connector); // unsafe!
 
    let ret = match b.connect(Duration::from_millis(timeout_millis)) {
 
        Ok(()) => 0,
 
        Err(e) => {
 
            overwrite_last_error(format!("{:?}", e).as_bytes());
 
            -1
 
        }
 
    };
 
    Box::into_raw(b); // don't drop!
 
    ret
 
}
 

	
 
/// Destroys the given connector, freeing its underlying resources.
 
/// # Safety
 
/// TODO
 
#[no_mangle]
 
pub unsafe extern "C" fn connector_destroy(connector: *mut Connector) {
 
    let c = Box::from_raw(connector); // unsafe!
 
    drop(c); // for readability
 
}
 

	
 
/// Prepares to synchronously put a message at the given port, reading it from the given buffer.
 
/// # Safety
 
/// TODO
 
#[no_mangle]
 
pub unsafe extern "C" fn connector_put(
 
    connector: *mut Connector,
 
    proto_port_index: c_uint,
 
    buf_ptr: *mut c_uchar,
 
    msg_len: c_uint,
 
) -> c_int {
 
    let buf = std::slice::from_raw_parts_mut(buf_ptr, msg_len.try_into().unwrap());
 
    let payload = buf.to_vec(); // unsafe
 
    let mut b = Box::from_raw(connector); // unsafe!
 
    let ret = b.put(proto_port_index.try_into().unwrap(), payload);
 
    Box::into_raw(b); // don't drop!
 
    match ret {
 
        Ok(()) => 0,
 
        Err(e) => {
 
            overwrite_last_error(format!("{:?}", e).as_bytes());
 
            -1
 
        }
 
    }
 
}
 

	
 
/// Prepares to synchronously put a message at the given port, writing it to the given buffer.
 
/// - 0 SUCCESS
 
/// - 1 this port has the wrong direction
 
/// - 2 this port is already marked to get
 
/// # Safety
 
/// TODO
 
#[no_mangle]
 
pub unsafe extern "C" fn connector_get(connector: *mut Connector, proto_port_index: c_uint) -> c_int {
 
pub unsafe extern "C" fn connector_get(
 
    connector: *mut Connector,
 
    proto_port_index: c_uint,
 
) -> c_int {
 
    let mut b = Box::from_raw(connector); // unsafe!
 
    let ret = b.get(proto_port_index.try_into().unwrap());
 
    Box::into_raw(b); // don't drop!
 
                      // use PortOperationErr::*;
 
    match ret {
 
        Ok(()) => 0,
 
        Err(e) => {
 
            overwrite_last_error(format!("{:?}", e).as_bytes());
 
            -1
 
        }
 
    }
 
}
 

	
 
/// # Safety
 
/// TODO
 
#[no_mangle]
 
pub unsafe extern "C" fn connector_gotten(
 
    connector: *mut Connector,
 
    proto_port_index: c_uint,
 
    buf_ptr_outptr: *mut *const c_uchar,
 
    len_outptr: *mut c_uint,
 
) -> c_int {
 
    let b = Box::from_raw(connector); // unsafe!
 
    let ret = b.read_gotten(proto_port_index.try_into().unwrap());
 
    // use ReadGottenErr::*;
 
    let result = match ret {
 
        Ok(ptr_slice) => {
 
            let buf_ptr = ptr_slice.as_ptr();
 
            let len = ptr_slice.len().try_into().unwrap();
 
            buf_ptr_outptr.write(buf_ptr);
 
            len_outptr.write(len);
 
            0
 
        }
 
        Err(e) => {
 
            overwrite_last_error(format!("{:?}", e).as_bytes());
 
            -1
 
        }
 
    };
 
    Box::into_raw(b); // don't drop!
 
    result
 
}
 

	
 
/// # Safety
 
/// TODO
 
#[no_mangle]
 
pub unsafe extern "C" fn port_close(connector: *mut Connector, _proto_port_index: c_uint) -> c_int {
 
    let b = Box::from_raw(connector); // unsafe!
 
                                      // TODO
 
    Box::into_raw(b); // don't drop!
 
pub unsafe extern "C" fn connector_dump_log(connector: *mut Connector) -> c_int {
 
    let mut b = Box::from_raw(connector); // unsafe!
 
    let result = match b.get_mut_logger() {
 
        Some(s) => {
 
            println!("{}", s);
 
            0
 
        }
 
        None => 1,
 
    };
 
    Box::into_raw(b); // don't drop!
 
    result
 
}
 

	
 
/// # Safety
 
/// TODO
 
#[no_mangle]
 
pub unsafe extern "C" fn connector_next_batch(connector: *mut Connector) -> c_int {
 
    let mut b = Box::from_raw(connector); // unsafe!
 
    let result = match b.next_batch() {
 
        Ok(batch_index) => batch_index.try_into().unwrap(),
 
        Err(e) => {
 
            overwrite_last_error(format!("{:?}", e).as_bytes());
 
            -1
 
        }
 
    };
 
    Box::into_raw(b); // don't drop!
 
    result
 
}
 

	
 
/// # Safety
 
/// TODO
 
#[no_mangle]
 
pub unsafe extern "C" fn connector_sync(connector: *mut Connector, timeout_millis: u64) -> c_int {
 
    let mut b = Box::from_raw(connector); // unsafe!
 
    let result = match b.sync(Duration::from_millis(timeout_millis)) {
 
        Ok(batch_index) => batch_index.try_into().unwrap(),
 
        Err(SyncErr::Timeout) => -1, // timeout!
 
        Err(e) => {
 
            overwrite_last_error(format!("{:?}", e).as_bytes());
 
            -1
 
            -2
 
        }
 
    };
 
    Box::into_raw(b); // don't drop!
 
    result
 
}
0 comments (0 inline, 0 general)