commotion.c File Reference

Client API for the Commotion Daemon. More...

#include <stdlib.h>
#include <stdbool.h>
#include <sys/socket.h>
#include "debug.h"
#include "obj.h"
#include "list.h"
#include "tree.h"
#include "socket.h"
#include "util.h"
#include "msg.h"
#include "commotion.h"

Macros

#define REQUEST_MAX   4096
 
#define RESPONSE_MAX   4096
 

Functions

int co_init (void)
 initializes API
 
int co_shutdown (void)
 shuts down the API
 
co_obj_tco_connect (const char *uri, const size_t ulen)
 creates a connection to Commotion daemon at the given URI More...
 
int co_disconnect (co_obj_t *connection)
 closes connection to Commotion daemon More...
 
co_obj_tco_request_create (void)
 create an API request
 
int co_request_append (co_obj_t *request, co_obj_t *object)
 appends object to request More...
 
int co_request_append_str (co_obj_t *request, const char *s, const size_t slen)
 appends string to request More...
 
int co_request_append_bin (co_obj_t *request, const char *s, const size_t slen)
 appends byte array to request More...
 
int co_request_append_int (co_obj_t *request, const int i)
 appends int to request More...
 
int co_request_append_uint (co_obj_t *request, const unsigned int i)
 appends unsigned int to request More...
 
int co_call (co_obj_t *connection, co_obj_t **response, const char *method, const size_t mlen, co_obj_t *request)
 sense procedure call to daemon More...
 
co_obj_tco_response_get (co_obj_t *response, const char *key, const size_t klen)
 retrieve object from response More...
 
size_t co_response_get_str (co_obj_t *response, char **output, const char *key, const size_t klen)
 retrieve string from response More...
 
size_t co_response_get_bin (co_obj_t *response, char **output, const char *key, const size_t klen)
 retrieve byte array from response More...
 
int co_response_get_uint (co_obj_t *response, unsigned long *output, const char *key, const size_t klen)
 retrieve unsigned int from response More...
 
int co_response_get_int (co_obj_t *response, signed long *output, const char *key, const size_t klen)
 retrieve signed int from response More...
 
int co_response_get_bool (co_obj_t *response, bool *output, const char *key, const size_t klen)
 retrieve bool from response More...
 
int co_response_print (co_obj_t *response)
 print response object More...
 
void co_free (co_obj_t *object)
 free API objects More...
 

Variables

co_socket_t unix_socket_proto
 

Detailed Description

Client API for the Commotion Daemon.

Author
Josh King (jheretic), jking.nosp@m.@cha.nosp@m.mbana.nosp@m..net

Function Documentation

int co_call ( co_obj_t connection,
co_obj_t **  response,
const char *  method,
const size_t  mlen,
co_obj_t request 
)

sense procedure call to daemon

Parameters
connectioncontext object for connection
responsepointer to response buffer
methodmethod name
mlenlength of method name
requestrequest object to send

References co_list_element(), co_list_import(), and co_request_alloc().

187 {
188  CHECK(method != NULL && mlen > 0 && mlen < UINT8_MAX, "Invalid method name.");
189  CHECK(connection != NULL && IS_SOCK(connection), "Invalid connection.");
190  co_obj_t *params = NULL, *rlist = NULL, *rtree = NULL;
191  int retval = 0;
192  size_t reqlen = 0;
193  ssize_t resplen = 0;
194  char req[REQUEST_MAX];
195  char resp[RESPONSE_MAX];
196  if(request != NULL)
197  {
198  CHECK(IS_LIST(request), "Not a valid request.");
199  params = request;
200  }
201  else
202  {
203  params = co_list16_create();
204  }
205  co_obj_t *m = co_str8_create(method, mlen, 0);
206  reqlen = co_request_alloc(req, sizeof(req), m, params);
207  CHECK(((co_socket_t*)connection)->send((co_obj_t*)((co_socket_t*)connection)->fd, req, reqlen) != -1, "Send error!");
208  if((resplen = ((co_socket_t*)connection)->receive(connection, (co_obj_t*)((co_socket_t*)connection)->fd, resp, sizeof(resp))) > 0)
209  {
210  CHECK(co_list_import(&rlist, resp, resplen) > 0, "Failed to parse response.");
211  rtree = co_list_element(rlist, 3);
212  if(!IS_NIL(rtree))
213  {
214  retval = 1;
215  }
216  else
217  {
218  rtree = co_list_element(rlist, 2);
219  retval = 0;
220  }
221  if(rtree != NULL && IS_TREE(rtree))
222  {
223  *response = rtree;
224  hattach(*response, _pool);
225  }
226  else SENTINEL("Invalid response.");
227  }
228  else SENTINEL("Failed to receive data.");
229 
230  co_obj_free(m);
231  if(params != request) co_obj_free(params);
232  return retval;
233 
234 error:
235  co_obj_free(m);
236  if(params != request) co_obj_free(params);
237  return retval;
238 }
size_t co_request_alloc(char *output, const size_t olen, const co_obj_t *method, co_obj_t *param)
allocate request
Definition: msg.c:64
Definition: obj.h:131
Definition: socket.h:65
size_t co_list_import(co_obj_t **list, const char *input, const size_t ilen)
import list from raw representation
Definition: list.c:562
co_obj_t * co_list_element(co_obj_t *list, const unsigned int index)
return item at specified position in list
Definition: list.c:483
co_obj_t* co_connect ( const char *  uri,
const size_t  ulen 
)

creates a connection to Commotion daemon at the given URI

Parameters
uriURI string
ulenlength of URI string

References co_list_append().

85 {
86  CHECK_MEM(_sockets);
87  CHECK(uri != NULL && ulen > 0, "Invalid URI.");
88  co_obj_t *socket = NEW(co_socket, unix_socket);
89  hattach(socket, _pool);
90  CHECK((((co_socket_t*)socket)->connect(socket, uri)), "Failed to connect to commotiond at %s\n", uri);
91  co_list_append(_sockets, socket);
92  return socket;
93 error:
94  co_obj_free(socket);
95  return NULL;
96 }
int co_list_append(co_obj_t *list, co_obj_t *new_obj)
insert new item at end of list
Definition: list.c:425
Definition: obj.h:131
Definition: socket.h:65
int co_disconnect ( co_obj_t connection)

closes connection to Commotion daemon

Parameters
connectioncontext object for active connection

References co_list_delete().

100 {
101  CHECK_MEM(connection);
102  CHECK_MEM(_sockets);
103  CHECK(IS_SOCK(connection), "Specified object is not a Commotion socket.");
104 
105  co_list_delete(_sockets, connection);
106  ((co_socket_t*)connection)->destroy(connection);
107  return 1;
108 error:
109  return 0;
110 }
co_obj_t * co_list_delete(co_obj_t *list, co_obj_t *item)
delete specified item from list
Definition: list.c:457
Definition: socket.h:65
void co_free ( co_obj_t object)

free API objects

Parameters
objectobject to free
363 {
364  hattach(object, NULL);
365  co_obj_free(object);
366  return;
367 }
int co_request_append ( co_obj_t request,
co_obj_t object 
)

appends object to request

Parameters
requestrequest object to append to
objectobject to append

References co_list_append().

120 {
121  CHECK_MEM(request);
122  CHECK_MEM(object);
123  CHECK(IS_LIST(request), "Not a valid request.");
124  return co_list_append(request, object);
125 error:
126  return 0;
127 }
int co_list_append(co_obj_t *list, co_obj_t *new_obj)
insert new item at end of list
Definition: list.c:425
int co_request_append_bin ( co_obj_t request,
const char *  s,
const size_t  slen 
)

appends byte array to request

Parameters
requestrequest object to append to
sarray to append
slenlength of array to append

References co_list_append().

145 {
146  CHECK_MEM(request);
147  CHECK_MEM(s);
148  CHECK(IS_LIST(request), "Not a valid request.");
149  CHECK(slen < UINT32_MAX, "Binary is too large.");
150  if(slen > UINT16_MAX) return co_list_append(request, co_bin32_create(s, slen, 0));
151  if(slen > UINT8_MAX) return co_list_append(request, co_bin16_create(s, slen, 0));
152  return co_list_append(request, co_bin8_create(s, slen, 0));
153  error:
154  return 0;
155 }
int co_list_append(co_obj_t *list, co_obj_t *new_obj)
insert new item at end of list
Definition: list.c:425
int co_request_append_int ( co_obj_t request,
const int  i 
)

appends int to request

Parameters
requestrequest object to append to
iinteger to append

References co_list_append().

159 {
160  CHECK_MEM(request);
161  CHECK(IS_LIST(request), "Not a valid request.");
162  CHECK(i < INT64_MAX && i > INT64_MIN, "Integer out of bounds.");
163  if(i > INT32_MAX || i < INT32_MIN) return co_list_append(request, co_int64_create(i, 0));
164  if(i > INT16_MAX || i < INT16_MIN) return co_list_append(request, co_int32_create(i, 0));
165  if(i > INT8_MAX || i < INT8_MIN) return co_list_append(request, co_int16_create(i, 0));
166  return co_list_append(request, co_int8_create(i, 0));
167 error:
168  return 0;
169 }
int co_list_append(co_obj_t *list, co_obj_t *new_obj)
insert new item at end of list
Definition: list.c:425
int co_request_append_str ( co_obj_t request,
const char *  s,
const size_t  slen 
)

appends string to request

Parameters
requestrequest object to append to
sstring to append
slenlength of string to append

References co_list_append().

131 {
132  CHECK_MEM(request);
133  CHECK_MEM(s);
134  CHECK(IS_LIST(request), "Not a valid request.");
135  CHECK(slen < UINT32_MAX, "String is too large.");
136  if(slen > UINT16_MAX) return co_list_append(request, co_str32_create(s, slen, 0));
137  if(slen > UINT8_MAX) return co_list_append(request, co_str16_create(s, slen, 0));
138  return co_list_append(request, co_str8_create(s, slen, 0));
139 error:
140  return 0;
141 }
int co_list_append(co_obj_t *list, co_obj_t *new_obj)
insert new item at end of list
Definition: list.c:425
int co_request_append_uint ( co_obj_t request,
const unsigned int  i 
)

appends unsigned int to request

Parameters
requestrequest object to append to
iinteger to append

References co_list_append().

173 {
174  CHECK_MEM(request);
175  CHECK(IS_LIST(request), "Not a valid request.");
176  CHECK(i < UINT64_MAX, "Integer out of bounds.");
177  if(i > UINT32_MAX) return co_list_append(request, co_uint64_create(i, 0));
178  if(i > UINT16_MAX) return co_list_append(request, co_uint32_create(i, 0));
179  if(i > UINT8_MAX) return co_list_append(request, co_uint16_create(i, 0));
180  return co_list_append(request, co_uint8_create(i, 0));
181 error:
182  return 0;
183 }
int co_list_append(co_obj_t *list, co_obj_t *new_obj)
insert new item at end of list
Definition: list.c:425
co_obj_t* co_response_get ( co_obj_t response,
const char *  key,
const size_t  klen 
)

retrieve object from response

Parameters
responsepointer to response object
keyidentifier for response element to retrieve
klenlength of key name

References co_tree_find().

Referenced by co_response_get_bin(), co_response_get_bool(), co_response_get_int(), co_response_get_str(), and co_response_get_uint().

242 {
243  CHECK(response != NULL && IS_TREE(response), "Invalid response object.");
244  CHECK(key != NULL && klen > 0, "Invalid key.");
245  return co_tree_find(response, key, klen);
246 error:
247  return NULL;
248 }
co_obj_t * co_tree_find(const co_obj_t *root, const char *key, const size_t klen)
return value from given tree that corresponds to key
Definition: tree.c:173
size_t co_response_get_bin ( co_obj_t response,
char **  output,
const char *  key,
const size_t  klen 
)

retrieve byte array from response

Parameters
responsepointer to response object
outputpointer to output buffer
keyidentifier for response element to retrieve
klenlength of key name

References co_response_get().

263 {
264  co_obj_t *obj = co_response_get(response, key, klen);
265  CHECK(obj != NULL, "Response value %s does not exist.", key);
266  CHECK(IS_BIN(obj), "Value %s is not a binary.", key);
267  return co_obj_data(output, obj);
268  error:
269  return -1;
270 }
co_obj_t * co_response_get(co_obj_t *response, const char *key, const size_t klen)
retrieve object from response
Definition: commotion.c:241
Definition: obj.h:131
int co_response_get_bool ( co_obj_t response,
bool *  output,
const char *  key,
const size_t  klen 
)

retrieve bool from response

Parameters
responsepointer to response object
outputpointer to output buffer
keyidentifier for response element to retrieve
klenlength of key name

References co_response_get().

331  {
332  co_obj_t *obj = co_response_get(response, key, klen);
333  CHECK(obj != NULL, "Response value %s does not exist.", key);
334  switch(CO_TYPE(obj))
335  {
336  case _false:
337  *output = false;
338  break;
339  case _true:
340  *output = true;
341  break;
342  default:
343  SENTINEL("Not a boolean.");
344  break;
345  }
346  return 1;
347 
348  error:
349  return 0;
350 }
co_obj_t * co_response_get(co_obj_t *response, const char *key, const size_t klen)
retrieve object from response
Definition: commotion.c:241
Definition: obj.h:131
int co_response_get_int ( co_obj_t response,
signed long *  output,
const char *  key,
const size_t  klen 
)

retrieve signed int from response

Parameters
responsepointer to response object
outputpointer to output buffer
keyidentifier for response element to retrieve
klenlength of key name

References co_response_get().

303 {
304  co_obj_t *obj = co_response_get(response, key, klen);
305  CHECK(obj != NULL, "Response value %s does not exist.", key);
306  switch(CO_TYPE(obj))
307  {
308  case _int8:
309  *output = (unsigned long)(((co_int8_t *)obj)->data);
310  break;
311  case _int16:
312  *output = (unsigned long)(((co_int16_t *)obj)->data);
313  break;
314  case _int32:
315  *output = (unsigned long)(((co_int32_t *)obj)->data);
316  break;
317  case _int64:
318  *output = (unsigned long)(((co_int64_t *)obj)->data);
319  break;
320  default:
321  SENTINEL("Not an unsigned integer.");
322  break;
323  }
324  return 1;
325 
326 error:
327  return 0;
328 }
co_obj_t * co_response_get(co_obj_t *response, const char *key, const size_t klen)
retrieve object from response
Definition: commotion.c:241
Definition: obj.h:131
size_t co_response_get_str ( co_obj_t response,
char **  output,
const char *  key,
const size_t  klen 
)

retrieve string from response

Parameters
responsepointer to response object
outputpointer to output buffer
keyidentifier for response element to retrieve
klenlength of key name

References co_response_get().

252 {
253  co_obj_t *obj = co_response_get(response, key, klen);
254  CHECK(obj != NULL, "Response value %s does not exist.", key);
255  CHECK(IS_STR(obj), "Value %s is not a string.", key);
256  return co_obj_data(output, obj);
257 error:
258  return -1;
259 }
co_obj_t * co_response_get(co_obj_t *response, const char *key, const size_t klen)
retrieve object from response
Definition: commotion.c:241
Definition: obj.h:131
int co_response_get_uint ( co_obj_t response,
unsigned long *  output,
const char *  key,
const size_t  klen 
)

retrieve unsigned int from response

Parameters
responsepointer to response object
outputpointer to output buffer
keyidentifier for response element to retrieve
klenlength of key name

References co_response_get().

274 {
275  co_obj_t *obj = co_response_get(response, key, klen);
276  CHECK(obj != NULL, "Response value %s does not exist.", key);
277  switch(CO_TYPE(obj))
278  {
279  case _uint8:
280  *output = (unsigned long)(((co_uint8_t *)obj)->data);
281  break;
282  case _uint16:
283  *output = (unsigned long)(((co_uint16_t *)obj)->data);
284  break;
285  case _uint32:
286  *output = (unsigned long)(((co_uint32_t *)obj)->data);
287  break;
288  case _uint64:
289  *output = (unsigned long)(((co_uint64_t *)obj)->data);
290  break;
291  default:
292  SENTINEL("Not an unsigned integer.");
293  break;
294  }
295  return 1;
296 
297 error:
298  return 0;
299 }
co_obj_t * co_response_get(co_obj_t *response, const char *key, const size_t klen)
retrieve object from response
Definition: commotion.c:241
Definition: obj.h:131
int co_response_print ( co_obj_t response)

print response object

Parameters
responsepointer to response object

References co_tree_print().

354 {
355  CHECK(response != NULL && IS_TREE(response), "Invalid response object.");
356  return co_tree_print(response);
357 error:
358  return 0;
359 }
int co_tree_print(co_obj_t *tree)
print tree
Definition: tree.c:822