forked from bartvdbraak/blender
397 lines
9.4 KiB
C
397 lines
9.4 KiB
C
/*
|
|
**
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "verse_header.h"
|
|
|
|
#include "v_cmd_buf.h"
|
|
#include "v_cmd_gen.h"
|
|
#include "v_connection.h"
|
|
#include "v_network.h"
|
|
#include "v_pack.h"
|
|
#include "v_encryption.h"
|
|
#include "v_network_out_que.h"
|
|
#include "v_util.h"
|
|
|
|
#if !defined(V_GENERATE_FUNC_MODE)
|
|
|
|
#define STD_QUE_SIZE 64
|
|
|
|
#define V_NOQ_OPTIMIZATION_SLOTS 2048
|
|
|
|
#define V_NOQ_WINDOW_SIZE 100000
|
|
#define V_NOQ_MAX_SORTED_COMMANDS 5000
|
|
|
|
typedef struct{
|
|
void *next;
|
|
char *data;
|
|
size_t size;
|
|
} NetPacked;
|
|
|
|
struct VNetOutQueue{
|
|
uint8 packet_buffer[V_NOQ_MAX_PACKET_SIZE];
|
|
size_t packet_buffer_use;
|
|
NetPacked *packed;
|
|
NetPacked *last;
|
|
VCMDBufHead *unsent[V_NOQ_OPTIMIZATION_SLOTS];
|
|
VCMDBufHead *history[V_NOQ_OPTIMIZATION_SLOTS];
|
|
VCMDBufHead *ack_nak;
|
|
VCMDBufHead *unsorted;
|
|
VCMDBufHead *unsorted_end;
|
|
uint32 unsorted_count; /* debug only */
|
|
uint32 unsent_comands;
|
|
size_t unsent_size;
|
|
size_t sent_size;
|
|
unsigned int packet_id;
|
|
unsigned int slot;
|
|
uint32 seconds;
|
|
uint32 fractions;
|
|
};
|
|
|
|
size_t verse_session_get_size(void)
|
|
{
|
|
const VNetOutQueue *queue;
|
|
|
|
queue = v_con_get_network_queue();
|
|
return queue->unsent_size + queue->sent_size;
|
|
}
|
|
|
|
VNetOutQueue * v_noq_create_network_queue(void)
|
|
{
|
|
VNetOutQueue *queue;
|
|
unsigned int i;
|
|
|
|
queue = malloc(sizeof *queue);
|
|
for(i = 0; i < V_NOQ_OPTIMIZATION_SLOTS; i++)
|
|
{
|
|
queue->unsent[i] = NULL;
|
|
queue->history[i] = NULL;
|
|
}
|
|
queue->unsent_comands = 0;
|
|
queue->unsent_size = 0;
|
|
queue->sent_size = 0;
|
|
queue->packet_id = 2;
|
|
queue->slot = 0;
|
|
queue->packed = NULL;
|
|
queue->last = NULL;
|
|
queue->ack_nak = NULL;
|
|
queue->unsorted = NULL;
|
|
queue->unsorted_end = NULL;
|
|
queue->unsorted_count = 0;
|
|
queue->packet_buffer_use = 0;
|
|
v_n_get_current_time(&queue->seconds, &queue->fractions);
|
|
return queue;
|
|
}
|
|
|
|
unsigned int v_noq_get_next_out_packet_id(VNetOutQueue *queue)
|
|
{
|
|
queue->packet_id++;
|
|
if(queue->packet_id == 0)
|
|
queue->packet_id++;
|
|
return queue->packet_id;
|
|
}
|
|
|
|
void v_noq_destroy_network_queue(VNetOutQueue *queue)
|
|
{
|
|
VCMDBufHead *buf, *b;
|
|
unsigned int i;
|
|
for(i = 0; i < V_NOQ_OPTIMIZATION_SLOTS; i++)
|
|
{
|
|
for(buf = queue->history[i]; buf != NULL; buf = b)
|
|
{
|
|
b = buf->next;
|
|
v_cmd_buf_free(buf);
|
|
}
|
|
for(buf = queue->unsent[i]; buf != NULL; buf = b)
|
|
{
|
|
b = buf->next;
|
|
v_cmd_buf_free(buf);
|
|
}
|
|
}
|
|
for(buf = queue->unsorted; buf != NULL; buf = b)
|
|
{
|
|
b = buf->next;
|
|
v_cmd_buf_free(buf);
|
|
}
|
|
free(queue);
|
|
}
|
|
|
|
|
|
void v_noq_sort_and_collapse_buf(VNetOutQueue *queue, VCMDBufHead *buf)
|
|
{
|
|
VCMDBufHead *b, *last = NULL;
|
|
unsigned int slot;
|
|
|
|
slot = buf->address_sum % V_NOQ_OPTIMIZATION_SLOTS;
|
|
queue->unsent_size += buf->size;
|
|
queue->unsent_comands++;
|
|
if(queue->unsent[slot] != NULL)
|
|
{
|
|
for(b = queue->unsent[slot]; !v_cmd_buf_compare(buf, b) && b->next != NULL; b = b->next)
|
|
last = b;
|
|
if(v_cmd_buf_compare(buf, b)) /* found a command to replace */
|
|
{
|
|
queue->unsent_size -= b->size;
|
|
queue->unsent_comands--;
|
|
if(last != NULL) /* if its not the first */
|
|
last->next = buf;
|
|
else
|
|
queue->unsent[slot] = buf;
|
|
buf->next = b->next;
|
|
v_cmd_buf_free(b);
|
|
}else /* inserting the command last in queue */
|
|
{
|
|
buf->next = NULL;
|
|
b->next = buf;
|
|
}
|
|
}else /* inserting the first command */
|
|
{
|
|
queue->unsent[slot] = buf;
|
|
buf->next = NULL;
|
|
}
|
|
if(queue->history[slot] != NULL) /* if there is a history clear it from any commnds with same address */
|
|
{
|
|
last = NULL;
|
|
for(b = queue->history[slot]; b != NULL && !v_cmd_buf_compare(buf, b); b = b->next)
|
|
last = b;
|
|
if(b != NULL) /* found a command to replace */
|
|
{
|
|
if(last == NULL)
|
|
queue->history[slot] = b->next;
|
|
else
|
|
last->next = b->next;
|
|
queue->sent_size -= b->size;
|
|
v_cmd_buf_free(b);
|
|
}
|
|
}
|
|
}
|
|
|
|
void v_noq_send_buf(VNetOutQueue *queue, VCMDBufHead *buf)
|
|
{
|
|
static int count = 0;
|
|
/* if(queue->unsent_comands > V_NOQ_MAX_SORTED_COMMANDS)
|
|
{
|
|
|
|
*/ if(queue->unsorted == NULL)
|
|
{
|
|
queue->unsorted_end = buf;
|
|
queue->unsorted = buf;
|
|
}else
|
|
{
|
|
queue->unsorted_end->next = buf;
|
|
queue->unsorted_end = buf;
|
|
}
|
|
queue->unsorted_count++;
|
|
/* }else
|
|
v_noq_sort_and_colapse_buf(queue, buf);
|
|
*/ count = (count + 1) % 30;
|
|
if(count == 0)
|
|
{
|
|
v_con_network_listen();
|
|
v_noq_send_queue(queue, v_con_get_network_address());
|
|
}
|
|
}
|
|
|
|
void v_noq_sort_unsorted(VNetOutQueue *queue)
|
|
{
|
|
VCMDBufHead *buf;
|
|
|
|
while(queue->unsent_comands < V_NOQ_MAX_SORTED_COMMANDS && queue->unsorted != NULL)
|
|
{
|
|
buf = queue->unsorted;
|
|
if(queue->unsorted == queue->unsorted_end)
|
|
{
|
|
queue->unsorted_end = NULL;
|
|
queue->unsorted = NULL;
|
|
}else
|
|
{
|
|
queue->unsorted = buf->next;
|
|
buf->next = NULL;
|
|
}
|
|
queue->unsorted_count--;
|
|
v_noq_sort_and_collapse_buf(queue, buf);
|
|
}
|
|
}
|
|
|
|
boolean v_noq_send_queue(VNetOutQueue *queue, void *address)
|
|
{
|
|
static unsigned int my_counter = 0;
|
|
VCMDBufHead *buf;
|
|
unsigned int size;
|
|
uint8 *data;
|
|
uint32 seconds, fractions;
|
|
double delta;
|
|
|
|
data = queue->packet_buffer;
|
|
v_n_get_current_time(&seconds, &fractions);
|
|
delta = seconds - queue->seconds + (fractions - queue->fractions) / (double) 0xffffffff;
|
|
|
|
if(queue->unsorted != NULL)
|
|
v_noq_sort_unsorted(queue);
|
|
|
|
if(queue->unsent_size == 0 && delta < 1.0 && (queue->ack_nak == NULL || queue->ack_nak->next == NULL))
|
|
return FALSE;
|
|
|
|
if(delta > 3.0 && queue->unsent_size == 0 && queue->ack_nak == NULL && queue->packet_buffer_use != 0)
|
|
{
|
|
/* printf("A) re-sending last delta=%g\n", delta);*/
|
|
v_n_send_data(address, data, queue->packet_buffer_use);
|
|
queue->seconds = seconds;
|
|
queue->fractions = fractions;
|
|
return TRUE;
|
|
}
|
|
|
|
size = 4;
|
|
buf = queue->ack_nak;
|
|
while(buf != NULL && size + buf->size < V_NOQ_MAX_PACKET_SIZE)
|
|
{
|
|
vnp_raw_pack_uint32(data, queue->packet_id);
|
|
queue->ack_nak = buf->next;
|
|
buf->next = queue->history[queue->slot];
|
|
queue->history[queue->slot] = buf;
|
|
buf->packet = queue->packet_id;
|
|
v_e_data_encrypt_command(data, size, ((VCMDBuffer1500 *)buf)->buf, buf->size, v_con_get_data_key());
|
|
size += buf->size;
|
|
queue->sent_size += buf->size;
|
|
buf = queue->ack_nak;
|
|
}
|
|
if(queue->unsent_size == 0 || queue->sent_size >= V_NOQ_WINDOW_SIZE)
|
|
{
|
|
if(size > 5)
|
|
{
|
|
/* printf("ACK: sending actual size=%u id=%u\n", size, queue->packet_id);*/
|
|
v_n_send_data(address, data, size);
|
|
queue->packet_buffer_use = size;
|
|
queue->seconds = seconds;
|
|
queue->fractions = fractions;
|
|
queue->packet_id++;
|
|
return TRUE;
|
|
}
|
|
/* printf("returning FALSE from send_queue()\n");*/
|
|
return FALSE;
|
|
}
|
|
/* if(queue->sent_size < V_NOQ_WINDOW_SIZE && queue->unsent_size != 0)*/
|
|
{
|
|
vnp_raw_pack_uint32(data, queue->packet_id);
|
|
while(queue->unsent_size != 0)
|
|
{
|
|
queue->slot = ((1 + queue->slot) % V_NOQ_OPTIMIZATION_SLOTS);
|
|
buf = queue->unsent[queue->slot];
|
|
if(buf != NULL)
|
|
{
|
|
if(buf->size + size > V_NOQ_MAX_PACKET_SIZE)
|
|
break;
|
|
queue->unsent[queue->slot] = buf->next;
|
|
buf->next = queue->history[queue->slot];
|
|
queue->history[queue->slot] = buf;
|
|
buf->packet = queue->packet_id;
|
|
|
|
v_e_data_encrypt_command(data, size, ((VCMDBuffer1500 *)buf)->buf, buf->size, v_con_get_data_key());
|
|
size += buf->size;
|
|
queue->unsent_comands--;
|
|
queue->unsent_size -= buf->size;
|
|
queue->sent_size += buf->size;
|
|
my_counter++;
|
|
}
|
|
}
|
|
v_n_send_data(address, data, size);
|
|
queue->packet_buffer_use = size;
|
|
queue->packet_id++;
|
|
/* size = vnp_raw_pack_uint32(data, queue->packet_id);*/
|
|
queue->seconds = seconds;
|
|
queue->fractions = fractions;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void v_noq_send_ack_nak_buf(VNetOutQueue *queue, VCMDBufHead *buf)
|
|
{
|
|
buf->next = queue->ack_nak;
|
|
queue->ack_nak = buf;
|
|
}
|
|
|
|
void callback_send_packet_ack(void *user, uint32 packet_id)
|
|
{
|
|
VNetOutQueue *queue;
|
|
VCMDBufHead *buf, *last;
|
|
unsigned int slot;
|
|
|
|
queue = v_con_get_network_queue();
|
|
for(slot = 0; slot < V_NOQ_OPTIMIZATION_SLOTS; slot++)
|
|
{
|
|
last = NULL;
|
|
for(buf = queue->history[slot]; buf != NULL && buf->packet != packet_id; buf = buf->next)
|
|
last = buf;
|
|
|
|
if(buf != NULL)
|
|
{
|
|
if(last == NULL)
|
|
{
|
|
while(queue->history[slot] != NULL && queue->history[slot]->packet == packet_id)
|
|
{
|
|
queue->sent_size -= queue->history[slot]->size;
|
|
buf = queue->history[slot]->next;
|
|
v_cmd_buf_free(queue->history[slot]);
|
|
queue->history[slot] = buf;
|
|
}
|
|
}else
|
|
{
|
|
for(; buf != NULL && buf->packet == packet_id; buf = last->next)
|
|
{
|
|
queue->sent_size -= buf->size;
|
|
last->next = buf->next;
|
|
v_cmd_buf_free(buf);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void callback_send_packet_nak(void *user, uint32 packet_id)
|
|
{
|
|
VNetOutQueue *queue;
|
|
VCMDBufHead *buf, *last;
|
|
unsigned int slot;
|
|
|
|
queue = v_con_get_network_queue();
|
|
for(slot = 0; slot < V_NOQ_OPTIMIZATION_SLOTS; slot++)
|
|
{
|
|
last = NULL;
|
|
for(buf = queue->history[slot]; buf != NULL && buf->packet != packet_id; buf = buf->next)
|
|
last = buf;
|
|
if(buf != NULL)
|
|
{
|
|
if(last == NULL)
|
|
{
|
|
for(; queue->history[slot] != NULL && queue->history[slot]->packet == packet_id; queue->history[slot] = buf)
|
|
{
|
|
queue->unsent_comands++;
|
|
queue->unsent_size += queue->history[slot]->size;
|
|
queue->sent_size -= queue->history[slot]->size;
|
|
buf = queue->history[slot]->next;
|
|
queue->history[slot]->next = queue->unsent[slot];
|
|
queue->unsent[slot] = queue->history[slot];
|
|
}
|
|
}else
|
|
{
|
|
for(; last->next != NULL && ((VCMDBufHead *)last->next)->packet == packet_id;)
|
|
{
|
|
queue->unsent_comands++;
|
|
queue->unsent_size += ((VCMDBufHead *)last->next)->size;
|
|
queue->sent_size -= ((VCMDBufHead *)last->next)->size;
|
|
buf = last->next;
|
|
last->next = buf->next;
|
|
buf->next = queue->unsent[slot];
|
|
queue->unsent[slot] = buf;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|