<commit_before>#include <stdlib.h>
#include <stdio.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 "serval-dna.h"
#include "client.h"
#include "crypto.h"

#define DEFAULT_SID "0000000000000000000000000000000000000000000000000000000000000000"
#define DEFAULT_MDP_PATH "/etc/commotion/keys.d/mdp.keyring/serval.keyring"
#define DEFAULT_SERVAL_PATH "/var/serval-node"

// Types & constructors

/* Extension type */
#define _alarm 42

#define IS_ALARM(J) (IS_EXT(J) && ((co_alarm_t *)J)->_exttype == _alarm)

typedef struct {
  co_obj_t _header;
  uint8_t _exttype;
  uint8_t _len;
  struct sched_ent *alarm;
} co_alarm_t;

static co_obj_t *co_alarm_create(struct sched_ent *alarm) {
  co_alarm_t *output = h_calloc(1,sizeof(co_alarm_t));
  CHECK_MEM(output);
  output->_header._type = _ext8;
  output->_exttype = _alarm;
  output->_len = (sizeof(co_alarm_t));
  output->alarm = alarm;
  return (co_obj_t*)output;
error:
  return NULL;
}

// Globals

extern keyring_file *mdp_keyring;
extern unsigned char *mdp_key;
extern int mdp_key_len;

keyring_file *co_keyring = NULL;
char *serval_path = NULL;
co_socket_t co_socket_proto = {};

static co_obj_t *sock_alarms = NULL;
static co_obj_t *timer_alarms = NULL;

// Private functions

/** Compares co_socket fd to serval alarm fd */
static co_obj_t *_alarm_fd_match_i(co_obj_t *alarms, co_obj_t *alarm, void *fd) {
  if(!IS_ALARM(alarm)) return NULL;
  const struct sched_ent *this_alarm = ((co_alarm_t*)alarm)->alarm;
  const int *this_fd = fd;
  if (this_alarm->poll.fd == *this_fd) return alarm;
  return NULL;
}

static co_obj_t *_alarm_ptr_match_i(co_obj_t *alarms, co_obj_t *alarm, void *ptr) {
  if(!IS_ALARM(alarm)) return NULL;
  const struct sched_ent *this_alarm = ((co_alarm_t*)alarm)->alarm;
  const void *this_ptr = ptr;
//   DEBUG("ALARM_PTR_MATCH: %p %p",this_alarm,this_ptr);
  if (this_alarm == this_ptr) return alarm;
  return NULL;
}

// Public functions

/** Callback function for when Serval socket has data to read */
int serval_socket_cb(co_obj_t *self, co_obj_t *context) {
  DEBUG("SERVAL_SOCKET_CB");
  co_socket_t *sock = (co_socket_t*)self;
  co_obj_t *node = NULL;
  struct sched_ent *alarm = NULL;
  
  // find alarm associated w/ sock, call alarm->function(alarm)
  if ((node = co_list_parse(sock_alarms, _alarm_fd_match_i, &sock->fd))) {
    alarm = ((co_alarm_t*)node)->alarm;
    alarm->poll.revents = sock->events;
    
//     DEBUG("CALLING ALARM FUNC");
    alarm->function(alarm); // Serval callback function associated with alarm/socket
    return 1;
  }
  
  return 0;
}

int serval_timer_cb(co_obj_t *self, co_obj_t **output, co_obj_t *context) {
  DEBUG("SERVAL_TIMER_CB");
  co_obj_t *timer = self;
  struct sched_ent *alarm = NULL;
  co_obj_t *alarm_node = NULL;
  
  // find alarm associated w/ timer, call alarm->function(alarm)
  if ((alarm_node = co_list_parse(timer_alarms, _alarm_ptr_match_i, ((co_timer_t*)timer)->ptr)) == NULL) {
    ERROR("Failed to find alarm for callback");
    exit(1);
  }
  alarm = ((co_alarm_t*)alarm_node)->alarm;
  co_list_delete(timer_alarms,alarm_node);
  co_obj_free(alarm_node);
  
  co_obj_free(timer);
    
//   DEBUG("# TIMER ALARMS: %lu",co_list_length(timer_alarms));
//   DEBUG("CALLING TIMER FUNC");
  alarm->function(alarm); // Serval callback function associated with alarm/socket

  return 0;
error:
  return 1;
}

/** Overridden Serval function to schedule timed events */
int _schedule(struct __sourceloc __whence, struct sched_ent *alarm) {
  DEBUG("###### SCHEDULE ######");
  co_obj_t *timer = NULL, *node = NULL;
  
  CHECK(alarm->function,"No callback function associated with timer");
  CHECK(!(node = co_list_parse(timer_alarms, _alarm_ptr_match_i, alarm)),"Trying to schedule duplicate alarm %p",alarm);
  
  time_ms_t now = gettime_ms();
  
  if (alarm->alarm - now > 86400000 || alarm->deadline - now > 86400000) {
    DEBUG("alarm: %lld %lld",alarm->alarm, now);
    DEBUG("deadline: %lld %lld",alarm->deadline, now);
    now;
  }
  
  if (alarm->deadline < alarm->alarm)
    alarm->deadline = alarm->alarm;
  
  CHECK(now - alarm->deadline <= 1000,"Alarm tried to schedule a deadline %lldms ago, from %s() %s:%d",
	 (now - alarm->deadline),
	 __whence.function,__whence.file,__whence.line);
  
  // if the alarm has already expired, execute callback function
  if (alarm->alarm <= now) {
    DEBUG("ALREADY EXPIRED, DEADLINE %lld %lld",alarm->alarm, gettime_ms());
    alarm->function(alarm);
    return 0;
  }
  
  DEBUG("NEW TIMER: ALARM %lld - %lld = %lld %p",alarm->alarm,now,alarm->alarm - now,alarm);
  CHECK(alarm->alarm - now < 86400000,"Timer deadline is more than 24 hrs from now, ignoring");

  time_ms_t deadline_time;
  struct timeval deadline;
//   if (alarm->alarm - now > 1)
    deadline_time = alarm->alarm;
//   else
//     deadline_time = alarm->deadline;
  deadline.tv_sec = deadline_time / 1000;
  deadline.tv_usec = (deadline_time % 1000) * 1000;<commit_msg>immediately firing timer alarms breaks serval overlay iface setup<commit_after>#include <stdlib.h>
#include <stdio.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 "serval-dna.h"
#include "client.h"
#include "crypto.h"

#define DEFAULT_SID "0000000000000000000000000000000000000000000000000000000000000000"
#define DEFAULT_MDP_PATH "/etc/commotion/keys.d/mdp.keyring/serval.keyring"
#define DEFAULT_SERVAL_PATH "/var/serval-node"

// Types & constructors

/* Extension type */
#define _alarm 42

#define IS_ALARM(J) (IS_EXT(J) && ((co_alarm_t *)J)->_exttype == _alarm)

typedef struct {
  co_obj_t _header;
  uint8_t _exttype;
  uint8_t _len;
  struct sched_ent *alarm;
} co_alarm_t;

static co_obj_t *co_alarm_create(struct sched_ent *alarm) {
  co_alarm_t *output = h_calloc(1,sizeof(co_alarm_t));
  CHECK_MEM(output);
  output->_header._type = _ext8;
  output->_exttype = _alarm;
  output->_len = (sizeof(co_alarm_t));
  output->alarm = alarm;
  return (co_obj_t*)output;
error:
  return NULL;
}

// Globals

extern keyring_file *mdp_keyring;
extern unsigned char *mdp_key;
extern int mdp_key_len;

keyring_file *co_keyring = NULL;
char *serval_path = NULL;
co_socket_t co_socket_proto = {};

static co_obj_t *sock_alarms = NULL;
static co_obj_t *timer_alarms = NULL;

// Private functions

/** Compares co_socket fd to serval alarm fd */
static co_obj_t *_alarm_fd_match_i(co_obj_t *alarms, co_obj_t *alarm, void *fd) {
  if(!IS_ALARM(alarm)) return NULL;
  const struct sched_ent *this_alarm = ((co_alarm_t*)alarm)->alarm;
  const int *this_fd = fd;
  if (this_alarm->poll.fd == *this_fd) return alarm;
  return NULL;
}

static co_obj_t *_alarm_ptr_match_i(co_obj_t *alarms, co_obj_t *alarm, void *ptr) {
  if(!IS_ALARM(alarm)) return NULL;
  const struct sched_ent *this_alarm = ((co_alarm_t*)alarm)->alarm;
  const void *this_ptr = ptr;
//   DEBUG("ALARM_PTR_MATCH: %p %p",this_alarm,this_ptr);
  if (this_alarm == this_ptr) return alarm;
  return NULL;
}

// Public functions

/** Callback function for when Serval socket has data to read */
int serval_socket_cb(co_obj_t *self, co_obj_t *context) {
  DEBUG("SERVAL_SOCKET_CB");
  co_socket_t *sock = (co_socket_t*)self;
  co_obj_t *node = NULL;
  struct sched_ent *alarm = NULL;
  
  // find alarm associated w/ sock, call alarm->function(alarm)
  if ((node = co_list_parse(sock_alarms, _alarm_fd_match_i, &sock->fd))) {
    alarm = ((co_alarm_t*)node)->alarm;
    alarm->poll.revents = sock->events;
    
//     DEBUG("CALLING ALARM FUNC");
    alarm->function(alarm); // Serval callback function associated with alarm/socket
    return 1;
  }
  
  return 0;
}

int serval_timer_cb(co_obj_t *self, co_obj_t **output, co_obj_t *context) {
  DEBUG("SERVAL_TIMER_CB");
  co_obj_t *timer = self;
  struct sched_ent *alarm = NULL;
  co_obj_t *alarm_node = NULL;
  
  // find alarm associated w/ timer, call alarm->function(alarm)
  if ((alarm_node = co_list_parse(timer_alarms, _alarm_ptr_match_i, ((co_timer_t*)timer)->ptr)) == NULL) {
    ERROR("Failed to find alarm for callback");
    exit(1);
  }
  alarm = ((co_alarm_t*)alarm_node)->alarm;
  co_list_delete(timer_alarms,alarm_node);
  co_obj_free(alarm_node);
  
  co_obj_free(timer);
    
//   DEBUG("# TIMER ALARMS: %lu",co_list_length(timer_alarms));
//   DEBUG("CALLING TIMER FUNC");
  alarm->function(alarm); // Serval callback function associated with alarm/socket

  return 0;
error:
  return 1;
}

/** Overridden Serval function to schedule timed events */
int _schedule(struct __sourceloc __whence, struct sched_ent *alarm) {
  DEBUG("###### SCHEDULE ######");
  co_obj_t *timer = NULL, *node = NULL;
  
  CHECK(alarm->function,"No callback function associated with timer");
  CHECK(!(node = co_list_parse(timer_alarms, _alarm_ptr_match_i, alarm)),"Trying to schedule duplicate alarm %p",alarm);
  
  time_ms_t now = gettime_ms();
  
  if (alarm->alarm - now > 86400000 || alarm->deadline - now > 86400000) {
    DEBUG("alarm: %lld %lld",alarm->alarm, now);
    DEBUG("deadline: %lld %lld",alarm->deadline, now);
    now;
  }
  
  if (alarm->deadline < alarm->alarm)
    alarm->deadline = alarm->alarm;
  
  CHECK(now - alarm->deadline <= 1000,"Alarm tried to schedule a deadline %lldms ago, from %s() %s:%d",
	 (now - alarm->deadline),
	 __whence.function,__whence.file,__whence.line);
  
  // if the alarm has already expired, execute callback function
//   if (alarm->deadline <= now) {
//     DEBUG("ALREADY EXPIRED, DEADLINE %lld %lld",alarm->alarm, gettime_ms());
//     alarm->function(alarm);
//     return 0;
//   }
  
  DEBUG("NEW TIMER: ALARM %lld - %lld = %lld %p",alarm->alarm,now,alarm->alarm - now,alarm);
  CHECK(alarm->alarm - now < 86400000,"Timer deadline is more than 24 hrs from now, ignoring");

  time_ms_t deadline_time;
  struct timeval deadline;
//   if (alarm->alarm - now > 1)
    deadline_time = alarm->alarm;
//   else
//     deadline_time = alarm->deadline;
  deadline.tv_sec = deadline_time / 1000;
  deadline.tv_usec = (deadline_time % 1000) * 1000;
{'fraction_non_alphanumeric': 0.14063714063714064, 'fraction_numerical': 0.023115773115773116, 'mean_word_length': 4.408088235294118, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 91, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3690153', 'n_tokens_mistral': 4156, 'n_tokens_neox': 3925, 'n_words': 885}