Doxygen Source Code Documentation
thd_iochan.c File Reference
#include "thd_iochan.h"#include "Amalloc.h"#include <errno.h>#include <signal.h>#include <time.h>Go to the source code of this file.
| Defines | |
| #define | PERROR(x) do{ if(pron) perror(x); } while(0) | 
| #define | STATUS(x) | 
| #define | USE_SHUTDOWN | 
| #define | CLOSEDOWN(ss) ( shutdown((ss),2) , close((ss)) ) | 
| #define | SOCKET_BUFSIZE (31*1024) | 
| #define | QBUF 1024 | 
| #define | MBUF 1048576 | 
| Functions | |
| char * | iochan_error_string (void) | 
| void | iochan_enable_perror (int q) | 
| int | tcp_readcheck (int sd, int msec) | 
| int | tcp_writecheck (int sd, int msec) | 
| void | tcp_set_cutoff (int sd) | 
| int | tcp_alivecheck (int sd) | 
| int | tcp_connect (char *host, int port) | 
| int | tcp_listen (int port) | 
| int | tcp_accept (int sd, char **hostname, char **hostaddr) | 
| key_t | string_to_key (char *key_string) | 
| int | shm_accept (char *key_string) | 
| int | shm_create (char *key_string, int size) | 
| char * | shm_attach (int shmid) | 
| int | shm_size (int shmid) | 
| int | shm_nattach (int shmid) | 
| IOCHAN * | iochan_init (char *name, char *mode) | 
| int | shm_alivecheck (int shmid) | 
| int | iochan_goodcheck (IOCHAN *ioc, int msec) | 
| void | iochan_close (IOCHAN *ioc) | 
| void | iochan_set_cutoff (IOCHAN *ioc) | 
| int | iochan_readcheck (IOCHAN *ioc, int msec) | 
| int | iochan_force_clear (IOCHAN *ioc) | 
| int | iochan_clearcheck (IOCHAN *ioc, int msec) | 
| int | iochan_writecheck (IOCHAN *ioc, int msec) | 
| int | iochan_send (IOCHAN *ioc, char *buffer, int nbytes) | 
| int | iochan_sendall (IOCHAN *ioc, char *buffer, int nbytes) | 
| int | iochan_recv (IOCHAN *ioc, char *buffer, int nbytes) | 
| int | iochan_recvloop (IOCHAN *ioc, char *buffer, int nbytes) | 
| int | iochan_recvall (IOCHAN *ioc, char *buffer, int nbytes) | 
| void | iochan_sleep (int msec) | 
| int | iochan_ctl (IOCHAN *ioc, int cmd, int arg) | 
| void | iochan_fork_sigfunc (int sig) | 
| pid_t | iochan_fork_relay (char *name_in, char *name_out) | 
| double | COX_clock_time (void) | 
| double | COX_cpu_time (void) | 
| Variables | |
| char * | error_string = NULL | 
| int | shm_RMID_delay = 0 | 
| int | pron = 1 | 
| int | nosigpipe = 0 | 
| IOCHAN * | ioc_kill_1 = NULL | 
| IOCHAN * | ioc_kill_2 = NULL | 
Define Documentation
| 
 | 
| 
 Definition at line 82 of file thd_iochan.c. | 
| 
 | 
| 
 | 
| 
 | 
| 
 Definition at line 72 of file thd_iochan.c. | 
| 
 | 
| Compute the number of readable bytes into nread. This routine should be called by the "reading" process. It will then be waiting until the "writing" process increments ioc->bend. * Definition at line 1031 of file thd_iochan.c. Referenced by iochan_force_clear(). | 
| 
 | 
| this is used to set the send/receive buffer size for sockets * Definition at line 89 of file thd_iochan.c. Referenced by tcp_connect(), and tcp_listen(). | 
| 
 | 
| 
 Definition at line 73 of file thd_iochan.c. | 
| 
 | 
| 
 Definition at line 80 of file thd_iochan.c. | 
Function Documentation
| 
 | 
| 
 Definition at line 1695 of file thd_iochan.c. Referenced by AFNI_splashdown(), AFNI_start_io(), calculate_results(), get_surf_data(), main(), and MAIN_workprocess(). 
 01696 {
01697    struct timeval  new_tval ;
01698    struct timezone tzone ;
01699    static struct timeval old_tval ;
01700    static int first = 1 ;
01701 
01702    gettimeofday( &new_tval , &tzone ) ;
01703 
01704    if( first ){
01705       old_tval = new_tval ;
01706       first    = 0 ;
01707       return 0.0 ;
01708    }
01709 
01710    if( old_tval.tv_usec > new_tval.tv_usec ){
01711       new_tval.tv_usec += 1000000 ;
01712       new_tval.tv_sec -- ;
01713    }
01714 
01715    return (double)( (new_tval.tv_sec  - old_tval.tv_sec )
01716                    +(new_tval.tv_usec - old_tval.tv_usec)*1.0e-6 ) ;
01717 }
 | 
| 
 | 
| 
 Definition at line 1723 of file thd_iochan.c. 
 01725 {
01726    struct tms ttt ;
01727 
01728    (void) times( &ttt ) ;
01729    return (  (double) (ttt.tms_utime /* + ttt.tms_stime */ )
01730            / (double) CLK_TCK ) ;
01731 }
01732 #else
01733 { return 0.0 ; }
 | 
| 
 | ||||||||||||
| loop until readcheck says no data available * Definition at line 1061 of file thd_iochan.c. References IOCHAN::bend, IOCHAN::bstart, IOCHAN::bufsize, error_string, IOCHAN::id, iochan_goodcheck(), iochan_sleep(), MIN, NEXTDMS, SHM_IOCHAN, SHMIOC_WRITE, TCP_IOCHAN, tcp_readcheck(), and IOCHAN::type. Referenced by AFNI_start_io(), AFNI_start_version_check(), ART_start_io(), main(), and RT_acquire_info(). 
 01062 {
01063    int ii ;
01064 
01065    /** check if the IOCHAN is good **/
01066 
01067    error_string = NULL ;
01068 
01069    ii = iochan_goodcheck(ioc,0) ;
01070    if( ii == -1 ) return -1 ;            /* some error */
01071    if( ii == 0  ) return  1 ;            /* not good yet, so can be no data */
01072 
01073    /** tcp: ==> use the Unix "select" mechanism **/
01074 
01075    if( ioc->type == TCP_IOCHAN ) return ( tcp_readcheck(ioc->id,msec) == 0 ) ;
01076 
01077    /** shm: ==> must loop and wait ourselves **/
01078 
01079    if( ioc->type == SHM_IOCHAN ){
01080       int nread , dms=0 , ms ;
01081 
01082       if( msec < 0 ) msec = 999999999 ;      /* a long time (11+ days) */
01083 
01084       ioc = SHMIOC_WRITE(ioc) ;  /* 24 June 1997 */
01085 
01086       for( ms=0 ; ms < msec ; ms += dms ){
01087          nread = (*(ioc->bend) - *(ioc->bstart) + ioc->bufsize + 1) % (ioc->bufsize) ;
01088          if( nread == 0 ) return 1 ;
01089          dms = NEXTDMS(dms) ; dms = MIN(dms,msec-ms) ; iochan_sleep(dms) ;
01090          ii = iochan_goodcheck(ioc,0) ; if( ii == -1 ) return -1 ;
01091       }
01092       nread = (*(ioc->bend) - *(ioc->bstart) + ioc->bufsize + 1) % (ioc->bufsize) ;
01093       return (nread == 0) ;
01094    }
01095 
01096    return -1 ;  /* should never be reached */
01097 }
 | 
| 
 | 
| if there is a second channel, check it too * Definition at line 931 of file thd_iochan.c. References IOCHAN::bstart, CLOSEDOWN, free, IOCHAN::id, IOCHAN::ioc2, SHM_IOCHAN, shm_nattach(), shm_RMID_delay, TCP_IOCHAN, and IOCHAN::type. Referenced by AFNI_exit(), AFNI_plugout_exit(), ART_exit(), iochan_fork_relay(), iochan_fork_sigfunc(), iochan_init(), RT_exit(), and vc_exit(). 
 00932 {
00933    if( ioc == NULL ) return ;
00934 
00935    if( ioc->ioc2 != NULL ) iochan_close(ioc->ioc2) ;
00936 
00937    if( ioc->type == TCP_IOCHAN ){
00938       if( ioc->id >= 0 ) CLOSEDOWN(ioc->id) ;
00939    }
00940 
00941    else if( ioc->type == SHM_IOCHAN ){
00942 #ifndef DONT_USE_SHM
00943       if( ioc->id >= 0 ){
00944          shmdt( (char *) ioc->bstart ) ;       /* detach */
00945                                                /* then kill */
00946          if( !shm_RMID_delay || shm_nattach(ioc->id) < 1 )
00947            shmctl( ioc->id , IPC_RMID , NULL ) ;
00948       }
00949 #endif
00950    }
00951 
00952    free( ioc ) ; return ;
00953 }
 | 
| 
 | ||||||||||||||||
| 
 Definition at line 1470 of file thd_iochan.c. References arg, IOC_TCP_SENDSIZE, and IOCHAN::sendsize. 
 01471 {
01472    if( ioc == NULL ) return -1 ;
01473 
01474    switch( cmd ){
01475 
01476       case IOC_TCP_SENDSIZE:
01477          if( arg >= 0 ){ ioc->sendsize = arg ; return  0 ; }
01478          else                                  return -1 ;
01479       break ;
01480 
01481    }
01482    return -1 ;
01483 }
 | 
| 
 | 
| 
 Definition at line 65 of file thd_iochan.c. Referenced by AFNI_start_version_check(). 
 | 
| 
 | 
| 
 Definition at line 13 of file thd_iochan.c. References error_string. Referenced by afni_io(), AFNI_process_plugout(), and iochan_fork_relay(). 
 00013 { return error_string; }
 | 
| 
 | 
| 
 Definition at line 1033 of file thd_iochan.c. References iochan_readcheck(), iochan_recv(), and QBUF. 
 01034 {
01035    int ii , ntot = 0 ;
01036    char qbuf[QBUF] ;
01037 
01038    do{
01039       ii = iochan_readcheck(ioc,0) ;
01040       if( ii == -1 ) return -1 ;
01041       if( ii ==  0 ) return  ntot ;
01042 
01043       ii = iochan_recv( ioc , qbuf , QBUF ) ;
01044       if( ii == -1 ) return -1 ;
01045       ntot += ii ;
01046 
01047    } while( 1 ) ;  /** loop until readcheck says no data available **/
01048 
01049    return -1 ;  /* should not be reached */
01050 }
 | 
| 
 | ||||||||||||
| 
 Definition at line 1566 of file thd_iochan.c. References AFMALL, iochan_close(), iochan_error_string(), iochan_fork_sigfunc(), iochan_goodcheck(), iochan_init(), iochan_readcheck(), iochan_recvloop(), iochan_sendall(), iochan_sleep(), and iochan_writecheck(). Referenced by AFNI_start_io(). 
 01567 {
01568    pid_t ppid = (pid_t)(-1) ;
01569    int jj , kk , nbuf ;
01570 #define MBUF 1048576           /* 1 Megabyte */
01571    char * buf , *sss ;
01572    IOCHAN *ioc_in, *ioc_out ;
01573 
01574    if( name_in == NULL || name_out == NULL ) return ppid ;
01575 
01576    /*-- fork into two processes --*/
01577 
01578    ppid = fork() ;
01579    if( ppid == (pid_t)(-1) ){
01580       perror("iochan_fork failed") ;
01581       return ppid ;
01582    }
01583 
01584    if( ppid != 0 ){      /* the parent process */
01585       pid_t qpid ;
01586       iochan_sleep(5) ;                         /* wait a little bit */
01587       qpid = waitpid( ppid , NULL , WNOHANG ) ; /* see if child died */
01588       if( qpid == ppid ) ppid = (pid_t)(-1) ;   /* if it did, return error */
01589       return ppid ;
01590    }
01591 
01592    /*--- from here on is the child process, which never returns ---*/
01593 
01594    ioc_in = iochan_init( name_in , "accept" ) ;  /* open input */
01595    if( ioc_in == NULL ) _exit(1) ;               /* failed?   */
01596 
01597    ioc_out = iochan_init( name_out , "create" ) ; /* open output */
01598    if( ioc_out == NULL ){                         /* failed?    */
01599       iochan_close(ioc_in) ; _exit(1) ;
01600    }
01601 
01602    /* set signal handler to deal with sudden death situations */
01603 
01604    ioc_kill_1 = ioc_in  ;
01605    ioc_kill_2 = ioc_out ;
01606    signal( SIGTERM , iochan_fork_sigfunc ) ;
01607    signal( SIGSEGV , iochan_fork_sigfunc ) ;
01608 
01609    fprintf(stderr,"forked process for shm->tcp started\n") ;
01610 
01611    do{  /* loop until both iochans are ready */
01612 
01613       jj = iochan_goodcheck(ioc_in ,1) ;
01614       kk = iochan_goodcheck(ioc_out,1) ;
01615       if( jj < 0 || kk < 0 ){
01616          iochan_close(ioc_in) ; iochan_close(ioc_out) ; _exit(1) ;
01617       }
01618 
01619    } while( jj == 0 || kk == 0 ) ;
01620 
01621    fprintf(stderr,"forked process fully connected\n") ;
01622 
01623    buf = AFMALL(char, MBUF) ; /* workspace for transfers */
01624    if( buf == NULL ){
01625       fprintf(stderr,"forked process can't malloc I/O buffer") ;
01626       iochan_close(ioc_in) ; iochan_close(ioc_out) ; _exit(1) ;
01627    }
01628 
01629    while(1){  /* loop, waiting for data */
01630 
01631       errno = 0 ;
01632       jj = iochan_readcheck( ioc_in , 20 ) ;          /* any input? */
01633       if( jj < 0 ){                                   /* bad news?  */
01634          if( errno ) perror( "forked readcheck" ) ;
01635          else        fprintf(stderr,"forked readcheck abort: jj=%d!\n",jj) ;
01636          sss = iochan_error_string() ;
01637          if( sss != NULL ) fprintf(stderr," ** %s\n",sss) ;
01638          break ;
01639       }
01640       if( jj == 0 ) continue ;                        /* no news    */
01641 
01642       nbuf = iochan_recvloop( ioc_in , buf , MBUF ) ; /* get input! */
01643       if( nbuf <= 0 ) continue ;                      /* too weird! */
01644 
01645 #if 0
01646       fprintf(stderr,"forked process read %d bytes\n",nbuf) ;
01647 #endif
01648 
01649       errno = 0 ;
01650       kk = iochan_writecheck( ioc_out , 1 ) ;         /* check      */
01651       if( kk == 0 ){
01652          int qq ;
01653          fprintf(stderr,"forked writecheck repeat:") ;
01654          for( qq=0 ; qq < 1000 ; qq++ ){
01655            if( qq%50 == 0 ) fprintf(stderr," %d",qq+1) ;
01656            kk = iochan_writecheck( ioc_out , 2 ) ;
01657            if( kk != 0 ) break ;
01658          }
01659          fprintf(stderr,"\n") ;
01660       }
01661       if( kk <= 0 ){
01662          if( errno ) perror( "forked writecheck" ) ;
01663          else        fprintf(stderr,"forked writecheck abort: kk=%d!\n",kk) ;
01664          sss = iochan_error_string() ;
01665          if( sss != NULL ) fprintf(stderr," ** %s\n",sss) ;
01666          break ;
01667       }
01668       kk = iochan_sendall( ioc_out , buf , nbuf ) ;   /* send data! */
01669       if( kk < 0 ){                                   /* bad news?  */
01670          if( errno ) perror( "forked sendall" ) ;
01671          else        fprintf(stderr,"forked sendall abort: kk=%d!\n",kk) ;
01672          sss = iochan_error_string() ;
01673          if( sss != NULL ) fprintf(stderr," ** %s\n",sss) ;
01674          break ;
01675       }
01676 
01677 #if 0
01678       fprintf(stderr,"forked process wrote %d bytes\n",nbuf) ;
01679 #endif
01680    }
01681 
01682    /* bad news ==> shut down child operations */
01683 
01684    fprintf(stderr,"forked process fails!\n") ;
01685 
01686    iochan_close(ioc_in) ; iochan_close(ioc_out) ; _exit(1) ;
01687 }
 | 
| 
 | 
| 
 Definition at line 1546 of file thd_iochan.c. References iochan_close(). Referenced by iochan_fork_relay(). 
 01547 {
01548    switch( sig ){
01549       case SIGTERM:
01550         if( ioc_kill_1 != NULL ) iochan_close(ioc_kill_1) ;
01551         if( ioc_kill_2 != NULL ) iochan_close(ioc_kill_2) ;
01552         fprintf(stderr,"\n*** iochan_fork received SIGTERM signal\n");
01553         fflush(stderr) ;
01554         _exit(1) ;
01555       case SIGSEGV:
01556         if( ioc_kill_1 != NULL ) iochan_close(ioc_kill_1) ;
01557         if( ioc_kill_2 != NULL ) iochan_close(ioc_kill_2) ;
01558         fprintf(stderr,"\n*** iochan_fork received SIGSEGV signal\n");
01559         fflush(stderr) ;
01560         _exit(1) ;
01561    }
01562 }
 | 
| 
 | ||||||||||||
| 
 Definition at line 810 of file thd_iochan.c. References IOCHAN::bad, IOCHAN::bend, IOCHAN::bstart, IOCHAN::buf, IOCHAN::bufsize, CLOSEDOWN, error_string, free, IOCHAN::id, IOCHAN::ioc2, IOC_BAD, iochan_sleep(), MIN, IOCHAN::name, NEXTDMS, IOCHAN::port, shm_accept(), shm_alivecheck(), shm_attach(), SHM_IOCHAN, shm_nattach(), shm_size(), STATUS, tcp_accept(), tcp_alivecheck(), tcp_connect(), TCP_IOCHAN, tcp_readcheck(), and IOCHAN::type. Referenced by afni_io(), AFNI_plugout_workproc(), AFNI_process_plugout(), iochan_clearcheck(), iochan_fork_relay(), iochan_readcheck(), iochan_recv(), iochan_recvloop(), iochan_send(), iochan_writecheck(), main(), new_RT_input(), RT_check_listen(), and RT_worker(). 
 00811 {
00812    int ii , jj ;
00813    char * bbb ;
00814 
00815    /** check inputs for OK-osity **/
00816 
00817    error_string = NULL ;
00818 
00819    if( ioc == NULL ){
00820       error_string = "iochan_goodcheck: bad input" ; return -1 ;
00821    }
00822 
00823    /** if it was good before, then check if it is still good **/
00824 
00825    if( IOC_BAD(ioc) == 0 ){
00826       int ich = 1 ;
00827 
00828       if( ioc->type == TCP_IOCHAN ){
00829          ich = tcp_alivecheck(ioc->id) ;
00830       } else if( ioc->type == SHM_IOCHAN ){
00831          ich = shm_alivecheck(ioc->id) ;
00832          if( ich && ioc->ioc2 != NULL )
00833             ich = shm_alivecheck(ioc->ioc2->id) ;
00834       }
00835 
00836       if( ich == 0 ){
00837          error_string = "iochan_goodcheck: no longer alive" ; return -1 ;
00838       }
00839       else
00840          return 1 ;
00841    }
00842 
00843    /** wasn't good before, so check if that condition has changed **/
00844 
00845    /** TCP/IP waiting to accept call from another host **/
00846 
00847    if( ioc->bad == TCP_WAIT_ACCEPT ){
00848       ii = tcp_readcheck(ioc->id,msec) ;               /* see if ready      */
00849       if( ii > 0 ){                                    /* if socket  ready  */
00850          STATUS("iochan_goodcheck: try to accept tcp");
00851          jj = tcp_accept( ioc->id , NULL,&bbb ) ;      /* accept connection */
00852          if( jj >= 0 ){                                /* if accept worked  */
00853             STATUS("iochan_goodcheck: accept worked!") ;
00854             CLOSEDOWN( ioc->id ) ;                     /* close old socket  */
00855             strcpy( ioc->name , bbb ) ;                /* put IP into name  */
00856             free(bbb) ; ioc->bad = 0 ; ioc->id = jj ;  /* and ready to go!  */
00857          } else {
00858            STATUS("iochan_goodcheck: accept failed!") ;
00859          }
00860       }
00861    }
00862 
00863    /** TCP/IP waiting to connect call to another host **/
00864 
00865    else if( ioc->bad == TCP_WAIT_CONNECT ){
00866       int dms=0 , ms ;
00867 
00868       if( msec < 0 ) msec = 999999999 ;      /* a long time (11+ days) */
00869       for( ms=0 ; ms < msec ; ms += dms ){
00870          ioc->id  = tcp_connect( ioc->name , ioc->port ) ; /* try to connect to host */
00871          if( ioc->id >= 0 ) break ;                        /* worked? break out      */
00872          dms = NEXTDMS(dms) ; dms = MIN(dms,msec-ms) ; iochan_sleep(dms) ;
00873       }
00874       if( ioc->id < 0 )                                    /* one last try?          */
00875          ioc->id  = tcp_connect( ioc->name , ioc->port ) ;
00876 
00877       if( ioc->id >= 0 ) ioc->bad = 0 ;                    /* succeeded?             */
00878    }
00879 
00880    /** shmem segment waiting for creation (by someone else) **/
00881 
00882    else if( ioc->bad == SHM_WAIT_CREATE ){
00883       int dms=0 , ms ;
00884 
00885       if( msec < 0 ) msec = 999999999 ;      /* a long time (11+ days) */
00886       for( ms=0 ; ms < msec ; ms += dms ){
00887          ioc->id = shm_accept( ioc->name ) ;  /* try to attach to shmem segment */
00888          if( ioc->id >= 0 ) break ;           /* works? break out               */
00889          dms = NEXTDMS(dms) ; dms = MIN(dms,msec-ms) ; iochan_sleep(dms) ;
00890       }
00891       if( ioc->id < 0 )                       /* one last try?                  */
00892          ioc->id = shm_accept( ioc->name ) ;
00893 
00894       if( ioc->id >= 0 ){                                     /* found it?     */
00895          char * bbb ;
00896          bbb          = shm_attach( ioc->id ) ;               /* attach it     */
00897          ioc->bstart  = (int *) bbb ;                         /* set start,    */
00898          ioc->bend    = (int *) (bbb + sizeof(int)) ;         /* end markers   */
00899          ioc->buf     = bbb + 2*sizeof(int) ;                 /* after markers */
00900          ioc->bufsize = shm_size(ioc->id) - 2*sizeof(int) ;   /* get its size  */
00901          ioc->bad     = 0 ;                                   /* mark ready    */
00902       }
00903    }
00904 
00905    /** shmem segment we created waiting for someone else to attach **/
00906 
00907    else if( ioc->bad == SHM_WAIT_ACCEPT ){
00908       int dms=0 , ms ;
00909 
00910       if( msec < 0 ) msec = 999999999 ;      /* a long time (11+ days) */
00911       for( ms=0 ; ms < msec ; ms += dms ){
00912          if( shm_nattach(ioc->id) > 1 ){ ioc->bad = 0 ; break ; }
00913          dms = NEXTDMS(dms) ; dms = MIN(dms,msec-ms) ; iochan_sleep(dms) ;
00914       }
00915       if( ioc->bad && shm_nattach(ioc->id) > 1 ) ioc->bad = 0 ;
00916    }
00917 
00918    /** if there is a second channel, check it too **/
00919 
00920    if( ioc->ioc2 != NULL && ioc->ioc2->bad != 0 )
00921       iochan_goodcheck( ioc->ioc2 , msec ) ;
00922 
00923    return ( IOC_BAD(ioc) == 0 ) ;
00924 }
 | 
| 
 | ||||||||||||
| 
 Definition at line 546 of file thd_iochan.c. References ACCEPTOR, IOCHAN::bad, IOCHAN::bend, IOCHAN::bstart, IOCHAN::buf, IOCHAN::bufsize, CLOSEDOWN, CREATOR, error_string, free, getenv(), IOCHAN::id, IOCHAN::ioc2, iochan_close(), iochan_sleep(), key, malloc, name, IOCHAN::name, IOCHAN::port, IOCHAN::sendsize, shm_accept(), shm_attach(), shm_create(), SHM_IOCHAN, shm_nattach(), shm_RMID_delay, shm_size(), tcp_accept(), tcp_connect(), TCP_IOCHAN, tcp_listen(), tcp_readcheck(), IOCHAN::type, and IOCHAN::whoami. Referenced by afni_io(), AFNI_plugout_workproc(), AFNI_start_io(), AFNI_start_version_check(), ART_start_io(), iochan_fork_relay(), main(), new_PLUGOUT_spec(), new_RT_input(), open_URL_hpf(), RT_acquire_info(), RT_check_listen(), and RT_start_child(). 
 00547 {
00548    IOCHAN * ioc ;
00549    int do_create , do_accept ;
00550 
00551    /** 12 Dec 2002: check if shm_RMID_delay needs to be set **/
00552 
00553 #ifndef DONT_USE_SHM
00554    { static int first=1 ;
00555      if( first ){
00556        char *eee = getenv("IOCHAN_DELAY_RMID") ;
00557        shm_RMID_delay = ( eee != NULL && (*eee=='Y' || *eee=='y') ) ;
00558        first = 0 ;
00559      }
00560    }
00561 #endif
00562 
00563    /** check if inputs are reasonable **/
00564 
00565    error_string = NULL ;
00566 
00567    if( name == NULL || strlen(name) < 6 || strlen(name) > 127 ){
00568       error_string = "iochan_init: bad name" ; return NULL ;
00569    }
00570 
00571    if( mode == NULL ){
00572       error_string = "iochan_init: bad mode" ; return NULL ;
00573    }
00574 
00575    do_create = (strcmp(mode,"create") == 0 || strcmp(mode,"w") == 0) ;
00576    do_accept = (strcmp(mode,"accept") == 0 || strcmp(mode,"r") == 0) ;
00577 
00578    if( !do_create && !do_accept ){
00579       error_string = "iochan_init: bad mode" ; return NULL ;
00580    }
00581 
00582 #ifdef DEBUG
00583 fprintf(stderr,"iochan_init: name=%s  mode=%s\n",name,mode) ;
00584 #endif
00585 
00586    /***** deal with TCP/IP sockets *****/
00587 
00588    if( strncmp(name,"tcp:",4) == 0 ){
00589       char host[128] , * hend ;
00590       int  port=-1 , ii , jj ;
00591 
00592       /** find "host" substring **/
00593 
00594       hend = strstr( name+4 , ":" ) ;
00595       if( hend == NULL || hend-name > 128 ){
00596          error_string = "iochan_init: bad name" ; return NULL ;
00597       }
00598       for( ii=4 ; name[ii] != ':' ; ii++ ) host[ii-4] = name[ii] ;
00599       host[ii-4] = '\0' ;
00600 
00601       /** get "port" number **/
00602 
00603       port = strtol( name+ii+1 , NULL , 10 ) ;
00604       if( port <= 0 ){
00605          error_string = "iochan_init: bad port" ; return NULL ;
00606       }
00607 
00608       /** initialize IOCHAN **/
00609 
00610       ioc = (IOCHAN *) malloc( sizeof(IOCHAN) ) ;
00611 
00612       ioc->type     = TCP_IOCHAN ;   /* what kind is this? */
00613       ioc->port     = port ;         /* save the port #    */
00614       ioc->bufsize  = 0 ;            /* TCP has no buffer  */
00615       ioc->buf      = NULL ;
00616       ioc->sendsize = 0 ;            /* no upper limit */
00617       ioc->ioc2     = NULL ;         /* TCP has no second channel */
00618 
00619       /** attach to incoming call **/
00620 
00621       if( do_accept ){
00622          ioc->whoami = ACCEPTOR ;                         /* 24 June 1997 */
00623          ioc->id = tcp_listen( port ) ;                   /* set up to listen  */
00624          if( ioc->id < 0 ){                               /* error? must die!  */
00625             error_string = "iochan_init: tcp_listen fails" ;
00626             free(ioc) ; return NULL ;
00627          }
00628          ioc->bad = TCP_WAIT_ACCEPT ;                     /* not connected yet */
00629          ii = tcp_readcheck(ioc->id,1) ;                  /* see if ready      */
00630          if( ii > 0 ){                                    /* if socket  ready  */
00631             jj = tcp_accept( ioc->id , NULL,&hend ) ;     /* accept connection */
00632             if( jj >= 0 ){                                /* if accept worked  */
00633                CLOSEDOWN( ioc->id ) ;                     /* close old socket  */
00634                strcpy( ioc->name , hend ) ;               /* put IP into name  */
00635                free(hend) ; ioc->bad = 0 ; ioc->id = jj ; /* and ready to go!  */
00636             }
00637          }
00638          return ioc ;
00639       }
00640 
00641       /** place an outgoing call **/
00642 
00643       if( do_create ){
00644          struct hostent * hostp ;
00645          ioc->whoami = CREATOR ;                           /* 24 June 1997 */
00646          hostp = gethostbyname(host) ;                     /* lookup host on net */
00647          if( hostp == NULL ){                              /* fails? must die!   */
00648              error_string = "iochan_init: gethostbyname fails" ;
00649              free(ioc) ; return NULL ;
00650          }
00651          ioc->id  = tcp_connect( host , port ) ;           /* connect to host    */
00652          ioc->bad = (ioc->id < 0) ? TCP_WAIT_CONNECT : 0 ; /* fails? must wait   */
00653          strcpy( ioc->name , host ) ;                      /* save the host name */
00654          return ioc ;
00655       }
00656       return NULL ;  /* should never be reached */
00657    }
00658 
00659    /***** deal with shared memory segments *****/
00660 
00661    if( strncmp(name,"shm:",4) == 0 ){
00662       char key[128] , * kend , shm2[256] ;
00663       int  size=-1 , ii , jj , size2=-1 ;
00664 
00665 #ifdef DONT_USE_SHM
00666       return NULL ;        /* 18 Dec 2002 */
00667 #endif
00668 
00669       /** get keystring **/
00670 
00671       kend = strstr( name+4 , ":" ) ;
00672       if( kend == NULL || kend-name > 128 ){
00673          error_string = "iochan_init: bad name" ; return NULL ;
00674       }
00675       for( ii=4 ; name[ii] != ':' ; ii++ ) key[ii-4] = name[ii] ;
00676       key[ii-4] = '\0' ;
00677 
00678       /** get size **/
00679 
00680       size = strtol( name+ii+1 , &kend , 10 ) ;
00681       if( size < 0 || (size == 0 && do_create) ){
00682          error_string = "iochan_init: bad size" ; return NULL ;
00683       }
00684            if( *kend == 'K' || *kend == 'k' ){ size *= 1024      ; kend++ ; }
00685       else if( *kend == 'M' || *kend == 'm' ){ size *= 1024*1024 ; kend++ ; }
00686 
00687       /** 24 June 1997: get second size **/
00688 
00689       if( *kend == '+' ){
00690          size2 = strtol( kend+1 , &kend , 10 ) ;
00691          if( size2 < 0 || (size2 == 0 && do_create) ){
00692             error_string = "iochan_init: bad size2" ; return NULL ;
00693          }
00694               if( *kend == 'K' || *kend == 'k' ){ size2 *= 1024      ; kend++ ; }
00695          else if( *kend == 'M' || *kend == 'm' ){ size2 *= 1024*1024 ; kend++ ; }
00696 
00697          sprintf(shm2,"shm:%s++:%d",key,size2) ;  /* second channel spec */
00698       } else {
00699          shm2[0] = '\0' ;                         /* no second channel */
00700       }
00701 
00702       /** initialize IOCHAN **/
00703 
00704       ioc = (IOCHAN *) malloc( sizeof(IOCHAN) ) ;
00705 
00706       ioc->type = SHM_IOCHAN ;     /* what type is this? */
00707       strcpy( ioc->name , key ) ;  /* save the key name  */
00708       ioc->ioc2 = NULL ;           /* maybe reset below? */
00709 
00710       /** open the second channel, if any **/
00711 
00712       if( shm2[0] != '\0' ){
00713          ioc->ioc2 = iochan_init( shm2 , mode ) ;
00714          if( ioc->ioc2 == NULL ){
00715             error_string = "iochan_init: can't open shm2" ;
00716             free(ioc) ; return NULL ;
00717          }
00718 #ifdef DEBUG
00719          fprintf(stderr,"iochan_init: input=%s shm2=%s\n",name,shm2) ;
00720 #endif
00721       }
00722 
00723       /** attach to existing shmem segment **/
00724 
00725       if( do_accept ){
00726          ioc->whoami = ACCEPTOR ;          /* 24 June 1997 */
00727          for( ii=0 ; ii < 2 ; ii++ ){      /* try to find segment */
00728             ioc->id = shm_accept( key ) ;  /* several times       */
00729             if( ioc->id >= 0 ) break ;     /* works? break out    */
00730             iochan_sleep(1) ;              /* wait 1 millisecond  */
00731          }
00732          if( ioc->id < 0 ) ioc->id = shm_accept( key ) ; /* 1 last try? */
00733 
00734          if( ioc->id < 0 ){                       /* failed to find segment? */
00735             ioc->bad = SHM_WAIT_CREATE ;          /* mark for waiting        */
00736 
00737          } else {                                                /* found it?     */
00738             char * bbb ;
00739             bbb = shm_attach( ioc->id ) ;                        /* attach it     */
00740             if( bbb == NULL ){                                   /* can't? quit   */
00741                error_string = "iochan_init: shm_attach fails" ;
00742                iochan_close(ioc) ; return NULL ;
00743             }
00744             ioc->bstart  = (int *) bbb ;                         /* set start,    */
00745             ioc->bend    = (int *) (bbb + sizeof(int)) ;         /* end markers   */
00746             ioc->buf     = bbb + 2*sizeof(int) ;                 /* after markers */
00747             ioc->bufsize = shm_size(ioc->id) - 2*sizeof(int) ;   /* get its size  */
00748             if( ioc->bufsize <= 0 ){                             /* can't? quit   */
00749                error_string = "iochan_init: bufsize < 0" ;
00750                iochan_close(ioc) ; return NULL ;
00751             }
00752             ioc->bad = 0 ;                                       /* mark ready    */
00753          }
00754          return ioc ;
00755       }
00756 
00757       /** make a new shmem segment **/
00758 
00759       if( do_create ){
00760          char * bbb ;
00761          ioc->whoami = CREATOR ;                             /* 24 June 1997*/
00762          size    = size + 1 ;                                /* extra byte  */
00763          ioc->id = shm_create( key , size+2*sizeof(int) ) ;  /* create it   */
00764          if( ioc->id < 0 ){                                  /* can't? quit */
00765             error_string = "iochan_init: shm_create fails" ;
00766             iochan_close(ioc->ioc2) ; free(ioc) ; return NULL ;
00767          }
00768          bbb = shm_attach( ioc->id ) ;                       /* attach it   */
00769          if( bbb == NULL ){                                  /* can't? quit */
00770             error_string = "iochan_init: shm_attach fails" ;
00771             iochan_close(ioc) ; free(ioc) ; return NULL ;
00772          }
00773          ioc->bstart    = (int *) bbb ;                      /* init start, */
00774          ioc->bend      = (int *) (bbb + sizeof(int)) ;      /* end markers */
00775          *(ioc->bstart) = 0 ;
00776          *(ioc->bend)   = size-1 ;
00777          ioc->buf       = bbb + 2*sizeof(int) ;              /* I/O buffer  */
00778          ioc->bufsize   = size ;                             /* buffer size */
00779          ioc->bad       = (shm_nattach(ioc->id) < 2)         /* ready if    */
00780                           ?  SHM_WAIT_ACCEPT                 /* both are    */
00781                           :  0 ;                             /* attached    */
00782          return ioc ;
00783       }
00784       return NULL ;  /* should never be reached */
00785    }
00786 
00787    return NULL ;  /* should never be reached */
00788 }
 | 
| 
 | ||||||||||||
| 
 Definition at line 974 of file thd_iochan.c. References IOCHAN::bend, IOCHAN::bstart, IOCHAN::bufsize, error_string, IOCHAN::id, iochan_goodcheck(), iochan_sleep(), MIN, NEXTDMS, SHM_IOCHAN, SHMIOC_READ, tcp_alivecheck(), TCP_IOCHAN, tcp_readcheck(), and IOCHAN::type. Referenced by afni_io(), AFNI_process_plugout(), AFNI_version_check(), iochan_force_clear(), iochan_fork_relay(), main(), new_RT_input(), open_URL_hpf(), read_URL_http(), RT_check_listen(), RT_process_data(), and RT_worker(). 
 00975 {
00976    int ii ;
00977 
00978    /** check if the IOCHAN is good **/
00979 
00980    error_string = NULL ;
00981 
00982    ii = iochan_goodcheck(ioc,0) ;
00983    if( ii == -1 ) return -1 ;            /* some error */
00984    if( ii == 0  ){                       /* not good yet */
00985       ii = iochan_goodcheck(ioc,msec) ;  /* so wait for it to get good */
00986       if( ii != 1 ) return 0 ;           /* if still not good, exit */
00987    }
00988 
00989    /** tcp: ==> just use the Unix "select" mechanism **/
00990 
00991    if( ioc->type == TCP_IOCHAN ){
00992       ii = tcp_alivecheck( ioc->id ) ; if( !ii ) return -1 ;
00993       ii = tcp_readcheck( ioc->id , msec ) ;
00994       if( ii < 0 ) error_string = "iochan_readcheck: socket is bad" ;
00995       return ii ;
00996    }
00997 
00998    /** shm: ==> must loop and wait ourselves **/
00999 
01000    if( ioc->type == SHM_IOCHAN ){
01001       int nread , dms=0 , ms ;
01002 
01003       if( msec < 0 ) msec = 999999999 ;      /* a long time (11+ days) */
01004 
01005       /** Compute the number of readable bytes into nread.  This routine
01006           should be called by the "reading" process.  It will then
01007           be waiting until the "writing" process increments ioc->bend.   **/
01008 
01009       ioc = SHMIOC_READ(ioc) ;  /* 24 June 1997 */
01010 
01011       for( ms=0 ; ms < msec ; ms += dms ){
01012          nread = (*(ioc->bend) - *(ioc->bstart) + ioc->bufsize + 1) % (ioc->bufsize) ;
01013          if( nread > 0 ) return nread ;
01014          dms = NEXTDMS(dms) ; dms = MIN(dms,msec-ms) ; iochan_sleep(dms) ;
01015          ii = iochan_goodcheck(ioc,0) ; if( ii == -1 ) return -1 ;
01016       }
01017       nread = (*(ioc->bend) - *(ioc->bstart) + ioc->bufsize + 1) % (ioc->bufsize) ;
01018       if( nread > 0 ) return nread ;
01019       return 0 ;
01020    }
01021 
01022    return -1 ;  /* should never be reached */
01023 }
 | 
| 
 | ||||||||||||||||
| check for reasonable inputs * Definition at line 1319 of file thd_iochan.c. References BCOPY, IOCHAN::bend, IOCHAN::bstart, IOCHAN::buf, IOCHAN::bufsize, error_string, IOCHAN::id, IOC_BAD, iochan_goodcheck(), PERROR, SHM_IOCHAN, SHMIOC_READ, TCP_IOCHAN, tcp_recv, and IOCHAN::type. Referenced by afni_io(), AFNI_plugout_workproc(), AFNI_process_plugout(), AFNI_version_check(), iochan_force_clear(), iochan_recvall(), iochan_recvloop(), main(), new_RT_input(), read_URL_http(), and RT_worker(). 
 01320 {
01321    /** check for reasonable inputs **/
01322 
01323    error_string = NULL ;
01324 
01325    if( ioc    == NULL || IOC_BAD(ioc) != 0 ||
01326        buffer == NULL || nbytes < 0          ){
01327 
01328       error_string = "iochan_recv: bad inputs" ; return -1 ;
01329    }
01330 
01331    if( nbytes == 0 ) return 0 ;
01332    if( iochan_goodcheck(ioc,0) != 1 ) return -1 ;
01333 
01334    /** tcp: just use recv **/
01335 
01336    if( ioc->type == TCP_IOCHAN ){
01337       int ii = tcp_recv( ioc->id , buffer , nbytes , 0 ) ;
01338       if( ii == -1 ){
01339          PERROR("Can't read from socket? tcp[recv]") ;
01340          error_string = "iochan_recv: tcp recv fails" ;
01341       }
01342       return ii ;
01343    }
01344 
01345    /** shm: read from the circular buffer, starting at bstart **/
01346 
01347    if( ioc->type == SHM_IOCHAN ){
01348       int nread, bend,bstart , size , sbot,stop ;
01349 
01350       ioc = SHMIOC_READ(ioc) ;  /* 24 June 1997 */
01351 
01352       bend  = *(ioc->bend) ; bstart = *(ioc->bstart) ; size = ioc->bufsize ;
01353       nread = ( bend - bstart + size + 1 ) % size ;    /* readable amount */
01354       if( nread <= 0 ) return 0 ;                      /* nothing!?       */
01355       if( nread > nbytes ) nread = nbytes ;            /* amount to read  */
01356 
01357       sbot = bstart ; stop = sbot + nread-1 ;          /* from sbot to stop */
01358 
01359       if( stop < size ){                             /* 1 piece to copy */
01360          BCOPY( buffer, ioc->buf + sbot, nread ) ;   /* copy the data   */
01361          *(ioc->bstart) = (stop+1) % size ;          /* move bstart up  */
01362 #ifdef DEBUG
01363 fprintf(stderr,"iochan_recv: get 1 piece:  %d to %d\n",sbot,stop) ;
01364 #endif
01365 
01366       } else {                                             /* 2 pieces to copy */
01367          int nn = size - sbot ;                            /* size of piece 1  */
01368          BCOPY( buffer   , ioc->buf + sbot, nn        ) ;  /* copy piece 1     */
01369          BCOPY( buffer+nn, ioc->buf       , nread-nn  ) ;  /* copy piece 2     */
01370          *(ioc->bstart) = nread-nn ;                       /* move bstart up   */
01371 #ifdef DEBUG
01372 fprintf(stderr,"iochan_recv: get 2 pieces: %d to %d AND %d to %d\n",
01373         sbot,sbot+nn-1,0,nread-nn-1) ;
01374 #endif
01375 
01376       }
01377       return nread ;
01378    }
01379 
01380    return -1 ;  /* should not be reached */
01381 }
 | 
| 
 | ||||||||||||||||
| check for reasonable inputs * Definition at line 1425 of file thd_iochan.c. References error_string, IOC_BAD, iochan_recv(), iochan_sleep(), and NEXTDMS. Referenced by afni_io(), main(), and RT_read_image(). 
 01426 {
01427    int ii , ntot=0 , dms=0 ;
01428 
01429    /** check for reasonable inputs **/
01430 
01431    error_string = NULL ;
01432 
01433    if( ioc    == NULL || IOC_BAD(ioc) != 0 ||
01434        buffer == NULL || nbytes < 0          ){
01435 
01436       error_string = "iochan_recvall: bad inputs" ; return -1 ;
01437    }
01438 
01439    if( nbytes == 0 ) return 0 ;
01440 
01441    while(1){
01442       ii = iochan_recv( ioc , buffer+ntot , nbytes-ntot ) ;  /* get what's left */
01443       if( ii == -1 ) return -1 ;                             /* an error!?      */
01444       ntot += ii ;                                           /* total so far    */
01445       if( ntot == nbytes ) return nbytes ;                   /* all done!?      */
01446       dms = NEXTDMS(dms) ; iochan_sleep(dms) ;               /* wait a while    */
01447    }
01448    return -1 ;   /* should never be reached */
01449 }
 | 
| 
 | ||||||||||||||||
| shm: read from the circular buffer, starting at bstart * Definition at line 1388 of file thd_iochan.c. References error_string, IOC_BAD, iochan_goodcheck(), iochan_recv(), and iochan_sleep(). Referenced by iochan_fork_relay(). 
 01389 {
01390    int jj , nbuf=0 ;
01391 
01392    error_string = NULL ;
01393 
01394    /** check for reasonable inputs **/
01395 
01396    if( ioc    == NULL || IOC_BAD(ioc) != 0 ||
01397        buffer == NULL || nbytes < 0          ){
01398 
01399       error_string = "iochan_recvloop: bad inputs" ; return -1 ;
01400    }
01401 
01402    if( iochan_goodcheck(ioc,0) != 1 ) return -1 ;
01403 
01404    if( nbytes == 0 ) return 0 ;
01405 
01406    while(1){
01407       jj = iochan_recv( ioc , buffer+nbuf , nbytes-nbuf ) ;
01408       if( jj < 1 ) break ;  /* stop if nothing more comes in */
01409       nbuf += jj ;
01410       if( nbuf >= nbytes ) break ;  /* stop if overflow */
01411       iochan_sleep(1) ;
01412    }
01413 
01414    return nbuf ;
01415 }
 | 
| 
 | ||||||||||||||||
| This routine is called by the "writing" process. It will wait until the reading process increments ioc->bstart. * Definition at line 1176 of file thd_iochan.c. References BCOPY, IOCHAN::bend, IOCHAN::bstart, IOCHAN::buf, IOCHAN::bufsize, error_string, IOCHAN::id, IOC_BAD, iochan_goodcheck(), iochan_writecheck(), MIN, nosigpipe, PERROR, send, IOCHAN::sendsize, SHM_IOCHAN, SHMIOC_WRITE, TCP_IOCHAN, tcp_writecheck(), and IOCHAN::type. Referenced by iochan_sendall(). 
 01177 {
01178    int ii ;
01179 
01180    /** check for reasonable inputs **/
01181 
01182    error_string = NULL ;
01183 
01184    if( ioc    == NULL || IOC_BAD(ioc) != 0 ||
01185        buffer == NULL || nbytes < 0          ){
01186 
01187      error_string = "iochan_send: bad inputs" ; return -1 ;
01188    }
01189 
01190    if( nbytes == 0 ) return 0 ;
01191 
01192    ii = iochan_goodcheck(ioc,0) ;
01193    if( ii != 1 ){
01194       if( error_string == NULL )
01195          error_string = "iochan_send: iochan_goodcheck fails" ;
01196       return ii ;
01197    }
01198 
01199    ii = iochan_writecheck(ioc,1) ;
01200    if( ii <= 0 ){
01201       if( error_string == NULL )
01202          error_string = "iochan_send: iochan_writecheck fails" ;
01203       return ii ;
01204    }
01205 
01206    /** tcp: ==> just use send **/
01207 
01208    if( ioc->type == TCP_IOCHAN ){
01209       if( !nosigpipe ){ signal( SIGPIPE , SIG_IGN ) ; nosigpipe = 1 ; }
01210 
01211       if( ioc->sendsize <= 0 || nbytes <= ioc->sendsize ){
01212          int nsent = send( ioc->id , buffer , nbytes , 0 ) ;
01213          if( nsent == -1 ) PERROR("Can't use socket? tcp[send]") ;
01214          if( nsent < 0 ) error_string = "iochan_send: tcp send fails" ;
01215          return nsent ;
01216       } else {
01217          int nsent , ntosend , ntot = 0 ;
01218          do{
01219             while( tcp_writecheck(ioc->id,1) == 0 ) ;      /* spin */
01220             ntosend = MIN( ioc->sendsize , nbytes-ntot ) ;
01221             nsent   = send( ioc->id , buffer+ntot , ntosend , 0 ) ;
01222             if( nsent == -1 ) PERROR("Can't use socket? tcp[send]") ;
01223             if( nsent <= 0 ){
01224                error_string = "iochan_send: tcp send fails" ;
01225                return ((ntot>0) ? ntot : nsent) ;
01226             }
01227             ntot += nsent ;
01228          } while( ntot < nbytes ) ;
01229          return ntot ;
01230       }
01231    }
01232 
01233    /** shm: ==> write into the circular buffer, past "bend" **/
01234 
01235    if( ioc->type == SHM_IOCHAN ){
01236       int nread,nwrite , bend,bstart , ebot,etop , size ;
01237 
01238       ioc = SHMIOC_WRITE(ioc) ;  /* 24 June 1997 */
01239 
01240       bend   = *(ioc->bend) ; bstart = *(ioc->bstart) ; size = ioc->bufsize ;
01241       nread  = ( bend - bstart + size + 1 ) % size ;  /* amount readable  */
01242       nwrite = size - 1 - nread ;                     /* amount writeable */
01243       if( nwrite <= 0 ) return 0 ;                    /* can't write!     */
01244 
01245       if( nwrite > nbytes ) nwrite = nbytes ;         /* how much to write */
01246 
01247       ebot = bend+1 ; if( ebot >= size ) ebot = 0 ;   /* start at ebot */
01248       etop = ebot+nwrite-1 ;                          /* end at etop */
01249 
01250       if( etop < size ){                              /* 1 piece to copy */
01251          BCOPY( ioc->buf + ebot, buffer, nwrite ) ;   /* copy data       */
01252          *(ioc->bend) = etop ;                        /* change bend     */
01253 #ifdef DEBUG
01254 fprintf(stderr,"iochan_send: shm 1 piece:  %d to %d\n",ebot,etop) ;
01255 #endif
01256 
01257       } else {                                             /* 2 pieces to copy */
01258          int nn = size - ebot ;                            /* size of piece 1  */
01259          BCOPY( ioc->buf + ebot, buffer   , nn        ) ;  /* copy piece 1     */
01260          BCOPY( ioc->buf       , buffer+nn, nwrite-nn ) ;  /* copy piece 2     */
01261          *(ioc->bend) = nwrite-nn-1 ;                      /* change bend      */
01262 #ifdef DEBUG
01263 fprintf(stderr,"iochan_send: shm 2 pieces: %d to %d AND %d to %d\n",
01264         ebot,ebot+nn-1,0,nwrite-nn-1) ;
01265 #endif
01266 
01267       }
01268       return nwrite ;
01269    }
01270 
01271    return -1 ;  /* should not be reached */
01272 }
 | 
| 
 | ||||||||||||||||
| shm: ==> write into the circular buffer, past "bend" * Definition at line 1282 of file thd_iochan.c. References error_string, IOC_BAD, iochan_send(), iochan_sleep(), and NEXTDMS. Referenced by afni_io(), AFNI_send_image(), AFNI_start_io(), AFNI_start_version_check(), ART_send_control_info(), ART_send_end_of_run(), ART_send_volume(), ART_start_io(), iochan_fork_relay(), main(), open_URL_hpf(), and RT_acquire_info(). 
 01283 {
01284    int ii , ntot=0 , dms=0 ;
01285 
01286    error_string = NULL ;
01287 
01288    /** check for reasonable inputs **/
01289 
01290    if( ioc    == NULL || IOC_BAD(ioc) != 0 ||
01291        buffer == NULL || nbytes < 0          ){
01292 
01293       error_string = "iochan_sendall: bad inputs" ; return -1 ;
01294    }
01295 
01296    if( nbytes == 0 ) return 0 ;
01297 
01298    while(1){
01299       ii = iochan_send( ioc , buffer+ntot , nbytes-ntot ); /* send what's left  */
01300       if( ii == -1 ){                                      /* an error!?        */
01301          if( error_string == NULL )
01302             error_string = "iochan_sendall: iochan_send fails" ;
01303          return -1 ;
01304       }
01305       ntot += ii ;                                         /* total sent so far */
01306       if( ntot == nbytes ) return nbytes ;                 /* all done!?        */
01307       dms = NEXTDMS(dms) ; iochan_sleep(dms) ;             /* wait a while      */
01308    }
01309    return -1 ;   /* should never be reached */
01310 }
 | 
| 
 | 
| 
 Definition at line 955 of file thd_iochan.c. References IOCHAN::id, TCP_IOCHAN, tcp_set_cutoff(), and IOCHAN::type. Referenced by afni_io(), AFNI_plugout_exit(), AFNI_plugout_workproc(), and open_URL_hpf(). 
 00956 {
00957    if( ioc == NULL ) return ;
00958 
00959    if( ioc->type == TCP_IOCHAN && ioc->id >= 0 ) tcp_set_cutoff( ioc->id ) ;
00960    return ;
00961 }
 | 
| 
 | 
| check for reasonable inputs * Definition at line 1455 of file thd_iochan.c. Referenced by AFNI_exit(), afni_io(), AFNI_plugout_workproc(), AFNI_send_image(), AFNI_start_io(), AFNI_start_version_check(), AFNI_startup_timeout_CB(), ART_open_afni_link(), ART_send_control_info(), ART_send_end_of_run(), ART_start_io(), calculate_results(), find_more_volumes(), iochan_clearcheck(), iochan_fork_relay(), iochan_goodcheck(), iochan_init(), iochan_readcheck(), iochan_recvall(), iochan_recvloop(), iochan_sendall(), iochan_writecheck(), main(), MAIN_workprocess(), new_PLUGOUT_spec(), new_RT_input(), RT_acquire_info(), RT_worker(), THD_fetch_dataset(), and THD_fetch_many_datasets(). 
 01456 {
01457    struct timeval tv ;
01458    if( msec <= 0 ) return ;
01459    tv.tv_sec  = msec/1000 ;
01460    tv.tv_usec = (msec%1000)*1000 ;
01461    select( 1 , NULL,NULL,NULL , &tv ) ;
01462    return ;
01463 }
 | 
| 
 | ||||||||||||
| shm: ==> must loop and wait ourselves * Definition at line 1110 of file thd_iochan.c. References IOCHAN::bend, IOCHAN::bstart, IOCHAN::bufsize, error_string, IOCHAN::id, iochan_goodcheck(), iochan_sleep(), MIN, NEXTDMS, SHM_IOCHAN, SHMIOC_WRITE, TCP_IOCHAN, tcp_writecheck(), and IOCHAN::type. Referenced by afni_io(), AFNI_send_image(), AFNI_start_io(), AFNI_start_version_check(), ART_start_io(), iochan_fork_relay(), iochan_send(), main(), open_URL_hpf(), and RT_acquire_info(). 
 01111 {
01112    int ii ;
01113 
01114    /** check if the IOCHAN is good **/
01115 
01116    error_string = NULL ;
01117 
01118    ii = iochan_goodcheck(ioc,0) ;
01119    if( ii == -1 ) return -1 ;            /* some error */
01120    if( ii == 0  ){                       /* not good yet */
01121       ii = iochan_goodcheck(ioc,msec) ;  /* so wait for it to get good */
01122       if( ii != 1 ) return ii ;          /* if still not good, exit */
01123    }
01124 
01125    /** tcp: ==> just use the Unix "select" mechanism **/
01126 
01127    if( ioc->type == TCP_IOCHAN ){
01128       ii = tcp_writecheck( ioc->id , msec ) ;
01129       if( ii == -1 ) error_string = "iochan_writecheck: socket not ready" ;
01130       return ii ;
01131    }
01132 
01133    /** shm: ==> must loop and wait ourselves **/
01134 
01135    if( ioc->type == SHM_IOCHAN ){
01136       int nread , dms=0 , ms , nwrite ;
01137 
01138       if( msec < 0 ) msec = 999999999 ;      /* a long time (11+ days) */
01139 
01140       ioc = SHMIOC_WRITE(ioc) ;  /* 24 June 1997 */
01141 
01142       /** This routine is called by the "writing" process.  It will
01143           wait until the reading process increments ioc->bstart.    **/
01144 
01145       for( ms=0 ; ms < msec ; ms += dms ){
01146          nread = (*(ioc->bend) - *(ioc->bstart) + ioc->bufsize + 1) % (ioc->bufsize) ;
01147          nwrite = ioc->bufsize - 1 - nread ;
01148          if( nwrite > 0 ) return nwrite ;
01149          dms = NEXTDMS(dms) ; dms = MIN(dms,msec-ms) ; iochan_sleep(dms) ;
01150          ii = iochan_goodcheck(ioc,0) ; if( ii == -1 ) return -1 ;
01151       }
01152       nread = (*(ioc->bend) - *(ioc->bstart) + ioc->bufsize + 1) % (ioc->bufsize) ;
01153       nwrite = ioc->bufsize - 1 - nread ;
01154       if( nwrite > 0 ) return nwrite ;
01155       return 0 ;
01156    }
01157 
01158    return -1 ;  /* should never be reached */
01159 }
 | 
| 
 | 
| 
 Definition at line 410 of file thd_iochan.c. References key, and string_to_key(). Referenced by iochan_goodcheck(), and iochan_init(). 
 00411 {
00412    key_t key ;
00413    int   shmid ;
00414 
00415    key   = string_to_key( key_string ) ;
00416    shmid = shmget( key , 0 , 0777 ) ;
00417    return shmid ;
00418 }
 | 
| 
 | 
| make a new shmem segment * Definition at line 795 of file thd_iochan.c. References shm_nattach(). Referenced by iochan_goodcheck(). 
 00796 {
00797    if( shmid < 0 ) return 0 ;
00798    return (shm_nattach(shmid) >= 2) ;
00799 }
 | 
| 
 | 
| 
 Definition at line 446 of file thd_iochan.c. References PERROR. Referenced by iochan_goodcheck(), iochan_init(), proc_finalize_shm_volumes(), and THD_alloc_datablock(). 
 00447 {
00448    char * adr ;
00449    adr = (char *) shmat( shmid , NULL , 0 ) ;
00450    if( adr == (char *) -1 ){
00451      adr = NULL ; PERROR("Can't attach? shm_attach") ;
00452    }
00453    return adr ;
00454 }
 | 
| 
 | ||||||||||||
| 
 Definition at line 425 of file thd_iochan.c. References key, PERROR, and string_to_key(). Referenced by iochan_init(), proc_finalize_shm_volumes(), and THD_alloc_datablock(). 
 00426 {
00427    key_t key ;
00428    int   shmid ;
00429 
00430    key   = string_to_key( key_string ) ;
00431    shmid = shmget( key , size , 0777 | IPC_CREAT ) ;
00432    if( shmid < 0 ){
00433      PERROR("Can't create? shm_create") ;
00434      if( pron ) fprintf(stderr,"key_string=%s key=%d size=%d\n",
00435                         key_string , (int)key , size ) ;
00436    }
00437    return shmid ;
00438 }
 | 
| 
 | 
| 
 Definition at line 477 of file thd_iochan.c. References PERROR, and STATUS. Referenced by iochan_close(), iochan_goodcheck(), iochan_init(), and shm_alivecheck(). 
 00478 {
00479    int ii ;
00480    struct shmid_ds buf ;
00481 
00482    if( shmid < 0 ){ STATUS("shm_nattach: illegal shmid") ; return -1 ; }
00483    errno = 0 ;
00484    ii = shmctl( shmid , IPC_STAT , &buf ) ;
00485    if( ii < 0 ){
00486      PERROR("Has shared memory buffer gone bad? shm_nattach") ;
00487      return -1 ;
00488    }
00489    return buf.shm_nattch ;
00490 }
 | 
| 
 | 
| 
 Definition at line 461 of file thd_iochan.c. References PERROR. Referenced by iochan_goodcheck(), and iochan_init(). 
 00462 {
00463    int ii ;
00464    struct shmid_ds buf ;
00465 
00466    if( shmid < 0 ) return -1 ;
00467    ii = shmctl( shmid , IPC_STAT , &buf ) ;
00468    if( ii < 0 ){ PERROR("Can't check? shm_size");  return -1; }
00469    return buf.shm_segsz ;
00470 }
 | 
| 
 | 
| get address of connector * Definition at line 388 of file thd_iochan.c. Referenced by shm_accept(), and shm_create(). 
 00389 {
00390    int ii , sum ;
00391 
00392    sum = 666 ;
00393    if( key_string == NULL ) return (key_t) sum ;
00394 
00395    for( ii=0 ; key_string[ii] != '\0' ; ii++ )
00396       sum += ((int)key_string[ii]) << ((ii%3)*8) ;
00397 
00398         if( sum  < 0 ) sum = -sum      ;
00399    else if( sum == 0 ) sum = 314159265 ;
00400 
00401    return (key_t) sum ;
00402 }
 | 
| 
 | ||||||||||||||||
| set port on remote computer * Definition at line 338 of file thd_iochan.c. References malloc, and PERROR. Referenced by iochan_goodcheck(), iochan_init(), NI_stream_goodcheck(), and NI_stream_open(). 
 00339 {
00340    struct sockaddr_in pin ;
00341    int addrlen , sd_new ;
00342    struct hostent * hostp ;
00343    char * sout , * str ;
00344 
00345    /** accept the connection **/
00346 
00347    /** STATUS("tcp_accept: about to call accept") ; **/
00348 
00349    addrlen = sizeof(pin) ;
00350    sd_new = accept( sd , (struct sockaddr *)&pin , &addrlen ) ;
00351    if( sd_new == -1 ){ PERROR("Can't accept? tcp_accept"); return -1; }
00352 
00353    /** get name of connector **/
00354 
00355    if( hostname != NULL ){
00356       hostp = gethostbyaddr( (char *) (&pin.sin_addr) ,
00357                              sizeof(struct in_addr) , AF_INET ) ;
00358       if( hostp != NULL ){
00359          sout = (char *) malloc( strlen(hostp->h_name)+1 ) ;
00360          strcpy(sout,hostp->h_name) ;
00361       } else {
00362          sout = (char *) malloc( strlen("UNKNOWN")+1 ) ;
00363          strcpy(sout,"UNKNOWN") ;
00364       }
00365       *hostname = sout ;
00366    }
00367 
00368    /** get address of connector **/
00369 
00370    if( hostaddr != NULL ){
00371       str = inet_ntoa( pin.sin_addr ) ;
00372       sout = (char *) malloc( strlen(str)+1 ) ;
00373       strcpy(sout,str) ;
00374       *hostaddr = sout ;
00375    }
00376 
00377    return sd_new ;
00378 }
 | 
| 
 | 
| 
 Definition at line 203 of file thd_iochan.c. References PERROR, tcp_readcheck(), and tcp_recv. Referenced by iochan_goodcheck(), iochan_readcheck(), NI_stream_goodcheck(), and NI_stream_readcheck(). 
 00204 {
00205    int ii ;
00206    char bbb[4] ;
00207 
00208    ii = tcp_readcheck(sd,0) ;                 /* can I read?          */
00209    if( ii == 0 ) return 1 ;                   /* can't read is OK     */
00210    if( ii <  0 ) return 0 ;                   /* some error is bad    */
00211    errno = 0 ;
00212    ii = tcp_recv( sd , bbb , 1 , MSG_PEEK ) ; /* try to read one byte */
00213    if( ii == 1 ) return 1 ;                   /* if we get it, good   */
00214    if( errno ) PERROR("Socket gone bad? tcp_alivecheck") ;
00215    return 0 ;                                 /* no data ==> death!   */
00216 }
 | 
| 
 | ||||||||||||
| 
 Definition at line 223 of file thd_iochan.c. References CLOSEDOWN, l, PERROR, socket, SOCKET_BUFSIZE, and STATUS. Referenced by iochan_goodcheck(), iochan_init(), NI_stream_goodcheck(), and NI_stream_open(). 
 00224 {
00225    int sd , l ;
00226    struct sockaddr_in sin ;
00227    struct hostent *   hostp ;
00228 
00229    if( host == NULL || port < 1 ){ STATUS("tcp_connect: illegal inputs") ; return -1 ; }
00230 
00231    /** open a socket **/
00232 
00233    sd = socket( AF_INET , SOCK_STREAM , 0 ) ;
00234    if( sd == -1 ){ PERROR("Can't create? tcp_connect[socket]"); return -1; }
00235 
00236    /** set socket options (no delays, large buffers) **/
00237 
00238 #if 0
00239    l = 1;
00240    setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, (void *)&l, sizeof(int)) ;
00241 #endif
00242    l = SOCKET_BUFSIZE ;
00243    setsockopt(sd, SOL_SOCKET, SO_SNDBUF, (void *)&l, sizeof(int)) ;
00244    setsockopt(sd, SOL_SOCKET, SO_RCVBUF, (void *)&l, sizeof(int)) ;
00245 
00246    /** set port on remote computer **/
00247 
00248    memset( &sin , 0 , sizeof(sin) ) ;
00249    sin.sin_family = AF_INET ;
00250    sin.sin_port   = htons(port) ;
00251 
00252    /** set remote computer **/
00253 
00254    hostp = gethostbyname(host) ;
00255    if( hostp == NULL ){
00256       PERROR("Can't lookup? tcp_connect[gethostbyname]"); CLOSEDOWN(sd); return -1;
00257    }
00258    sin.sin_addr.s_addr = ((struct in_addr *)(hostp->h_addr))->s_addr ;
00259 
00260    if( connect(sd , (struct sockaddr *)&sin , sizeof(sin)) == -1 ){
00261       PERROR("Can't connect? tcp_connect[connect]") ; CLOSEDOWN(sd); return -1;
00262    }
00263 
00264    return sd ;
00265 }
 | 
| 
 | 
| set remote computer * Definition at line 276 of file thd_iochan.c. References CLOSEDOWN, l, PERROR, socket, SOCKET_BUFSIZE, and STATUS. Referenced by iochan_init(), and NI_stream_open(). 
 00277 {
00278    int sd , l ;
00279    struct sockaddr_in sin ;
00280 
00281    if( port < 1 ){ STATUS("tcp_listen: illegal port") ; return -1 ; }
00282 
00283    /** open a socket **/
00284 
00285    sd = socket( AF_INET , SOCK_STREAM , 0 ) ;
00286    if( sd == -1 ){ PERROR("Can't create? tcp_listen[socket]"); return -1; }
00287 
00288    /** set socket options (no delays, large buffers) **/
00289 
00290 #if 0
00291    l = 1;
00292    setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, (void *)&l, sizeof(int)) ;
00293 #endif
00294    l = SOCKET_BUFSIZE ;
00295    setsockopt(sd, SOL_SOCKET, SO_SNDBUF, (void *)&l, sizeof(int)) ;
00296    setsockopt(sd, SOL_SOCKET, SO_RCVBUF, (void *)&l, sizeof(int)) ;
00297 
00298    /** set port on remote computer **/
00299 
00300    memset( &sin , 0 , sizeof(sin) ) ;
00301    sin.sin_family      = AF_INET ;
00302    sin.sin_port        = htons(port) ;
00303    sin.sin_addr.s_addr = INADDR_ANY ;  /* reader reads from anybody */
00304 
00305    if( bind(sd , (struct sockaddr *)&sin , sizeof(sin)) == -1 ){
00306       PERROR("Can't bind? tcp_listen[bind]"); CLOSEDOWN(sd); return -1;
00307    }
00308 
00309    if( listen(sd,1) == -1 ){
00310       PERROR("Can't listen? tcp_listen[listen]"); CLOSEDOWN(sd); return -1;
00311    }
00312 
00313    return sd ;
00314 }
 | 
| 
 | ||||||||||||
| 
 Definition at line 107 of file thd_iochan.c. References PERROR, and STATUS. Referenced by iochan_clearcheck(), iochan_goodcheck(), iochan_init(), iochan_readcheck(), NI_stream_goodcheck(), NI_stream_open(), NI_stream_read(), NI_stream_readcheck(), and tcp_alivecheck(). 
 00108 {
00109    int ii ;
00110    fd_set rfds ;
00111    struct timeval tv , * tvp ;
00112 
00113    if( sd < 0 ){ STATUS("tcp_readcheck: illegal sd") ; return -1 ; } /* bad socket id */
00114 
00115    FD_ZERO(&rfds) ; FD_SET(sd, &rfds) ;         /* check only sd */
00116 
00117    if( msec >= 0 ){                             /* set timer */
00118       tv.tv_sec  = msec/1000 ;
00119       tv.tv_usec = (msec%1000)*1000 ;
00120       tvp        = &tv ;
00121    } else {
00122       tvp        = NULL ;                       /* forever */
00123    }
00124 
00125    /** STATUS("tcp_readcheck: call select") ; **/
00126 
00127    ii = select(sd+1, &rfds, NULL, NULL, tvp) ;  /* check it */
00128    if( ii == -1 ) PERROR( "Socket gone bad? tcp_readcheck[select]" ) ;
00129    return ii ;
00130 }
 | 
| 
 | 
| STATUS("tcp_writecheck: call select") ; * Definition at line 179 of file thd_iochan.c. Referenced by iochan_set_cutoff(), tcp_accept(), tcp_connect(), and tcp_listen(). 
 00180 {
00181 #ifdef SO_LINGER
00182    { struct linger lg ;
00183      lg.l_onoff  = 1 ;
00184      lg.l_linger = 0 ;
00185      setsockopt(sd, SOL_SOCKET, SO_LINGER, (void *)&lg, sizeof(struct linger)) ;
00186    }
00187 #endif
00188 #ifdef SO_REUSEADDR
00189    { int optval = 1;
00190      setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval)) ;
00191    }
00192 #endif
00193    return ;
00194 }
 | 
| 
 | ||||||||||||
| STATUS("tcp_readcheck: call select") ; * Definition at line 132 of file thd_iochan.c. References PERROR, and STATUS. Referenced by iochan_send(), iochan_writecheck(), NI_stream_write(), NI_stream_writecheck(), RT_mp_comm_close(), and RT_mp_comm_send_data(). 
 00133 {
00134    int ii ;
00135    fd_set wfds ;
00136    struct timeval tv , * tvp ;
00137 
00138    if( sd < 0 ){ STATUS("tcp_writecheck: illegal sd") ; return -1 ; } /* bad socket id */
00139 
00140    FD_ZERO(&wfds) ; FD_SET(sd, &wfds) ;         /* check only sd */
00141 
00142    if( msec >= 0 ){                             /* set timer */
00143       tv.tv_sec  = msec/1000 ;
00144       tv.tv_usec = (msec%1000)*1000 ;
00145       tvp        = &tv ;
00146    } else {
00147       tvp        = NULL ;                       /* forever */
00148    }
00149 
00150    /** STATUS("tcp_writecheck: call select") ; **/
00151 
00152    ii = select(sd+1, NULL , &wfds, NULL, tvp) ;  /* check it */
00153    if( ii == -1 ) PERROR( "Socket gone bad? tcp_writecheck[select]" ) ;
00154    return ii ;
00155 }
 | 
Variable Documentation
| 
 | 
| 
 Definition at line 11 of file thd_iochan.c. Referenced by iochan_clearcheck(), iochan_error_string(), iochan_goodcheck(), iochan_init(), iochan_readcheck(), iochan_recv(), iochan_recvall(), iochan_recvloop(), iochan_send(), iochan_sendall(), and iochan_writecheck(). | 
| 
 | 
| 
 Definition at line 1543 of file thd_iochan.c. | 
| 
 | 
| 
 Definition at line 1544 of file thd_iochan.c. | 
| 
 | 
| 
 Definition at line 78 of file thd_iochan.c. Referenced by iochan_send(). | 
| 
 | 
| 
 Definition at line 64 of file thd_iochan.c. Referenced by iochan_enable_perror(). | 
| 
 | 
| 
 Definition at line 16 of file thd_iochan.c. Referenced by iochan_close(), and iochan_init(). | 
 
                             
                             
                             
                             
                             
                             
                             
                             
                             
                             
                             
                             
 
 
 
 
       
	   
	   
	   
	  