00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "_dicelib.h"
00025 #include <string.h>
00026 #include <errno.h>
00027 #include <fcntl.h>
00028 #ifndef WINDOWS
00029 #include <netdb.h>
00030 #include <sys/socket.h>
00031 #include <sys/types.h>
00032 #include <unistd.h>
00033 #include <arpa/inet.h>
00034 #include <netinet/in.h>
00035 #else
00036 #include <winsock.h>
00037 #endif
00038
00039 #define PACK_MAX_LENGTH 16384
00040
00041 #define FUNCTION "DICE_packet_send"
00042
00053 int dice_packet_send ( dice_packet *p, int socket ) {
00054 static char packet[PACK_MAX_LENGTH];
00055 char *buffer;
00056 int size = 256, sent = 0, i;
00057 unsigned short length = 4;
00058
00059 _dice_debug(3, dice_printf(FUNCTION, "(%p,%d)\n", p, socket);)
00060
00061 memset(packet, 0, size);
00062 packet[0] = (char)p->packtype;
00063 packet[1] = '\0';
00064
00065 switch ( p->packtype ) {
00066 case INVALID:
00067 return -1;
00068 case SYNC:
00069 length = 4;
00070 break;
00071 case VARIABLE_ASYNC:
00072 case VARIABLE_SYNC:
00073 buffer = DICE_type_pack("string", (void *)p->variable.name, &i);
00074 memcpy(&packet[length], buffer, i);
00075 length += i;
00076 free(buffer);
00077 buffer = DICE_type_pack("string", (void *)p->variable.type, &i);
00078 memcpy(&packet[length], buffer, i);
00079 length += i;
00080 free(buffer);
00081 buffer = DICE_type_pack(p->variable.type, (void *)p->variable.value, &i);
00082 if (length + i >= PACK_MAX_LENGTH) {
00083 _dice_debug(1, dice_printf(FUNCTION, "Packet %s is too big: %d bytes\n",
00084 p->variable.name, length+i);)
00085 return -1;
00086 }
00087 memcpy(&packet[length], buffer, i);
00088 length += i;
00089 free(buffer);
00090 break;
00091 case VARIABLE_FREE_ASYNC:
00092 case VARIABLE_FREE_SYNC:
00093 buffer = DICE_type_pack("string", (void *)p->variable.name, &i);
00094 memcpy(&packet[length], buffer, i);
00095 length += i;
00096 free(buffer);
00097 break;
00098 case READY:
00099 length = 4;
00100 break;
00101 case CONTINUE:
00102 length = 4;
00103 break;
00104 case HELLO:
00105 buffer = DICE_type_pack("unsigned_long", (void *)&p->hello.id, &i);
00106 memcpy(&packet[length], buffer, i);
00107 length += i;
00108 free(buffer);
00109 buffer = DICE_type_pack("string", (void *)p->hello.function, &i);
00110 memcpy(&packet[length], buffer, i);
00111 length += i;
00112 free(buffer);
00113 break;
00114 case GOODBYE:
00115 length = 4;
00116 break;
00117 default:
00118 return -1;
00119 break;
00120 }
00121
00122 packet[2] = (length>>8) & 0xFF;
00123 packet[3] = length & 0xFF;
00124
00125 _dice_debug(3, dice_printf(FUNCTION, "type %s, length %d, sending.\n",
00126 dice_packet_name(p->packtype), length);)
00127 while ( sent < length ) {
00128 i = send(socket, packet+sent, length-sent, 0);
00129 if ( i == -1 ) {
00130
00131 _dice_debug(1, dice_printf(FUNCTION, "%s\n",
00132 strerror(errno));)
00133 return -1;
00134 }
00135 sent += i;
00136 }
00137 return 0;
00138 }
00139
00140 #undef FUNCTION
00141 #define FUNCTION "DICE_packet_get"
00142
00151 dice_packet dice_packet_get ( int socket ) {
00152 static unsigned char queue[16384];
00153 dice_packet pack;
00154 int i;
00155 unsigned short length;
00156 char *p;
00157
00158 _dice_debug(3, dice_printf(FUNCTION, "(%d)\n", socket);)
00159
00160 pack.packtype = INVALID;
00161
00162 i = read(socket, queue, 4);
00163 if ( i < 0 ) {
00164 _dice_debug(1, dice_printf(FUNCTION, "%s\n",
00165 strerror(errno));)
00166 return pack;
00167 }
00168 if ( i == 0 ) {
00169
00170 return pack;
00171 }
00172 while ( i != 4 ) {
00173 i += read(socket, queue+i, 4-i);
00174 };
00175
00176 pack.packtype = (dice_packet_type)queue[0];
00177 if ( queue[1] != '\0' ) {
00178 _dice_debug(1, dice_printf(FUNCTION, "Packet has problems.\n");)
00179 return pack;
00180 }
00181 length = (((unsigned int)queue[2])<<8) + (unsigned int)queue[3];
00182
00183 _dice_debug(3, dice_printf(FUNCTION, "type %s, length %d.\n",
00184 dice_packet_name(pack.packtype), length);)
00185
00186 i = 4;
00187 while ( i < length )
00188 i += read(socket, queue+i, length-i);
00189 p = queue+4;
00190
00191
00192 switch ( pack.packtype ) {
00193 case SYNC:
00194 return pack;
00195 case VARIABLE_SYNC:
00196 case VARIABLE_ASYNC:
00197 pack.variable.name = (char *)DICE_type_unpack("string", p, &i);
00198 p += i;
00199 pack.variable.type = (char *)DICE_type_unpack("string", p, &i);
00200 p += i;
00201 if ( !dice_type_is_valid(pack.variable.type) && !dice_is_server() ) {
00202 _dice_debug(1, dice_printf(FUNCTION,
00203 "register %s!", pack.variable.type);)
00204 return pack;
00205 #if 0
00206 if ( DICE_type_register(pack.variable.type) == -1 ) {
00207
00208 }
00209 #endif
00210 }
00211 pack.variable.value = DICE_type_unpack(pack.variable.type, p, &i);
00212 p += i;
00213 if ( p - (char *)queue != length )
00214 _dice_debug(2, dice_printf(FUNCTION,
00215 "Packet has problems: size[%d] nominal:[%d].\n",
00216 p - (char *)queue, length);)
00217 return pack;
00218 case VARIABLE_FREE_SYNC:
00219 case VARIABLE_FREE_ASYNC:
00220 pack.variable.name = (char *)DICE_type_unpack("string", p, &i);
00221 p += i;
00222 if ( p - (char *)queue != length )
00223 _dice_debug(2, dice_printf(FUNCTION, "Packet has problems.\n");)
00224 return pack;
00225 case READY:
00226 return pack;
00227 case CONTINUE:
00228 return pack;
00229 case HELLO:
00230 pack.hello.id = *(unsigned long *)DICE_type_unpack("unsigned_long", p, &i);
00231 p += i;
00232 pack.hello.function = (char *)DICE_type_unpack("string", p, &i);
00233 p += i;
00234 if ( p - (char *)queue != length )
00235 _dice_debug(2, dice_printf(FUNCTION,
00236 "Packet has problems: size[%d] nominal:[%d]; (%ld %s)\n",
00237 p - (char *)queue, length, pack.hello.id, pack.hello.function);)
00238 return pack;
00239 case GOODBYE:
00240 return pack;
00241 default:
00242 pack.packtype = INVALID;
00243 return pack;
00244 }
00245 }
00246
00247 char *dice_packet_name ( dice_packet_type t ) {
00248 switch ( t ) {
00249 case INVALID:
00250 return "INVALID";
00251 case SYNC:
00252 return "SYNC";
00253 case VARIABLE_ASYNC:
00254 return "VARIABLE_ASYNC";
00255 case VARIABLE_SYNC:
00256 return "VARIABLE_SYNC";
00257 case VARIABLE_FREE_ASYNC:
00258 return "VARIABLE_FREE_ASYNC";
00259 case VARIABLE_FREE_SYNC:
00260 return "VARIABLE_FREE_SYNC";
00261 case READY:
00262 return "READY";
00263 case CONTINUE:
00264 return "CONTINUE";
00265 case HELLO:
00266 return "HELLO";
00267 case GOODBYE:
00268 return "GOODBYE";
00269 }
00270 return NULL;
00271 };