1 /*************************************************************/
2 /* FGD_MCP.C by Oliver Delise */
4 /* e-mail: delise@mail.isis.de */
5 /* www: http://www.isis.de/members/~odelise/progs/mmx-emu/ */
6 /* ftp: http://www.isis.de/members/~odelise/progs/flightgear */
8 /* Version 0.1-alpha */
9 /* The author of this program offers no waranty at all */
10 /* about the correct execution of this software material. */
11 /* Furthermore, the author can NOT be held responsible for */
12 /* any physical or moral damage caused by the use of this */
15 /* This is an interactive standalone Tool to communicate */
16 /* with any FlightGear-Deamon. */
17 /* This is Open Source Software with many parts */
18 /* shamelessly stolen from others... */
20 /* -> This program will use a TCP port listening on a */
21 /* remote or local host inside the range you give to it. */
22 /* I offer no warranty over the accuracy though :) */
23 /* There are 3 verbose modes: No info, service info, and */
24 /* full info. No info is good of you only want the list */
25 /* of the ports, no more info. The best mode is Full */
26 /* info, as you get error information,etc. The main */
27 /* output is STDOUT, and ALL the errors go to STDERR. */
29 /* History: v0.1pre-alpha: May 25 1999 -> First release */
30 /* v0.1-alpha Nov 11 1999 */
31 /*************************************************************/
41 struct sockaddr_in address;
42 struct sockaddr_in my_address;
44 extern char *sys_errlist[];
46 int current_port = 10000;
47 u_short base_port = 10000;
48 u_short end_port = 10000;
50 struct hostent *host_info, *f_host_info;
51 struct servent *service_info;
52 struct utsname myname;
56 int fgd_len_msg = 1, fgd_status, fgd_ele_len, fgd_curpos, fgd_cnt, fgd_ppl,
57 fgd_ppl_old, fgd_loss;
59 char *fgd_job, *fgd_callsign, *fgd_name, *fgd_ip, *fgd_mcp_ip;
60 char *buffp, *src_host, *fgd_host, *fgfs_host, *fgfs_pilot, *fgd_txt;
68 unsigned char ipadr[16], callsign[16];
69 unsigned char lon[8], lat[8], alt[8], roll[8], pitch[8], yaw[8];
70 float lonf, latf, altf, speedf, rollf, pitchf, yawf;
71 struct list_ele *next, *prev;
74 struct list_ele *head, *tail, *act, *test, *incoming, *boss, *other; /* fgd_msg; */
76 /*...Create head and tail of list */
77 void list_init( void) {
79 incoming = (struct list_ele*) malloc(sizeof(struct list_ele));
80 boss = (struct list_ele*) malloc(sizeof(struct list_ele));
81 other = (struct list_ele*) malloc(sizeof(struct list_ele));
82 head = (struct list_ele*) malloc(sizeof(struct list_ele));
83 tail = (struct list_ele*) malloc(sizeof(struct list_ele));
84 if (head == NULL || tail == NULL) { printf("Out of memory\n"); exit(1); }
88 head->prev = tail->prev = head;
89 head->next = tail->next = tail;
90 act = head; /* put listpointer to beginning of list */
93 void list_output( void) {
96 void list_search( char name[16]) {
98 if (strcmp(name, head->next->ipadr) <= 0) act = head;
99 else if (strcmp(name, tail->prev->ipadr) > 0) act = tail->prev;
101 int vergleich = strcmp(name, act->ipadr);
103 while (strcmp(name, act->next->ipadr) > 0) {
106 else if (vergleich < 0)
107 while (strcmp(name, act->ipadr) < 0) {
111 while (strcmp(name, act->ipadr) == 0) {
117 void list_insert( char newip[16]) {
118 struct list_ele *new_ele;
120 new_ele = (struct list_ele*) malloc(sizeof(struct list_ele));
121 if (new_ele == NULL) { printf("Out of memory\n"); exit(1); }
122 strcpy(new_ele->ipadr, newip);
123 /* setting default */
124 strcpy(new_ele->callsign, "not assigned");
127 new_ele->next = act->next;
128 act->next->prev = act->next = new_ele;
131 void list_setval( char newip[16]) {
134 strcpy( act->next->callsign, incoming->callsign);
135 printf("Callsign %s\n", act->next->callsign);
139 void list_clear( char clrip[16]) {
140 struct list_ele *clr_ele;
143 if ( strcmp( clrip, act->next->ipadr))
144 printf("....Name %s nicht vorhanden", clrip);
147 act->next = act->next->next;
148 act->next->prev = act;
153 int list_not_in( char name[16]) {
157 while ((test != tail) && (i==True)) {
158 i = (strcmp(test->ipadr, name) ? True : False);
160 if (verbose != 0) printf("list_not_in : %d\n",i);
167 /* Let's init a few things */
168 printf("MCP: Allocating memory...");
169 buffp = (char *) malloc(1024); /* No I don't check if there are another KB */
170 fgd_job = (char *) malloc(8);
171 fgd_host = (char *) malloc(64);
172 fgd_callsign = (char *) malloc(64);
173 fgd_name = (char*) malloc(64);
174 fgd_ip = (char *) malloc(16);
175 fgd_mcp_ip = (char *) malloc(16);
176 fgfs_host = (char *) malloc(64);
177 fgfs_pilot = (char *) malloc(64);
178 src_host = (char *) malloc(64);
179 fgd_txt = (char *) malloc(1024);
180 printf("ok\nMCP: Initializing values...");
181 strcpy( fgd_job, "xxx");
182 strcpy( fgd_host, "Johnny");
183 strcpy( fgd_callsign, "Unknown");
184 strcpy( fgd_name, "Unknown");
185 strcpy( fgd_ip, (char *) inet_ntoa(address.sin_addr));
186 strcpy( fgd_txt, "");
191 boss->speedf = 100.95;
194 boss->yawf = 456.789;
196 bzero((char *)&address, sizeof(address));
197 address.sin_family = AF_INET;
198 /* determinating the source/sending host */
199 if (uname(&myname) == 0) strcpy(src_host , myname.nodename);
200 printf("MCP: I'm running on HOST : %s ", src_host);
201 if (host_info = gethostbyname( src_host)) {
202 bcopy(host_info->h_addr, (char *)&address.sin_addr,host_info->h_length);
203 strcpy((char *) fgd_mcp_ip, (char *) inet_ntoa(address.sin_addr));
205 printf("IP : %s\n", fgd_mcp_ip);
206 /* resolving the destination host, here fgd's host */
207 if (verbose == 2) printf(" Resolving default DEAMON: %s ->", fgd_host);
208 if (host_info = gethostbyname( fgd_host)) {
209 bcopy(host_info->h_addr, (char *)&address.sin_addr,host_info->h_length);
210 strcpy((char *) fgd_ip, (char *) inet_ntoa(address.sin_addr));
212 printf(" resolved\n FGD running on HOST : %s", fgd_host);
213 printf(" IP : %s\n", fgd_ip);
215 } else if ((address.sin_addr.s_addr = inet_addr( fgd_host)) == INADDR_NONE) {
216 fprintf(stderr," Could not get %s host entry !\n", fgd_host);
217 printf(" NOT resolved !!!\n");
219 } else if (verbose == 2) printf(" address valid\n");
221 if ((base_port > end_port) || ((short)base_port < 0)) {
222 fprintf(stderr,"Bad port range : start=%d end=%d !\n");
224 } else if (verbose == 2) {
225 printf(" Port range: %d to %d\n",base_port,end_port);
230 void fgd_send_com( char *FGD_com, char *FGFS_host) {
233 current_port = base_port;
234 printf(" Sending : %s\n", FGD_com);
235 while (current_port <= end_port) {
236 /* fprintf(stderr,"Trying port: %d\n",current_port); */
237 sock = socket(PF_INET, SOCK_STREAM, 0);
240 fprintf(stderr, "Error assigning master socket: %s\n",sys_errlist[errno]);
244 address.sin_port = htons(current_port);
245 printf(" address.sin_port : %d\n",htons(address.sin_port));
247 f_host_info = gethostbyname(src_host);
249 //printf ("src_host : %s", ntohs(f_host_info->h_addr));
251 if (connect(sock, (struct sockaddr *)&address, sizeof(address)) == 0) {
252 /* FIXME: make a single string instead of sending elements */
254 fgd_len_msg = (int) sizeof(f_host_info->h_addr);
255 /* send length of sender-ip */
256 write( sock, &fgd_len_msg,1);
258 write( sock, f_host_info->h_addr, fgd_len_msg);
260 write( sock, FGD_com, 1);
261 /* send length of dummy-string, for the moment with _WHO_ to execute commando
262 here: his length of ip */
263 f_host_info = gethostbyname(FGFS_host);
264 fgd_len_msg = (int) sizeof(f_host_info->h_addr);
265 write( sock, &fgd_len_msg,1);
266 /* send dummy-string, for the moment with _WHO_ to execute commando
268 write( sock, f_host_info->h_addr, fgd_len_msg);
271 /* Here we send subsequent data... */
272 switch (atoi((char *) FGD_com)) {
273 case 5: fgd_len_msg = strlen( fgd_callsign);
274 write( sock, &fgd_len_msg,1);
275 /* send string, for the moment, here: callsign */
276 write( sock, fgd_callsign, fgd_len_msg);
277 /* Lon, Lat, Alt, Speed, Roll, Pitch, Yaw
278 hope this sprintf call is not too expensive */
279 sprintf( fgd_txt, " %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f",
280 boss->latf, boss->lonf, boss->altf, boss->speedf,
281 boss->rollf, boss->pitchf, boss->yawf);
282 write( sock, fgd_txt, 56);
288 /* be verbose, this goes later into own (*void) */
289 printf(" Message : %s\n", FGD_com);
291 case 0: printf("%d\n",current_port);
293 case 1: service_info = getservbyport(htons(current_port),"tcp");
295 printf("%d -> service name unknown\n",current_port);
297 printf("%d -> %s\n",current_port,service_info->s_name);
300 case 2: service_info = getservbyport(htons(current_port),"tcp");
302 printf(" Port %d found. Service name unknown\n",current_port);
304 printf(" Port %d found. Service name: %s\n",current_port,service_info->s_name);
308 } else if (errno == 113) {
309 fprintf(stderr,"No route to host !\n");
312 /* fprintf(stderr,"Error %d connecting socket %d to port %d: %s\n",
313 errno,sock,current_port,sys_errlist[errno]); */
315 // service_info = getservbyport(htons(current_port),"tcp");
316 // if (!service_info) {
320 /* The Receiving Part, fgd returns errormessages, succes, etc... */
322 fgd_status = recv( sock, (char *) buffp, 4, MSG_WAITALL);
323 printf(" status %d\n", fgd_status);
325 // while ( (fgd_status != 4) && (fgd_status != 0) );
326 while ( (fgd_status == -1) || (fgd_status == -1) );
328 printf(" Got reply : %x %x %x\n", buffp[0], buffp[1], buffp[2]);
329 printf(" Got reply : %x\n", &buffp);
331 if (strncmp( buffp, "FGD", 3) == 0) {
332 switch (atoi((char *) FGD_com)) {
333 case 0: read( sock, fgd_name, buffp[3]);
334 fgd_name[buffp[3]] = 0;
335 printf("FGD: FlightGear-Deamon %s detected\n", fgd_name);
337 case 1: printf("FGD: Registering Host %s\n", FGFS_host);
339 case 2: printf("FGD: Showing registered Hosts at %s\n", fgd_host);
341 /* FIXME: replace with SELECT to avoid broken pipes, known bug (-; */
343 fgd_status = recv( sock, fgd_txt, buffp[3]-4, MSG_WAITALL);
344 // printf(" status %d\n", fgd_status);
346 // while ( (fgd_status != 4) && (fgd_status != 0) );
347 while ( (fgd_status == -1) || (fgd_status == -1) );
348 // read( sock, fgd_txt, buffp[3]-4);
350 for (fgd_cnt = 1; fgd_cnt < (fgd_txt[0]+1); fgd_cnt++) {
351 fgd_ele_len = fgd_txt[fgd_curpos-1];
352 bcopy( &fgd_txt[fgd_curpos], fgfs_host, fgd_ele_len);
353 fgfs_host[fgd_ele_len] = 0;
354 fgd_curpos = fgd_curpos + fgd_ele_len + 1;
355 printf(" #%d %s\n", fgd_cnt, fgfs_host);
360 case 5: printf("FGD: Receiving data from Host %s\n", FGFS_host);
361 read( sock, fgd_txt, buffp[3]);
362 fgd_txt[buffp[3]] = 0;
363 if (strcmp(fgd_txt, "UNKNOWN") == -1) {
364 printf("FGD: Data from Host %s received\n", fgd_txt);
366 else printf("FGD: Host not in list, sorry...\n");
368 case 6: printf("FGD: Sending data to Host %s\n", FGFS_host);
370 /* FIXME: replace with SELECT */
371 if (verbose == 2) printf("Noch %d bytes\n", (unsigned char) buffp[3]);
373 fgd_status = recv( sock, fgd_txt, (unsigned char) buffp[3]-4, MSG_PEEK);
374 if (verbose == 2) printf("Status %d\n", fgd_status);
376 while ( (fgd_status == 4) || (fgd_status == -1) );
377 // while ( (fgd_status == -1) || (fgd_status == -1) );
378 read( sock, fgd_txt, buffp[3]-4);
380 fgd_ppl_old = fgd_ppl;
381 fgd_ppl = fgd_txt[0];
382 /* Check if list has changed (pilot joined/left) */
383 if (fgd_ppl != fgd_ppl_old) {
384 printf(" List changed!!!\n");
385 for (fgd_cnt = 1; fgd_cnt <= abs(fgd_ppl - fgd_ppl_old); fgd_cnt++) {
386 printf(" Checkpoint\n");
387 incoming = head->next;
388 if ((fgd_ppl - fgd_ppl_old) > 0) list_insert("test\0");
390 printf(" Clearing entry.\n");
391 list_clear(incoming->ipadr);
396 incoming = head->next;
397 for (fgd_cnt = 1; fgd_cnt < (fgd_ppl+1); fgd_cnt++) {
399 fgd_ele_len = fgd_txt[fgd_curpos-1];
400 bcopy( &fgd_txt[fgd_curpos], incoming->ipadr, fgd_ele_len);
401 incoming->ipadr[fgd_ele_len] = 0;
402 fgd_curpos = fgd_curpos + fgd_ele_len + 1;
404 fgd_ele_len = fgd_txt[fgd_curpos-1];
405 bcopy( &fgd_txt[fgd_curpos], incoming->callsign, fgd_ele_len);
406 incoming->callsign[fgd_ele_len] = 0;
407 fgd_curpos = fgd_curpos + fgd_ele_len + 1;
409 printf(" #%d %-16s %s\n", fgd_cnt, incoming->ipadr, incoming->callsign);
410 printf(" curpos:%d\n", fgd_curpos);
411 sscanf( &fgd_txt[fgd_curpos]," %7f %7f %7f %7f %7f %7f %7f",
412 &incoming->latf, &incoming->lonf,
413 &incoming->altf, &incoming->speedf, &incoming->rollf,
414 &incoming->pitchf, &incoming->yawf);
415 printf(" lat :%7.3f\n lon :%7.3f\n alt :%7.3f\n speed :%7.3f\n roll :%7.3f\n pitch :%7.3f\n yaw :%7.3f\n",
416 incoming->latf, incoming->lonf, incoming->altf, incoming->speedf,
417 incoming->rollf, incoming->pitchf, incoming->yawf);
419 incoming = incoming->next;
422 } /* end if "data available" */
423 /* Here reading the answer of completed command by fgd */
424 /* read( sock, fgd_txt, buffp[3]);
425 fgd_txt[buffp[3]] = 0;
426 if (strcmp(fgd_txt, "UNKNOWN") == -1) {
427 printf("FGD: Data to Host sent\n");
429 else printf("FGD: Host not in list, sorry...\n");
432 case 8: printf("FGD: Unregistering Host %s\n", FGFS_host);
433 read( sock, fgd_txt, buffp[3]);
434 fgd_txt[buffp[3]] = 0;
435 if (strcmp(fgd_txt, "UNKNOWN") == -1) {
436 printf("FGD: Host %s unregistered\n", fgd_txt);
438 else printf("FGD: Host not in list, sorry...\n");
440 case 9: printf(" Shutdown FlightGear-Deamon %s .\n", fgd_name);
444 } else printf(" Huh?: no deamon present, yuk!!!\n");
450 if (verbose == 2) printf("fgd_com completed.\n");
454 int main(int argc, char **argv) {
458 for ( ; (atoi( (char*) fgd_job)) != 99;){
459 printf("MCP: ready...enter commando (42 help) ");
460 gets((char *) fgd_job);
461 if (verbose == 2) printf("MCP: got %s %d\n", (char *) fgd_job, strlen((char *) fgd_job));
462 if ( strcmp( fgd_job, "") > 0 ) switch( atoi((char*) fgd_job)) {
463 case 0 : if ( strcmp( (char *) fgd_job, "0") == 0 ){
464 printf("MCP: Scan for fgd\n");
465 fgd_send_com( "0", src_host);
468 case 1 : printf("MCP: Register to fgd\n");
469 fgd_send_com( "1", src_host);
471 case 2 : printf("MCP: Show registered\n");
472 fgd_send_com( "2", src_host);
474 case 3 : printf("MCP: Send MSG\n");
476 case 4 : printf("MCP: Send MSG to ALL\n");
478 case 5 : printf("MCP: Push Data to fgd\n");
479 fgd_send_com( "5", src_host);
481 case 6 : printf("MCP: Pop Data from fgd\n");
482 fgd_send_com( "6", src_host);
484 case 8 : printf("MCP: Unregister from fgd\n");
485 fgd_send_com( "8", src_host);
487 case 9 : printf("MCP: Shutdown fgd-deamon\n");
488 fgd_send_com( "9", src_host);
490 case 10 : printf("MCP: Choose default deamon HOST:\n");
491 printf(" Deamon Host IP Port\n");
492 printf(" %-16s%-16s%-16s%-16d\n", fgd_name, fgd_host, fgd_ip, base_port);
493 printf("\n Enter new Host:[%s] ", fgd_host);
494 gets((char *) fgd_txt);
495 if ( strlen(fgd_txt) != 0 ) {
496 strcpy(fgd_host, fgd_txt);
497 if (host_info = gethostbyname( fgd_host)) {
498 bcopy(host_info->h_addr, (char *)&address.sin_addr,host_info->h_length);
499 strcpy((char *) fgd_ip, (char *) inet_ntoa(address.sin_addr));
501 printf(" resolved\n FGD running on HOST : %s", fgd_host);
502 printf(" IP : %s\n", fgd_ip);
504 } else if ((address.sin_addr.s_addr = inet_addr( fgd_host)) == INADDR_NONE) {
505 fprintf(stderr," Could not get %s host entry !\n", fgd_host);
506 printf(" NOT resolved !!!\n");
508 } else if (verbose == 2) printf(" address valid\n");
511 case 11 : printf("MCP: Choose default deamon Port:\n");
512 printf(" Deamon Host IP Port\n");
513 printf(" %-16s%-16s%-16s%-16d\n", fgd_name, fgd_host, fgd_ip, base_port);
514 printf(" Enter new Port: ");
515 gets((char *) buffp);
516 current_port = atoi((char*) buffp);
517 if (current_port != 0) {
518 base_port = atoi((char*) buffp);
519 end_port = base_port;
522 case 20 : printf("MCP: Current values:\n");
523 printf(" Deamon Host IP Port\n");
524 printf(" %-16s%-16s%-16s%-16d\n", fgd_name, fgd_host, fgd_ip, base_port);
525 printf(" -----------------------------------------------------\n");
526 printf(" Callsign Host IP Port\n");
527 printf(" %-16s%-16s%-16s%-16d\n", fgd_callsign, src_host, fgd_mcp_ip, base_port);
528 printf(" Lat Lon Alt Speed Roll Pitch Yaw\n");
529 printf(" %-8s % 7.3f % 7.3f % 7.3f % 7.3f % 7.3f % 7.3f % 7.3f\n", fgd_callsign, boss->latf,
530 boss->lonf, boss->altf, boss->speedf, boss->rollf, boss->pitchf, boss->yawf);
531 printf(" -----------------------------------------------------\n");
532 printf(" Pilot list:\n");
534 while (test != tail) {
535 printf(" Callsign Host\n");
536 printf(" %-16s%-16s\n", test->callsign, test->ipadr);
537 printf(" Lat Lon Alt Speed Roll Pitch Yaw\n");
538 printf(" %-8s % 7.3f % 7.3f % 7.3f % 7.3f % 7.3f % 7.3f % 7.3f\n", test->callsign, test->latf,
539 test->lonf, test->altf, test->speedf, test->rollf, test->pitchf, test->yawf);
542 printf(" -----------------------------------------------------\n");
545 case 21 : printf("MCP: Enter your callsign, Pilot ");
546 gets((char *) fgd_callsign);
548 case 42 : printf("MCP: Commands available:\n 0 Scan for fgd\n 1 Register\n");
549 printf(" 2 Show registered\n 3 Send MSG\n 4 Send MSG to ALL\n");
550 printf(" 5 Push Data to fgd\n 6 Pop Data from fgd\n");
551 printf(" 8 Unregister from fgd\n 9 Shutdown fgd\n");
552 printf("10 Set deamon HOST\n11 Set deamon PORT\n");
553 printf("20 Show values\n21 Set own callsign\n");
554 printf("31 Set deamon PORT\n");
555 printf("98 Stress test\n");
556 printf("99 Quit Master Control Program (not recommended)\n");
558 case 98 : printf("MCP: Stress test ");
560 list_search(fgd_mcp_ip);
562 printf("other-ip %s\n", other->ipadr);
564 for ( j=1; j<10000; j++) {
566 fgd_send_com( "5", src_host);
567 fgd_send_com( "6", src_host);
568 printf("other lat:%7.3f boss lat:%7.3f\n", other->latf, boss->latf);
569 if (fabs(boss->latf - other->latf) > 0.001) {
570 printf("other lat:%7.3f boss lat:%7.3f\n", other->latf, boss->latf);
574 printf(" Packets lost: %d\n", fgd_loss);
579 // fgd_send_com( argv[5], argv[6]);
591 printf("MCP: Exit...\n");