forked from bartvdbraak/blender
195 lines
4.9 KiB
C
195 lines
4.9 KiB
C
|
/*
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include "verse_header.h"
|
||
|
#include "v_pack.h"
|
||
|
#include "v_cmd_gen.h"
|
||
|
#include "v_connection.h"
|
||
|
#if !defined(V_GENERATE_FUNC_MODE)
|
||
|
#include "verse.h"
|
||
|
#include "v_cmd_buf.h"
|
||
|
#include "v_network_out_que.h"
|
||
|
|
||
|
#define V_FS_MAX_CMDS 256
|
||
|
|
||
|
extern void init_pack_and_unpack(void);
|
||
|
|
||
|
static struct {
|
||
|
unsigned int (*unpack_func[V_FS_MAX_CMDS])(const char *data, size_t length);
|
||
|
void *pack_func[V_FS_MAX_CMDS];
|
||
|
void *user_func[V_FS_MAX_CMDS];
|
||
|
void *user_data[V_FS_MAX_CMDS];
|
||
|
void *alias_pack_func[V_FS_MAX_CMDS];
|
||
|
void *alias_user_func[V_FS_MAX_CMDS];
|
||
|
void *alias_user_data[V_FS_MAX_CMDS];
|
||
|
boolean call;
|
||
|
} VCmdData;
|
||
|
|
||
|
static boolean v_fs_initialized = FALSE;
|
||
|
|
||
|
extern void verse_send_packet_ack(uint32 packet_id);
|
||
|
extern void callback_send_packet_ack(void *user, uint32 packet_id);
|
||
|
extern void verse_send_packet_nak(uint32 packet_id);
|
||
|
extern void callback_send_packet_nak(void *user, uint32 packet_id);
|
||
|
|
||
|
void v_fs_init(void)
|
||
|
{
|
||
|
unsigned int i;
|
||
|
if(v_fs_initialized)
|
||
|
return;
|
||
|
for(i = 0; i < V_FS_MAX_CMDS; i++)
|
||
|
{
|
||
|
VCmdData.unpack_func[i] = NULL;
|
||
|
VCmdData.pack_func[i] = NULL;
|
||
|
VCmdData.user_func[i] = NULL;
|
||
|
VCmdData.user_data[i] = NULL;
|
||
|
VCmdData.alias_pack_func[i] = NULL;
|
||
|
VCmdData.alias_user_func[i] = NULL;
|
||
|
VCmdData.alias_user_data[i] = NULL;
|
||
|
}
|
||
|
#if !defined(V_GENERATE_FUNC_MODE)
|
||
|
init_pack_and_unpack();
|
||
|
#endif
|
||
|
for(i = 0; i < V_FS_MAX_CMDS && VCmdData.pack_func[i] != verse_send_packet_ack; i++);
|
||
|
VCmdData.user_func[i] = callback_send_packet_ack;
|
||
|
for(i = 0; i < V_FS_MAX_CMDS && VCmdData.pack_func[i] != verse_send_packet_nak; i++);
|
||
|
VCmdData.user_func[i] = callback_send_packet_nak;
|
||
|
|
||
|
v_fs_initialized = TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
void v_fs_add_func(unsigned int cmd_id, unsigned int (*unpack_func)(const char *data, size_t length), void *pack_func, void *alias_func)
|
||
|
{
|
||
|
VCmdData.unpack_func[cmd_id] = unpack_func;
|
||
|
VCmdData.pack_func[cmd_id] = pack_func;
|
||
|
VCmdData.alias_pack_func[cmd_id] = alias_func;
|
||
|
}
|
||
|
|
||
|
void *v_fs_get_user_func(unsigned int cmd_id)
|
||
|
{
|
||
|
/* if(VCmdData.call)*/
|
||
|
return VCmdData.user_func[cmd_id];
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
void *v_fs_get_user_data(unsigned int cmd_id)
|
||
|
{
|
||
|
return VCmdData.user_data[cmd_id];
|
||
|
}
|
||
|
|
||
|
void *v_fs_get_alias_user_func(unsigned int cmd_id)
|
||
|
{
|
||
|
/* if(VCmdData.call)*/
|
||
|
return VCmdData.alias_user_func[cmd_id];
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
void *v_fs_get_alias_user_data(unsigned int cmd_id)
|
||
|
{
|
||
|
return VCmdData.alias_user_data[cmd_id];
|
||
|
}
|
||
|
|
||
|
void verse_callback_set(void *command, void *callback, void *user)
|
||
|
{
|
||
|
unsigned int i;
|
||
|
if(!v_fs_initialized)
|
||
|
v_fs_init();
|
||
|
|
||
|
for(i = 0; i < V_FS_MAX_CMDS; i++)
|
||
|
{
|
||
|
if(VCmdData.pack_func[i] == command)
|
||
|
{
|
||
|
VCmdData.user_data[i] = user;
|
||
|
VCmdData.user_func[i] = callback;
|
||
|
return;
|
||
|
}
|
||
|
if(VCmdData.alias_pack_func[i] == command)
|
||
|
{
|
||
|
VCmdData.alias_user_data[i] = user;
|
||
|
VCmdData.alias_user_func[i] = callback;
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Do we accept incoming connections, i.e. are we a host implementation? */
|
||
|
boolean v_fs_func_accept_connections(void)
|
||
|
{
|
||
|
return VCmdData.user_func[0] != NULL;
|
||
|
}
|
||
|
|
||
|
/* Inspect beginning of packet, looking for ACK or NAK commands. */
|
||
|
void v_fs_unpack_beginning(const uint8 *data, unsigned int length)
|
||
|
{
|
||
|
uint32 id, i = 4;
|
||
|
uint8 cmd_id;
|
||
|
|
||
|
i += vnp_raw_unpack_uint8(&data[i], &cmd_id);
|
||
|
while(i < length && (cmd_id == 7 || cmd_id == 8))
|
||
|
{
|
||
|
i += vnp_raw_unpack_uint32(&data[i], &id);
|
||
|
if(cmd_id == 7)
|
||
|
callback_send_packet_ack(NULL, id);
|
||
|
else
|
||
|
callback_send_packet_nak(NULL, id);
|
||
|
i += vnp_raw_unpack_uint8(&data[i], &cmd_id);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void v_fs_unpack(uint8 *data, unsigned int length)
|
||
|
{
|
||
|
uint32 i, output, pack_id;
|
||
|
uint8 cmd_id, last = 255;
|
||
|
|
||
|
i = vnp_raw_unpack_uint32(data, &pack_id); /* each packet starts with a 32 bit id */
|
||
|
vnp_raw_unpack_uint8(&data[i], &cmd_id);
|
||
|
while(i < length && (cmd_id == 7 || cmd_id == 8))
|
||
|
{
|
||
|
i += 5;
|
||
|
vnp_raw_unpack_uint8(&data[i], &cmd_id);
|
||
|
}
|
||
|
while(i < length)
|
||
|
{
|
||
|
i += vnp_raw_unpack_uint8(&data[i], &cmd_id);
|
||
|
if(VCmdData.unpack_func[cmd_id] != NULL)
|
||
|
{
|
||
|
VCmdData.call = TRUE;
|
||
|
output = VCmdData.unpack_func[cmd_id](&data[i], length - i);
|
||
|
if(output == (unsigned int) -1) /* Can this happen? Should be size_t or int, depending. */
|
||
|
{
|
||
|
printf("** Aborting decode, command %u unpacker returned failure\n", cmd_id);
|
||
|
/* verse_send_packet_nak(pack_id);*/
|
||
|
return;
|
||
|
}
|
||
|
last = cmd_id;
|
||
|
i += output;
|
||
|
}
|
||
|
else /* If unknown command byte was found, complain loudly and stop parsing packet. */
|
||
|
{
|
||
|
size_t j;
|
||
|
|
||
|
printf("\n** Unknown command ID %u (0x%02X) encountered--aborting packet decode len=%u pos=%u last=%u\n", cmd_id, cmd_id, length, i, last);
|
||
|
printf(" decoded %u bytes: ", --i);
|
||
|
for(j = 0; j < i; j++)
|
||
|
printf("%02X ", data[j]);
|
||
|
printf("\n (packet id=%u)", pack_id);
|
||
|
printf(" remaining %u bytes: ", length - i);
|
||
|
for(j = i; j < length; j++)
|
||
|
printf("%02X ", data[j]);
|
||
|
printf("\n");
|
||
|
/* *(char *) 0 = 0;*/
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
/* if(expected != NULL)
|
||
|
verse_send_packet_ack(pack_id);*/
|
||
|
}
|
||
|
|
||
|
extern unsigned int v_unpack_connection(const char *data, size_t length);
|
||
|
|
||
|
#endif
|