static int dispatch_queued(lo_server s) { char *path, *types, *data; queued_msg_list *head = s->queued; queued_msg_list *tailhead; lo_timetag disp_time; if (!head) { lo_throw(s, LO_INT_ERR, "attempted to dispatch with empty queue", "timeout"); return 1; } disp_time = head->ts; do { tailhead = head->next; path = ((queued_msg_list *)s->queued)->data; types = path + lo_strsize(path) + 1; data = types + lo_strsize(types); dispatch_method(s, path, types, data); free(((queued_msg_list *)s->queued)->data); free((queued_msg_list *)s->queued); s->queued = tailhead; head = tailhead; } while (head && lo_timetag_diff(head->ts, disp_time) < FLT_EPSILON); return 0; }
static int dispatch_queued(lo_server s) { queued_msg_list *head = s->queued; queued_msg_list *tailhead; lo_timetag disp_time; if (!head) { lo_throw(s, LO_INT_ERR, "attempted to dispatch with empty queue", "timeout"); return 1; } disp_time = head->ts; do { char *path; lo_message msg; tailhead = head->next; path = ((queued_msg_list *)s->queued)->path; msg = ((queued_msg_list *)s->queued)->msg; dispatch_method(s, path, msg); free(path); lo_message_free(msg); free((queued_msg_list *)s->queued); s->queued = tailhead; head = tailhead; } while (head && lo_timetag_diff(head->ts, disp_time) < FLT_EPSILON); return 0; }
/* returns the time in seconds until the next scheduled event */ double lo_server_next_event_delay(lo_server s) { if (s->queued) { lo_timetag now; double delay; lo_timetag_now(&now); delay = lo_timetag_diff(((queued_msg_list *)s->queued)->ts, now); delay = delay > 100.0 ? 100.0 : delay; delay = delay < 0.0 ? 0.0 : delay; return delay; } return 100.0; }
int jitter_handler(const char *path, const char *types, lo_arg **argv, int argc, lo_message data, void *user_data) { lo_timetag now; float jitter; lo_timetag_now(&now); jitter = fabs(lo_timetag_diff(now, argv[0]->t)); jitter_count++; //printf("jitter: %f\n", jitter); printf("%d expected: %x:%x received %x:%x\n", argv[1]->i, argv[0]->t.sec, argv[0]->t.frac, now.sec, now.frac); jitter_total += jitter; if (jitter > jitter_max) jitter_max = jitter; if (jitter < jitter_min) jitter_min = jitter; return 0; }
static void queue_data(lo_server s, lo_timetag ts, void *data, size_t len) { /* insert blob into future dispatch queue */ queued_msg_list *it = s->queued; queued_msg_list *prev = NULL; queued_msg_list *ins = calloc(1, sizeof(queued_msg_list)); ins->ts = ts; ins->len = len; ins->data = malloc(len); memcpy(ins->data, data, len); while (it) { if (lo_timetag_diff(it->ts, ts) > 0.0) { if (prev) { prev->next = ins; } else { s->queued = ins; ins->next = NULL; } ins->next = it; return; } prev = it; it = it->next; } /* fell through, so this event is last */ if (prev) { prev->next = ins; } else { s->queued = ins; } ins->next = NULL; }
static void queue_data(lo_server s, lo_timetag ts, const char *path, lo_message msg) { /* insert blob into future dispatch queue */ queued_msg_list *it = s->queued; queued_msg_list *prev = NULL; queued_msg_list *ins = calloc(1, sizeof(queued_msg_list)); ins->ts = ts; ins->path = strdup(path); ins->msg = msg; while (it) { if (lo_timetag_diff(it->ts, ts) > 0.0) { if (prev) { prev->next = ins; } else { s->queued = ins; ins->next = NULL; } ins->next = it; return; } prev = it; it = it->next; } /* fell through, so this event is last */ if (prev) { prev->next = ins; } else { s->queued = ins; } ins->next = NULL; }
double Pure_lo_timetag_diff(lo_timetag* arg0, lo_timetag* arg1) { return lo_timetag_diff(*arg0, *arg1); }
int lo_server_recv(lo_server s) { void *data; size_t size; char *path; char *types; double sched_time = lo_server_next_event_delay(s); #ifdef WIN32 fd_set ps; struct timeval stimeout; int res; #else struct pollfd ps; #endif again: if (sched_time > 0.01) { if (sched_time > 10.0) { sched_time = 10.0; } #ifdef WIN32 if(!initWSock()) return 0; ps.fd_count = 1; ps.fd_array[0] = s->socket; stimeout.tv_sec = sched_time; stimeout.tv_usec = (sched_time-stimeout.tv_sec)*1.e6; res = select(1,&ps,NULL,NULL,&stimeout); if(res == SOCKET_ERROR) { return 0; } if(!res) { sched_time = lo_server_next_event_delay(s); if (sched_time > 0.01) { goto again; } return dispatch_queued(s); } #else ps.fd = s->socket; ps.events = POLLIN | POLLPRI | POLLERR | POLLHUP; ps.revents = 0; poll(&ps, 1, (int)(sched_time * 1000.0)); if (ps.revents == POLLERR || ps.revents == POLLHUP) { return 0; } if (!ps.revents) { sched_time = lo_server_next_event_delay(s); if (sched_time > 0.01) { goto again; } return dispatch_queued(s); } #endif } else { return dispatch_queued(s); } if (s->protocol == LO_TCP) { data = lo_server_recv_raw_stream(s, &size); } else { data = lo_server_recv_raw(s, &size); } if (!data) { return 0; } path = data; types = data + lo_strsize(path); if (!strcmp(path, "#bundle")) { char *pos = types; uint32_t len; lo_timetag ts, now; lo_timetag_now(&now); ts.sec = lo_otoh32(*((uint32_t *)pos)); pos += 4; ts.frac = lo_otoh32(*((uint32_t *)pos)); pos += 4; while (pos - (char *)data < size) { len = lo_otoh32(*((uint32_t *)pos)); pos += 4; /* test for immedaite dispatch */ if ((ts.sec == 0 && ts.frac == 1) || lo_timetag_diff(ts, now) <= 0.0) { types = pos + lo_strsize(pos); dispatch_method(s, pos, types + 1, types + lo_strsize(types)); } else { queue_data(s, ts, pos, len); } pos += len; } free(data); return size; } else if (*types != ',') { lo_throw(s, LO_ENOTYPE, "Missing typetag", path); return -1; } dispatch_method(s, path, types+1, data); free(data); return size; }
int lo_server_dispatch_data(lo_server s, void *data, size_t size) { int result = 0; char *path = data; ssize_t len = lo_validate_string(data, size); if (len < 0) { lo_throw(s, -len, "Invalid message path", NULL); return len; } if (!strcmp(data, "#bundle")) { char *pos; int remain; uint32_t elem_len; lo_timetag ts, now; ssize_t bundle_result = lo_validate_bundle(data, size); if (bundle_result < 0) { lo_throw(s, -bundle_result, "Invalid bundle", NULL); return bundle_result; } pos = (char *)data + len; remain = size - len; lo_timetag_now(&now); ts.sec = lo_otoh32(*((uint32_t *)pos)); pos += 4; ts.frac = lo_otoh32(*((uint32_t *)pos)); pos += 4; remain -= 8; while (remain >= 4) { lo_message msg; elem_len = lo_otoh32(*((uint32_t *)pos)); pos += 4; remain -= 4; msg = lo_message_deserialise(pos, elem_len, &result); if (!msg) { lo_throw(s, result, "Invalid bundle element received", path); return -result; } // set timetag from bundle msg->ts = ts; // test for immediate dispatch if ((ts.sec == LO_TT_IMMEDIATE.sec && ts.frac == LO_TT_IMMEDIATE.frac) || lo_timetag_diff(ts, now) <= 0.0) { dispatch_method(s, pos, msg); lo_message_free(msg); } else { queue_data(s, ts, pos, msg); } pos += elem_len; remain -= elem_len; } } else { lo_message msg = lo_message_deserialise(data, size, &result); if (NULL == msg) { lo_throw(s, result, "Invalid message received", path); return -result; } dispatch_method(s, data, msg); lo_message_free(msg); } return size; }