serval-dna.c File Reference

re-implementation of the serval-dna daemon as a commotiond plugin More...

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <poll.h>
#include <serval.h>
#include <serval/conf.h>
#include "debug.h"
#include "plugin.h"
#include "socket.h"
#include "loop.h"
#include "util.h"
#include "list.h"
#include "tree.h"
#include "profile.h"
#include "cmd.h"
#include "serval-dna.h"
#include "crypto.h"

Classes

struct  co_alarm_t
 

Macros

#define _alarm   42
 
#define IS_ALARM(J)   (IS_EXT(J) && ((co_alarm_t *)J)->_exttype == _alarm)
 
#define SCHEDULE(X, Y, D)
 

Functions

int serval_socket_cb (co_obj_t *self, co_obj_t *context)
 
int serval_timer_cb (co_obj_t *self, co_obj_t **output, co_obj_t *context)
 
int _schedule (struct __sourceloc __whence, struct sched_ent *alarm)
 
int _unschedule (struct __sourceloc __whence, struct sched_ent *alarm)
 
int _watch (struct __sourceloc __whence, struct sched_ent *alarm)
 
int _unwatch (struct __sourceloc __whence, struct sched_ent *alarm)
 
int co_plugin_name (co_obj_t *self, co_obj_t **output, co_obj_t *params)
 
 SCHEMA (serval)
 
 SCHEMA (mdp)
 
int co_plugin_register (co_obj_t *self, co_obj_t **output, co_obj_t *params)
 
int co_plugin_init (co_obj_t *self, co_obj_t **output, co_obj_t *params)
 
int co_plugin_shutdown (co_obj_t *self, co_obj_t **output, co_obj_t *params)
 
int serval_daemon_handler (co_obj_t *self, co_obj_t **output, co_obj_t *params)
 

Variables

keyring_file * keyring
 
char * serval_path
 
co_socket_t co_socket_proto = {}
 
svl_crypto_ctxglobal_ctx = NULL
 
bool serval_registered = false
 
bool daemon_started = false
 
co_obj_terr_msg
 

Detailed Description

re-implementation of the serval-dna daemon as a commotiond plugin

Author
Dan Staples (dismantl), danst.nosp@m.aple.nosp@m.s@ope.nosp@m.ntec.nosp@m.hinst.nosp@m.itut.nosp@m.e.org

Macro Definition Documentation

#define SCHEDULE (   X,
  Y,
 
)
Value:
{ \
static struct profile_total _stats_##X={.name="" #X "",}; \
static struct sched_ent _sched_##X={\
.stats = &_stats_##X, \
.function=X,\
}; \
_sched_##X.alarm=(gettime_ms()+Y);\
_sched_##X.deadline=(gettime_ms()+Y+D);\
schedule(&_sched_##X); }

Function Documentation

int _schedule ( struct __sourceloc  __whence,
struct sched_ent *  alarm 
)

Overridden Serval function to schedule timed events

this messes up Serval's overlay interface setup

References co_list_append(), co_list_parse(), co_loop_add_timer(), and co_timer_create().

160  {
161 // DEBUG("###### SCHEDULE ######");
162  co_obj_t *timer = NULL, *node = NULL;
163 
164  CHECK(alarm->function,"No callback function associated with timer");
165  CHECK(!(node = co_list_parse(timer_alarms, _alarm_ptr_match_i, alarm)),"Trying to schedule duplicate alarm %p",alarm);
166 
167  time_ms_t now = gettime_ms();
168 
169  if (alarm->deadline < alarm->alarm)
170  alarm->deadline = alarm->alarm;
171 
172  CHECK(now - alarm->alarm <= 1000,"Alarm tried to schedule a deadline %lldms ago, from %s() %s:%d",
173  (now - alarm->deadline),
174  __whence.function,__whence.file,__whence.line);
175 
176  /** this messes up Serval's overlay interface setup */
177  // if the alarm has already expired, execute callback function
178 // if (alarm->deadline <= now) {
179 // DEBUG("ALREADY EXPIRED, DEADLINE %lld %lld",alarm->alarm, gettime_ms());
180 // alarm->function(alarm);
181 // return 0;
182 // }
183 
184 // DEBUG("NEW TIMER: ALARM %lld - %lld = %lld %p",alarm->alarm,now,alarm->alarm - now,alarm);
185  CHECK(alarm->alarm - now < 86400000,"Timer deadline is more than 24 hrs from now, ignoring");
186 
187  time_ms_t deadline_time;
188  struct timeval deadline;
189 // if (alarm->alarm - now > 1)
190  deadline_time = alarm->alarm;
191 // else
192 // deadline_time = alarm->deadline;
193 
194  deadline.tv_sec = deadline_time / 1000;
195  deadline.tv_usec = (deadline_time % 1000) * 1000;
196  if (deadline.tv_usec > 1000000) {
197  deadline.tv_sec++;
198  deadline.tv_usec %= 1000000;
199  }
200 
201  CHECK_MEM((timer = co_timer_create(deadline, serval_timer_cb, alarm)));
202  CHECK(co_loop_add_timer(timer,NULL),"Failed to add timer %ld.%06ld %p",deadline.tv_sec,deadline.tv_usec,alarm);
203  CHECK(co_list_append(timer_alarms,co_alarm_create(alarm)),"Failed to add to timer_alarms");
204 
205  return 0;
206 
207 error:
208  if (timer) free(timer);
209  return -1;
210 }
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_timer_create(struct timeval deadline, co_cb_t timer_cb, void *ptr)
malloc and initialize a timer
Definition: loop.c:476
Definition: obj.h:131
int co_loop_add_timer(co_obj_t *new_timer, co_obj_t *context)
schedules a new timer with the event loop
Definition: loop.c:397
co_obj_t * co_list_parse(co_obj_t *list, co_iter_t iter, void *context)
process list with given iterator function
Definition: list.c:233
int _unschedule ( struct __sourceloc  __whence,
struct sched_ent *  alarm 
)

Overridden Serval function to unschedule timed events

References co_list_delete(), co_list_parse(), co_loop_get_timer(), and co_loop_remove_timer().

213  {
214 // DEBUG("###### UNSCHEDULE ######");
215  co_obj_t *alarm_node = NULL, *timer = NULL;
216 
217 // CHECK((alarm_node = co_list_parse(timer_alarms, _alarm_ptr_match_i, alarm)),"Attempting to unschedule timer that is not scheduled");
218  if (!(alarm_node = co_list_parse(timer_alarms, _alarm_ptr_match_i, alarm))) goto error;
219  co_list_delete(timer_alarms,alarm_node);
220  co_obj_free(alarm_node);
221 
222  // Get the timer associated with the alarm
223  CHECK((timer = co_loop_get_timer(alarm,NULL)),"Could not find timer to remove");
224  CHECK(co_loop_remove_timer(timer,NULL),"Failed to remove timer from event loop");
225  co_obj_free(timer);
226 
227  return 0;
228 
229 error:
230  return -1;
231 }
int co_loop_remove_timer(co_obj_t *old_timer, co_obj_t *context)
removes a timer from the event loop
Definition: loop.c:429
co_obj_t * co_loop_get_timer(void *ptr, co_obj_t *context)
gets a socket that is registered with the event loop
Definition: loop.c:448
co_obj_t * co_list_delete(co_obj_t *list, co_obj_t *item)
delete specified item from list
Definition: list.c:457
Definition: obj.h:131
co_obj_t * co_list_parse(co_obj_t *list, co_iter_t iter, void *context)
process list with given iterator function
Definition: list.c:233
int _watch ( struct __sourceloc  __whence,
struct sched_ent *  alarm 
)

Overridden Serval function to register sockets with event loop

need to set: sock->fd sock->rfd sock->listen sock->uri sock->poll_cb sock->fd_registered sock->rfd_registered

References co_fd_create(), co_list_append(), co_list_parse(), co_loop_add_socket(), and serval_socket_cb().

234  {
235 // DEBUG("OVERRIDDEN WATCH FUNCTION!");
236  co_socket_t *sock = NULL;
237 
238  /** need to set:
239  * sock->fd
240  * sock->rfd
241  * sock->listen
242  * sock->uri
243  * sock->poll_cb
244  * sock->fd_registered
245  * sock->rfd_registered
246  */
247 
248  if ((alarm->_poll_index == 1) || co_list_parse(sock_alarms, _alarm_ptr_match_i, alarm)) {
249  WARN("Socket %d already registered: %d",alarm->poll.fd,alarm->_poll_index);
250  } else {
251  sock = (co_socket_t*)NEW(co_socket, co_socket);
252 
253  sock->fd = (co_fd_t*)co_fd_create((co_obj_t*)sock,alarm->poll.fd);
254  sock->rfd_lst = co_list16_create();
255  sock->listen = true;
256  // NOTE: Aren't able to get the Serval socket uris, so instead use string representation of fd
257  sock->uri = h_calloc(1,6);
258  hattach(sock->uri,sock);
259  sprintf(sock->uri,"%d",sock->fd->fd);
260  sock->fd_registered = false;
261  sock->local = NULL;
262  sock->remote = NULL;
263 
264  sock->poll_cb = serval_socket_cb;
265 
266  // register sock
267  CHECK(co_loop_add_socket((co_obj_t*)sock, (co_obj_t*)sock->fd) == 1,"Failed to add socket %d",sock->fd->fd);
268  DEBUG("Successfully added socket %d",sock->fd->fd);
269 
270  sock->fd_registered = true;
271  // NOTE: it would be better to get the actual poll index from the event loop instead of this:
272  alarm->_poll_index = 1;
273  alarm->poll.revents = 0;
274 
275  CHECK(co_list_append(sock_alarms, co_alarm_create(alarm)),"Failed to add to sock_alarms");
276  DEBUG("Successfully added to sock_alarms %p",alarm);
277  }
278 
279  return 0;
280 error:
281  if (sock) free((co_obj_t*)sock);
282  return -1;
283 }
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_loop_add_socket(co_obj_t *new_sock, co_obj_t *context)
adds a new socket to the event loop (for it to listen on)
Definition: loop.c:330
int serval_socket_cb(co_obj_t *self, co_obj_t *context)
Definition: serval-dna.c:117
Definition: obj.h:131
Definition: socket.h:65
Definition: socket.h:48
co_obj_t * co_list_parse(co_obj_t *list, co_iter_t iter, void *context)
process list with given iterator function
Definition: list.c:233
co_obj_t * co_fd_create(co_obj_t *parent, int fd)
creates a file descriptor object
Definition: socket.c:47
int serval_socket_cb ( co_obj_t self,
co_obj_t context 
)

Callback function for when Serval socket has data to read

References co_list_parse().

Referenced by _watch().

117  {
118 // DEBUG("SERVAL_SOCKET_CB");
119  co_socket_t *sock = (co_socket_t*)self;
120  co_obj_t *node = NULL;
121  struct sched_ent *alarm = NULL;
122 
123  // find alarm associated w/ sock, call alarm->function(alarm)
124  if ((node = co_list_parse(sock_alarms, _alarm_fd_match_i, &sock->fd->fd))) {
125  alarm = ((co_alarm_t*)node)->alarm;
126  alarm->poll.revents = sock->events;
127 
128  alarm->function(alarm); // Serval callback function associated with alarm/socket
129  alarm->poll.revents = 0;
130 
131  return 1;
132  }
133 
134  return 0;
135 }
Definition: obj.h:131
Definition: socket.h:65
co_obj_t * co_list_parse(co_obj_t *list, co_iter_t iter, void *context)
process list with given iterator function
Definition: list.c:233
Definition: serval-dna.c:60