/
bang-routing.c
206 lines (166 loc) · 6.42 KB
/
bang-routing.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#include"bang-com.h"
#include"bang-routing.h"
#include"bang-module.h"
#include"bang-module-api.h"
#include"bang-types.h"
#include<assert.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
/* I am really reeling in those external libraries! */
#include<sqlite3.h>
#include<uuid/uuid.h>
#define DB_SCHEMA "CREATE TABLE mappings(route_uuid blob unique primary key, remote integer, peer_id int, module blob, name text, version blob)"
#define REMOTE_ROUTE 2
#define LOCAL_ROUTE 1
static sqlite3 *db;
/* TODO: Many elements in the functions are the same, consolidate somehow. DRY, afterall*/
static sqlite3_stmt* prepare_select_statement(uuid_t uuid);
static void insert_route(uuid_t uuid, int remote, BANG_module *module, int peer_id, char *module_name, unsigned char *module_version);
static sqlite3_stmt* prepare_select_statement(uuid_t uuid) {
assert(!uuid_is_null(uuid));
sqlite3_stmt *get_peer_route;
sqlite3_prepare_v2(db,"SELECT remote,module,peer_id,name,version FROM mappings WHERE ? = route_uuid",90,&get_peer_route,NULL);
sqlite3_bind_blob(get_peer_route,1,uuid,sizeof(uuid_t),SQLITE_STATIC);
return get_peer_route;
}
void BANG_route_job(uuid_t authority, uuid_t peer, BANG_job *job) {
assert(!uuid_is_null(authority));
assert(!uuid_is_null(peer));
assert(job != NULL);
sqlite3_stmt *get_peer_route = prepare_select_statement(peer);
if (sqlite3_step(get_peer_route) == SQLITE_ROW) {
if (sqlite3_column_int(get_peer_route,1) == REMOTE_ROUTE) {
/* TODO: Make a request to peer. */
BANG_request request;
request.type = BANG_SEND_JOB_REQUEST;
/* We are being a little presumptuous, and constructing the actual message
* that the communications infrastructure will send...
*
* Probably should move this to bang-com.c
*/
request.length = LENGTH_OF_HEADER +sizeof(uuid_t) * 2 +
4 /* A MAGIC NUMBER! */ +
LENGTH_OF_LENGTHS +
job->length;
request.request = malloc(request.length);
unsigned int header = BANG_SEND_JOB;
memcpy(request.request,&header,LENGTH_OF_HEADER);
memcpy(request.request,authority,sizeof(uuid_t));
memcpy(request.request,peer,sizeof(uuid_t));
memcpy(request.request,&(job->job_number),4);
memcpy(request.request,job->data,job->length);
BANG_request_peer_id(sqlite3_column_int(get_peer_route,3),request);
} else {
/* const BANG_module *module = */sqlite3_column_blob(get_peer_route,2);
/* TODO: Callback peer with job */
}
}
}
/* COPY AND PASTE FUNCTIONS... must find better way.. */
void BANG_route_finished_job(uuid_t uuid, BANG_job *job) {
assert(!uuid_is_null(uuid));
assert(job != NULL);
sqlite3_stmt *get_peer_route = prepare_select_statement(uuid);
if (sqlite3_step(get_peer_route) == SQLITE_ROW) {
if (sqlite3_column_int(get_peer_route,1) == REMOTE_ROUTE) {
/* TODO: Make a request to peer. */
} else {
/* const BANG_module *module = */sqlite3_column_blob(get_peer_route,2);
/* TODO: Callback peer with job */
}
}
}
void BANG_route_assertion_of_authority(uuid_t authority, uuid_t peer) {
assert(!uuid_is_null(authority));
assert(!uuid_is_null(peer));
sqlite3_stmt *get_peer_route = prepare_select_statement(peer);
if (sqlite3_step(get_peer_route) == SQLITE_ROW) {
if (sqlite3_column_int(get_peer_route,1) == REMOTE_ROUTE) {
/* TODO: Make a request to peer. */
} else {
const BANG_module *module = sqlite3_column_blob(get_peer_route,2);
BANG_module_callback_jobs_available(module,authority,peer);
}
}
}
void BANG_route_send_message(uuid_t uuid, char *message) {
assert(!uuid_is_null(uuid));
assert(message != NULL);
sqlite3_stmt *get_peer_route = prepare_select_statement(uuid);
if (sqlite3_step(get_peer_route) == SQLITE_ROW) {
if (sqlite3_column_int(get_peer_route,1) == REMOTE_ROUTE) {
/* TODO: Make a request to peer. */
} else {
/* Might as well print it out here, no reason to
* do stuipd contorions like making a call back
* function */
fprintf(stderr,"%s",message);
}
}
}
int BANG_route_get_peer_id(uuid_t uuid) {
assert(!uuid_is_null(uuid));
sqlite3_stmt *get_peer_route = prepare_select_statement(uuid);
if (sqlite3_step(get_peer_route) == SQLITE_ROW) {
if (sqlite3_column_int(get_peer_route,1) == REMOTE_ROUTE) {
/* TODO: Make a request to peer. */
return sqlite3_column_int(get_peer_route,3);
}
}
return - 1;
}
static void insert_route(uuid_t uuid, int remote, BANG_module *module, int peer_id, char *module_name, unsigned char *module_version) {
assert(!uuid_is_null(uuid));
assert(remote == LOCAL_ROUTE || remote == REMOTE_ROUTE);
assert(peer_id >= 0);
assert(module_name != NULL);
assert(module_version != NULL);
sqlite3_stmt *insert;
sqlite3_prepare_v2(db,"INSERT INTO mappings (route_uuid,remote,module,peer_id,name,text) VALUES (?,?,?,?,?)",85,&insert,NULL);
sqlite3_bind_blob(insert,1,uuid,sizeof(uuid_t),SQLITE_STATIC);
sqlite3_bind_int(insert,2,remote);
sqlite3_bind_blob(insert,3,module,sizeof(BANG_module*),SQLITE_STATIC);
sqlite3_bind_int(insert,4,peer_id);
sqlite3_bind_text(insert,5,module_name,-1,SQLITE_STATIC);
sqlite3_bind_blob(insert,6,module_version,LENGTH_OF_VERSION,SQLITE_STATIC);
sqlite3_step(insert);
sqlite3_finalize(insert);
}
void BANG_register_module_route(BANG_module *module) {
assert(module != NULL);
/* MORE DEREFENCES THAN YOU CAN HANDLE!
* Create a uuid and insert into the module.
*/
module->info->peers_info->uuids = calloc(1,sizeof(uuid_t));
module->info->my_id = 0;
uuid_generate(module->info->peers_info->uuids[module->info->my_id]);
module->info->peers_info->peer_number = 1;
module->info->peers_info->validity[module->info->my_id] = 1;
/* Insert the route in the database. */
insert_route(module->info->peers_info->uuids[module->info->my_id],LOCAL_ROUTE,module,-1,module->module_name,module->module_version);
}
void BANG_register_peer_route(uuid_t uuid, int peer, char *module_name, unsigned char* module_version) {
assert(!uuid_is_null(uuid));
assert(peer >= 0);
assert(module_name != NULL);
assert(module_version != NULL);
insert_route(uuid,REMOTE_ROUTE,NULL,peer,module_name,module_version);
}
void BANG_route_init() {
#ifdef BDEBUG_1
fprintf(stderr,"BANG route initializing.\n");
#endif
sqlite3_close(db);
}
void BANG_route_close() {
#ifdef BDEBUG_1
fprintf(stderr,"BANG route closing.\n");
#endif
/* Keep the mappings database in memory. */
sqlite3_open_v2(":memory",&db,SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX,NULL);
/*TODO: check for errors.
* Create database.
*/
sqlite3_exec(db,DB_SCHEMA,NULL,NULL,NULL);
}