marnet.cpp

Go to the documentation of this file.
00001 /*********************************************************************
00002  *
00003  * scan345: marnet.c
00004  *
00005  * Copyright by Dr. Claudio Klein, X-Ray Research GmbH.
00006  *
00007  * Version:     2.2
00008  * Date:        15/06/2000
00009  *
00010  * History:
00011  *
00012  * Date         Version         Description
00013  * ---------------------------------------------------------------------
00014  * 15/06/00     2.2             net_data rewritten as in mar345 >= 2.3
00015  *
00016  **********************************************************************/
00017 
00018 #include "marnet.h"
00019 
00020 #include <stdio.h>
00021 #include <string.h>
00022 #include <sys/types.h>
00023 #include <sys/socket.h>
00024 #include <sys/time.h>
00025 #include <unistd.h>
00026 #include <netinet/in.h>
00027 #include <netdb.h>
00028 #include <fcntl.h>
00029 #include <errno.h>
00030 #include <signal.h>
00031 #include <time.h>
00032 
00033 /* For TIMER function */
00034 #include "marcmd.h"
00035 
00036 #define                 MAX_TRY         1000
00037 #define                 DATA_SIZE       16386
00038 #define                 STAT_SIZE       404
00039 #define                 MESS_SIZE       84
00040 #define                 FD_MAX          FD_SETSIZE
00041 
00042 #define                 SK_COMM         0
00043 #define                 SK_STAT         1       
00044 #define                 SK_DATA         2
00045 #define                 SK_MESS         3       
00046 
00047 static char             net_buf         [ DATA_SIZE ];
00048 static char             msg_buf         [ MESS_SIZE ];
00049 
00050 char                    net_timeout     = 0;
00051 int                     mar_socket[4]   = {-1, -1, -1, -1};
00052 static char             *sk_type[4]     = { "COMM", "STAT", "DATA", "MESS"};
00053 static char             stop_trying     = 0;
00054 extern char             str             [1024];
00055 extern char             scan_in_progress;
00056 extern int              debug;
00057 extern int              netcontrol;
00058 static struct timeval   timeout;
00059 
00060 extern "C" {
00061   void  swaplong(char*, int);
00062   void  swapshort(char*, int);
00063 }
00064 
00065 MarNet::MarNet(QObject *parent)
00066   : inherited(parent)
00067 {
00068 }
00069 
00070 /******************************************************************
00071  * Function: net_open
00072  ******************************************************************/
00073 int 
00074 MarNet::net_open(int sk)
00075 {
00076   int                   i,retry=0;
00077   int                   protocol;
00078   int                   new_socket;
00079   struct sockaddr_in    sin;
00080   struct sockaddr*        sinPtr;
00081   struct hostent                *hp=NULL;
00082   extern int            mar_port;
00083   extern char           mar_host[32];
00084 
00085   /* Get host address */
00086   hp = gethostbyname(mar_host);
00087   if (hp == NULL) {
00088     return(0);
00089   }
00090   if ( strlen( mar_host ) < 1 ) return 0;
00091 
00092   if ( mar_socket[sk]  != -1 ) {
00093     close( mar_socket[sk] );
00094     mar_socket[sk] = -1;
00095   }
00096 
00097 
00098   /* Set timeout for socket op's */
00099   timeout.tv_sec  = 0;
00100   timeout.tv_usec = 0;
00101 
00102   /*****************************************************
00103    * Create a socket: try 10 times 
00104    *****************************************************/
00105   protocol   = getprotobyname("tcp")->p_proto;
00106 
00107   signal( SIGINT,  stop_net);
00108   stop_trying = 0;
00109 
00110   while ( retry < MAX_TRY ) {
00111 
00112     if ( stop_trying ) {
00113       retry = MAX_TRY;
00114       break;
00115     }
00116 
00117     new_socket = socket(AF_INET, SOCK_STREAM, protocol);
00118 
00119     if ( new_socket < 0 ) {
00120       fprintf( stdout, "scan345: Cannot open socket %s at port %d\n",sk_type[sk],mar_port+sk);
00121       return(0);
00122     }
00123 
00124     /*****************************************************
00125      * Connect to the server.
00126      *****************************************************/
00127 
00128     sin.sin_family      = AF_INET;
00129     sin.sin_port        = htons(mar_port+sk);
00130     bcopy (hp->h_addr, &(sin.sin_addr.s_addr), hp->h_length);
00131     sinPtr              = (struct sockaddr *)&sin;
00132 
00133     if ( ::connect(new_socket, sinPtr, sizeof(sin)) < 0) {
00134       fprintf(stdout, "scan345: %d. try to connect to host '%s' ...\n",retry,mar_host);
00135       if ( retry%5 == 0 ) 
00136         fprintf(stdout, "        To interrupt, press Ctrl+C\n");
00137       sleep( 1 );
00138       close( new_socket );
00139       retry++;
00140     }
00141     else 
00142       break;
00143   }
00144 
00145 //   signal( SIGINT,  mar_kill);
00146 //   signal( SIGKILL, mar_kill );
00147 //   signal( SIGTERM, mar_kill );
00148 //   signal( SIGQUIT, mar_abort);
00149 
00150   if ( retry >= MAX_TRY ) {
00151     fprintf(stdout, "scan345: Giving up ...\n");
00152     close(new_socket);
00153     new_socket = -1;
00154     return 0;
00155   }
00156 
00157 //   fprintf(stdout,"scan345: Connected to host '%s' on port %d (%s)\n",mar_host,mar_port+sk,sk_type[sk]);
00158   emit print_message(tr("scan345: Connected to host '%1' on port %2 (%3)\n").arg(mar_host).arg(mar_port+sk).arg(sk_type[sk]));
00159 
00160   /* We don't need the previous socket any more, close it */
00161   if ( mar_socket[sk] != -1 )
00162     close( mar_socket[sk] );
00163 
00164   mar_socket[sk] = new_socket;
00165 
00166   /* Set socket NON BLOCKING */
00167   if ( fcntl( mar_socket[sk], F_SETFL, O_NONBLOCK ) < 0 ) {
00168     fprintf(stdout,"scan345: Socket %s cannot be set to NON BLOCKING\n",sk_type[sk]);
00169   }
00170 
00171   return 1;
00172 }
00173 
00174 /******************************************************************
00175  * Function: net_close
00176  ******************************************************************/
00177 int 
00178 MarNet::net_close(int sk)
00179 {
00180   if ( mar_socket[sk] < 0 || netcontrol < 1 ) return 0;
00181   close         ( mar_socket[sk] );
00182   mar_socket[sk] = -1;
00183   return 1;
00184 }
00185 
00186 /******************************************************************
00187  * Function: net_data: read blocks on data socket
00188  ******************************************************************/
00189 int
00190 MarNet::net_data()
00191 {
00192   static int    p_pixels= 9999;
00193   static int    size    = DATA_SIZE;
00194   static int    tot_pix = 0;
00195   static int    nbeg    = 0;
00196   int           nend    = 0;
00197   int           nread   = 0;
00198   int           ncop    = 0;
00199   int           ioff    = 0;
00200   int           j       = 0;
00201   int           i,n;
00202   char          *buf_ptr;
00203   char            rbuf[ DATA_SIZE ];
00204   fd_set                r;
00205   static unsigned short block_no;
00206 
00207   extern int    stat_blocks_scanned;
00208   extern int    stat_blocks_sent;
00209   extern int    ict1,ict2;
00210   extern int    bytes2xfer,maximum_bytes;
00211 
00212   ict1++;
00213 
00214   if ( mar_socket[SK_DATA] < 0 || netcontrol < 1 ) return 0;
00215   FD_ZERO( &r );
00216   FD_SET ( mar_socket[SK_DATA], &r );
00217   i = select(FD_MAX,&r,(fd_set *)0,(fd_set *)0,&timeout);
00218   if ( i < 1 ) return (-2);
00219 
00220   /* Read from socket */
00221   nread = read(mar_socket[SK_DATA], rbuf, size); 
00222 
00223   if ( nread<1 ) return -1;
00224 
00225   bytes2xfer    += nread;
00226 
00227   /* Increase pointer for end of this chunk of data */
00228   nend  = nbeg+nread;
00229 
00230   /* Make sure that we dont exceed 16386 kB */
00231   if ( nend > DATA_SIZE) {
00232     ioff = nend-DATA_SIZE;
00233     ncop = nread - ioff;
00234     nend = DATA_SIZE;
00235   }
00236   else {
00237     ioff = 0;
00238     ncop = nread;
00239   }
00240 
00241   /* Copy latest data into net_buf (16kB block) */
00242   memcpy( net_buf + nbeg, rbuf, ncop );
00243 
00244 #ifdef DEBUG
00245   if (debug & 0x200 )
00246     printf("scan345: net_data %5d  block=%4d\n",nread,block_no);
00247 #endif
00248 
00249   /* Increase pointer for begin of next chunk of data */
00250   nbeg += ncop;
00251 
00252   /* Block not yet finished: read more data */
00253   if ( nend < 16386 ) {
00254     block_no        = stat_blocks_sent;
00255     return nread;
00256   }
00257 
00258   /* Block of data finished: transform it ... */
00259 #if ( __linux__ || __osf__ )
00260   swapshort( (char *)net_buf, nend);
00261 #endif
00262 
00263   ict2++;
00264 
00265   /* Start of data block: get block no from first 2 bytes */
00266   memcpy( &block_no, net_buf, sizeof(short) );
00267 
00268   stat_blocks_sent        = block_no;
00269   buf_ptr                 = net_buf+2;
00270   n                       = (DATA_SIZE-2)/2;
00271   tot_pix                 += n;
00272 
00273   /* Transform ... */
00274   if ( scan_in_progress )
00275     Transform( n, block_no, (unsigned short *)buf_ptr);
00276 
00277   nbeg = 0;
00278 
00279   /* This time, there are still some data in rbuf that we can't
00280    * loose. Copy into start of net_buf
00281    */
00282   if ( ioff )  {
00283     memcpy( net_buf, rbuf+ncop, ioff);
00284     nbeg = ioff;
00285     ioff = 0;
00286   }
00287 
00288   return nread;
00289 }
00290 
00291 /******************************************************************
00292  * Function: net_comm: send command to scanner
00293  ******************************************************************/
00294 int 
00295 MarNet::net_comm(int mode, char *buf)
00296 {
00297   int   i,j,nwrite,fail=0;
00298   int   sel;
00299   fd_set        r;
00300 
00301   if ( mar_socket[SK_COMM] < 0 || netcontrol < 1 ) return -1;
00302 
00303   /* Check that we can write to socket ... */
00304   FD_ZERO( &r );
00305   FD_SET ( mar_socket[SK_COMM], &r );
00306 
00307   if ( mode == 0 )      /* Something to read on socket ? */     
00308     sel = select(FD_MAX,&r,(fd_set *)0,(fd_set *)0,&timeout);
00309   else                  /* Something to write on socket ? */    
00310     sel = select(FD_MAX,(fd_set *)0,&r,(fd_set *)0,&timeout);
00311 
00312   if ( sel < 0 ) return -1;
00313 
00314   /* There are data to read on socket: USER PARAMETERS */
00315   if ( mode == 0 ) {
00316     return 64;
00317     nwrite = 0;
00318     while ( ( i=read(mar_socket[SK_COMM], buf, 64)) > 0 ) {
00319       nwrite += i;
00320     }
00321     return nwrite;
00322   }
00323 
00324   net_timeout = 0;
00325   i = nwrite  = 0;
00326   j = 60;
00327 
00328 #if ( __linux__ || __osf__ )
00329   swaplong( buf+4, sizeof(char)*28 );
00330 #endif
00331 
00332   while ( nwrite<j ) {
00333     i=write(mar_socket[SK_COMM], buf+nwrite, j);
00334     if  ( i < 1 ) {
00335       fail++;
00336       if ( fail > 100 ) {
00337         net_timeout++;
00338         return -1;
00339       }
00340       continue;
00341     }
00342     nwrite+=i;
00343     j     -=i;
00344   }
00345 
00346   return nwrite;
00347 }
00348 
00349 /******************************************************************
00350  * Function: net_select
00351  ******************************************************************/
00352 int 
00353 MarNet::net_select(int sk)
00354 {
00355   int   sel;
00356   fd_set        r;
00357 
00358   if ( mar_socket[sk] < 0 || netcontrol < 1 ) return -1;
00359 
00360   FD_ZERO( &r );
00361   FD_SET ( mar_socket[sk], &r );
00362 
00363   sel = select(FD_MAX,(fd_set *)0,&r,(fd_set *)0,&timeout);
00364 
00365   if ( sel < 0 )
00366     return -1;
00367 
00368   return sel;
00369 }
00370 
00371 /******************************************************************
00372  * Function: stop_net
00373  ******************************************************************/
00374 void
00375 MarNet::stop_net( int signo )
00376 {
00377   printf( "scan345: signal SIGINT caught\n");
00378   stop_trying = 1;
00379 }
00380 
00381 /******************************************************************
00382  * Function: net_status: read status block
00383  ******************************************************************/
00384 int 
00385 MarNet::net_stat()
00386 {
00387   register unsigned int j;
00388   static char   s1buf[STAT_SIZE];
00389   int           nread,i,size,sel;
00390   time_t                t1, t2;
00391   fd_set                r;
00392 
00393   if ( mar_socket[SK_STAT] < 0 || netcontrol < 1 || net_timeout ) return 0;
00394 
00395   /* Check that we can read from socket ... */
00396 
00397   FD_ZERO( &r );
00398   FD_SET ( mar_socket[SK_STAT], &r );
00399   sel = select(FD_MAX,&r,(fd_set *)0,(fd_set *)0,&timeout);
00400 
00401   if ( sel < 1 ) return sel;
00402 
00403   size  = STAT_SIZE;
00404   nread         = 0;
00405   j     = 0;
00406   t1    = time(NULL);
00407 
00408   while ( nread < STAT_SIZE ) {
00409     j++;
00410     i     = read(mar_socket[SK_STAT], s1buf+nread, size); 
00411     if ( j > 10000000 ) {
00412       t2    = time(NULL);
00413       if ( difftime( t2, t1 ) > 5.0 ) break;
00414       continue;
00415     }
00416     if ( i < 0 ) continue;
00417     nread += i;
00418     size  -= i;
00419   }
00420 
00421 #ifdef DEBUG
00422   if (debug & 0x800 )
00423     printf("scan345: net_stat %d\n",i);
00424 #endif
00425 
00426 #if ( __linux__ || __osf__ )
00427   swaplong( s1buf, (int)STAT_SIZE);
00428 #endif
00429 
00430   if ( nread >= STAT_SIZE )
00431     i = process_status( s1buf+4 );
00432   else {
00433     fprintf( stdout, "scan345: Only %d bytes in status block !!!\n",nread);
00434   }
00435 
00436   return nread;
00437 }
00438 
00439 /******************************************************************
00440  * Function: net_msg: read message block
00441  ******************************************************************/
00442 int 
00443 MarNet::net_msg()
00444 {
00445   int           sel;
00446   fd_set                r;
00447 
00448   if ( mar_socket[SK_MESS] < 0 || netcontrol < 1 || net_timeout ) return 0;
00449 
00450   /* We can't accumulate messages in the port, so always try to read
00451    * as much as possible 
00452    */
00453 
00454   while ( 1 ) {
00455     sel = read(mar_socket[SK_MESS], msg_buf, MESS_SIZE); 
00456 
00457     if ( sel < 1 ) break;
00458 
00459     print_msg( msg_buf );
00460   }
00461 
00462   return sel;
00463 }