4
4
5
5
#define ERL_FUNCTION (FUNCTION_NAME ) static ERL_NIF_TERM FUNCTION_NAME(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
6
6
7
- #define ERL_FUNCTION_GETTER (NAME , GETTER ) \
8
- ERL_FUNCTION(NAME) \
9
- { \
10
- uintptr_t _handle = get_handle_from_term(env, argv[0]); \
11
- IF_ERROR(_handle == 0, "invalid first argument"); \
12
- uintptr_t _res = GETTER(_handle); \
13
- return get_handle_result(env, _res); \
7
+ #define ERL_FUNCTION_GETTER (NAME , RECV_TYPE , ATTR_TYPE , GETTER ) \
8
+ ERL_FUNCTION(NAME) \
9
+ { \
10
+ uintptr_t _handle = get_handle_from_term(env, RECV_TYPE, argv[0]); \
11
+ IF_ERROR(_handle == 0, "invalid first argument"); \
12
+ uintptr_t _res = GETTER(_handle); \
13
+ return get_handle_result(env, ATTR_TYPE, _res); \
14
14
}
15
15
16
16
#define IF_ERROR (COND , MSG ) \
19
19
return make_error_msg(env, (MSG)); \
20
20
}
21
21
22
- #define GET_HANDLE (TERM , NAME ) \
23
- ({ \
24
- uintptr_t _handle = get_handle_from_term(env, (TERM)); \
25
- IF_ERROR(_handle == 0, "invalid " NAME); \
26
- _handle; \
22
+ #define GET_HANDLE (TERM , TYPE ) \
23
+ ({ \
24
+ uintptr_t _handle = get_handle_from_term(env, (TYPE), ( TERM)); \
25
+ IF_ERROR(_handle == 0, "invalid " #TYPE); \
26
+ _handle; \
27
27
})
28
28
29
29
#define NIF_ENTRY (FUNCTION_NAME , ARITY ) \
@@ -38,38 +38,52 @@ const uint64_t BUFFER_SIZE = 4096;
38
38
/* NIF Setup */
39
39
/*************/
40
40
41
- ErlNifResourceType * Option_type ;
41
+ ErlNifResourceType * Option ;
42
+ ErlNifResourceType * Host ;
43
+ ErlNifResourceType * Peerstore ;
44
+ ErlNifResourceType * peer_ID ;
45
+ ErlNifResourceType * Multiaddr_arr ;
46
+ ErlNifResourceType * Stream ;
42
47
43
48
// Resource type helpers
44
- void Option_type_cleanup (ErlNifEnv * env , void * arg )
49
+ void handle_cleanup (ErlNifEnv * env , void * arg )
45
50
{
46
51
uintptr_t handle = (uintptr_t )arg ;
47
52
DeleteHandle (handle );
48
53
}
49
54
55
+ static int open_resource_types (ErlNifEnv * env , ErlNifResourceFlags flags )
56
+ {
57
+ int ok = 0 ;
58
+ ok &= NULL == (Option = enif_open_resource_type (env , NULL , "Option_type" , handle_cleanup , flags , NULL ));
59
+ ok &= NULL == (Host = enif_open_resource_type (env , NULL , "Host_type" , handle_cleanup , flags , NULL ));
60
+ ok &= NULL == (Peerstore = enif_open_resource_type (env , NULL , "Peerstore_type" , handle_cleanup , flags , NULL ));
61
+ ok &= NULL == (peer_ID = enif_open_resource_type (env , NULL , "peer_ID_type" , handle_cleanup , flags , NULL ));
62
+ ok &= NULL == (Multiaddr_arr = enif_open_resource_type (env , NULL , "Multiaddr_arr_type" , handle_cleanup , flags , NULL ));
63
+ ok &= NULL == (Stream = enif_open_resource_type (env , NULL , "Stream_type" , handle_cleanup , flags , NULL ));
64
+ return ok ? 1 : 0 ;
65
+ }
66
+
50
67
static int load (ErlNifEnv * env , void * * priv_data , ERL_NIF_TERM load_info )
51
68
{
52
- ErlNifResourceFlags flags = ERL_NIF_RT_CREATE | ERL_NIF_RT_TAKEOVER ;
53
- Option_type = enif_open_resource_type (env , NULL , "Option_type" , Option_type_cleanup , flags , NULL );
54
- return Option_type == NULL ? 1 : 0 ;
69
+ return open_resource_types (env , ERL_NIF_RT_CREATE | ERL_NIF_RT_TAKEOVER );
55
70
}
56
71
57
72
static int upgrade (ErlNifEnv * env , void * * priv_data , void * * old_priv_data ,
58
73
ERL_NIF_TERM load_info )
59
74
{
60
- ErlNifResourceFlags flags = ERL_NIF_RT_TAKEOVER ;
61
- Option_type = enif_open_resource_type (env , NULL , "Option_type" , Option_type_cleanup , flags , NULL );
62
- return Option_type == NULL ? 1 : 0 ;
75
+ return open_resource_types (env , ERL_NIF_RT_TAKEOVER );
63
76
}
64
77
65
78
/***********/
66
79
/* Helpers */
67
80
/***********/
68
81
69
- static uintptr_t get_handle_from_term (ErlNifEnv * env , ERL_NIF_TERM term )
82
+ static uintptr_t get_handle_from_term (ErlNifEnv * env , ErlNifResourceType * type , ERL_NIF_TERM term )
70
83
{
71
- uintptr_t handle ;
72
- return enif_get_uint64 (env , term , & handle ) ? handle : 0 ;
84
+ uintptr_t * obj ;
85
+ int result = enif_get_resource (env , term , type , (void * * )& obj );
86
+ return (!result || obj == NULL ) ? 0 : * obj ;
73
87
}
74
88
75
89
static ERL_NIF_TERM _make_error_msg (ErlNifEnv * env , uint len , const char * msg )
@@ -90,10 +104,14 @@ static ERL_NIF_TERM make_ok_tuple2(ErlNifEnv *env, ERL_NIF_TERM term)
90
104
return enif_make_tuple2 (env , enif_make_atom (env , "ok" ), term );
91
105
}
92
106
93
- static ERL_NIF_TERM get_handle_result (ErlNifEnv * env , uintptr_t handle )
107
+ static ERL_NIF_TERM get_handle_result (ErlNifEnv * env , ErlNifResourceType * type , uintptr_t handle )
94
108
{
95
109
IF_ERROR (handle == 0 , "invalid handle returned" );
96
- return make_ok_tuple2 (env , enif_make_uint64 (env , handle ));
110
+ uintptr_t * obj = enif_alloc_resource (type , sizeof (uintptr_t ));
111
+ IF_ERROR (obj == NULL , "couldn't create resource" );
112
+ * obj = handle ;
113
+ ERL_NIF_TERM term = enif_make_resource (env , obj );
114
+ return make_ok_tuple2 (env , term );
97
115
}
98
116
99
117
/*********/
@@ -108,12 +126,7 @@ ERL_FUNCTION(listen_addr_strings)
108
126
109
127
uintptr_t handle = ListenAddrStrings (listen_addr );
110
128
111
- IF_ERROR (handle == 0 , "invalid handle returned" );
112
- uintptr_t * obj = enif_alloc_resource (Option_type , sizeof (uintptr_t ));
113
- IF_ERROR (obj == NULL , "couldn't create resource" );
114
- * obj = handle ;
115
- ERL_NIF_TERM term = enif_make_resource (env , obj );
116
- return make_ok_tuple2 (env , term );
129
+ return get_handle_result (env , Option , handle );
117
130
}
118
131
119
132
/****************/
@@ -130,26 +143,24 @@ ERL_FUNCTION(host_new)
130
143
while (!enif_is_empty_list (env , tail ) && i < MAX_OPTIONS )
131
144
{
132
145
enif_get_list_cell (env , tail , & head , & tail );
133
- uintptr_t * obj ;
134
- enif_get_resource (env , head , Option_type , (void * * )& obj );
135
- IF_ERROR (obj == NULL , "invalid option" );
136
- options [i ++ ] = * obj ;
146
+ uintptr_t handle = GET_HANDLE (head , Option );
147
+ options [i ++ ] = handle ;
137
148
}
138
149
GoSlice go_options = {options , i , MAX_OPTIONS };
139
150
uintptr_t result = HostNew (go_options );
140
- return get_handle_result (env , result );
151
+ return get_handle_result (env , Host , result );
141
152
}
142
153
143
154
ERL_FUNCTION (host_close )
144
155
{
145
- uintptr_t host = GET_HANDLE (argv [0 ], "host" );
156
+ uintptr_t host = GET_HANDLE (argv [0 ], Host );
146
157
HostClose (host );
147
158
return enif_make_atom (env , "ok" );
148
159
}
149
160
150
161
ERL_FUNCTION (host_set_stream_handler )
151
162
{
152
- uintptr_t host = GET_HANDLE (argv [0 ], "host" );
163
+ uintptr_t host = GET_HANDLE (argv [0 ], Host );
153
164
154
165
ErlNifBinary bin ;
155
166
IF_ERROR (!enif_inspect_binary (env , argv [1 ], & bin ), "invalid protocol ID" );
@@ -167,30 +178,30 @@ ERL_FUNCTION(host_set_stream_handler)
167
178
168
179
ERL_FUNCTION (host_new_stream )
169
180
{
170
- uintptr_t host = GET_HANDLE (argv [0 ], "host" );
171
- uintptr_t id = GET_HANDLE (argv [1 ], "peer id" );
181
+ uintptr_t host = GET_HANDLE (argv [0 ], Host );
182
+ uintptr_t id = GET_HANDLE (argv [1 ], peer_ID );
172
183
173
184
ErlNifBinary bin ;
174
185
IF_ERROR (!enif_inspect_binary (env , argv [2 ], & bin ), "invalid protocol ID" );
175
186
GoString proto_id = {(const char * )bin .data , bin .size };
176
187
177
- int result = NewStream (host , id , proto_id );
178
- return get_handle_result (env , result );
188
+ uintptr_t result = NewStream (host , id , proto_id );
189
+ return get_handle_result (env , Stream , result );
179
190
}
180
191
181
- ERL_FUNCTION_GETTER (host_peerstore , Peerstore )
182
- ERL_FUNCTION_GETTER (host_id , ID )
183
- ERL_FUNCTION_GETTER (host_addrs , Addrs )
192
+ ERL_FUNCTION_GETTER (host_peerstore , Host , Peerstore , HostPeerstore )
193
+ ERL_FUNCTION_GETTER (host_id , Host , peer_ID , HostID )
194
+ ERL_FUNCTION_GETTER (host_addrs , Host , Multiaddr_arr , HostAddrs )
184
195
185
196
/*********************/
186
197
/* Peerstore methods */
187
198
/*********************/
188
199
189
200
ERL_FUNCTION (peerstore_add_addrs )
190
201
{
191
- uintptr_t ps = GET_HANDLE (argv [0 ], "peerstore" );
192
- uintptr_t id = GET_HANDLE (argv [1 ], "peer id" );
193
- uintptr_t addrs = GET_HANDLE (argv [2 ], "addrs" );
202
+ uintptr_t ps = GET_HANDLE (argv [0 ], Peerstore );
203
+ uintptr_t id = GET_HANDLE (argv [1 ], peer_ID );
204
+ uintptr_t addrs = GET_HANDLE (argv [2 ], Multiaddr_arr );
194
205
u_long ttl ;
195
206
IF_ERROR (!enif_get_uint64 (env , argv [3 ], & ttl ), "invalid TTL" );
196
207
@@ -204,7 +215,7 @@ ERL_FUNCTION(peerstore_add_addrs)
204
215
205
216
ERL_FUNCTION (stream_read )
206
217
{
207
- uintptr_t stream = GET_HANDLE (argv [0 ], "stream" );
218
+ uintptr_t stream = GET_HANDLE (argv [0 ], Stream );
208
219
209
220
char buffer [BUFFER_SIZE ];
210
221
GoSlice go_buffer = {buffer , BUFFER_SIZE , BUFFER_SIZE };
@@ -221,7 +232,7 @@ ERL_FUNCTION(stream_read)
221
232
222
233
ERL_FUNCTION (stream_write )
223
234
{
224
- uintptr_t stream = GET_HANDLE (argv [0 ], "stream" );
235
+ uintptr_t stream = GET_HANDLE (argv [0 ], Stream );
225
236
226
237
ErlNifBinary bin ;
227
238
IF_ERROR (!enif_inspect_binary (env , argv [1 ], & bin ), "invalid data" );
@@ -235,7 +246,7 @@ ERL_FUNCTION(stream_write)
235
246
236
247
ERL_FUNCTION (stream_close )
237
248
{
238
- uintptr_t stream = GET_HANDLE (argv [0 ], "stream" );
249
+ uintptr_t stream = GET_HANDLE (argv [0 ], Stream );
239
250
StreamClose (stream );
240
251
return enif_make_atom (env , "ok" );
241
252
}
0 commit comments