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 #ifndef WINDOWS
00028 #include <signal.h>
00029 #include <sys/time.h>
00030 #include <sys/types.h>
00031 #include <unistd.h>
00032 #include <sys/socket.h>
00033 #include <netinet/in.h>
00034 #include <netinet/tcp.h>
00035 #include <arpa/inet.h>
00036 #include <netdb.h>
00037 #else
00038 #include <winsock.h>
00039 #endif
00040
00041 static int syncnum = 0;
00042 static int readynum = 0;
00043 static int fdmax;
00044 static fd_set clients;
00045 static int *hierarchy;
00046 int packetfrom;
00047
00048 #define FUNCTION "dice_broadcast"
00049
00059 int dice_broadcast ( dice_packet *packet, int except ) {
00060 int i;
00061
00062 _dice_debug(3, dice_printf(FUNCTION, "(%p, %d)\n", packet, except);)
00063 for ( i = 0; i <= fdmax; i++ ) {
00064 if ( FD_ISSET(i, &clients) && i != except )
00065 if ( dice_packet_send(packet, i) == -1 )
00066 return -1;
00067 }
00068 return 0;
00069 }
00070
00074 void dice_control_byebye ( int signum ) {
00075 dice_packet packet;
00076 int i;
00077
00078 _dice_debug(3, dice_printf("dice_control_byebye", "(%d)\n", signum);)
00079 if ( signum == SIGTERM )
00080 _dice_debug(3, dice_printf(NULL, "Control: got SIGTERM\n");)
00081
00082
00083 packet.packtype = GOODBYE;
00084 dice_broadcast(&packet, (signum == -1 ? readynum : -1));
00085
00086 #ifdef USE_ASYNC
00087 dice_async_end();
00088 #endif
00089 dice_sync_end();
00090 if ( dice_data.clients ) {
00091 for ( i = 0; i < dice_data.clientnum; i++ ) {
00092 dice_free(dice_data.clients[i].address);
00093 dice_free(dice_data.clients[i].path);
00094 dice_free(dice_data.clients[i].function);
00095 }
00096
00097 }
00098 dice_free(dice_data.color[0]);
00099 dice_free(dice_data.color[1]);
00100 dice_free(hierarchy);
00101
00102
00103 #ifndef WINDOWS
00104 signal(SIGTERM, SIG_DFL);
00105 #endif
00106 exit(0);
00107 }
00108
00109
00119 int dice_control_hierarchy ( int a, int b ) {
00120 int i;
00121
00122 if ( a == b )
00123 return 1;
00124 for ( i = 0; i < dice_data.clientnum; i++ ) {
00125 if ( hierarchy[i] == a )
00126 return 0;
00127 else if ( hierarchy[i] == b )
00128 return 1;
00129 }
00130 return -1;
00131 }
00132
00133
00134 #undef FUNCTION
00135 #define FUNCTION "dice_control_process"
00136
00149 int dice_control_process ( dice_packet *packet, int from ) {
00150 dice_packet p;
00151 _dice_debug(3, dice_printf(FUNCTION, "(%p, %d); type %s\n", packet, from,
00152 dice_packet_name(packet->packtype));)
00153
00154 switch ( packet->packtype ) {
00155 case INVALID:
00156 return 0;
00157 case SYNC:
00158
00159 p = dice_packet_get(from);
00160 packetfrom = from;
00161 while ( p.packtype == VARIABLE_SYNC ||
00162 p.packtype == VARIABLE_FREE_SYNC ) {
00163
00164 if ( dice_data.original_only && hierarchy[0] != from )
00165 continue;
00166
00167 if ( p.packtype == VARIABLE_SYNC ) {
00168 if ( DICE_sync_update(p.variable.name,
00169 p.variable.value) == -2 )
00170 DICE_sync_new(p.variable.name,
00171 p.variable.type,
00172 p.variable.value );
00173 }
00174 else
00175 DICE_sync_delete(p.variable.name);
00176 free(p.variable.name);
00177 free(p.variable.type);
00178 p = dice_packet_get(from);
00179 }
00180 if ( p.packtype != READY ) {
00181 _dice_debug(1, dice_printf(FUNCTION, "did not get READY, got %s instead\n",
00182 dice_packet_name(p.packtype));)
00183 return -1;
00184 }
00185
00186 syncnum++;
00187 if ( syncnum == dice_data.clientnum ) {
00188
00189 dice_sync_update_send();
00190
00191 p.packtype = SYNC;
00192 dice_broadcast(&p, -1);
00193 syncnum = 0;
00194 }
00195 return 0;
00196 case VARIABLE_ASYNC:
00197 case VARIABLE_FREE_ASYNC:
00198 #ifdef USE_ASYNC
00199 if ( dice_data.original_only && hierarchy[0] != from ) {
00200 DICE_async_update(packet->variable.name, packet->variable.value);
00201 dice_broadcast(packet, from);
00202 }
00203 #endif
00204 return 0;
00205 case VARIABLE_SYNC:
00206 case VARIABLE_FREE_SYNC:
00207 _dice_debug(1, dice_printf(FUNCTION, "got a lonely %s!\n",
00208 dice_packet_name(p.packtype));)
00209 return -1;
00210 case READY:
00211 readynum++;
00212 if ( readynum == dice_data.clientnum ) {
00213 p.packtype = CONTINUE;
00214 dice_broadcast(&p, -1);
00215 readynum = 0;
00216 }
00217 return 0;
00218 case CONTINUE:
00219 _dice_debug(1, dice_printf(FUNCTION, "Control should never get CONTINUE!\n");)
00220 return -1;
00221 case GOODBYE:
00222
00223 readynum = from;
00224 dice_control_byebye(-1);
00225 return 0;
00226 case HELLO:
00227 _dice_debug(1, dice_printf(FUNCTION, "Control should never get HELLO!\n");)
00228 return -1;
00229 }
00230 return -1;
00231 }
00232
00233 #undef FUNCTION
00234 #define FUNCTION "dice_control_loop"
00235
00244 int dice_control_loop ( int argc, char **argv ) {
00245 struct sockaddr_in myaddr, remote;
00246 int sockfd, i;
00247 fd_set fdtemp;
00248 dice_packet packet;
00249
00250 _dice_debug(3, dice_printf(FUNCTION, "()\n");)
00251
00252 #ifndef WINDOWS
00253
00254 signal(SIGTERM, dice_control_byebye);
00255 #endif
00256
00257 FD_ZERO(&clients);
00258 FD_ZERO(&fdtemp);
00259
00260 hierarchy = (int *)malloc(dice_data.clientnum*sizeof(int));
00261 if ( !hierarchy ) {
00262 _dice_debug(1, dice_printf(FUNCTION, "hierarchy: %s\n", strerror(errno));)
00263 return -1;
00264 }
00265
00266
00267 if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) {
00268 _dice_debug(1, dice_printf(FUNCTION, "%s\n", strerror(errno));)
00269 return -1;
00270 }
00271
00272
00273
00274
00275
00276 i = 1;
00277 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(int));
00278
00279
00280 i = 1;
00281 setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &i, sizeof(int));
00282
00283
00284 myaddr.sin_port = htons(dice_data.port);
00285 myaddr.sin_family = AF_INET;
00286 myaddr.sin_addr.s_addr = INADDR_ANY;
00287 memset((void *)&myaddr.sin_zero, 0, 8);
00288
00289
00290 if ( bind(sockfd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0 ) {
00291 _dice_debug(1, dice_printf(FUNCTION, ": %s\n", strerror(errno));)
00292 return -1;
00293 }
00294
00295
00296 if ( listen(sockfd, dice_data.max_connections) < 0 ) {
00297 _dice_debug(1, dice_printf(FUNCTION, "%s\n", strerror(errno));)
00298 return -1;
00299 }
00300
00301
00302 _dice_debug(3, dice_printf(FUNCTION, "waiting for %d clients.\n", dice_data.clientnum);)
00303 for ( i = 0; i < dice_data.clientnum; i++ ) {
00304 int len = sizeof(remote), fdnew, pid;
00305
00306
00307 if ( dice_data.spawn != NONE ) {
00308 _dice_debug(3, dice_printf(FUNCTION, "Spawning %s...\n",
00309 dice_data.clients[i].address);)
00310
00311 argv[0] = dice_data.clients[i].address;
00312 argv[1] = ( dice_data.clients[i].path == NULL ?
00313 defaultpath : dice_data.clients[i].path );
00314 argv[3] = dice_data.controlname;
00315 pid = fork();
00316 if ( pid == 0 ) {
00317 switch ( dice_data.spawn ) {
00318 case RSH:
00319 execvp("rsh", argv);
00320 break;
00321 case SSH:
00322 execvp("ssh", argv);
00323 break;
00324 case BPROC:
00325 _dice_debug(1, dice_printf(FUNCTION,
00326 "BPROC not implemented yet");)
00327
00328 break;
00329 default:
00330 break;
00331 }
00332 _dice_debug(1, dice_printf(FUNCTION, "exec: %s\n",
00333 strerror(errno));)
00334 _exit(1);
00335 }
00336 if ( pid < 0 ) {
00337 _dice_debug(1, dice_printf(FUNCTION, "fork: %s\n",
00338 strerror(errno));)
00339 exit(1);
00340 }
00341
00342 }
00343
00344
00345 if ( (fdnew = accept(sockfd, (struct sockaddr *)&remote, &len)) == -1 ) {
00346 _dice_debug(1, dice_printf(FUNCTION,
00347 "error connecting: %s\n", strerror(errno));)
00348 }
00349 else {
00350 struct hostent *host;
00351 int len2 = sizeof(remote.sin_addr);
00352 char *name;
00353
00354 FD_SET(fdnew, &clients);
00355 if ( fdnew > fdmax )
00356 fdmax = fdnew;
00357
00358
00359 hierarchy[i] = fdnew;
00360
00361
00362 len2 = sizeof(remote.sin_addr);
00363 name = inet_ntoa(remote.sin_addr);
00364 host = gethostbyaddr((char *)&remote.sin_addr, len2, AF_INET);
00365 if ( !host ) {
00366 _dice_debug(1, dice_printf(FUNCTION,
00367 "couldn't get host name for %s: %s\n"
00368 "This may lead to problems in hierarchy.\n",
00369 inet_ntoa(remote.sin_addr), strerror(errno));)
00370 continue;
00371 }
00372 _dice_debug(2, dice_printf(FUNCTION,
00373 "Connection from socket %d by %s(%s)\n", fdnew,
00374 host->h_name, inet_ntoa(remote.sin_addr));)
00375
00376
00377 packet.packtype = HELLO;
00378 packet.hello.id = (unsigned long)i;
00379 packet.hello.function = dice_data.clients[i].function;
00380 dice_packet_send(&packet, fdnew);
00381 }
00382 }
00383
00384 _dice_debug(2, dice_printf(FUNCTION, "All connected");)
00385
00386 while ( 1 ) {
00387 fdtemp = clients;
00388 if ( select(fdmax+1, &fdtemp, NULL, NULL, NULL) == -1 ) {
00389 _dice_debug(1, dice_printf(FUNCTION, "%s\n", strerror(errno));)
00390 }
00391
00392 for ( i = 0; i <= fdmax; i++ ) {
00393 if ( FD_ISSET(i, &fdtemp) && i != sockfd ) {
00394
00395 packet = dice_packet_get(i);
00396 dice_control_process(&packet, i);
00397 }
00398 }
00399 }
00400 return -1;
00401 }