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 "hash.h"
00026 #include <string.h>
00027 #include <signal.h>
00028 #include <fcntl.h>
00029
00030
00031 static HashTable dice_sync_var;
00032 extern int packetfrom;
00033
00034
00035
00036
00037 struct dice_sync_var_item {
00038 struct dice_sync *ds;
00039 struct dice_sync_var_item *next;
00040 };
00041
00042 static struct dice_sync_var_item *sync_head, *sync_last;
00043
00044 #define dice_sync_add_to_list(ds) \
00045 item = (struct dice_sync_var_item *)malloc(sizeof(struct dice_sync_var_item)); \
00046 if ( !item ) { \
00047 _dice_debug(1, dice_printf(FUNCTION, "NULL malloc 2\n");) \
00048 free(ds); \
00049 return -1; \
00050 } \
00051 item->ds = ds; \
00052 item->next = NULL; \
00053 if ( !sync_head ) \
00054 sync_head = item; \
00055 if ( sync_last ) \
00056 sync_last->next = item; \
00057 sync_last = item;
00058
00062 enum dice_variable_state {
00063 UPTODATE,
00064 CHANGED,
00065 CREATED,
00066 DELETED
00067 };
00068
00072 struct dice_sync {
00073 char *name;
00074 char *type;
00075 void *value;
00076 void *nextvalue;
00077 enum dice_variable_state state;
00079
00080 int owner;
00081 int changedby;
00082 };
00083
00088 void dice_sync_free ( void *data ) {
00089 struct dice_sync *ds;
00090 if ( !data )
00091 return;
00092
00093 ds = data;
00094 dice_free(ds->name);
00095 DICE_type_free(ds->type, ds->value);
00096
00097 dice_free(ds->type);
00098 free(ds);
00099 }
00100
00104 int dice_sync_init ( void ) {
00105 if ( hash_init(&dice_sync_var, 128, NULL) == -1 )
00106 return -1;
00107 sync_head = NULL;
00108 sync_last = NULL;
00109 return 0;
00110 }
00111
00115 void dice_sync_end ( void ) {
00116 struct dice_sync_var_item *item, *tmp;
00117 if ( sync_head )
00118 for ( item = sync_head; item != NULL; ) {
00119 if ( item->ds->state == CREATED )
00120 free(item->ds);
00121 tmp = item->next;
00122 free(item);
00123 item = tmp;
00124 }
00125 hash_free(&dice_sync_var, dice_sync_free);
00126 }
00127
00128 #define FUNCTION "dice_sync_update_send"
00129
00134 void dice_sync_update_send ( void ) {
00135 struct dice_sync_var_item *item, *tmp;
00136 dice_packet packet;
00137
00138 _dice_debug(3, dice_printf(FUNCTION, "()\n");)
00139
00140 for ( item = sync_head; item != NULL; item = item->next ) {
00141 switch ( item->ds->state ) {
00142 case CREATED:
00143 case CHANGED:
00144 packet.packtype = VARIABLE_SYNC;
00145 packet.variable.name = item->ds->name;
00146 packet.variable.type = item->ds->type;
00147 packet.variable.value = (item->ds->state == CREATED ?
00148 item->ds->value : item->ds->nextvalue );
00149 if ( dice_is_server() ) {
00150 dice_broadcast(&packet, -1);
00151 item->ds->state = UPTODATE;
00152 }
00153 else
00154 dice_packet_send(&packet, dice_data.controlsock);
00155 break;
00156 case DELETED:
00157 packet.packtype = VARIABLE_FREE_SYNC;
00158 packet.variable_free.name = item->ds->name;
00159 if ( dice_is_server() )
00160 dice_broadcast(&packet, -1);
00161 else
00162 dice_packet_send(&packet, dice_data.controlsock);
00163 break;
00164 case UPTODATE:
00165 break;
00166 }
00167 }
00168
00169
00170 for ( item = sync_head; item != NULL; ) {
00171 if ( item->ds->state == CREATED ) {
00172 dice_free(item->ds->name);
00173 dice_free(item->ds->type);
00174 free(item->ds);
00175 }
00176 else {
00177 item->ds->nextvalue = NULL;
00178 if ( dice_is_server() )
00179 item->ds->changedby = -1;
00180 }
00181 tmp = item;
00182 item = item->next;
00183 free(tmp);
00184 }
00185 sync_head = sync_last = NULL;
00186 }
00187
00188 #undef FUNCTION
00189 #define FUNCTION "dice_sync_new"
00190
00203 int dice_sync_new ( char *name, char *type, void *value,
00204 enum dice_variable_state state ) {
00205 struct dice_sync *ds;
00206 struct dice_sync_var_item *item;
00207 int exists = 0;
00208
00209 _dice_debug(3, dice_printf(FUNCTION, "(%s,%s,%p)\n",
00210 name, type, value);)
00211
00212 if ( !name ) {
00213 _dice_debug(1, dice_printf(FUNCTION, "Invalid name\n");)
00214 return -1;
00215 }
00216
00217 if ( !dice_type_is_valid(type) ) {
00218 #if 0
00219 if ( DICE_type_register(type) == -1 ) {
00220 _dice_debug(1, dice_printf(FUNCTION, "Couldn't register type.\n");)
00221 return -1;
00222 }
00223 #endif
00224 _dice_debug(1, dice_printf(FUNCTION, "Invalid type %s.\n", type);)
00225 return -1;
00226 }
00227 for ( item = sync_head; item != NULL; item = item->next )
00228 if ( strcmp(item->ds->name, name) == 0 ) {
00229 exists = 1;
00230 break;
00231 }
00232
00233 if ( (ds = hash_data(&dice_sync_var, name)) != NULL || exists ) {
00234 _dice_debug(2, dice_printf(FUNCTION, "Variable exists\n");)
00235 return -2;
00236 }
00237
00238 ds = (struct dice_sync *)malloc(sizeof(struct dice_sync));
00239 if ( !ds ) {
00240 _dice_debug(1, dice_printf(FUNCTION, "NULL malloc\n");)
00241 return -1;
00242 }
00243
00244 ds->name = strdup(name);
00245 if ( !ds->name ) {
00246 _dice_debug(1, dice_printf(FUNCTION, "NULL strdup\n");)
00247 return -1;
00248 }
00249 ds->type = strdup(type);
00250 if ( !ds->type ) {
00251 _dice_debug(1, dice_printf(FUNCTION, "NULL strdup2\n");)
00252 return -1;
00253 }
00254 ds->value = value;
00255 ds->nextvalue = NULL;
00256
00257 if ( state == CREATED ) {
00258 ds->state = CREATED;
00259 dice_sync_add_to_list(ds);
00260 if ( dice_is_server() ) {
00261 ds->owner = ds->changedby = packetfrom;
00262 hash_insert(&dice_sync_var, ds->name, ds);
00263 }
00264 }
00265 else if ( state == UPTODATE ) {
00266 ds->nextvalue = NULL;
00267 ds->state = UPTODATE;
00268 hash_insert(&dice_sync_var, ds->name, ds);
00269 } else {
00270 _dice_debug(1, dice_printf(FUNCTION, "Wrong state!\n");)
00271
00272 return -1;
00273 }
00274
00275 return 0;
00276 }
00277
00278 #undef FUNCTION
00279 #define FUNCTION "dice_sync_delete"
00280
00288 void dice_sync_delete ( char *name ) {
00289 struct dice_sync *ds;
00290
00291 _dice_debug(3, dice_printf(FUNCTION, "(%s)\n", name);)
00292
00293 if ( !name ) {
00294 _dice_debug(2, dice_printf(FUNCTION, "NULL name.\n");)
00295 return;
00296 }
00297 ds = hash_del(&dice_sync_var, name);
00298 if ( !ds ) {
00299 _dice_debug(2, dice_printf(FUNCTION, "variable not found.\n");)
00300 return;
00301 }
00302
00303 dice_sync_free((void *)ds);
00304 }
00305
00306 #undef FUNCTION
00307 #define FUNCTION "dice_sync_update"
00308
00316 void dice_sync_update ( char *name, char *type, void *value ) {
00317 struct dice_sync *ds;
00318
00319 _dice_debug(3, dice_printf(FUNCTION, "(%s)\n", name);)
00320
00321 if ( !name || !dice_type_is_valid(type)) {
00322 _dice_debug(2, dice_printf(FUNCTION, "NULL name or invalid type.\n");)
00323 return;
00324 }
00325 ds = (struct dice_sync *)hash_data(&dice_sync_var, name);
00326 if ( !ds ) {
00327 dice_sync_new(name, type, value, UPTODATE);
00328 return;
00329 }
00330
00331 DICE_type_free(type, ds->value);
00332 if ( ds->nextvalue )
00333 DICE_type_free(type, ds->nextvalue);
00334 ds->nextvalue = NULL;
00335 ds->value = value;
00336 ds->state = UPTODATE;
00337 return;
00338 }
00339
00340
00341
00342
00343
00344 #undef FUNCTION
00345 #define FUNCTION "DICE_sync_new"
00346
00360 int DICE_sync_new ( char *name, char *type, void *value ) {
00361 if ( !dice_is_server() && dice_data.original_only == 1 &&
00362 dice_data.id != 0 )
00363 return -3;
00364 return dice_sync_new(name, type, value, CREATED);
00365 }
00366
00367 #undef FUNCTION
00368 #define FUNCTION "DICE_sync_delete"
00369
00381 int DICE_sync_delete ( char *name ) {
00382 struct dice_sync *ds;
00383 struct dice_sync_var_item *item;
00384
00385 _dice_debug(3, dice_printf(FUNCTION, "(%s)\n", name);)
00386
00387 if ( dice_data.original_only == 1 && dice_data.id != 0 )
00388 return -3;
00389
00390 if ( !name ) {
00391 _dice_debug(2, dice_printf(FUNCTION, "NULL name.\n");)
00392 return -1;
00393 }
00394 ds = (struct dice_sync *)hash_data(&dice_sync_var, name);
00395 if ( !ds ) {
00396 _dice_debug(2, dice_printf(FUNCTION, "variable not found.\n");)
00397 return -2;
00398 }
00399
00400
00401 if ( dice_is_server() ) {
00402 switch ( dice_control_hierarchy(ds->changedby == -1 ?
00403 ds->owner : ds->changedby, packetfrom) ) {
00404 case 0:
00405 return -3;
00406 case 1:
00407 ds->changedby = packetfrom;
00408 break;
00409 case -1:
00410
00411 break;
00412 }
00413 }
00414
00415
00416 for ( item = sync_head; item != NULL; item = item->next )
00417 if ( strcmp(item->ds->name, name) == 0 ) {
00418 _dice_debug(2, dice_printf(FUNCTION,
00419 "variable %s already deleted.\n",
00420 item->ds->name);)
00421 return 0;
00422 }
00423
00424 ds->state = DELETED;
00425 dice_sync_add_to_list(ds);
00426
00427 return 0;
00428 }
00429
00430 #undef FUNCTION
00431 #define FUNCTION "DICE_sync_update"
00432
00445 int DICE_sync_update ( char *name, void *value ) {
00446 struct dice_sync *ds;
00447 struct dice_sync_var_item *item;
00448
00449 _dice_debug(3, dice_printf(FUNCTION,"(%s,%p)\n",
00450 name, value);)
00451
00452 if ( dice_data.original_only == 1 && dice_data.id != 0 )
00453 return -3;
00454
00455 if ( !name ) {
00456 _dice_debug(1, dice_printf(FUNCTION, "NULL name.\n");)
00457 return -1;
00458 }
00459 ds = hash_data(&dice_sync_var, name);
00460 if ( !ds ) {
00461 if ( !dice_is_server() )
00462 _dice_debug(1, dice_printf(FUNCTION,
00463 "Data %s doesn't exist.\n", name);)
00464 return -2;
00465 }
00466
00467
00468 if ( dice_is_server() ) {
00469 _dice_debug(3, dice_printf(FUNCTION,"Owned by %d, changed by %d, from %d\n",
00470 ds->owner, ds->changedby, packetfrom);)
00471 switch ( dice_control_hierarchy(ds->changedby == -1 ?
00472 ds->owner : ds->changedby, packetfrom) ) {
00473 case 0:
00474 _dice_debug(3, dice_printf(FUNCTION,"Less hierarchy\n");)
00475 return -3;
00476 case 1:
00477 ds->changedby = packetfrom;
00478 break;
00479 case -1:
00480
00481 break;
00482 }
00483 }
00484
00485 ds->nextvalue = value;
00486 ds->state = CHANGED;
00487
00488
00489 for ( item = sync_head; item != NULL; item = item->next )
00490 if ( strcmp(item->ds->name, name) == 0 )
00491 return 0;
00492
00493 dice_sync_add_to_list(ds);
00494
00495 return 0;
00496 }
00497
00498 #undef FUNCTION
00499 #define FUNCTION "DICE_sync"
00500
00515 int DICE_sync ( void ) {
00516 dice_packet packet;
00517 #ifdef USE_ASYNC
00518 struct sigaction action, ignore;
00519 int flags;
00520 #endif
00521
00522 _dice_debug(3, dice_printf(FUNCTION, "()\n");)
00523
00524 #ifdef USE_ASYNC
00525
00526 ignore.sa_handler = SIG_IGN;
00527 sigemptyset(&ignore.sa_mask);
00528 sigaction(SIGIO, &ignore, &action);
00529 flags = fcntl(dice_data.controlsock, F_GETFL, 0);
00530 if ( flags == -1 ) {
00531
00532 }
00533 fcntl(dice_data.controlsock, F_SETFL, flags &(~O_ASYNC));
00534 #endif
00535
00536
00537 packet.packtype = SYNC;
00538 dice_packet_send(&packet, dice_data.controlsock);
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548 dice_sync_update_send();
00549 packet.packtype = READY;
00550 dice_packet_send(&packet, dice_data.controlsock);
00551
00552
00553 packet = dice_packet_get(dice_data.controlsock);
00554 while ( packet.packtype == VARIABLE_SYNC ||
00555 packet.packtype == VARIABLE_FREE_SYNC ) {
00556 if ( packet.packtype == VARIABLE_SYNC )
00557 dice_sync_update(packet.variable.name, packet.variable.type,
00558 packet.variable.value);
00559
00560 else
00561 dice_sync_delete(packet.variable.name);
00562 packet = dice_packet_get(dice_data.controlsock);
00563 }
00564 if ( packet.packtype != SYNC ) {
00565 #ifndef USE_ASYNC
00566 if ( packet.packtype == GOODBYE ) {
00567 _dice_debug(1, dice_printf(FUNCTION,
00568 "got a goodbye, quitting.\n");)
00569 exit(0);
00570 }
00571 #endif
00572 _dice_debug(1, dice_printf(FUNCTION,
00573 "expecting SYNC, got %s\n",
00574 dice_packet_name(packet.packtype));)
00575 #ifdef USE_ASYNC
00576 sigaction(SIGIO, &action, NULL);
00577 fcntl(dice_data.controlsock, F_SETFL, flags);
00578 #endif
00579 return -1;
00580 }
00581
00582
00583 packet.packtype = READY;
00584 dice_packet_send(&packet, dice_data.controlsock);
00585
00586
00587 packet = dice_packet_get(dice_data.controlsock);
00588 if ( packet.packtype != CONTINUE ) {
00589 _dice_debug(1, dice_printf(FUNCTION,
00590 "expecting CONTINUE, got %s",
00591 dice_packet_name(packet.packtype));)
00592 #ifdef USE_ASYNC
00593 sigaction(SIGIO, &action, NULL);
00594 fcntl(dice_data.controlsock, F_SETFL, flags);
00595 #endif
00596 return -1;
00597 }
00598 #ifdef USE_ASYNC
00599
00600 sigaction(SIGIO, &action, NULL);
00601 fcntl(dice_data.controlsock, F_SETFL, flags);
00602 #endif
00603 return 0;
00604 }
00605
00606 #undef FUNCTION
00607 #define FUNCTION "DICE_sync_get"
00608
00618 void *DICE_sync_get ( char *name ) {
00619 struct dice_sync *ds;
00620
00621 _dice_debug(3, dice_printf(FUNCTION, "(%s)\n",
00622 name);)
00623
00624 if ( !name ) {
00625 _dice_debug(1, dice_printf(FUNCTION, "NULL name.\n");)
00626 return NULL;
00627 }
00628 ds = hash_data(&dice_sync_var, name);
00629 if ( !ds ) {
00630 _dice_debug(1, dice_printf(FUNCTION, "variable not found.\n");)
00631 return NULL;
00632 }
00633 return ds->value;
00634 }
00635
00636 #undef FUNCTION
00637 #define FUNCTION "DICE_sync_get_next"
00638
00647 void *DICE_sync_get_next ( char *name ) {
00648 struct dice_sync *ds;
00649
00650 _dice_debug(3, dice_printf("DICE_sync_get_next(%s)\n",
00651 name);)
00652
00653 if ( !name ) {
00654 _dice_debug(1, dice_printf(FUNCTION, "NULL name.\n");)
00655 return NULL;
00656 }
00657 ds = hash_data(&dice_sync_var, name);
00658 if ( !ds ) {
00659 _dice_debug(1, dice_printf(FUNCTION, "variable not found.\n");)
00660 return NULL;
00661 }
00662
00663 return ds->nextvalue;
00664 }