]> git.evergreen-ils.org Git - OpenSRF.git/blob - src/srfsh/srfsh.c
ebc9a6186b5484d8a2fbb01319e4d2921ba49395
[OpenSRF.git] / src / srfsh / srfsh.c
1 #include "srfsh.h"
2
3 int is_from_script = 0;
4 FILE* shell_writer = NULL;
5 FILE* shell_reader = NULL;
6
7 int main( int argc, char* argv[] ) {
8
9         /* --------------------------------------------- */
10         /* see if they have a .srfsh.xml in their home directory */
11         char* home = getenv("HOME");
12         int l = strlen(home) + 36;
13         char fbuf[l];
14         memset(fbuf, 0, l);
15         sprintf(fbuf,"%s/.srfsh.xml",home);
16
17         if(!access(fbuf, R_OK)) {
18                 if( ! osrf_system_bootstrap_client(fbuf, "srfsh") ) 
19                         fatal_handler( "Unable to bootstrap client for requests");
20
21         } else {
22                 fatal_handler( "No Config file found at %s", fbuf );
23         }
24
25         if(argc > 1) {
26                 /* for now.. the first arg is used as a script file for processing */
27                 int f;
28                 if( (f = open(argv[1], O_RDONLY)) == -1 )
29                         fatal_handler("Unable to open file %s for reading, exiting...", argv[1]);
30
31                 if(dup2(f, STDIN_FILENO) == -1)
32                         fatal_handler("Unable to duplicate STDIN, exiting...");
33
34                 close(f);
35                 is_from_script = 1;
36         }
37                 
38         /* --------------------------------------------- */
39         load_history();
40
41
42         client = osrf_system_get_transport_client();
43
44         /* open the shell handle */
45         shell_writer = popen( "bash", "w");
46         //shell_reader = popen( "bash", "r");
47
48         /* main process loop */
49         char* request;
50         while((request=readline(prompt))) {
51
52                 if( !strcmp(request, "exit") || !strcmp(request,"quit")) 
53                         break; 
54
55                 char* req_copy = strdup(request);
56
57                 parse_request( req_copy ); 
58                 if( request && strlen(request) > 1 ) {
59                         add_history(request);
60                 }
61
62                 free(request);
63                 free(req_copy);
64
65                 fflush(shell_writer);
66                 fflush(stderr);
67                 fflush(stdout);
68         }
69
70         if(history_file != NULL )
71                 write_history(history_file);
72
73         free(request);
74
75         osrf_system_shutdown();
76         return 0;
77 }
78
79 void sig_child_handler( int s ) {
80         child_dead = 1;
81 }
82
83 /*
84 void sig_int_handler( int s ) {
85         printf("\n");
86         caught_sigint = 1;
87         signal(SIGINT,sig_int_handler);
88 }
89 */
90
91 int load_history() {
92
93         char* home = getenv("HOME");
94         int l = strlen(home) + 24;
95         char fbuf[l];
96
97         memset(fbuf, 0, l);
98         sprintf(fbuf,"%s/.srfsh_history",home);
99         history_file = strdup(fbuf);
100
101         if(!access(history_file, W_OK | R_OK )) {
102                 history_length = 999;
103                 read_history(history_file);
104         }
105         return 1;
106 }
107
108
109 int parse_error( char* words[] ) {
110
111         if( ! words )
112                 return 0;
113
114
115         int i = 0;
116         char* current;
117         char buffer[256];
118         memset(buffer, 0, 256);
119         while( (current=words[i++]) ) {
120                 strcat(buffer, current);
121                 strcat(buffer, " ");
122         }
123         if( ! buffer || strlen(buffer) < 1 ) 
124                 printf("\n");
125
126         fprintf( stderr, "???: %s\n", buffer );
127         return 0;
128
129 }
130
131
132 int parse_request( char* request ) {
133
134         if( request == NULL )
135                 return 0;
136
137         int ret_val = 0;
138         int i = 0;
139         char* words[COMMAND_BUFSIZE]; 
140         memset(words,0,COMMAND_BUFSIZE);
141         char* req = request;
142
143         char* cur_tok = strtok( req, " " );
144
145         if( cur_tok == NULL )
146                 return 0;
147
148         while(cur_tok != NULL) {
149                 words[i++] = cur_tok;
150                 cur_tok = strtok( NULL, " " );
151         }
152
153
154         // not sure why (strtok?), but this is necessary
155         memset( words + i, 0, COMMAND_BUFSIZE - i );
156
157         /* pass off to the top level command */
158         if( !strcmp(words[0],"router") ) 
159                 ret_val = handle_router( words );
160
161         else if( !strcmp(words[0],"time") ) 
162                 ret_val = handle_time( words );
163
164         else if (!strcmp(words[0],"request"))
165                 ret_val = handle_request( words, 0 );
166
167         else if (!strcmp(words[0],"relay"))
168                 ret_val = handle_request( words, 1 );
169
170         else if (!strcmp(words[0],"help"))
171                 ret_val = print_help();
172
173         else if (!strcmp(words[0],"set"))
174                 ret_val = handle_set(words);
175
176         else if (!strcmp(words[0],"print"))
177                 ret_val = handle_print(words);
178
179         else if (!strcmp(words[0],"math_bench"))
180                 ret_val = handle_math(words);
181
182         else if (!strcmp(words[0],"introspect"))
183                 ret_val = handle_introspect(words);
184
185         else if (!strcmp(words[0],"login"))
186                 ret_val = handle_login(words);
187
188         else if (words[0][0] == '!')
189                 ret_val = handle_exec( words, 1 );
190
191         if(!ret_val) {
192                 #ifdef EXEC_DEFAULT
193                         return handle_exec( words, 0 );
194                 #else
195                         return parse_error( words );
196                 #endif
197         }
198
199         return 1;
200
201 }
202
203
204 int handle_introspect(char* words[]) {
205
206         if(words[1] && words[2]) {
207                 fprintf(stderr, "--> %s\n", words[1]);
208                 char buf[256];
209                 memset(buf,0,256);
210                 sprintf( buf, "request %s opensrf.system.method %s", words[1], words[2] );
211                 return parse_request( buf );
212
213         } else {
214         
215                 if(words[1]) {
216                         fprintf(stderr, "--> %s\n", words[1]);
217                         char buf[256];
218                         memset(buf,0,256);
219                         sprintf( buf, "request %s opensrf.system.method.all", words[1] );
220                         return parse_request( buf );
221                 }
222         }
223
224         return 0;
225 }
226
227
228 int handle_login( char* words[]) {
229
230         if( words[1] && words[2]) {
231
232                 char* username = words[1];
233                 char* password = words[2];
234
235                 char buf[256];
236                 memset(buf,0,256);
237
238                 char buf2[256];
239                 memset(buf2,0,256);
240
241                 sprintf( buf, 
242                                 "request open-ils.auth open-ils.auth.authenticate.init \"%s\"", username );
243                 parse_request(buf); 
244
245                 char* hash;
246                 if(last_result && last_result->_result_content) {
247                         jsonObject* r = last_result->_result_content;
248                         hash = jsonObjectGetString(r);
249                 } else return 0;
250
251
252                 char* pass_buf = md5sum(password);
253
254                 char both_buf[256];
255                 memset(both_buf,0,256);
256                 sprintf(both_buf,"%s%s",hash, pass_buf);
257
258                 char* mess_buf = md5sum(both_buf);
259
260                 sprintf( buf2,
261                                 "request open-ils.auth open-ils.auth.authenticate.complete \"%s\", \"%s\", \"opac\"", 
262                                 username, mess_buf );
263
264                 free(pass_buf);
265                 free(mess_buf);
266
267                 parse_request( buf2 );
268
269                 char* x = jsonObjectGetString(last_result->_result_content);
270                 if(x) login_session = strdup(x);
271                 else login_session = NULL;
272
273                 printf("Login Session: %s\n", login_session );
274                 
275                 return 1;
276
277         }
278
279         return 0;
280 }
281
282 char* md5sum( char* text ) {
283
284         struct md5_ctx ctx;
285         unsigned char digest[16];
286
287         MD5_start (&ctx);
288
289         int i;
290         for ( i=0 ; i != strlen(text) ; i++ )
291                 MD5_feed (&ctx, text[i]);
292
293         MD5_stop (&ctx, digest);
294
295         char buf[16];
296         memset(buf,0,16);
297
298         char final[256];
299         memset(final,0,256);
300
301         for ( i=0 ; i<16 ; i++ ) {
302                 sprintf(buf, "%02x", digest[i]);
303                 strcat( final, buf );
304         }
305
306         return strdup(final);
307
308 }
309
310
311 int handle_set( char* words[]) {
312
313         char* variable;
314         if( (variable=words[1]) ) {
315
316                 char* val;
317                 if( (val=words[2]) ) {
318
319                         if(!strcmp(variable,"pretty_print")) {
320                                 if(!strcmp(val,"true")) {
321                                         pretty_print = 1;
322                                         printf("pretty_print = true\n");
323                                         return 1;
324                                 } 
325                                 if(!strcmp(val,"false")) {
326                                         pretty_print = 0;
327                                         printf("pretty_print = false\n");
328                                         return 1;
329                                 } 
330                         }
331
332                         if(!strcmp(variable,"raw_print")) {
333                                 if(!strcmp(val,"true")) {
334                                         raw_print = 1;
335                                         printf("raw_print = true\n");
336                                         return 1;
337                                 } 
338                                 if(!strcmp(val,"false")) {
339                                         raw_print = 0;
340                                         printf("raw_print = false\n");
341                                         return 1;
342                                 } 
343                         }
344
345                 }
346         }
347
348         return 0;
349 }
350
351
352 int handle_print( char* words[]) {
353
354         char* variable;
355         if( (variable=words[1]) ) {
356                 if(!strcmp(variable,"pretty_print")) {
357                         if(pretty_print) {
358                                 printf("pretty_print = true\n");
359                                 return 1;
360                         } else {
361                                 printf("pretty_print = false\n");
362                                 return 1;
363                         }
364                 }
365
366                 if(!strcmp(variable,"login")) {
367                         printf("login session = %s\n", login_session );
368                         return 1;
369                 }
370
371         }
372         return 0;
373 }
374
375 int handle_router( char* words[] ) {
376
377         if(!client)
378                 return 1;
379
380         int i;
381
382         if( words[1] ) { 
383                 if( !strcmp(words[1],"query") ) {
384                         
385                         if( words[2] && !strcmp(words[2],"servers") ) {
386                                 for(i=3; i < COMMAND_BUFSIZE - 3 && words[i]; i++ ) {   
387                                         router_query_servers( words[i] );
388                                 }
389                                 return 1;
390                         }
391                         return 0;
392                 }
393                 return 0;
394         }
395         return 0;
396 }
397
398
399 /* if new shell, spawn a new child and subshell to do the work,
400         otherwise pipe the request to the currently open (piped) shell */
401 int handle_exec(char* words[], int new_shell) {
402
403         if(!words[0]) return 0;
404
405         if( words[0] && words[0][0] == '!') {
406                 int len = strlen(words[0]);
407                 char command[len];
408                 memset(command,0,len);
409         
410                 int i; /* chop out the ! */
411                 for( i=1; i!= len; i++) {
412                         command[i-1] = words[0][i];
413                 }
414         
415                 free(words[0]);
416                 words[0] = strdup(command);
417         }
418
419         if(new_shell) {
420                 signal(SIGCHLD, sig_child_handler);
421
422                 if(fork()) {
423         
424                         waitpid(-1, 0, 0);
425                         if(child_dead) {
426                                 signal(SIGCHLD,sig_child_handler);
427                                 child_dead = 0;
428                         }
429         
430                 } else {
431                         execvp( words[0], words );
432                         exit(0);
433                 }
434
435         } else {
436
437
438                 growing_buffer* b = buffer_init(64);
439                 int i = 0;
440                 while(words[i]) 
441                         buffer_fadd( b, "%s ", words[i++] );
442         
443                 buffer_add( b, "\n");
444         
445                 //int reader;
446                 //int reader = dup2(STDOUT_FILENO, reader);
447                 //int reader = dup(STDOUT_FILENO);
448                 //close(STDOUT_FILENO);
449
450                 fprintf( shell_writer, b->buf );
451                 buffer_free(b);
452         
453                 fflush(shell_writer);
454                 usleep(1000);
455
456                 /*
457                 char c[4096];
458                 bzero(c, 4096);
459                 read( reader, c, 4095 );
460                 fprintf(stderr, "read %s", c);
461                 dup2(reader, STDOUT_FILENO);
462                 */
463
464         }
465
466         
467         return 1;
468 }
469
470
471 int handle_request( char* words[], int relay ) {
472
473         if(!client)
474                 return 1;
475
476         if(words[1]) {
477                 char* server = words[1];
478                 char* method = words[2];
479                 int i;
480                 growing_buffer* buffer = NULL;
481                 if(!relay) {
482                         buffer = buffer_init(128);
483                         buffer_add(buffer, "[");
484                         for(i = 3; words[i] != NULL; i++ ) {
485                                 /* removes trailing semicolon if user accidentally enters it */
486                                 if( words[i][strlen(words[i])-1] == ';' )
487                                         words[i][strlen(words[i])-1] = '\0';
488                                 buffer_add( buffer, words[i] );
489                                 buffer_add(buffer, " ");
490                         }
491                         buffer_add(buffer, "]");
492                 }
493
494                 return send_request( server, method, buffer, relay );
495         } 
496
497         return 0;
498 }
499
500 int send_request( char* server, 
501                 char* method, growing_buffer* buffer, int relay ) {
502         if( server == NULL || method == NULL )
503                 return 0;
504
505         jsonObject* params = NULL;
506         if( !relay ) {
507                 if( buffer != NULL && buffer->n_used > 0 ) 
508                         params = json_parse_string(buffer->buf);
509         } else {
510                 if(!last_result || ! last_result->_result_content) { 
511                         printf("We're not going to call 'relay' with no result params\n");
512                         return 1;
513                 }
514                 else {
515                         jsonObject* o = jsonNewObject(NULL);
516                         jsonObjectPush(o, last_result->_result_content );
517                         params = o;
518                 }
519         }
520
521
522         if(buffer->n_used > 0 && params == NULL) {
523                 fprintf(stderr, "JSON error detected, not executing\n");
524                 return 1;
525         }
526
527         osrf_app_session* session = osrf_app_client_session_init(server);
528
529         if(!osrf_app_session_connect(session)) {
530                 warning_handler( "Unable to connect to remote service %s\n", server );
531                 return 1;
532         }
533
534         double start = get_timestamp_millis();
535         //int req_id = osrf_app_session_make_request( session, params, method, 1, NULL );
536         int req_id = osrf_app_session_make_req( session, params, method, 1, NULL );
537
538
539         osrf_message* omsg = osrf_app_session_request_recv( session, req_id, 60 );
540
541         if(!omsg) 
542                 printf("\nReceived no data from server\n");
543         
544         
545         signal(SIGPIPE, SIG_IGN);
546
547         FILE* less; 
548         if(!is_from_script) less = popen( "less -EX", "w");
549         else less = stdout;
550
551         if( less == NULL ) { less = stdout; }
552
553         growing_buffer* resp_buffer = buffer_init(4096);
554
555         while(omsg) {
556
557                 if(raw_print) {
558
559                         if(omsg->_result_content) {
560         
561                                 osrf_message_free(last_result);
562                                 last_result = omsg;
563         
564                                 char* content;
565         
566                                 if( pretty_print && omsg->_result_content ) {
567                                         char* j = jsonObjectToJSON(omsg->_result_content);
568                                         //content = json_printer(j); 
569                                         content = jsonFormatString(j);
570                                         free(j);
571                                 } else
572                                         content = jsonObjectGetString(omsg->_result_content);
573         
574                                 printf( "\nReceived Data: %s\n", content ); 
575                                 free(content);
576         
577                         } else {
578
579                                 char code[16];
580                                 memset(code, 0, 16);
581                                 sprintf( code, "%d", omsg->status_code );
582                                 buffer_add( resp_buffer, code );
583
584                                 printf( "\nReceived Exception:\nName: %s\nStatus: %s\nStatus: %s\n", 
585                                                 omsg->status_name, omsg->status_text, code );
586
587                                 fflush(stdout);
588                         }
589
590                 } else {
591
592                         if(omsg->_result_content) {
593         
594                                 osrf_message_free(last_result);
595                                 last_result = omsg;
596         
597                                 char* content;
598         
599                                 if( pretty_print && omsg->_result_content ) {
600                                         char* j = jsonObjectToJSON(omsg->_result_content);
601                                         //content = json_printer(j); 
602                                         content = jsonFormatString(j);
603                                         free(j);
604                                 } else
605                                         content = jsonObjectGetString(omsg->_result_content);
606         
607                                 buffer_add( resp_buffer, "\nReceived Data: " ); 
608                                 buffer_add( resp_buffer, content );
609                                 buffer_add( resp_buffer, "\n" );
610                                 free(content);
611         
612                         } else {
613         
614                                 buffer_add( resp_buffer, "\nReceived Exception:\nName: " );
615                                 buffer_add( resp_buffer, omsg->status_name );
616                                 buffer_add( resp_buffer, "\nStatus: " );
617                                 buffer_add( resp_buffer, omsg->status_text );
618                                 buffer_add( resp_buffer, "\nStatus: " );
619                                 char code[16];
620                                 memset(code, 0, 16);
621                                 sprintf( code, "%d", omsg->status_code );
622                                 buffer_add( resp_buffer, code );
623                         }
624                 }
625
626
627                 omsg = osrf_app_session_request_recv( session, req_id, 5 );
628
629         }
630
631         double end = get_timestamp_millis();
632
633         fprintf( less, resp_buffer->buf );
634         buffer_free( resp_buffer );
635         fprintf( less, "\n------------------------------------\n");
636         if( osrf_app_session_request_complete( session, req_id ))
637                 fprintf(less, "Request Completed Successfully\n");
638
639
640         fprintf(less, "Request Time in seconds: %.3f\n", end - start );
641         fprintf(less, "------------------------------------\n");
642
643         pclose(less); 
644
645         osrf_app_session_request_finish( session, req_id );
646         osrf_app_session_disconnect( session );
647         osrf_app_session_destroy( session );
648
649
650         return 1;
651
652
653 }
654
655 int handle_time( char* words[] ) {
656
657         if( ! words[1] ) {
658
659                 char buf[36];
660                 memset(buf,0,36);
661                 get_timestamp(buf);
662                 printf( "%s\n", buf );
663                 return 1;
664         }
665
666         if( words[1] ) {
667                 time_t epoch = (time_t)atoi( words[1] );
668                 char* localtime = strdup( ctime( &epoch ) );
669                 printf( "%s => %s", words[1], localtime );
670                 free(localtime);
671                 return 1;
672         }
673
674         return 0;
675
676 }
677
678                 
679
680 int router_query_servers( char* router_server ) {
681
682         if( ! router_server || strlen(router_server) == 0 ) 
683                 return 0;
684
685         char rbuf[256];
686         memset(rbuf,0,256);
687         sprintf(rbuf,"router@%s/router", router_server );
688                 
689         transport_message* send = 
690                 message_init( "servers", NULL, NULL, rbuf, NULL );
691         message_set_router_info( send, NULL, NULL, NULL, "query", 0 );
692
693         client_send_message( client, send );
694         message_free( send );
695
696         transport_message* recv = client_recv( client, -1 );
697         if( recv == NULL ) {
698                 fprintf(stderr, "NULL message received from router\n");
699                 return 1;
700         }
701         
702         printf( 
703                         "---------------------------------------------------------------------------------\n"
704                         "Received from 'server' query on %s\n"
705                         "---------------------------------------------------------------------------------\n"
706                         "original reg time | latest reg time | last used time | class | server\n"
707                         "---------------------------------------------------------------------------------\n"
708                         "%s"
709                         "---------------------------------------------------------------------------------\n"
710                         , router_server, recv->body );
711
712         message_free( recv );
713         
714         return 1;
715 }
716                 
717 int print_help() {
718
719         printf(
720                         "---------------------------------------------------------------------------------\n"
721                         "Commands:\n"
722                         "---------------------------------------------------------------------------------\n"
723                         "help                   - Display this message\n"
724                         "!<command> [args] - Forks and runs the given command in the shell\n"
725                         "time                   - Prints the current time\n"                                    
726                         "time <timestamp>       - Formats seconds since epoch into readable format\n"   
727                         "set <variable> <value> - set a srfsh variable (e.g. set pretty_print true )\n"
728                         "print <variable>               - Displays the value of a srfsh variable\n"
729                         "---------------------------------------------------------------------------------\n"
730
731                         "router query servers <server1 [, server2, ...]>\n"
732                         "       - Returns stats on connected services\n"
733                         "\n"
734                         "\n"
735                         "request <service> <method> [ <json formatted string of params> ]\n"
736                         "       - Anything passed in will be wrapped in a json array,\n"
737                         "               so add commas if there is more than one param\n"
738                         "\n"
739                         "\n"
740                         "relay <service> <method>\n"
741                         "       - Performs the requested query using the last received result as the param\n"
742                         "\n"
743                         "\n"
744                         "math_bench <num_batches> [0|1|2]\n"
745                         "       - 0 means don't reconnect, 1 means reconnect after each batch of 4, and\n"
746                         "                2 means reconnect after every request\n"
747                         "\n"
748                         "introspect <service>\n"
749                         "       - prints the API for the service\n"
750                         "\n"
751                         "\n"
752                         "---------------------------------------------------------------------------------\n"
753                         " Commands for Open-ILS\n"
754                         "---------------------------------------------------------------------------------\n"
755                         "login <username> <password>\n"
756                         "       -       Logs into the 'server' and displays the session id\n"
757                         "       - To view the session id later, enter: print login\n"
758                         "---------------------------------------------------------------------------------\n"
759                         "\n"
760                         "\n"
761                         "Note: long output is piped through 'less'.  To search in 'less', type: /<search>\n"
762                         "---------------------------------------------------------------------------------\n"
763                         "\n"
764                         );
765
766         return 1;
767 }
768
769
770
771 char* tabs(int count) {
772         growing_buffer* buf = buffer_init(24);
773         int i;
774         for(i=0;i!=count;i++)
775                 buffer_add(buf, "  ");
776
777         char* final = buffer_data( buf );
778         buffer_free( buf );
779         return final;
780 }
781
782 int handle_math( char* words[] ) {
783         if( words[1] && words[2] ) 
784                 return do_math( atoi(words[1]), atoi(words[2]) );
785         return 0;
786 }
787
788
789 int do_math( int count, int style ) {
790
791         osrf_app_session* session = osrf_app_client_session_init(  "opensrf.math" );
792
793         jsonObject* params = json_parse_string("[]");
794         jsonObjectPush(params,jsonNewObject("1"));
795         jsonObjectPush(params,jsonNewObject("2"));
796
797         char* methods[] = { "add", "sub", "mult", "div" };
798         char* answers[] = { "3", "-1", "2", "0.500000" };
799
800         float times[ count * 4 ];
801         memset(times,0,count*4);
802
803         int k;
804         for(k=0;k!=100;k++) {
805                 if(!(k%10)) 
806                         fprintf(stderr,"|");
807                 else
808                         fprintf(stderr,".");
809         }
810
811         fprintf(stderr,"\n\n");
812
813         int running = 0;
814         int i;
815         for(i=0; i!= count; i++) {
816
817                 int j;
818                 for(j=0; j != 4; j++) {
819
820                         ++running;
821                         struct timeb t1;
822                         struct timeb t2;
823
824                         ftime(&t1);
825                         //int req_id = osrf_app_session_make_request( session, params, methods[j], 1, NULL );
826                         int req_id = osrf_app_session_make_req( session, params, methods[j], 1, NULL );
827
828                         osrf_message* omsg = osrf_app_session_request_recv( session, req_id, 5 );
829
830
831                         ftime(&t2);
832
833                         double start    = ( (int)t1.time        + ( ((float)t1.millitm) / 1000 ) );
834                         double end              = ( (int)t2.time        + ( ((float)t2.millitm) / 1000 ) );
835
836                         times[(4*i) + j] = end - start;
837
838                         if(omsg) {
839         
840                                 if(omsg->_result_content) {
841                                         char* jsn = jsonObjectToJSON(omsg->_result_content);
842                                         if(!strcmp(jsn, answers[j]))
843                                                 fprintf(stderr, "+");
844                                         else
845                                                 fprintf(stderr, "\n![%s] - should be %s\n", jsn, answers[j] );
846                                         free(jsn);
847                                 }
848
849
850                                 osrf_message_free(omsg);
851                 
852                         } else { fprintf( stderr, "\nempty message for tt: %d\n", req_id ); }
853
854                         osrf_app_session_request_finish( session, req_id );
855
856                         if(style == 2)
857                                 osrf_app_session_disconnect( session );
858
859                         if(!(running%100))
860                                 fprintf(stderr,"\n");
861                 }
862
863                 if(style==1)
864                         osrf_app_session_disconnect( session );
865         }
866
867         osrf_app_session_destroy( session );
868         jsonObjectFree(params);
869
870         int c;
871         float total = 0;
872         for(c=0; c!= count*4; c++) 
873                 total += times[c];
874
875         float avg = total / (count*4); 
876         fprintf(stderr, "\n      Average round trip time: %f\n", avg );
877
878         return 1;
879 }