Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

niml_stream.c File Reference

#include "niml_private.h"
#include <signal.h>
#include <fcntl.h>

Go to the source code of this file.


Defines

#define PERROR(x)   perror(x)
#define CLOSEDOWN(ss)   ( shutdown((ss),2) , close((ss)) )
#define SOCKET_BUFSIZE   (31*1024)
#define tcp_recv   recv
#define tcp_send   send
#define MIN(a, b)   (((a)>(b)) ? (b) : (a))
#define NEXTDMS(dm)   MIN(1.1*(dm)+1.01,66.0)
#define INIT_NHO   (sizeof(init_hosts)/sizeof(char *))
#define HSIZE   32

Functions

void add_open_stream (NI_stream_type *ns)
void remove_open_stream (NI_stream_type *ns)
void atexit_open_streams (void)
void tcp_sigurg_handler (int sig)
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)
char * NI_hostname_to_inet (char *host)
int hostname_dotted (char *hnam)
void add_trusted_host (char *hnam)
void init_trusted_list (void)
void NI_add_trusted_host (char *hostname)
int NI_trust_host (char *hostid)
key_t SHM_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)
int SHM_fill_accept (SHMioc *ioc)
SHMiocSHM_init (char *name, char *mode)
int SHM_alivecheck (int shmid)
int SHM_goodcheck (SHMioc *ioc, int msec)
void SHM_close (SHMioc *ioc)
int SHM_readcheck (SHMioc *ioc, int msec)
int SHM_writecheck (SHMioc *ioc, int msec)
int SHM_send (SHMioc *ioc, char *buffer, int nbytes)
int SHM_sendall (SHMioc *ioc, char *buffer, int nbytes)
int SHM_recv (SHMioc *ioc, char *buffer, int nbytes)
NI_stream NI_stream_open (char *name, char *mode)
int NI_stream_reopen (NI_stream_type *ns, char *nname)
void NI_stream_seek (NI_stream_type *ns, int offset, int whence)
int NI_stream_readable (NI_stream_type *ns)
int NI_stream_writeable (NI_stream_type *ns)
char * NI_stream_name (NI_stream_type *ns)
int NI_stream_setbufsize (NI_stream_type *ns, int bs)
int NI_stream_getbufsize (NI_stream_type *ns)
char * NI_stream_getbuf (NI_stream_type *ns)
void NI_stream_clearbuf (NI_stream_type *ns)
void NI_stream_setbuf (NI_stream_type *ns, char *str)
int NI_stream_goodcheck (NI_stream_type *ns, int msec)
void NI_stream_close_keep (NI_stream_type *ns, int flag)
void NI_stream_close (NI_stream_type *ns)
void NI_stream_closenow (NI_stream_type *ns)
void NI_stream_kill (NI_stream_type *ns)
int NI_stream_hasinput (NI_stream_type *ns, int msec)
int NI_stream_readcheck (NI_stream_type *ns, int msec)
int NI_stream_writecheck (NI_stream_type *ns, int msec)
int NI_stream_writestring (NI_stream_type *ns, char *str)
int NI_stream_write (NI_stream_type *ns, char *buffer, int nbytes)
int NI_stream_read (NI_stream_type *ns, char *buffer, int nbytes)
int NI_stream_fillbuf (NI_stream_type *ns, int minread, int msec)
int NI_stream_readbuf (NI_stream_type *ns, char *buffer, int nbytes)
int NI_stream_readbuf64 (NI_stream_type *ns, char *buffer, int nbytes)

Variables

int nosigpipe = 0
int sigurg = 0
int num_open_streams = 0
NI_stream_type ** open_streams = NULL
volatile int doing_atexit = 0
int atexit_is_setup = 0
int host_num = 0
char ** host_list = NULL
char * init_hosts []

Define Documentation

#define CLOSEDOWN ss       ( shutdown((ss),2) , close((ss)) )
 

How to close a socket, given the descriptor ss.

Definition at line 32 of file niml_stream.c.

Referenced by iochan_close(), iochan_goodcheck(), iochan_init(), NI_stream_close_keep(), NI_stream_goodcheck(), NI_stream_open(), tcp_accept(), tcp_connect(), tcp_listen(), and tcp_sigurg_handler().

#define HSIZE   32
 

Definition at line 560 of file niml_stream.c.

Referenced by add_trusted_host(), and init_trusted_list().

#define INIT_NHO   (sizeof(init_hosts)/sizeof(char *))
 

Definition at line 559 of file niml_stream.c.

Referenced by init_trusted_list().

#define MIN a,
b       (((a)>(b)) ? (b) : (a))
 

Duh.

Definition at line 49 of file niml_stream.c.

#define NEXTDMS dm       MIN(1.1*(dm)+1.01,66.0)
 

Next delay in milliseconds, given current delay.

Definition at line 54 of file niml_stream.c.

Referenced by iochan_clearcheck(), iochan_goodcheck(), iochan_readcheck(), iochan_recvall(), iochan_sendall(), iochan_writecheck(), NI_stream_goodcheck(), SHM_goodcheck(), SHM_readcheck(), SHM_sendall(), and SHM_writecheck().

#define PERROR      perror(x)
 

To print a system error message.

Definition at line 12 of file niml_stream.c.

Referenced by iochan_recv(), iochan_send(), NI_stream_read(), NI_stream_write(), shm_attach(), SHM_attach(), shm_create(), SHM_create(), shm_nattach(), SHM_nattach(), shm_size(), SHM_size(), tcp_accept(), tcp_alivecheck(), tcp_connect(), tcp_listen(), tcp_readcheck(), and tcp_writecheck().

#define SOCKET_BUFSIZE   (31*1024)
 

This is used to set the send/receive buffer size for sockets. It should be below the upper limit on all Unix systems.

Definition at line 37 of file niml_stream.c.

Referenced by tcp_connect(), and tcp_listen().

#define tcp_recv   recv
 

This macro is used so I can replace recv() with something else if I want.

Definition at line 41 of file niml_stream.c.

Referenced by iochan_recv(), NI_stream_read(), and tcp_alivecheck().

#define tcp_send   send
 

This macro is used so I can replace send() with something else if I want.

Definition at line 45 of file niml_stream.c.

Referenced by NI_stream_close_keep(), and NI_stream_write().


Function Documentation

void add_open_stream NI_stream_type   ns [static]
 

Add a stream to the open list.

Definition at line 79 of file niml_stream.c.

References num_open_streams, and realloc.

Referenced by NI_stream_open(), and NI_stream_reopen().

00080 {
00081    int nn = num_open_streams ;
00082 
00083    if( ns == NULL ) return ;  /* bad input */
00084 
00085    open_streams = (NI_stream_type **)realloc( (void *)open_streams ,
00086                                               sizeof(NI_stream_type *)*(nn+1) );
00087 
00088    open_streams[nn] = ns ; num_open_streams++ ; return ;
00089 }

void add_trusted_host char *    hnam [static]
 

Add a host to the trusted list (internal version). ------------------------------------------------------------------

Definition at line 603 of file niml_stream.c.

References host_list, host_num, hostname_dotted(), HSIZE, NI_free, NI_hostname_to_inet(), NI_malloc, and NI_realloc.

Referenced by init_trusted_list(), and NI_add_trusted_host().

00604 {
00605    char *hh=NULL ;
00606    int ii ;
00607 
00608    if( hnam == NULL || hnam[0] == '\0' ) return ;
00609 
00610    if( !hostname_dotted(hnam) ){         /* not a dotted number */
00611      hh = NI_hostname_to_inet( hnam ) ;  /* so do a lookup on it */
00612      if( hh == NULL ) return ;           /* failed? */
00613 
00614    } else if( strlen(hnam) > HSIZE-1 ){   /* something bad? */
00615      return ;
00616    } else {
00617      hh = hnam ;                     /* store dotted number */
00618    }
00619 
00620    host_list = NI_realloc(host_list, char*,sizeof(char *)*(host_num+1)) ;
00621    host_list[host_num] = NI_malloc(char, HSIZE) ;
00622    strcpy( host_list[host_num] , hh ) ; host_num++ ;
00623 
00624    if( hh != hnam ) NI_free(hh) ;
00625 }

void atexit_open_streams void    [static]
 

At program exit, close all open streams.

Definition at line 113 of file niml_stream.c.

References doing_atexit, NI_sleep(), NI_stream_close_keep(), and num_open_streams.

Referenced by NI_stream_open().

00114 {
00115    int ii ;
00116    if( doing_atexit ) return ;
00117    doing_atexit = 1 ;
00118    for( ii=0 ; ii < num_open_streams ; ii++ ){
00119      NI_sleep(2) ;
00120      NI_stream_close_keep( open_streams[ii] , 5 ) ;
00121    }
00122    return ;
00123 }

int hostname_dotted char *    hnam [static]
 

Check if hostname is in dotted form. ------------------------------------------------------------------

Definition at line 589 of file niml_stream.c.

Referenced by add_trusted_host(), and NI_trust_host().

00590 {
00591    int ii, nh ;
00592    if( hnam == NULL ) return 0 ;
00593    nh = strlen(hnam) ;
00594    for( ii=0 ; ii < nh ; ii++ )
00595      if( !isdigit(hnam[ii]) && hnam[ii] != '.' ) return 0 ;
00596    return 1 ;
00597 }

void init_trusted_list void    [static]
 

Initialize trusted list from the internal table and the environment. ----------------------------------------------------------------------------

Definition at line 631 of file niml_stream.c.

References add_trusted_host(), getenv(), host_list, host_num, HSIZE, init_hosts, INIT_NHO, and NI_malloc.

Referenced by NI_add_trusted_host(), and NI_trust_host().

00632 {
00633    int ii ;
00634    char ename[HSIZE] , *str ;
00635 
00636    if( host_num == 0 ){      /** only execute this once **/
00637      host_num = INIT_NHO ;
00638      host_list = NI_malloc(char*, sizeof(char *) * INIT_NHO ) ;
00639      for( ii=0 ; ii < INIT_NHO ; ii++ ){
00640        host_list[ii] = NI_malloc(char, HSIZE) ;
00641        strcpy( host_list[ii] , init_hosts[ii] ) ;
00642      }
00643 
00644      for( ii=0 ; ii <= 99 ; ii++ ){
00645        sprintf(ename,"NIML_TRUSTHOST_%02d",ii) ; str = getenv(ename) ;
00646        if( str == NULL && ii <= 9 ){
00647          sprintf(ename,"NIML_TRUSTHOST_%1d",ii) ; str = getenv(ename) ;
00648        }
00649        if( str == NULL && ii <= 9 ){
00650          sprintf(ename,"NIML_TRUSTHOST_O%1d",ii) ; str = getenv(ename) ;
00651        }
00652        if( str != NULL ) add_trusted_host(str) ;
00653      }
00654 
00655      for( ii=0 ; ii <= 99 ; ii++ ){
00656        sprintf(ename,"AFNI_TRUSTHOST_%02d",ii) ; str = getenv(ename) ;
00657        if( str == NULL && ii <= 9 ){
00658          sprintf(ename,"AFNI_TRUSTHOST_%1d",ii) ; str = getenv(ename) ;
00659        }
00660        if( str == NULL && ii <= 9 ){
00661          sprintf(ename,"AFNI_TRUSTHOST_O%1d",ii) ; str = getenv(ename) ;
00662        }
00663        if( str != NULL ) add_trusted_host(str) ;
00664      }
00665    }
00666    return ;
00667 }

void NI_add_trusted_host char *    hostname
 

Externally callable routine to add a host to the trusted list. If call with NULL, will just initialize the default trusted host list. ----------------------------------------------------------------------------

Definition at line 675 of file niml_stream.c.

References add_trusted_host(), host_num, and init_trusted_list().

Referenced by main(), NI_suck_stream(), and TRUST_addhost().

00676 {
00677    if( host_num == 0 ) init_trusted_list() ;
00678    if( hostname == NULL || hostname[0] == '\0' ) return ;
00679    add_trusted_host(hostname) ;
00680 }

char* NI_hostname_to_inet char *    host
 

Return the Internet address (in 'dot' format, as a string) given the name of the host. If NULL is returned, some error occurrrrred. The string is NI_malloc()-ed, and should be NI_free()-ed when no longer needed. ------------------------------------------------------------------

Definition at line 569 of file niml_stream.c.

References NI_strdup().

Referenced by add_trusted_host(), and NI_trust_host().

00570 {
00571    struct hostent *hostp ;
00572    char * iname = NULL , *str ;
00573    int ll ;
00574 
00575    if( host == NULL || host[0] == '\0' ) return NULL ;
00576 
00577    hostp = gethostbyname(host) ; if( hostp == NULL ) return NULL ;
00578 
00579    str = inet_ntoa(*((struct in_addr *)(hostp->h_addr))) ;
00580    if( str == NULL || str[0] == '\0' ) return NULL ;
00581 
00582    iname = NI_strdup(str) ; return iname ;
00583 }

void NI_stream_clearbuf NI_stream_type   ns
 

Clear the buffer of a str: writing NI_stream. This is intended to let you write anew without having to close and open again. -------------------------------------------------------------------------

Definition at line 2219 of file niml_stream.c.

References NI_stream_type::buf, NI_stream_type::bufsize, NI_stream_type::io_mode, NI_stream_type::nbuf, NI_free, NI_malloc, NI_OUTPUT_MODE, NI_STRING_TYPE, and NI_stream_type::type.

02220 {
02221    if( ns          == NULL           ||
02222        ns->type    != NI_STRING_TYPE ||
02223        ns->io_mode != NI_OUTPUT_MODE   ) return ;  /* bad inputs */
02224 
02225    NI_free(ns->buf) ;
02226    ns->nbuf    = 0 ;
02227    ns->bufsize = 1 ;
02228    ns->buf     = NI_malloc(char, 1) ; /* 1 byte set to zero */
02229 }

void NI_stream_close NI_stream_type   ns
 

Close a NI_stream. Note that this will also free what ns points to. Don't use this pointer again. Use the NI_STREAM_CLOSE macro to call this function and then also set the pointer "ns" to NULL. -------------------------------------------------------------------------

Definition at line 2460 of file niml_stream.c.

References NI_free, and NI_stream_close_keep().

Referenced by AFNI_start_version_check(), AFNI_version_check(), Dtable_from_nimlstring(), Dtable_to_nimlstring(), main(), NI_read_file_nohead(), nifti_set_afni_extension(), NIML_to_stderr(), open_URL_hpf(), read_URL_http(), SUMA_DsetInfo(), SUMA_Engine(), SUMA_FakeIt(), SUMA_LoadNimlDset(), SUMA_LoadVisualState(), SUMA_nel_stdout(), SUMA_niml_hangup(), SUMA_niml_workproc(), SUMA_OpenDrawnROI_NIML(), SUMA_SaveVisualState(), SUMA_SendToAfni(), SUMA_SendToSuma(), SUMA_ShowNel(), SUMA_Write_DrawnROI_NIML(), THD_load_3D(), THD_open_3D(), THD_open_nifti(), THD_read_niml_atr(), THD_write_nimlatr(), v2s_write_outfile_niml(), XSAVE_input(), and XSAVE_output().

02461 {
02462    NI_stream_close_keep(ns,1) ; NI_free(ns) ; return ;
02463 }

void NI_stream_close_keep NI_stream_type   ns,
int    flag
 

Close a NI_stream, but don't free the insides. If (flag&1 != 0) send a "close_this" message to the other end. If (flag&2 != 0) use TCP OOB data to send a SIGURG to the other end. If (flag&4 != 0) don't remove from open_stream list [only from atexit()] -----------------------------------------------------------------------------

Definition at line 2389 of file niml_stream.c.

References NI_stream_type::bad, NI_stream_type::buf, CLOSEDOWN, NI_stream_type::fp, NI_stream_type::io_mode, MARKED_FOR_DEATH, NI_FD_TYPE, NI_FILE_TYPE, NI_free, NI_OUTPUT_MODE, NI_REMOTE_TYPE, NI_SHM_TYPE, NI_sleep(), NI_stream_writecheck(), NI_stream_writestring(), NI_STRING_TYPE, NI_TCP_TYPE, NI_stream_type::orig_name, remove_open_stream(), NI_stream_type::sd, SHM_close(), NI_stream_type::shmioc, tcp_send, and NI_stream_type::type.

Referenced by atexit_open_streams(), NI_do(), NI_stream_close(), NI_stream_closenow(), NI_stream_kill(), and NI_stream_reopen().

02390 {
02391    if( ns == NULL || !isgraph(ns->orig_name[0]) ) return ;
02392 
02393    if( (flag & 4) == 0 )         /* 22 Apr 2005 */
02394      remove_open_stream( ns ) ;  /* 02 Jan 2004 */
02395 
02396    if( ns->bad == MARKED_FOR_DEATH ){
02397      if( ns->buf != NULL ){ NI_free(ns->buf); ns->buf = NULL;}
02398      return ;
02399    }
02400 
02401    /*-- 20 Dec 2002: write a farewell message to the other end? --*/
02402 
02403    if( (flag & 1) != 0                                      &&
02404        (ns->type == NI_TCP_TYPE || ns->type == NI_SHM_TYPE) &&
02405        NI_stream_writecheck(ns,1) > 0                          ){
02406 
02407      NI_stream_writestring( ns , "<?ni_do ni_verb='close_this' ?>\n" ) ;
02408      NI_sleep(9) ;  /* give it an instant to read the message */
02409    }
02410 
02411    /*-- mechanics of closing for different stream types --*/
02412 
02413    switch( ns->type ){
02414 
02415 #ifndef DONT_USE_SHM
02416       case NI_SHM_TYPE:
02417         NI_sleep(9) ;                          /* 31 Mar 2005 */
02418         SHM_close( ns->shmioc ) ;              /* detach shared memory */
02419       break ;
02420 #endif
02421 
02422       case NI_FD_TYPE:
02423         if( ns->fp != NULL && ns->io_mode == NI_OUTPUT_MODE ) fflush(ns->fp) ;
02424       break ;
02425 
02426       case NI_REMOTE_TYPE:
02427       case NI_STRING_TYPE:                     /* nothing to do */
02428       break ;
02429 
02430       case NI_FILE_TYPE:
02431         if( ns->fp != NULL ) fclose(ns->fp) ;  /* close file */
02432       break ;
02433 
02434       case NI_TCP_TYPE:
02435         if( ns->sd >= 0 ){
02436           if( (flag & 2) != 0 ){
02437             tcp_send( ns->sd , "X" , 1 , MSG_OOB ) ;   /* 02 Jan 2004 */
02438             NI_sleep(9) ;
02439           }
02440           NI_sleep(2) ;        /* 31 Mar 2005 */
02441           CLOSEDOWN(ns->sd) ;  /* close socket */
02442         }
02443       break ;
02444    }
02445 
02446    ns->bad = MARKED_FOR_DEATH ; /* label this as unclean, not to be touched */
02447    if( (flag & 4) == 0 ){       /* only free buf if program is NOT exiting */
02448      NI_free(ns->buf) ; ns->buf = NULL ;
02449    }
02450    return ;
02451 }

void NI_stream_closenow NI_stream_type   ns
 

Close a NI_stream without sending a "close_this" message to the other end of the stream.

Definition at line 2469 of file niml_stream.c.

References NI_free, and NI_stream_close_keep().

Referenced by AFNI_niml_atexit(), AFNI_niml_workproc(), AFNI_serverlog(), AIVVV_niml_quitter(), AIVVV_workproc(), main(), NI_stream_reopen(), NI_suck_stream(), and NIML_to_stderr().

02470 {
02471    NI_stream_close_keep(ns,0) ; NI_free(ns) ; return ;
02472 }

int NI_stream_fillbuf NI_stream_type   ns,
int    minread,
int    msec
 

Try to fill up the stream's input buffer. Don't call this function until NI_stream_goodcheck() is 1!

  • minread = Minimum number of bytes to read. Will wait until we get at least this many, until the stream is bad or the buffer is full. If minread=0, then may read nothing (but will try).
  • msec = Maximum amount of time to wait to satisfy minread, in milliseconds. If msec<0, will wait nearly forever. If msec=0, will return after 1st read attempt, even if nothing was obtained.
Returns number of bytes read (-1 if input stream goes bad before any data is read). If the input stream goes bad AFTER some data is read, there is no indication of that (until the next time you call this, of course). -------------------------------------------------------------------------

Definition at line 2865 of file niml_stream.c.

References NI_stream_type::buf, NI_stream_type::bufsize, NI_stream_type::nbuf, NI_clock_time(), NI_REMOTE_TYPE, NI_stream_goodcheck(), NI_stream_read(), NI_stream_readcheck(), NI_STRING_TYPE, and NI_stream_type::type.

Referenced by NI_decode_one_double(), NI_decode_one_string(), NI_stream_readbuf(), NI_stream_readbuf64(), and scan_for_angles().

02866 {
02867    int nn , ii , ntot=0 , ngood=0 , mwait=0 ;
02868    int start_msec = NI_clock_time() ;
02869 
02870    if( NI_stream_goodcheck(ns,0) < 0 ) return -1 ;   /* bad input */
02871 
02872    if( ns->type == NI_STRING_TYPE ) return -1 ;      /* goofy input */
02873    if( ns->type == NI_REMOTE_TYPE ) return -1 ;      /* goofy input */
02874 
02875    if( ns->nbuf >= ns->bufsize ) return 0 ; /* buffer already full */
02876 
02877    if( msec < 0 ) msec = 999999999 ;        /* a long time (11+ days) */
02878 
02879    /* read loop */
02880 
02881    while(1){
02882 
02883       ngood = NI_stream_readcheck(ns,mwait); /* check if data can be read */
02884 
02885       if( ngood < 0 ) break ;                /* data stream gone bad, so exit */
02886 
02887       if( ngood > 0 ){                       /* we can read ==> */
02888                                              /* try to fill buffer completely */
02889 
02890          ii = NI_stream_read( ns, ns->buf+ns->nbuf, ns->bufsize-ns->nbuf ) ;
02891 
02892          if( ii > 0 ){                 /* we got data! */
02893             ns->nbuf += ii ;           /* buffer is now longer */
02894             ntot     += ii ;           /* total bytes read here so far */
02895 
02896             /* if buffer is full,
02897                or we have all the data that was asked for, then exit */
02898 
02899             if( ns->nbuf >= ns->bufsize || ntot >= minread ) break ;
02900 
02901          } else if( ii < 0 ){          /* stream suddenly died horribly? */
02902             ngood = -1 ; break ;
02903          }
02904       }
02905 
02906       /* if we don't require data, then exit no matter what our status is */
02907 
02908       if( minread <= 0 ) break ;
02909 
02910       /* if the max time has elapsed, then exit */
02911 
02912       if( NI_clock_time()-start_msec >= msec ) break ;
02913 
02914       /* otherwise, sleep a little bit before trying again */
02915 
02916       if( mwait < 9 ) mwait++ ;
02917    }
02918 
02919    /* if didn't get any data, and
02920       if the NI_stream was bad, return -1 as a flag of displeasure */
02921 
02922    if( ntot == 0 && ngood < 0 ) ntot = -1 ;
02923 
02924    return ntot ;  /* otherwise, return # of bytes read (may be 0) */
02925 }

char* NI_stream_getbuf NI_stream_type   ns
 

Return the output string buffer for a NI_stream of str: type. If the input is not a "w" str: stream, then NULL is returned. Otherwise a pointer to the internal buffer is returned. This will be a NUL terminated string. -------------------------------------------------------------------------

Definition at line 2204 of file niml_stream.c.

References NI_stream_type::bad, NI_stream_type::buf, NI_stream_type::io_mode, MARKED_FOR_DEATH, NI_OUTPUT_MODE, NI_STRING_TYPE, and NI_stream_type::type.

Referenced by Dtable_to_nimlstring(), main(), nifti_set_afni_extension(), and SUMA_DsetInfo().

02205 {
02206    if( ns          == NULL             ||
02207        ns->type    != NI_STRING_TYPE   ||
02208        ns->io_mode != NI_OUTPUT_MODE   ||
02209        ns->bad     == MARKED_FOR_DEATH   ) return NULL ;  /* bad inputs */
02210 
02211    return ns->buf ;
02212 }

int NI_stream_getbufsize NI_stream_type   ns
 

Get the input buffer size for a NI_stream. Returns -1 if the stream is bad, or has been sentenced to death. -------------------------------------------------------------------------

Definition at line 2191 of file niml_stream.c.

References NI_stream_type::bad, NI_stream_type::bufsize, and MARKED_FOR_DEATH.

02192 {
02193    if( ns == NULL || ns->bad  == MARKED_FOR_DEATH ) return -1 ;
02194    return ns->bufsize ;
02195 }

int NI_stream_goodcheck NI_stream_type   ns,
int    msec
 

Check if the given NI_stream is properly opened for I/O.

If not, wait up to msec milliseconds to establish the connection to the other end; if msec < 0, will wait nearly forever. Returns 1 if ready; 0 if not (but may become good later); -1 if an error occurs. Possible -1 errors are:

  • ns was connected to a socket, and now has become disconnected
  • ns is passed in as NULL (bad user, bad bad bad)
  • ns is reading a file or a string, and we are already at its end
  • ns is marked for death The only cases in which 0 is returned is if the NI_stream is tcp: or shm: and the stream is waiting for a connection from the other program. These are also the only cases in which input parameter msec is actually used. -------------------------------------------------------------------------

Definition at line 2276 of file niml_stream.c.

References NI_stream_type::bad, CLOSEDOWN, NI_stream_type::fp, NI_stream_type::io_mode, MARKED_FOR_DEATH, MIN, NI_stream_type::name, NEXTDMS, NI_dpr(), NI_FD_TYPE, NI_FILE_TYPE, NI_free, NI_INPUT_MODE, NI_REMOTE_TYPE, NI_SHM_TYPE, NI_sleep(), NI_stream_readcheck(), NI_STRING_TYPE, NI_strncpy(), NI_TCP_TYPE, NI_stream_type::port, NI_stream_type::sd, SHM_goodcheck(), NI_stream_type::shmioc, tcp_accept(), tcp_alivecheck(), tcp_connect(), tcp_readcheck(), and NI_stream_type::type.

Referenced by AFNI_niml_redisplay_CB(), AFNI_niml_viewpoint_CB(), AFNI_niml_workproc(), AIVVV_workproc(), main(), NI_read_columns(), NI_read_element(), NI_stream_fillbuf(), NI_stream_read(), NI_stream_readcheck(), NI_stream_reopen(), NI_stream_writecheck(), NI_suck_stream(), NI_write_columns(), NI_write_element(), NI_write_procins(), SUMA_Engine(), SUMA_niml_workproc(), SUMA_SendToAfni(), and SUMA_SendToSuma().

02277 {
02278    int ii , jj ;
02279    char *bbb ;
02280 
02281    /** check inputs for OK-osity **/
02282 
02283    if( ns == NULL || ns->bad == MARKED_FOR_DEATH ) return -1 ;
02284 
02285    switch( ns->type ){
02286 
02287 #ifndef DONT_USE_SHM
02288       /** Shared memory **/
02289 
02290       case NI_SHM_TYPE:
02291         return SHM_goodcheck( ns->shmioc , msec ) ;
02292 #endif
02293 
02294       /** File I/O [there is never any waiting here] **/
02295 
02296       case NI_FILE_TYPE:
02297         if( ns->fp == NULL ) return -1 ;        /* should never happen */
02298         if( ns->io_mode == NI_INPUT_MODE )
02299           return NI_stream_readcheck(ns,0) ;    /* input mode */
02300         else
02301           return 1 ;                            /* output mode */
02302 
02303       case NI_FD_TYPE:
02304           return 1 ;                            /* no way to check */
02305 
02306       /** String I/O **/
02307 
02308       case NI_STRING_TYPE:
02309         if( ns->io_mode == NI_INPUT_MODE )
02310           return NI_stream_readcheck(ns,0) ;    /* input mode */
02311         else
02312           return 1 ;                            /* output mode */
02313 
02314       /** remote Web input */
02315 
02316       case NI_REMOTE_TYPE:
02317         if( ns->io_mode == NI_INPUT_MODE )
02318           return NI_stream_readcheck(ns,0) ;    /* input mode */
02319         else
02320           return -1 ;                           /* output mode */
02321 
02322       /** Socket I/O **/
02323 
02324       case NI_TCP_TYPE:
02325         if( ns->bad == 0 ){  /** if good before, then check if is still good **/
02326           int ich ;
02327           ich = tcp_alivecheck(ns->sd) ;
02328 
02329 #ifdef NIML_DEBUG
02330           if( ich == 0 )  /* 17 Jun 2003 */
02331             NI_dpr("++ Socket %s (port %d) has gone bad!\n",ns->name,ns->port);
02332 #endif
02333 
02334           if( ich == 0 ) return -1 ;
02335           return 1 ;
02336         }
02337 
02338         /** wasn't good before, so check if that condition has changed **/
02339 
02340         /** TCP/IP waiting to accept call from another host **/
02341 
02342         if( ns->bad == TCP_WAIT_ACCEPT ){
02343           ii = tcp_readcheck(ns->sd,msec) ;             /* see if ready      */
02344           if( ii > 0 ){                                 /* if socket ready:  */
02345             jj = tcp_accept( ns->sd , NULL,&bbb ) ;     /* accept connection */
02346             if( jj >= 0 ){                              /* if accept worked  */
02347               CLOSEDOWN( ns->sd ) ;                     /* close old socket  */
02348               NI_strncpy(ns->name,bbb,256) ;            /* put IP into name  */
02349               NI_free(bbb); ns->bad = 0; ns->sd = jj;   /* and ready to go!  */
02350               fcntl( ns->sd, F_SETOWN, (int)getpid() ); /* 02 Jan 2004 */
02351             }
02352           }
02353         }
02354 
02355         /** TCP/IP waiting to connect call to another host **/
02356 
02357         else if( ns->bad == TCP_WAIT_CONNECT ){
02358           int dms=0 , ms ;
02359 
02360           if( msec < 0 ) msec = 999999999 ;        /* a long time (11+ days) */
02361           for( ms=0 ; ms < msec ; ms += dms ){
02362             ns->sd = tcp_connect( ns->name , ns->port );  /* try to connect  */
02363             if( ns->sd >= 0 ) break ;                     /* worked? get out */
02364             dms = NEXTDMS(dms); dms = MIN(dms,msec-ms); NI_sleep(dms);
02365           }
02366           if( ns->sd < 0 )                                  /* one last try? */
02367             ns->sd  = tcp_connect( ns->name , ns->port ) ;
02368 
02369           if( ns->sd >= 0 ) ns->bad = 0 ;                   /* succeeded?    */
02370           if( ns->sd >= 0 )
02371             fcntl( ns->sd, F_SETOWN, (int)getpid() );         /* 02 Jan 2004 */
02372         }
02373 
02374         /** see if it turned from bad to good **/
02375 
02376         return (ns->bad == 0) ;
02377    }
02378 
02379    return -1 ;  /* unreachable, I hope */
02380 }

int NI_stream_hasinput NI_stream_type   ns,
int    msec
 

Check if the NI_stream has data read to be read, or has data stored in its internal buffer.

Definition at line 2490 of file niml_stream.c.

References NI_stream_type::bad, MARKED_FOR_DEATH, NI_stream_type::nbuf, NI_stream_readcheck(), and NI_stream_type::npos.

Referenced by AFNI_niml_workproc(), AIVVV_workproc(), NI_read_columns(), and SUMA_niml_workproc().

02491 {
02492    if( ns == NULL || ns->bad == MARKED_FOR_DEATH ) return -1 ;
02493 
02494    if( ns->npos < ns->nbuf ) return 1 ;      /* check if has data in buffer */
02495    return NI_stream_readcheck( ns , msec ) ; /* see if any data can be read */
02496 }

void NI_stream_kill NI_stream_type   ns
 

Definition at line 2478 of file niml_stream.c.

References NI_free, and NI_stream_close_keep().

Referenced by SUMA_niml_hangup().

02479 {
02480    NI_stream_close_keep(ns,3) ; NI_free(ns) ; return ;
02481 }

char* NI_stream_name NI_stream_type   ns
 

Return the name set in the NI_stream header. (This is the pointer to the internal string, so don't free it!) -------------------------------------------------------------------------

Definition at line 2151 of file niml_stream.c.

References NI_stream_type::name.

Referenced by AFNI_niml_workproc(), and SUMA_niml_workproc().

02152 {
02153    if( ns == NULL ) return NULL ;
02154    return ns->name ;
02155 }

NI_stream NI_stream_open char *    name,
char *    mode
 

Open a NIML input or output stream, and return a pointer to it.

  • NULL is returned if an error occurs.
  • Otherwise, you can read and write data using NI_stream_read() and NI_stream_write().
  • Buffered input is also available using NI_stream_readbuf() to read data from an internal buffer. The advantage of buffered input is that it will return the number of bytes requested (waiting, if needed), rather than just the number available at that moment.
Several different types of streams are available. The first two ("tcp:" and "shm:") are for 2-way interprocess communication. The later ones ("file:", "str:", "http:", "ftp:", and "fd:") are for 1-way communication, either to read bytes or to write them. The formats for the "name" input are described below:

name = "tcp:host:port" to connect a socket to system "host" on the given port number. One process should open in "w" mode and one in "r" mode.

name = "shm:keyname:size1+size2" to connect to a shared memory segment created with "keyname" for the ID and with I/O buffer sizes of size1 ("w" process to "r" process) and size2 ("r" process to "w" process).

  • Like tcp: streams, one process should open with "w" and the other with "r".
  • The "size" strings can end in 'K' to multiply by 1024, or end in 'M' to multiply by 1024*1024.
  • If neither size is given, a default value is used.
  • If only size1 is given, size2=size1 (symmetric stream).
  • The total size of the shared memory segment will be size1+size2+36 bytes. (Some systems put an upper limit on this size.)
  • "keyname" is a string used to identify this shared memory segment
  • If you are communicating a lot of data between 2 processes on the same system, shm: streams are usually much faster than tcp: streams.
  • Also see NI_stream_reopen() for a way to open a tcp: stream and then re-open it to another tcp: port or to be a shm: stream.
name = "file:filename" to open a file for I/O.
  • For this type of name ONLY, you can use "a" as the mode string to indicate that you want to append to the file if it already exists.
name = "str:" to read/write data from/to a string

name = "http://hostname/filename" to read data from a Web server name = "ftp://hostname/filename" to read data from an FTP server

  • The data for these types is transferred all at once from the remote server and stored in a memory buffer (much like the str: stream type).
  • Data can be read from this buffer using NI_stream_read().
  • When the stream is closed, the buffer is NI_free()-ed.
name = "fd:integer" to read or write data from a pre-opened file descriptor (returned by the open() function).
  • For example, "fd:1" is used to write to stdout directly.
  • When an "fd:" stream is closed, nothing is actually done; closing the descriptor is the responsibility of the application.
  • Descriptors 0,1,2 use stdin, stdout, and stderr, respectively.
  • All other descriptors use fdopen() to open a FILE stream and then treat the result like file:. This means that if the descriptor comes from fileno() on a previously opened FILE stream, you will have trouble if you mix I/O to this stream with NI_stream_read()/NI_stream_write().
  • You can use "stdin:", "stdout:", or "stderr:" as synonyms for "fd:0", "fd:1", and "fd:2".
The formats for the "mode" input are described below:

mode = "w" to open a stream for writing

  • tcp: host must be specified ("w" is for a tcp client).
  • shm: keyname determines the ID of the segment to create (which can be attached to by a shm: "r" process).
  • file: filename is opened in write mode (and will be overwritten if already exists).
  • str: data will be written to a buffer in the NI_stream struct; you can later access this buffer with the function NI_stream_getbuf(), and clear it with NI_stream_clearbuf().
  • You can't open "fd:0" (stdin) for reading
  • You can't open "http:" or "ftp:" streams for writing.
  • "a" can be used for "file:" ONLY to append to a file.
mode = "r" to open a stream for reading
  • tcp: host is ignored (but must be present); ("r" is for a tcp server).
  • shm: keyname determines the ID of the segment to attach to (which must be created by a shm: "w" process).
  • file: filename is opened in read mode.
  • str: characters after the colon are the source of the input data (will be copied to internal buffer); OR, you can later set the internal buffer string later with function NI_stream_setbuf().
  • You can't open "fd:1" or "fd:2" (stdout or stderr) for reading.
  • ftp:/http: The remote files are fetched and loaded into memory. After that, these streams operate pretty much the same as str: streams for reading.
For a file:, fd:, or str: stream, you can either read from or write to the stream, but not both, depending on how you opened it ("r" or "w"). For a tcp: or shm: stream, once it is connected, you can both read and write. The asymmetry in tcp: and shm: streams only comes at the opening (one process must make the call using "w" and one must listen for the call using "r").

The inputs "host" (for tcp:) and "filename" (for file:) are limited to a maximum of 127 bytes. For str:, there is no limit for the "r" stream (but clearly you can't have any NUL bytes in there). For shm:, "keyname" is limited to 127 bytes also.

Since opening a socket or shared memory segment requires sychronizing two processes, you can't read or write to a tcp: or shm: stream immediately. Instead you have to check if it is "good" first. This can be done using the function NI_stream_goodcheck().

After a tcp: "r" stream is good, then the string ns->name contains the IP address of the connecting host, in "dot" form (e.g., "201.202.203.204"); here, "ns" is the NI_stream returned by this routine.

  • You can use the NI_add_trusted_host() function to set a list of IP addresses from which the NIML library will accept connections.
  • Systems not on the trusted list will have their sockets closed immediately after the connection is accepted. Nothing will be read from these sockets.
For a file: stream, ns->name contains the filename. ---------------------------------------------------------------------------

Definition at line 1609 of file niml_stream.c.

References add_open_stream(), atexit(), atexit_is_setup, atexit_open_streams(), NI_stream_type::b64_numleft, NI_stream_type::bad, NI_stream_type::bin_thresh, NI_stream_type::buf, NI_stream_type::bufsize, CLOSEDOWN, fd, fdopen(), NI_stream_type::fp, NI_stream_type::fsize, getenv(), NI_stream_type::goodcheck_time, NI_stream_type::io_mode, NI_stream_type::name, name, NI_stream_type::nbuf, NI_BUFSIZE, NI_FD_TYPE, NI_FILE_TYPE, NI_filesize(), NI_free, NI_INPUT_MODE, NI_malloc, NI_malloc_enable_tracking(), NI_OUTPUT_MODE, NI_read_URL(), NI_REMOTE_TYPE, NI_SHM_TYPE, NI_STRING_TYPE, NI_strlen(), NI_strncpy(), NI_TCP_TYPE, NI_stream_type::npos, NI_stream_type::orig_name, NI_stream_type::port, NI_stream_type::sd, SHM_init(), NI_stream_type::shmioc, sigurg, tcp_accept(), tcp_connect(), tcp_listen(), tcp_readcheck(), tcp_sigurg_handler(), and NI_stream_type::type.

Referenced by AFNI_niml_workproc(), AFNI_serverlog(), AFNI_start_version_check(), AFNI_version_check(), AIVVV_workproc(), Dtable_from_nimlstring(), Dtable_to_nimlstring(), DWI_Open_NIML_stream(), main(), NI_do(), NI_read_file_nohead(), NI_stream_reopen(), NI_suck_stream(), nifti_set_afni_extension(), NIML_to_stderr(), open_URL_hpf(), SUMA_DsetInfo(), SUMA_Engine(), SUMA_FakeIt(), SUMA_LoadNimlDset(), SUMA_LoadVisualState(), SUMA_nel_stdout(), SUMA_niml_call(), SUMA_niml_workproc(), SUMA_OpenDrawnROI_NIML(), SUMA_SaveVisualState(), SUMA_SendToSuma(), SUMA_ShowNel(), SUMA_Write_DrawnROI_NIML(), THD_load_3D(), THD_open_3D(), THD_open_nifti(), THD_read_niml_atr(), THD_write_nimlatr(), v2s_write_outfile_niml(), XSAVE_input(), and XSAVE_output().

01610 {
01611    NI_stream_type *ns ;
01612    int do_create , do_accept ;
01613 
01614    /** perhaps initialize debug output **/
01615 
01616 #ifdef NIML_DEBUG
01617    if( dfp == NULL ){
01618      char *eee = getenv("NIML_DEBUG") ;
01619      if( eee != NULL ){
01620        dfp = (strcmp(eee,"stderr")==0) ? stderr : fopen(eee,"w") ;
01621        if( dfp == NULL ){ dfp = stderr; eee = "stderr [defaulted]"; }
01622        fprintf(stderr,"NIML: debug output to %s\n",eee) ;
01623      }
01624    }
01625 #endif
01626 
01627 #ifdef NIML_DEBUG
01628    NI_malloc_enable_tracking() ;
01629 #endif
01630 
01631    /** check if inputs are reasonable **/
01632 
01633    if( NI_strlen(name) < 4 ) return NULL ;
01634 
01635    if( mode == NULL ) return NULL ;
01636 
01637    do_create = (*mode == 'w' || *mode == 'a') ;
01638    do_accept = (*mode == 'r') ;
01639 
01640    if( !do_create && !do_accept ) return NULL ;
01641 
01642    if( ! atexit_is_setup ){         /* 22 Apr 2005 */
01643      atexit(atexit_open_streams) ; atexit_is_setup = 1 ;
01644    }
01645 
01646    /************************************/
01647    /***** deal with TCP/IP sockets *****/
01648 
01649    if( strncmp(name,"tcp:",4) == 0 ){
01650       char host[256] , *hend ;
01651       int  port=-1 , ii , jj ;
01652 
01653       if( NI_strlen(name) > 127 ) return NULL ;
01654 
01655       /** find "host" substring **/
01656 
01657       hend = strstr( name+4 , ":" ) ;
01658       if( hend == NULL || hend-name > 255 ) return NULL ;
01659 
01660       for( ii=4 ; name[ii] != ':' ; ii++ ) host[ii-4] = name[ii] ;
01661       host[ii-4] = '\0' ;
01662 
01663       /** get "port" number **/
01664 
01665       port = strtol( name+ii+1 , NULL , 10 ) ;
01666       if( port <= 0 ) return NULL ;
01667 
01668       /** initialize NI_stream_type output struct **/
01669 
01670       ns = NI_malloc(NI_stream_type, sizeof(NI_stream_type) ) ;
01671 
01672       ns->type = NI_TCP_TYPE;   /* what kind is this? */
01673       ns->port = port ;         /* save the port #    */
01674       ns->nbuf = 0 ;            /* buffer is empty    */
01675       ns->npos = 0 ;            /* scan starts at 0   */
01676       ns->b64_numleft = 0 ;
01677 
01678       ns->buf     = NI_malloc(char, NI_BUFSIZE) ;
01679       ns->bufsize = NI_BUFSIZE ;
01680       ns->name[0] = '\0' ;
01681       NI_strncpy(ns->orig_name,name,256) ;  /* 23 Aug 2002 */
01682 
01683       ns->bin_thresh = -1 ;     /* write in text mode */
01684 
01685       /* 02 Jan 2004: setup SIGURG handler for OOB data reception. */
01686 
01687       if( !sigurg ){ signal(SIGURG,tcp_sigurg_handler); sigurg = 1; }
01688 
01689       /** attach to incoming call "r" **/
01690 
01691       if( do_accept ){
01692          ns->io_mode = NI_INPUT_MODE ;
01693          ns->sd = tcp_listen( port ) ;                   /* set up to listen  */
01694          if( ns->sd < 0 ){                               /* error? must die!  */
01695            NI_free(ns->buf); NI_free(ns); return NULL;
01696          }
01697          ns->bad = TCP_WAIT_ACCEPT ;                     /* not connected yet */
01698          ii = tcp_readcheck(ns->sd,1) ;                  /* see if ready      */
01699          if( ii > 0 ){                                   /* if socket ready:  */
01700            jj = tcp_accept( ns->sd , NULL,&hend ) ;      /* accept connection */
01701            if( jj >= 0 ){                                /* if accept worked  */
01702              CLOSEDOWN( ns->sd ) ;                       /* close old socket  */
01703              NI_strncpy(ns->name,hend,256) ;             /* put IP into name  */
01704              NI_free(hend); ns->bad = 0; ns->sd = jj ;   /* and ready to go!  */
01705              fcntl( ns->sd, F_SETOWN, (int)getpid() ) ;  /* 02 Jan 2004 */
01706            }
01707          }
01708 
01709          add_open_stream(ns) ;       /* 02 Jan 2004 */
01710          ns->goodcheck_time = -99 ;  /* 23 Nov 2004 */
01711          return ns ;
01712       }
01713 
01714       /** place an outgoing call "w" **/
01715 
01716       if( do_create ){
01717         struct hostent *hostp ;
01718         ns->io_mode = NI_OUTPUT_MODE ;
01719         hostp = gethostbyname(host) ;                   /* lookup host on net */
01720         if( hostp == NULL ){                            /* fails? must die!   */
01721           NI_free(ns->buf); NI_free(ns); return NULL;
01722         }
01723         ns->sd  = tcp_connect( host , port ) ;          /* connect to host    */
01724         ns->bad = (ns->sd < 0) ? TCP_WAIT_CONNECT : 0 ; /* fails? must wait   */
01725         NI_strncpy(ns->name,host,256) ;                 /* save the host name */
01726         if( ns->sd >= 0 )
01727           fcntl( ns->sd, F_SETOWN, (int)getpid() ) ;    /* 02 Jan 2004 */
01728 
01729         add_open_stream(ns) ;   /* 02 Jan 2004 */
01730         ns->goodcheck_time = -99 ;  /* 23 Nov 2004 */
01731         return ns ;
01732       }
01733       return NULL ;  /* should never be reached */
01734    }
01735 
01736 #ifndef DONT_USE_SHM
01737    /*********************************************/
01738    /***** deal with shared memory transport *****/
01739 
01740    if( strncmp(name,"shm:",4) == 0 ){
01741       SHMioc *ioc ;
01742 
01743       if( *mode == 'a' ) mode = "w" ;
01744       ioc = SHM_init( name , mode ) ;  /* open segment */
01745       if( ioc == NULL ) return NULL ;  /* this is bad bad bad */
01746 
01747       /** initialize NI_stream_type output **/
01748 
01749       ns = NI_malloc(NI_stream_type, sizeof(NI_stream_type) ) ;
01750 
01751       ns->type     = NI_SHM_TYPE;    /* what kind is this? */
01752       ns->nbuf     = 0 ;             /* buffer is empty    */
01753       ns->npos     = 0 ;             /* scan starts at 0   */
01754       ns->io_mode  = do_create ? NI_OUTPUT_MODE
01755                                : NI_INPUT_MODE  ;
01756       ns->bad      = 0 ;
01757       ns->shmioc   = ioc ;
01758       ns->b64_numleft = 0 ;
01759 
01760       ns->buf      = NI_malloc(char, NI_BUFSIZE) ;
01761       ns->bufsize  = NI_BUFSIZE ;
01762 
01763       NI_strncpy( ns->name , name , 256 ) ;
01764 
01765       NI_strncpy(ns->orig_name,name,256) ;  /* 23 Aug 2002 */
01766 
01767       add_open_stream(ns) ;  /* 02 Jan 2004 */
01768       ns->goodcheck_time = -99 ;  /* 23 Nov 2004 */
01769       return ns ;
01770    }
01771 #endif /* DONT_USE_SHM */
01772 
01773    /**********************************/
01774    /***** deal with simple files *****/
01775 
01776    if( strncmp(name,"file:",5) == 0 ){
01777 
01778       char *fname = name+5 , *fmode ;
01779       FILE *fp ;
01780 
01781       if( NI_strlen(name) > 255 || NI_strlen(fname) < 1 ) return NULL ;
01782 
01783       if( *mode == 'a' ) fmode = "ab" ;
01784       else               fmode = do_create ? (char *)"wb" : (char *)"rb" ;
01785       fp = fopen( fname , fmode ) ;
01786 
01787       if( fp == NULL ) return NULL ;
01788 
01789       /** initialize NI_stream_type output **/
01790 
01791       ns = NI_malloc(NI_stream_type, sizeof(NI_stream_type) ) ;
01792 
01793       ns->type     = NI_FILE_TYPE;   /* what kind is this? */
01794       ns->nbuf     = 0 ;             /* buffer is empty    */
01795       ns->npos     = 0 ;             /* scan starts at 0   */
01796       ns->fp       = fp ;
01797       ns->io_mode  = do_create ? NI_OUTPUT_MODE
01798                                : NI_INPUT_MODE  ;
01799       ns->bad      = 0 ;
01800       ns->b64_numleft = 0 ;
01801 
01802       ns->bufsize  = do_create ? 16 : NI_BUFSIZE ;
01803       ns->buf      = NI_malloc(char, ns->bufsize) ;
01804 
01805       NI_strncpy( ns->name , fname , 256 ) ;
01806 
01807       NI_strncpy(ns->orig_name,name,256) ;  /* 23 Aug 2002 */
01808 
01809       if( ns->io_mode == NI_INPUT_MODE )     /* save the file size */
01810          ns->fsize = NI_filesize( fname ) ;  /* if we are reading  */
01811       else
01812          ns->fsize = -1 ;
01813 
01814       add_open_stream(ns) ;  /* 02 Jan 2004 */
01815       ns->goodcheck_time = -99 ;  /* 23 Nov 2004 */
01816       return ns ;
01817    }
01818 
01819    /********************************************************************/
01820    /***** fd: very similar to a file, but we don't have to open it *****/
01821 
01822         if( strncmp(name,"stdin:" ,6) == 0 ) name = "fd:0" ;  /* 25 Mar 2003 */
01823    else if( strncmp(name,"stdout:",7) == 0 ) name = "fd:1" ;
01824    else if( strncmp(name,"stderr:",7) == 0 ) name = "fd:2" ;
01825 
01826    if( strncmp(name,"fd:",3) == 0 ){
01827       int fd=-1 ; FILE *fp ;
01828 
01829       sscanf(name+3,"%d",&fd) ;
01830       if( fd < 0 ) return NULL ;   /* bad integer */
01831 
01832       switch( fd ){
01833         default:
01834           fp = fdopen( fd , do_create ? "wb" : "rb" ) ;
01835           if( fp == NULL ) return NULL ;
01836         break ;
01837 
01838         case 0:
01839           fp = stdin ;
01840           if( do_create ) return NULL ;
01841         break ;
01842 
01843         case 1:
01844           fp = stdout ;
01845           if( !do_create ) return NULL ;
01846         break ;
01847 
01848         case 2:
01849           fp = stderr ;
01850           if( !do_create ) return NULL ;
01851         break ;
01852       }
01853 
01854       /** initialize NI_stream_type output **/
01855 
01856       ns = NI_malloc(NI_stream_type, sizeof(NI_stream_type) ) ;
01857 
01858       ns->type     = NI_FD_TYPE;     /* what kind is this? */
01859       ns->nbuf     = 0 ;             /* buffer is empty    */
01860       ns->npos     = 0 ;             /* scan starts at 0   */
01861       ns->fp       = fp ;
01862       ns->io_mode  = do_create ? NI_OUTPUT_MODE
01863                                : NI_INPUT_MODE  ;
01864       ns->bad      = 0 ;
01865       ns->b64_numleft = 0 ;
01866 
01867       ns->bufsize  = do_create ? 16 : NI_BUFSIZE ;
01868       ns->buf      = NI_malloc(char, ns->bufsize) ;
01869 
01870       NI_strncpy( ns->name , name , 256 ) ;
01871 
01872       NI_strncpy(ns->orig_name,name,256) ;  /* 23 Aug 2002 */
01873 
01874       ns->fsize = -1 ;
01875 
01876       add_open_stream(ns) ;  /* 02 Jan 2004 */
01877       ns->goodcheck_time = -99 ;  /* 23 Nov 2004 */
01878       return ns ;
01879    }
01880 
01881    /*********************************/
01882    /***** str: string array I/O *****/
01883 
01884    if( strncmp(name,"str:",4) == 0 ){
01885 
01886       int nn = NI_strlen(name+4) ;  /* may be 0 */
01887 
01888       ns = NI_malloc(NI_stream_type, sizeof(NI_stream_type) ) ;
01889 
01890       ns->type     = NI_STRING_TYPE; /* what kind is this? */
01891       ns->io_mode  = do_create ? NI_OUTPUT_MODE
01892                                : NI_INPUT_MODE  ;
01893       ns->bad      = 0 ;
01894       ns->npos     = 0 ;             /* scan starts at 0   */
01895       ns->b64_numleft = 0 ;
01896 
01897       /* Note that bufsize == nbuf+1 for str:
01898          This is because we don't count the terminal NUL
01899          in nbuf (number of readable bytes),
01900          but do count it in bufsize (size of the buf array) */
01901 
01902       if( do_accept ){               /* read from stuff after str: */
01903          ns->nbuf    = nn ;
01904          ns->bufsize = nn+1 ;
01905          ns->buf     = NI_malloc(char, nn+1) ;
01906          strcpy(ns->buf,name+4) ;
01907       } else {                       /* write to a string */
01908          ns->nbuf    = 0 ;
01909          ns->bufsize = 1 ;
01910          ns->buf     = NI_malloc(char, 1) ; /* 1 byte set to zero */
01911       }
01912 
01913       strcpy( ns->name , "ElvisHasLeftTheBuilding" ) ;
01914 
01915       NI_strncpy(ns->orig_name,name,256) ;  /* 23 Aug 2002 */
01916 
01917       add_open_stream(ns) ;  /* 02 Jan 2004 */
01918       ns->goodcheck_time = -99 ;  /* 23 Nov 2004 */
01919       return ns ;
01920    }
01921 
01922    /*********************************/
01923    /***** http:// or ftp:// I/O *****/
01924 
01925    if( strncmp(name,"http://",7) == 0 || strncmp(name,"ftp://",6) == 0 ){
01926       int nn ;
01927       char *data=NULL ;
01928 
01929       if( do_create ) return NULL ;                  /* bad */
01930 
01931       nn = NI_read_URL( name , &data ) ;
01932 
01933       if( data == NULL || nn <= 4 ){                 /* bad */
01934          NI_free(data); return NULL;
01935       }
01936 
01937       ns = NI_malloc(NI_stream_type, sizeof(NI_stream_type) ) ;
01938 
01939       ns->type     = NI_REMOTE_TYPE; /* what kind is this? */
01940       ns->io_mode  = NI_INPUT_MODE  ;
01941       ns->bad      = 0 ;
01942       ns->npos     = 0 ;             /* scan starts at 0   */
01943       ns->nbuf     = nn ;
01944       ns->bufsize  = nn ;
01945       ns->buf      = data ;
01946       ns->b64_numleft = 0 ;
01947 
01948       NI_strncpy( ns->name , name , 256 ) ;
01949 
01950       NI_strncpy(ns->orig_name,name,256) ;  /* 23 Aug 2002 */
01951 
01952       add_open_stream(ns) ;  /* 02 Jan 2004 */
01953       ns->goodcheck_time = -99 ;  /* 23 Nov 2004 */
01954       return ns ;
01955    }
01956 
01957    return NULL ;  /* should never be reached */
01958 }

int NI_stream_read NI_stream_type   ns,
char *    buffer,
int    nbytes
 

Read up to nbytes of data from the NI_stream, into buffer.

Returns the number of bytes actually read. For both the case of sockets and files, this may be less than nbytes (may even be 0). If an error occurs and no data is read, -1 is returned.

For tcp: streams, if no data is available, this function will wait until something can be read. If this behavior is undesirable, then you should use NI_stream_readcheck() before calling this function in order to see if any data is available.

For shm: streams, will return immediately if no data is available.

For file: streams, this function simply tries to read from the file. Whether or not it succeeds, it will return immediately. It should never return -1; if it returns 0, this means end-of-file. ---------------------------------------------------------------------------

Definition at line 2783 of file niml_stream.c.

References NI_stream_type::bad, NI_stream_type::buf, NI_stream_type::fp, NI_stream_type::io_mode, NI_stream_type::nbuf, NI_dpr(), NI_FD_TYPE, NI_FILE_TYPE, NI_OUTPUT_MODE, NI_REMOTE_TYPE, NI_SHM_TYPE, NI_stream_goodcheck(), NI_STRING_TYPE, NI_TCP_TYPE, NI_stream_type::npos, PERROR, NI_stream_type::sd, SHM_recv(), NI_stream_type::shmioc, tcp_readcheck(), tcp_recv, and NI_stream_type::type.

Referenced by main(), NI_stream_fillbuf(), and read_URL_http().

02784 {
02785    int ii ;
02786 
02787    /** check for reasonable inputs **/
02788 
02789    if( ns == NULL || ns->bad || buffer == NULL || nbytes < 0 ) return -1 ;
02790 
02791    if( nbytes == 0 ) return 0 ;
02792 
02793 #ifdef NIML_DEBUG
02794 NI_dpr("ENTER NI_stream_read\n") ;
02795 #endif
02796 
02797    switch( ns->type ){
02798 
02799 #ifndef DONT_USE_SHM
02800      case NI_SHM_TYPE:
02801        return SHM_recv( ns->shmioc , buffer , nbytes ) ;
02802 #endif
02803 
02804      /** tcp: just use recv **/
02805 
02806      case NI_TCP_TYPE:
02807        ii = NI_stream_goodcheck(ns,1) ; if( ii != 1 ) return ii ;
02808 #if 0
02809        /* wait 'till we can read fer shur */
02810        do{ ii=tcp_readcheck(ns->sd,1); } while( ii==0 ) ;
02811        if( ii < 0 ) return -1 ;
02812 #endif
02813        errno = 0 ;
02814        ii = tcp_recv( ns->sd , buffer , nbytes , 0 ) ;
02815        if( ii == -1 || errno != 0 ) PERROR("NI_stream_read(recv)") ;
02816 #ifdef NIML_DEBUG
02817 NI_dpr("  tcp: got %d/%d bytes ***\n",ii,nbytes) ;
02818 #endif
02819        return ii ;
02820 
02821      /** file: just use fread **/
02822 
02823      case NI_FD_TYPE:
02824      case NI_FILE_TYPE:
02825        if( ns->fp == NULL || ns->io_mode == NI_OUTPUT_MODE ) return -1 ;
02826        ii = fread( buffer , 1 , nbytes , ns->fp ) ;
02827        return ii ;
02828 
02829      /** str: copy bytes out of the buffer string **/
02830 
02831      case NI_REMOTE_TYPE:
02832      case NI_STRING_TYPE:
02833        if( ns->io_mode == NI_OUTPUT_MODE ) return -1 ; /* bad stream */
02834        ii = ns->nbuf - ns->npos ;                      /* how much is left */
02835        if( ii <= 0                       ) return -1 ; /* no data left */
02836        if( ii > nbytes ) ii = nbytes ;                 /* amount to copy */
02837        memcpy( buffer , ns->buf+ns->npos , ii ) ;      /* copy it */
02838        ns->npos += ii ;                                /* advance position */
02839        return ii ;
02840    }
02841 
02842    return -1 ;  /* should not be reached */
02843 }

int NI_stream_readable NI_stream_type   ns
 

Return 1 if it is legal to read from this stream, 0 if it isn't. This doesn't say anything about if it is practical to read at this moment; for that, use NI_stream_readcheck(). -------------------------------------------------------------------------

Definition at line 2126 of file niml_stream.c.

References NI_stream_type::bad, NI_stream_type::io_mode, MARKED_FOR_DEATH, NI_INPUT_MODE, NI_SHM_TYPE, NI_TCP_TYPE, and NI_stream_type::type.

Referenced by NI_read_columns(), NI_stream_readbuf(), and NI_stream_readbuf64().

02127 {
02128    if( ns == NULL || ns->bad == MARKED_FOR_DEATH ) return 0 ;
02129    if( ns->type == NI_TCP_TYPE || ns->type == NI_SHM_TYPE ) return 1 ;
02130    return (ns->io_mode == NI_INPUT_MODE) ;
02131 }

int NI_stream_readbuf NI_stream_type   ns,
char *    buffer,
int    nbytes
 

Buffered read from a NI_stream. Unlike NI_stream_read(), will try to read all nbytes of data, waiting if necessary. Also works through the internal buffer, rather than directly to the stream.

Return value is number of bytes read. May be less than nbytes if the stream closed (or was used up) before nbytes of data was read. Will return -1 if something is rotten. -------------------------------------------------------------------------

Definition at line 2937 of file niml_stream.c.

References NI_stream_type::buf, NI_stream_type::bufsize, MIN, NI_stream_type::nbuf, NI_REMOTE_TYPE, NI_reset_buffer(), NI_stream_fillbuf(), NI_stream_readable(), NI_STRING_TYPE, NI_stream_type::npos, and NI_stream_type::type.

Referenced by NI_binary_to_val(), and NI_read_columns().

02938 {
02939    int ii , jj , bs , nout=0 ;
02940 
02941    /** check for reasonable inputs **/
02942 
02943    if( nbytes  == 0                        ) return  0; /* that was real easy */
02944    if( buffer  == NULL || nbytes      <  0 ) return -1; /* stupid caller */
02945    if( ns->buf == NULL || ns->bufsize == 0 ) return -1; /* shouldn't happen */
02946    if( !NI_stream_readable(ns) )             return -1; /* stupid stream */
02947 
02948    /* see how many unused bytes are already in the input buffer */
02949 
02950    ii = ns->nbuf - ns->npos ;
02951 
02952    if( ii >= nbytes ){    /* have all the data we need already */
02953      memcpy( buffer , ns->buf + ns->npos , nbytes ) ;
02954      ns->npos += nbytes ;
02955      if( ns->npos == ns->nbuf ) ns->nbuf = ns->npos = 0 ;  /* buffer used up */
02956      return nbytes ;
02957    }
02958 
02959    /* copy what data we already have, if any */
02960 
02961    if( ii > 0 ){
02962      memcpy( buffer , ns->buf + ns->npos , ii ) ; nout = ii ;
02963    }
02964    ns->nbuf = ns->npos = 0 ;                               /* buffer used up */
02965 
02966    /* input streams with fixed length buffers ==> can't do no more */
02967 
02968    if( ns->type == NI_REMOTE_TYPE || ns->type == NI_STRING_TYPE )
02969      return (nout > 0) ? nout : -1 ;
02970 
02971    /* otherwise, fill the buffer and try again */
02972 
02973    bs = ns->bufsize ;
02974 
02975    while( nout < nbytes ){
02976 
02977      jj = MIN( bs , nbytes-nout ) ;         /* how much to try to read */
02978      ii = NI_stream_fillbuf( ns,jj,1666 ) ; /* read into stream buffer */
02979 
02980      if( ii > 0 ){                          /* got something */
02981        ii = ns->nbuf ;                      /* how much now in buffer */
02982        if( ii > nbytes-nout ) ii = nbytes-nout ;
02983        memcpy( buffer+nout , ns->buf , ii ) ; nout += ii ;
02984        ns->npos += ii ; NI_reset_buffer( ns ) ;
02985      } else {                               /* got nothing */
02986        break ;                              /* so quit */
02987      }
02988    }
02989 
02990    if( nout == 0 && ii < 0 ) nout = -1 ;    /* no data and an I/O error */
02991    return nout ;
02992 }

int NI_stream_readbuf64 NI_stream_type   ns,
char *    buffer,
int    nbytes
 

Buffered read from a NI_stream, like NI_stream_readbuf, but also:

  • Converts from Base64 to binary 'on the fly'.
  • Will stop at a '<'.
Return value is number of bytes put into the buffer. May be less than nbytes if the stream closed (or was used up, or hit a '<') before nbytes of data was read. Will return -1 if something is rotten. -------------------------------------------------------------------------

Definition at line 3004 of file niml_stream.c.

References a, B64_decode4, B64_decode_count, B64_goodchar, NI_stream_type::b64_left, NI_stream_type::b64_numleft, NI_stream_type::buf, NI_stream_type::bufsize, c, load_decode_table(), NI_stream_type::nbuf, NI_reset_buffer(), NI_stream_fillbuf(), NI_stream_readable(), and NI_stream_type::npos.

Referenced by NI_base64_to_val(), and NI_read_columns().

03005 {
03006    int ii , jj , bs , nout=0 ;
03007    byte a ,b ,c  , w,x,y,z ;
03008    byte ag,bg,cg ;
03009    int num_reread , bpos ;
03010 
03011    /** check for reasonable inputs **/
03012 
03013    if( nbytes  == 0                        ) return  0; /* that was real easy */
03014    if( buffer  == NULL || nbytes      <  0 ) return -1; /* stupid caller */
03015    if( ns->buf == NULL || ns->bufsize == 0 ) return -1; /* shouldn't happen */
03016    if( !NI_stream_readable(ns) )             return -1; /* stupid stream */
03017 
03018    /* are there decoded leftover bytes from a previous call?
03019       if so, use them up first */
03020 
03021    if( ns->b64_numleft > 0 ){
03022 
03023      if( ns->b64_numleft >= nbytes ){    /* have enough leftovers for all! */
03024        memcpy( buffer , ns->b64_left , nbytes ) ;
03025        ns->b64_numleft -= nbytes ;
03026        if( ns->b64_numleft > 0 )   /* must shift remaining leftovers down */
03027          memmove( ns->b64_left , ns->b64_left + nbytes , ns->b64_numleft ) ;
03028        return nbytes ;                                 /* done done done! */
03029      }
03030 
03031      /* if here, have a few bytes leftover, but not enough */
03032 
03033      memcpy( buffer , ns->b64_left , ns->b64_numleft ) ;
03034      nout            = ns->b64_numleft ;   /* how many so far */
03035      ns->b64_numleft = 0 ;                 /* have none left now */
03036    }
03037 
03038    /* now need to decode some bytes from the input stream;
03039       this is done 4 input bytes at a time,
03040       which are decoded to 3 output bytes                   */
03041 
03042    load_decode_table() ;   /* prepare for Base64 decoding */
03043 
03044    /** loopback point for reading more data from stream into internal buffer **/
03045 
03046    num_reread = 0 ;
03047  Base64Reread:
03048    ag = bg = cg = 0 ;
03049    num_reread++ ; if( num_reread > 5 ) goto Base64Done ; /* done waiting! */
03050 
03051    /* read more data into buffer, if needed */
03052 
03053    if( num_reread > 1 || ns->nbuf - ns->npos < 4 ){
03054      NI_reset_buffer(ns) ;          /* discard used up data => ns->npos==0 */
03055      ii = 5 - ns->nbuf ; if( ii <= 1 ) ii = 2 ;
03056      ii = NI_stream_fillbuf( ns , ii , 1666 ) ;
03057      if( ns->nbuf < 4 ) goto Base64Done ;     /* can't get no satisfaction! */
03058    }
03059 
03060    /*** Copy valid Base64 bytes out of buffer (skipping others),
03061         converting them to binary as we get full quads,
03062         putting the results into buffer.
03063 
03064         Exit loop if we hit a '<' character (end of NIML element),
03065         or hit an '=' character (end of Base64 data stream).
03066 
03067         Jump back to Base64Reread (above) if we run out of data in the
03068         buffer before we fulfill the caller's demand for nbytes of output. ***/
03069 
03070    while( 1 ){
03071      ag = bg = cg = 0 ;
03072      bpos = ns->npos ;    /* scan forward in buffer using bpos */
03073 
03074      /* get next valid Base64 character into w;
03075         skip whitespaces and other non-Base64 stuff;
03076         if we hit the end token '<' first, quit;
03077         if we hit the end of the buffer first, need more data */
03078 
03079      w = ns->buf[bpos++] ;
03080      while( !B64_goodchar(w) && w != '<' && bpos < ns->nbuf )
03081        w = ns->buf[bpos++] ;
03082      ns->npos = bpos-1 ;  /** if we have to reread, will start here, at w **/
03083      if( w == '<' ) goto Base64Done;
03084      if( bpos == ns->nbuf ) goto Base64Reread;  /* not enuf data yet */
03085 
03086      /* repeat to fill x */
03087 
03088      x = ns->buf[bpos++] ;
03089      while( !B64_goodchar(x) && x != '<' && bpos < ns->nbuf )
03090        x = ns->buf[bpos++] ;
03091      if( x == '<' ){ ns->npos = bpos-1; goto Base64Done; }
03092      if( bpos == ns->nbuf ) goto Base64Reread;
03093 
03094      /* repeat to fill y */
03095 
03096      y = ns->buf[bpos++] ;
03097      while( !B64_goodchar(y) && y != '<' && bpos < ns->nbuf )
03098        y = ns->buf[bpos++] ;
03099      if( y == '<' ){ ns->npos = bpos-1; goto Base64Done; }
03100      if( bpos == ns->nbuf ) goto Base64Reread;
03101 
03102      /* repeat to fill z */
03103 
03104      z = ns->buf[bpos++] ;
03105      while( !B64_goodchar(z) && z != '<' && bpos < ns->nbuf )
03106        z = ns->buf[bpos++] ;
03107      if( z == '<' ){ ns->npos = bpos-1; goto Base64Done; }
03108 
03109      /* at this point, have w,x,y,z to decode */
03110 
03111      ns->npos = bpos ;  /* scan continues at next place in buffer */
03112 
03113      B64_decode4(w,x,y,z,a,b,c) ;  /* decode 4 bytes into 3 */
03114 
03115      if( z == '=' ){                        /* got to the end of Base64? */
03116        int nn = B64_decode_count(w,x,y,z) ; /* see how many bytes to save */
03117        ag = (nn > 0) ;  /* a byte is good? */
03118        bg = (nn > 1) ;  /* b byte is good? */
03119        cg = 0        ;  /* c byte is bad!! */
03120 
03121        /* save good bytes into output buffer;
03122           if we reach end of the required number of bytes, we're done */
03123 
03124        if( ag ){ buffer[nout++]=a; ag=0; if(nout >= nbytes) goto Base64Done; }
03125        if( bg ){ buffer[nout++]=b; bg=0; if(nout >= nbytes) goto Base64Done; }
03126        goto Base64Done ;
03127      }
03128 
03129      /* not at the end of Base64 =>
03130         save bytes, and skip out if we fill up the output array */
03131 
03132      ag = bg = cg = 1 ;  /* all 3 bytes are good */
03133      buffer[nout++]=a; ag=0; if(nout >= nbytes) goto Base64Done;
03134      buffer[nout++]=b; bg=0; if(nout >= nbytes) goto Base64Done;
03135      buffer[nout++]=c; cg=0; if(nout >= nbytes) goto Base64Done;
03136 
03137      /* now, loop back to decode the next 4 bytes;
03138         BUT, if we don't have at least 4 bytes in the input buffer,
03139              must do a re-read first!                               */
03140 
03141      num_reread = 1 ; /* finished at least 1 quad ==> reset penalty clock */
03142      if( ns->nbuf - ns->npos < 4 ) goto Base64Reread ;
03143 
03144    } /* end of while(1) loop */
03145 
03146   /* At this point:
03147       have finished reading and decoding,
03148       have nout bytes in output buffer,
03149       and might have some good bytes left that need to be saved */
03150 
03151 Base64Done:
03152    ns->b64_numleft = 0 ;
03153    if( ag ) ns->b64_left[ ns->b64_numleft++ ] = a ;
03154    if( bg ) ns->b64_left[ ns->b64_numleft++ ] = b ;
03155    if( cg ) ns->b64_left[ ns->b64_numleft++ ] = c ;
03156 
03157    return nout ;
03158 }

int NI_stream_readcheck NI_stream_type   ns,
int    msec
 

Check if the NI_stream is ready to have data read out of it.

If not, the routine will wait up to msec milliseconds for data to be available. If msec < 0, this routine will wait nearly forever. The return value is 1 if data is ready, 0 if not; -1 will be returned if some unrecoverable error is detected:

  • tcp: the socket connection was dropped
  • shm: the other process died or detached the segment
  • file: you have reached the end of the file, and are still trying to read.
Also see NI_stream_hasinput() and NI_stream_readbuf(). -----------------------------------------------------------------------------

Definition at line 2512 of file niml_stream.c.

References NI_stream_type::bad, NI_stream_type::fp, NI_stream_type::fsize, NI_stream_type::io_mode, MARKED_FOR_DEATH, NI_stream_type::nbuf, NI_FD_TYPE, NI_FILE_TYPE, NI_OUTPUT_MODE, NI_REMOTE_TYPE, NI_SHM_TYPE, NI_stream_goodcheck(), NI_STRING_TYPE, NI_TCP_TYPE, NI_stream_type::npos, NI_stream_type::sd, SHM_readcheck(), NI_stream_type::shmioc, tcp_alivecheck(), tcp_readcheck(), and NI_stream_type::type.

Referenced by main(), NI_read_element(), NI_stream_fillbuf(), NI_stream_goodcheck(), NI_stream_hasinput(), open_URL_hpf(), read_URL_http(), and SUMA_niml_workproc().

02513 {
02514    int ii ;
02515 
02516    if( ns == NULL || ns->bad == MARKED_FOR_DEATH ) return -1 ;
02517 
02518    switch( ns->type ){
02519 
02520 #ifndef DONT_USE_SHM
02521       case NI_SHM_TYPE:
02522         ii = SHM_readcheck( ns->shmioc , msec ) ;
02523         if( ii > 0 ) ii = 1 ;
02524         return ii ;
02525 #endif
02526 
02527       /** tcp: ==> uses the Unix "select" mechanism **/
02528 
02529       case NI_TCP_TYPE:
02530         ii = NI_stream_goodcheck(ns,0) ;       /* check if it is connected */
02531         if( ii == -1 ) return -1 ;             /* some error */
02532         if( ii == 0  ){                        /* not good yet */
02533           ii = NI_stream_goodcheck(ns,msec) ;  /* so wait for it to get good */
02534           if( ii != 1 ) return ii ;            /* if still not good, exit */
02535         }
02536         ii = tcp_alivecheck( ns->sd ) ;        /* see if it is still open  */
02537         if( !ii ) return -1 ;                  /* if not open, error exit  */
02538         ii = tcp_readcheck( ns->sd , msec ) ;  /* see if any data is there */
02539         return ii ;
02540 
02541       /** fd: ==> use select, as in tcp: **/
02542 
02543       case NI_FD_TYPE:
02544         ii = tcp_readcheck( fileno(ns->fp) , msec ) ;
02545         return ii ;
02546 
02547       /** file: ==> check current file position and length of file **/
02548 
02549       case NI_FILE_TYPE:{
02550          long f_len , f_pos ;
02551 
02552          if( ns->fp == NULL                ||
02553              ns->io_mode == NI_OUTPUT_MODE   ) return -1 ; /* never? */
02554 
02555          f_len = ns->fsize ;               /* length of file      */
02556          if( f_len < 0 ) return -1 ;       /* file not found (?)  */
02557 
02558          f_pos = ftell( ns->fp ) ;         /* where are we now?   */
02559          if( f_pos < 0 ) return -1 ;       /* should never happen */
02560 
02561          return (f_pos < f_len) ? 1 : -1 ; /* is good or bad, but */
02562                                            /* never just neutral  */
02563       }
02564 
02565       /** str: ==> check current buffer position **/
02566 
02567       case NI_REMOTE_TYPE:
02568       case NI_STRING_TYPE:{
02569          if( ns->io_mode == NI_OUTPUT_MODE ) return -1 ; /* never? */
02570 
02571          return (ns->npos < ns->nbuf) ? 1 : -1 ;  /* is data left? */
02572       }
02573    }
02574 
02575    return -1 ;  /* should never happen */
02576 }

int NI_stream_reopen NI_stream_type   ns,
char *    nname
 

Re-open a NI_stream on a different channel. This is only possible if the input original stream (ns) is tcp: type.

  • The new stream (nname) can be of the form "tcp::port", which will reopen the stream to the same host on the new port.
  • Or the new stream can be of the form "shm:key:size1+size2", but only if the existing stream was opened to localhost.
  • The main purpose of this function is to let a process connect to a "standard" port on a server process, then tell the server to reopen on another port (or to use shm:). In this way, the standard port can be freed up quickly for reuse.
If necessary, this function will wait until the connection to the other program is ready. Then it will exchange the information with the other program about changing things, and will again wait until the new connection is established. Assuming all goes well, then when this function returns, the input stream (ns) will be modified so that it now refers to the new connection.

Return value is 1 if things are OK, 0 if not. Failure can occur because:

  • Input ns or nname was badly formed.
  • You tried to open shm: when the input tcp: stream was not to localhost.
  • The input tcp: stream can't become connected within 10 seconds. -----------------------------------------------------------------------------

Definition at line 1986 of file niml_stream.c.

References add_open_stream(), NI_stream_type::bad, getenv(), MARKED_FOR_DEATH, NI_stream_type::name, NI_dpr(), NI_free, NI_stream_close_keep(), NI_stream_closenow(), NI_stream_goodcheck(), NI_stream_open(), NI_stream_write(), NI_strncpy(), NI_TCP_TYPE, NI_stream_type::orig_name, NI_stream_type::port, remove_open_stream(), and NI_stream_type::type.

Referenced by DWI_Open_NIML_stream(), main(), and SUMA_niml_call().

01987 {
01988    NI_stream_type *nsnew ;
01989    int typ_new=0 , port_new=0 , jj,kk ;
01990    char msg[1024] ;
01991 
01992    /* check inputs for sanity */
01993 
01994    if( ns == NULL || ns->type != NI_TCP_TYPE ) return 0 ; /* bad input stream */
01995    if( ns->bad == MARKED_FOR_DEATH )           return 0 ; /* really bad */
01996    if( nname == NULL || nname[0] == '\0' )     return 0 ; /* bad new name */
01997 
01998    if( strncmp(nname,"tcp::",5) == 0 ){                   /* new is tcp:? */
01999       typ_new = NI_TCP_TYPE ;
02000       port_new = strtol(nname+5,NULL,10) ;
02001       if( port_new <= 0        ) return 0 ;               /* bad new port */
02002       if( port_new == ns->port ) return 1 ;               /* same as before? */
02003 #ifndef DONT_USE_SHM
02004    } else if( strncmp(nname,"shm:" ,4) == 0 ){            /* new is shm:? */
02005       char *eee = getenv("AFNI_NOSHM") ;                  /* 06 Jun 2003 */
02006       if( eee != NULL && toupper(*eee) == 'Y' ){          /* shm: is disabled */
02007         fprintf(stderr,"** NI_stream_reopen: shm is disabled\n");
02008         return 0 ;
02009       }
02010       if( strstr(ns->orig_name,":localhost:") == NULL ){  /* can't do shm: */
02011         fprintf(stderr,"** NI_stream_reopen: shm not localhost!\n");  /* but on localhost */
02012         return 0 ;
02013       }
02014 #endif
02015    } else {
02016      fprintf(stderr,"** NI_stream_reopen: illegal input '%s'\n",nname);
02017      return 0 ;                                           /* bad new name */
02018    }
02019 
02020 #ifdef NIML_DEBUG
02021 NI_dpr("NI_stream_reopen: waiting for original connection to be good\n") ;
02022 #endif
02023 
02024    /* wait for existing stream to be connected */
02025 
02026    for( kk=0 ; kk < 10 ; kk++ ){
02027      jj = NI_stream_goodcheck( ns , 1000 ) ;   /* wait 1 sec */
02028      if( jj > 0 ) break;                       /* good :-) */
02029      if( kk == 0 )
02030        fprintf(stderr,"++ NI_stream_reopen: Waiting for socket connection") ;
02031      else
02032        fprintf(stderr,".") ;
02033    }
02034    if( kk == 10 ){ fprintf(stderr," *Failed*\n"); return 0; }
02035    if( kk >  0  )  fprintf(stderr," *Good*\n") ;
02036 
02037    /* open new stream as the writer */
02038 
02039    if( strncmp(nname,"tcp::",5) == 0 ){
02040      sprintf(msg,"tcp:%s:%d",ns->name,port_new) ;  /* old hostname */
02041    }
02042 #ifndef DONT_USE_SHM
02043    else if( strncmp(nname,"shm:" ,4) == 0 ){
02044      NI_strncpy(msg,nname,1024) ;
02045    }
02046 #endif
02047 
02048 #ifdef NIML_DEBUG
02049 NI_dpr("NI_stream_reopen: opening new stream %s\n",msg) ;
02050 #endif
02051 
02052    nsnew = NI_stream_open( msg, "w" ) ;
02053    if( nsnew == NULL ) return 0 ;             /* bad :-( */
02054 
02055    /* send message on old stream to other
02056       program, telling it to open the new stream */
02057 
02058    sprintf(msg,"<?ni_do ni_verb='reopen_this' ni_object='%s' ?>\n",nname) ;
02059    kk = strlen(msg) ;
02060 
02061 #ifdef NIML_DEBUG
02062 NI_dpr("NI_stream_reopen: sending message %s",msg) ;
02063 #endif
02064 
02065    jj = NI_stream_write( ns , msg , kk ) ;
02066    if( jj < kk ){
02067      NI_stream_closenow(nsnew) ; return 0 ;  /* bad write! */
02068    }
02069 
02070    /* now wait for other program to open the new stream */
02071 
02072 #ifdef NIML_DEBUG
02073 NI_dpr("NI_stream_reopen: waiting for new stream to be good\n") ;
02074 #endif
02075 
02076    jj = NI_stream_goodcheck( nsnew , 5000 ) ;  /* wait up to 5 sec */
02077    if( jj <= 0 ){
02078      NI_stream_closenow(nsnew) ; return 0 ;  /* never got good */
02079    }
02080 
02081    /* if here, new stream is ready:
02082       close the old stream and replace its
02083       contents with the contents of the new stream */
02084 
02085 #ifdef NIML_DEBUG
02086 NI_dpr("NI_stream_reopen: closing old stream\n") ;
02087 #endif
02088 
02089    NI_stream_close_keep(ns,0) ;   /* will be removed from open streams list */
02090 
02091    *ns = *nsnew ;
02092 
02093    /* 10 Jun 2005: at this point, nsnew is in the open streams list,
02094                    but the pointer nsnew is about to die, and so we
02095                    must munge the open streams list around now to
02096                    make sure that nsnew is removed and ns is re-added! */
02097 
02098    remove_open_stream(nsnew) ; NI_free(nsnew) ; add_open_stream(ns) ;
02099 
02100    return 1 ; /* :-) */
02101 }

void NI_stream_seek NI_stream_type   ns,
int    offset,
int    whence
 

Seek file: stream to a specific offset location.

  • whence is one of SEEK_SET, SEEK_CUR, SEEK_END (cf. "man fseek").
  • Also clears the stream buffer. -------------------------------------------------------------------------

Definition at line 2109 of file niml_stream.c.

References NI_stream_type::bad, NI_stream_type::fp, MARKED_FOR_DEATH, NI_stream_type::nbuf, NI_FILE_TYPE, NI_stream_type::npos, offset, and NI_stream_type::type.

02110 {
02111    if( ns          == NULL             ||
02112        ns->bad     == MARKED_FOR_DEATH ||
02113        ns->type    != NI_FILE_TYPE     ||
02114        ns->fp      == NULL               ) return ;
02115 
02116    fseek( ns->fp , offset , whence ) ;   /* seek file */
02117    ns->nbuf = ns->npos = 0 ;             /* clear buffer */
02118 }

void NI_stream_setbuf NI_stream_type   ns,
char *    str
 

Reset the input string buffer for a NI_stream of str: type. If the input is not a "r" str: stream, then nothing happens. Otherwise, the current contents of the buffer are discarded, and the buffer is replaced with a copy of the input string. -------------------------------------------------------------------------

Definition at line 2238 of file niml_stream.c.

References NI_stream_type::bad, NI_stream_type::buf, NI_stream_type::bufsize, NI_stream_type::io_mode, MARKED_FOR_DEATH, NI_stream_type::nbuf, NI_free, NI_INPUT_MODE, NI_malloc, NI_STRING_TYPE, NI_strlen(), NI_stream_type::npos, and NI_stream_type::type.

Referenced by Dtable_from_nimlstring(), and THD_open_nifti().

02239 {
02240    int nn ;
02241 
02242    if( ns          == NULL             ||
02243        ns->type    != NI_STRING_TYPE   ||
02244        ns->io_mode != NI_INPUT_MODE    ||
02245        str         == NULL             ||
02246        ns->bad     == MARKED_FOR_DEATH   ) return ;  /* bad inputs */
02247 
02248    NI_free(ns->buf) ;               /* take out the trash */
02249    nn = NI_strlen(str) ;            /* size of new buffer string */
02250    ns->nbuf    = nn ;               /* set num char in new buffer */
02251    ns->npos    = 0  ;               /* reset scan position */
02252    ns->bufsize = nn+1 ;             /* allow space for NUL byte */
02253    ns->buf     = NI_malloc(char, nn+1) ;  /* and make the buffer */
02254    strcpy(ns->buf,str) ;            /* and set its contents */
02255    return ;
02256 }

int NI_stream_setbufsize NI_stream_type   ns,
int    bs
 

Alter the input buffer size for a NI_stream.

  • Only works for tcp: & shm: streams, and for "r" file: & fd: streams.
  • Return value is 1 if it worked OK, -1 if it didn't.
  • NI_realloc() is used, so buffer contents aren't affected (if the size is increased!). -------------------------------------------------------------------------

Definition at line 2165 of file niml_stream.c.

References NI_stream_type::bad, NI_stream_type::buf, NI_stream_type::bufsize, NI_stream_type::io_mode, MARKED_FOR_DEATH, NI_stream_type::nbuf, NI_FD_TYPE, NI_FILE_TYPE, NI_INPUT_MODE, NI_realloc, NI_SHM_TYPE, NI_STRING_TYPE, NI_TCP_TYPE, and NI_stream_type::type.

Referenced by AFNI_niml_workproc(), and THD_read_niml_atr().

02166 {
02167    char *qbuf ;
02168    if( ns       == NULL             ||
02169        ns->type == NI_STRING_TYPE   ||
02170        ns->bad  == MARKED_FOR_DEATH ||
02171        bs       <  666              ||
02172        bs       <  ns->nbuf           ) return -1 ;  /* bad inputs */
02173 
02174    if( !(  ns->type == NI_TCP_TYPE  || ns->type    == NI_SHM_TYPE    ||
02175           (ns->type == NI_FILE_TYPE && ns->io_mode == NI_INPUT_MODE) ||
02176           (ns->type == NI_FD_TYPE   && ns->io_mode == NI_INPUT_MODE)   ) )
02177     return -1 ;
02178 
02179    qbuf = NI_realloc( ns->buf , char , bs ) ;
02180    if( qbuf == NULL ) return -1 ;         /* this is bad */
02181    ns->buf     = qbuf ;
02182    ns->bufsize = bs ;
02183    return 1 ;
02184 }

int NI_stream_write NI_stream_type   ns,
char *    buffer,
int    nbytes
 

Send nbytes of data from buffer down the NI_stream.

Return value is the number of bytes actually sent, or is -1 if some error occurs (which means that the NI_stream is bad). If 0 is returned, this means you tried to write to something that is temporarily unavailable.

  • tcp: We use blocking sends, so that all the data should be sent properly unless the connection to the other end fails for some reason (e.g., the planet explodes in a fiery cataclysm of annihilation).
  • shm: We also block until everything can be written, even if it requires filling the shared memory buffer many times and waiting for the reading process to empty it many times.
  • file: Everything should be written, unless the filesystem fills up. If nothing at all gets written, -1 is returned.
  • str: Everything will be written, or the program will crash. Do not include the NUL byte at the end of the string in the nbytes count. ------------------------------------------------------------------------------

Definition at line 2674 of file niml_stream.c.

References NI_stream_type::bad, NI_stream_type::buf, NI_stream_type::bufsize, NI_stream_type::fp, MARKED_FOR_DEATH, NI_stream_type::nbuf, NI_dpr(), NI_FD_TYPE, NI_FILE_TYPE, NI_realloc, NI_REMOTE_TYPE, NI_SHM_TYPE, NI_stream_writecheck(), NI_STRING_TYPE, NI_TCP_TYPE, nosigpipe, PERROR, NI_stream_type::sd, SHM_sendall(), NI_stream_type::shmioc, tcp_send, tcp_writecheck(), and NI_stream_type::type.

Referenced by AFNI_serverlog(), main(), NI_stream_reopen(), NI_stream_writestring(), NI_write_columns(), NI_write_element(), and open_URL_hpf().

02675 {
02676    int ii , nsent ;
02677 
02678    /** check for reasonable inputs **/
02679 
02680    if( ns     == NULL || ns->bad    ||
02681        buffer == NULL || nbytes < 0 || ns->bad == MARKED_FOR_DEATH ) return -1;
02682 
02683    if( nbytes == 0 ) return 0 ;  /* that was easy */
02684 
02685 #ifdef NIML_DEBUG
02686 NI_dpr("ENTER NI_stream_write\n") ;
02687 #endif
02688 
02689    if( ns->type != NI_TCP_TYPE ){
02690      ii = NI_stream_writecheck(ns,66) ; /* check if stream is still OK */
02691      if( ii < 0 ) return ii ;           /* if not, vamoose the ranch  */
02692    }
02693 
02694    switch( ns->type ){
02695 
02696 #ifndef DONT_USE_SHM
02697      case NI_SHM_TYPE:
02698        return SHM_sendall( ns->shmioc , buffer , nbytes ) ;
02699 #endif
02700 
02701      /** tcp: ==> just use send **/
02702 
02703      case NI_TCP_TYPE:
02704 
02705        if( ns->bad ) return 0 ;  /* socket not ready yet */
02706 
02707        /* turn off SIGPIPE signals, which will otherwise be
02708           raised if we send to a socket when the other end has crashed */
02709 
02710        if( !nosigpipe ){ signal(SIGPIPE,SIG_IGN); nosigpipe = 1; }
02711 
02712 #if 0
02713        /* 03 Mar 2002: wait until we can write fer shur */
02714        do{ ii=tcp_writecheck(ns->sd,1) ; } while(ii==0) ;
02715        if( ii < 0 ) return -1 ;
02716 #endif
02717 
02718        errno = 0 ;
02719        nsent = tcp_send( ns->sd , buffer , nbytes , 0 ) ;
02720        if( nsent < nbytes || errno != 0 ) PERROR("NI_stream_write(send)") ;
02721        if( nsent == 0 ){ fprintf(stderr,"tcp send: 0/%d\n",nbytes); nsent=-1; }
02722        return nsent ;
02723 
02724      /** file: ==> just fwrite **/
02725 
02726      case NI_FD_TYPE:
02727      case NI_FILE_TYPE:
02728 #ifdef NIML_DEBUG
02729 NI_dpr("  file: about to write %d bytes\n",nbytes) ;
02730 #endif
02731        nsent = fwrite( buffer , 1 , nbytes , ns->fp ) ;
02732        if( nsent < nbytes ) PERROR("NI_stream_write(fwrite)") ;
02733 #ifdef NIML_DEBUG
02734 NI_dpr("  file: actually wrote %d bytes\n",nsent) ;
02735 #endif
02736        if( nsent == 0 ) nsent = -1 ;
02737        fflush(ns->fp) ;
02738        return nsent ;
02739 
02740      /** str: ==> append to buffer in stream struct **/
02741 
02742      case NI_STRING_TYPE:
02743 #ifdef NIML_DEBUG
02744 NI_dpr("NI_stream_write str: input=%s\n",ns->buf) ;
02745 #endif
02746         ns->buf = NI_realloc( ns->buf , char , ns->bufsize+nbytes ) ;
02747         memcpy( ns->buf+ns->nbuf , buffer , nbytes ) ;
02748         ns->nbuf    += nbytes ; ns->buf[ns->nbuf] = '\0' ;
02749         ns->bufsize += nbytes ;
02750 #ifdef NIML_DEBUG
02751 NI_dpr("NI_stream_write str: output=%s\n",ns->buf) ;
02752 #endif
02753         return nbytes ;
02754 
02755      /** ftp: or http: ==> can't write! */
02756 
02757      case NI_REMOTE_TYPE:
02758         return -1 ;
02759    }
02760 
02761    return -1 ;  /* should not be reached */
02762 }

int NI_stream_writeable NI_stream_type   ns
 

Return 1 if it is legal to write to this stream, 0 if it isn't. This doesn't say anything about if it is practical to write at this moment; for that, use NI_stream_writecheck(). -------------------------------------------------------------------------

Definition at line 2139 of file niml_stream.c.

References NI_stream_type::bad, NI_stream_type::io_mode, MARKED_FOR_DEATH, NI_OUTPUT_MODE, NI_SHM_TYPE, NI_TCP_TYPE, and NI_stream_type::type.

Referenced by NI_stream_writecheck(), NI_write_columns(), NI_write_element(), and NI_write_procins().

02140 {
02141    if( ns == NULL || ns->bad == MARKED_FOR_DEATH ) return 0 ;
02142    if( ns->type == NI_TCP_TYPE || ns->type == NI_SHM_TYPE ) return 1 ;
02143    return (ns->io_mode == NI_OUTPUT_MODE) ;
02144 }

int NI_stream_writecheck NI_stream_type   ns,
int    msec
 

Check if the NI_stream is ready to have data written into it.

If not, the routine will wait up to msec milliseconds for writing to be allowable. If msec < 0, this routine will wait nearly forever. The return value is 1 if data can be sent, 0 if not; -1 will be returned if some unrecoverable error is detected:

  • tcp: the socket closed down at the other end
  • file: this should never happen, unless you try to write to a readonly NI_stream -----------------------------------------------------------------------------

Definition at line 2590 of file niml_stream.c.

References NI_stream_type::bad, NI_stream_type::fp, NI_stream_type::io_mode, NI_FD_TYPE, NI_FILE_TYPE, NI_OUTPUT_MODE, NI_REMOTE_TYPE, NI_SHM_TYPE, NI_stream_goodcheck(), NI_stream_writeable(), NI_STRING_TYPE, NI_TCP_TYPE, NI_stream_type::sd, SHM_writecheck(), NI_stream_type::shmioc, tcp_writecheck(), and NI_stream_type::type.

Referenced by AFNI_serverlog(), DWI_Open_NIML_stream(), main(), NI_stream_close_keep(), NI_stream_write(), NI_write_columns(), NI_write_element(), NI_write_procins(), open_URL_hpf(), and SUMA_niml_call().

02591 {
02592    int ii ;
02593 
02594    if( !NI_stream_writeable(ns) ) return -1 ;
02595 
02596    switch( ns->type ){
02597 
02598 #ifndef DONT_USE_SHM
02599       case NI_SHM_TYPE:
02600         ii = SHM_writecheck( ns->shmioc , msec ) ;
02601         if( ii > 0 ) ii = 1 ;
02602         return ii ;
02603 #endif
02604 
02605       /** tcp: ==> uses the Unix "select" mechanism **/
02606 
02607       case NI_TCP_TYPE:
02608         if( ns->bad ){                         /* not marked as good */
02609           ii = NI_stream_goodcheck(ns,0) ;     /* check if has become good */
02610           if( ii == -1 ) return -1 ;           /* some error when checking */
02611           if( ii == 0  ){                      /* not good yet, */
02612             ii = NI_stream_goodcheck(ns,msec); /* so wait for it to get good */
02613             if( ii != 1 ) return ii ;          /* if still not good, exit */
02614           }
02615         }
02616                                                /* socket is good, so */
02617         return tcp_writecheck(ns->sd,msec) ;   /* check if we can write bytes */
02618 
02619       /** fd: ==> use select, as in tcp: **/
02620 
02621       case NI_FD_TYPE:
02622         return tcp_writecheck( fileno(ns->fp) , msec ) ;
02623 
02624       /** file: ==> if the file was opened in write mode **/
02625 
02626       case NI_FILE_TYPE:
02627         return ( (ns->fp != NULL && ns->io_mode == NI_OUTPUT_MODE) ? 1
02628                                                                    : -1 ) ;
02629 
02630       /** str: ==> if the string was opened in write mode **/
02631 
02632       case NI_STRING_TYPE:
02633         return ( (ns->io_mode == NI_OUTPUT_MODE) ? 1
02634                                                  : -1 ) ;
02635       /** http: or ftp: **/
02636 
02637       case NI_REMOTE_TYPE:   /* can't write to remote files */
02638         return -1 ;
02639    }
02640 
02641    return -1 ;  /* should never be reached */
02642 }

int NI_stream_writestring NI_stream_type   ns,
char *    str
 

Send a string (without the NUL byte) down the NI_stream. [15 Oct 2002] ------------------------------------------------------------------------------

Definition at line 2648 of file niml_stream.c.

References NI_stream_write().

Referenced by NI_stream_close_keep(), NI_write_columns(), NI_write_element(), NI_write_procins(), nifti_set_afni_extension(), and THD_write_nimlatr().

02649 {
02650    if( str == NULL ) return -1 ;
02651    return NI_stream_write( ns , str , strlen(str) ) ;
02652 }

int NI_trust_host char *    hostid
 

Return 1 if we like hostid, 0 if we don't. -----------------------------------------------------------------------------

Definition at line 686 of file niml_stream.c.

References getenv(), host_list, host_num, hostname_dotted(), init_trusted_list(), NI_free, and NI_hostname_to_inet().

Referenced by tcp_accept().

00687 {
00688    int ii ;
00689    char *hh = hostid ;
00690 
00691    /* if the trusted list is empty,
00692       see if we want to be completely trusting;
00693       if not, then initialize the trusted list and then check */
00694 
00695    if( host_num == 0 ){
00696       char *eee = getenv("NIML_COMPLETE_TRUST") ;
00697       if( eee != NULL && toupper(*eee) == 'Y' ) return 1 ; /* complete trust */
00698       init_trusted_list() ;
00699    }
00700 
00701    if( hostid == NULL || hostid[0] == '\0' ) return 0 ;
00702 
00703    if( !hostname_dotted(hostid) ){
00704       hh = NI_hostname_to_inet(hostid) ;  /* will be NI_malloc()-ed */
00705       if( hh == NULL ) return 0 ;
00706    }
00707 
00708    /* to be trusted, hostid must start with same
00709       string as something in the trusted host_list array */
00710 
00711    for( ii=0 ; ii < host_num ; ii++ ){
00712       if( strstr(hh,host_list[ii]) == hh ){
00713         if( hh != hostid ) NI_free(hh) ;
00714         return 1 ;
00715       }
00716    }
00717 
00718    if( hh != hostid ) NI_free(hh) ;
00719    return 0 ;
00720 }

void remove_open_stream NI_stream_type   ns [static]
 

Remove a stream from the open list.

Definition at line 94 of file niml_stream.c.

References doing_atexit, and num_open_streams.

Referenced by NI_stream_close_keep(), and NI_stream_reopen().

00095 {
00096    int nn = num_open_streams , ii,jj ;
00097 
00098    if( doing_atexit || nn <= 0 || ns == NULL ) return ;  /* bad input */
00099 
00100    for( ii=0 ; ii < nn ; ii++ )          /* find input */
00101      if( open_streams[ii] == ns ) break ;
00102    if( ii == nn ) return ;               /* not found!? */
00103 
00104    for( jj=ii+1 ; jj < nn ; jj++ )       /* move those above down */
00105      open_streams[jj-1] = open_streams[jj] ;
00106 
00107    open_streams[nn-1] = NULL ; num_open_streams-- ; return ;
00108 }

int SHM_accept char *    key_string [static]
 

Get a pre-existing shmem segment. Returns the shmid >= 0 if successful; returns -1 if failure. -----------------------------------------------------------------

Definition at line 755 of file niml_stream.c.

References key, and SHM_string_to_key().

Referenced by SHM_goodcheck(), and SHM_init().

00756 {
00757    key_t key ;
00758    int   shmid ;
00759 
00760    key   = SHM_string_to_key( key_string ) ;
00761    shmid = shmget( key , 0 , 0777 ) ;
00762    return shmid ;
00763 }

int SHM_alivecheck int    shmid [static]
 

Check if the shmem segment is alive (has 2 attached processes). Returns 0 if not alive, 1 if life is happy. ---------------------------------------------------------------------------

Definition at line 1073 of file niml_stream.c.

References SHM_nattach().

Referenced by SHM_goodcheck().

01074 {
01075    if( shmid < 0 ) return 0 ;
01076    return (SHM_nattach(shmid) == 2) ;
01077 }

char* SHM_attach int    shmid [static]
 

Actually attach to the shmem segment. Returns the pointer to the segment start. NULL is returned if an error occurs. -----------------------------------------------------------------

Definition at line 787 of file niml_stream.c.

References PERROR.

Referenced by SHM_fill_accept(), and SHM_init().

00788 {
00789    char *adr ;
00790    adr = (char *) shmat( shmid , NULL , 0 ) ;
00791    if( adr == (char *) -1 ){ adr = NULL ; PERROR("SHM_attach") ; }
00792    return adr ;
00793 }

void SHM_close SHMioc   ioc [static]
 

Close a SHMioc. Note that this will free what ioc points to. -------------------------------------------------------------------------

Definition at line 1170 of file niml_stream.c.

References SHMioc::bad, SHMioc::id, NI_free, SHM_IS_DEAD, and SHMioc::shmbuf.

Referenced by NI_stream_close_keep().

01171 {
01172    if( ioc == NULL ) return ;
01173 
01174    if( ioc->id >= 0 && ioc->bad != SHM_IS_DEAD ){
01175       shmdt( ioc->shmbuf ) ;                 /* detach */
01176       shmctl( ioc->id , IPC_RMID , NULL ) ;  /* delete */
01177       ioc->bad = SHM_IS_DEAD ;               /* leave for dead */
01178    }
01179 
01180    NI_free(ioc) ; return ;
01181 }

int SHM_create char *    key_string,
int    size
[static]
 

Connect to, or create if needed, a shmem segment. Returns the shmid >= 0 if successful; returns -1 if failure. -----------------------------------------------------------------

Definition at line 770 of file niml_stream.c.

References key, PERROR, and SHM_string_to_key().

Referenced by SHM_init().

00771 {
00772    key_t key ;
00773    int   shmid ;
00774 
00775    key   = SHM_string_to_key( key_string ) ;
00776    shmid = shmget( key , size , 0777 | IPC_CREAT ) ;
00777    if( shmid < 0 ) PERROR("SHM_create") ;
00778    return shmid ;
00779 }

int SHM_fill_accept SHMioc   ioc [static]
 

Fill a SHMioc struct that has just been attached as an "r".

  • ioc->id should be non-negative at this point.
  • return value is 1 if things are good, -1 if not. -----------------------------------------------------------------

Definition at line 858 of file niml_stream.c.

References SHMioc::bad, SHMioc::bend1, SHMioc::bend2, SHMioc::bstart1, SHMioc::bstart2, SHMioc::buf1, SHMioc::buf2, SHMioc::bufsize1, SHMioc::bufsize2, SHMioc::id, NI_sleep(), SHM_attach(), SHM_BEND1, SHM_BEND2, SHM_BSTART1, SHM_BSTART2, SHM_HSIZE, SHM_IS_DEAD, SHM_nattach(), SHM_size(), SHM_SIZE1, SHM_SIZE2, SHMioc::shmbuf, and SHMioc::shmhead.

Referenced by SHM_goodcheck(), and SHM_init().

00859 {
00860    char *bbb ;
00861    int jj ;
00862 
00863    if( ioc == NULL || ioc->id < 0 ) return -1 ;      /* bad inputs?   */
00864 
00865    NI_sleep(2) ;                                     /* wait a bit    */
00866    bbb = SHM_attach( ioc->id ) ;                     /* attach it     */
00867    if( bbb == NULL ) return -1 ;                     /* can't? quit   */
00868 
00869    if( SHM_nattach(ioc->id) != 2 ){                  /* 2 processes?  */
00870       NI_sleep(10) ;                                 /* wait a bit,   */
00871       if( SHM_nattach(ioc->id) != 2 ){               /* and try again */
00872         shmdt( bbb ) ;                               /* this is bad!  */
00873         shmctl( ioc->id , IPC_RMID , NULL ) ;
00874         ioc->bad = SHM_IS_DEAD ; return -1 ;
00875       }
00876    }
00877 
00878    jj = SHM_size(ioc->id) ;                          /* shmbuf size   */
00879    if( jj <= SHM_HSIZE ){                            /* too small?    */
00880       shmdt( bbb ) ;                                 /* this is bad!  */
00881       shmctl( ioc->id , IPC_RMID , NULL ) ;
00882       ioc->bad = SHM_IS_DEAD ; return -1 ;
00883    }
00884 
00885    ioc->shmbuf   = bbb ;                             /* buffer */
00886    ioc->shmhead  = (int *) bbb ;                     /* buffer as int */
00887 
00888    ioc->bufsize1 = ioc->shmhead[SHM_SIZE1] ;         /* size of buf 1 */
00889    ioc->bstart1  = ioc->shmhead + SHM_BSTART1 ;      /* start marker 1*/
00890    ioc->bend1    = ioc->shmhead + SHM_BEND1 ;        /* end marker 1  */
00891    ioc->buf1     = ioc->shmbuf  + SHM_HSIZE ;        /* buffer 1      */
00892 
00893    ioc->bufsize2 = ioc->shmhead[SHM_SIZE2] ;         /* size of buf 2 */
00894    ioc->bstart2  = ioc->shmhead + SHM_BSTART2 ;      /* start marker 2*/
00895    ioc->bend2    = ioc->shmhead + SHM_BEND2 ;        /* end marker 2  */
00896    ioc->buf2     = ioc->buf1    + ioc->bufsize1 ;    /* buffer 2      */
00897 
00898    if( jj < SHM_HSIZE+ioc->bufsize1+ioc->bufsize2 ){ /* too small?    */
00899       shmdt( bbb ) ;                                 /* this is bad!  */
00900       shmctl( ioc->id , IPC_RMID , NULL ) ;
00901       ioc->bad = SHM_IS_DEAD ; return -1 ;
00902    }
00903 
00904    ioc->bad = 0 ; return 1 ;                         /** DONE **/
00905 }

int SHM_goodcheck SHMioc   ioc,
int    msec
[static]
 

Check if the given SHMioc is ready for I/O. If not, wait up to msec milliseconds to establish the connection to the other end; if msec < 0, will wait indefinitely. Returns 1 if ready; 0 if not; -1 if an error occurs. Possible errors are: + SHMioc was connected, and now has become disconnected + SHMioc is passed in as NULL ---------------------------------------------------------------------------

Definition at line 1094 of file niml_stream.c.

References SHMioc::bad, SHMioc::goodcheck_time, SHMioc::id, MIN, SHMioc::name, NEXTDMS, NI_clock_time(), NI_dpr(), NI_sleep(), SHM_accept(), SHM_alivecheck(), SHM_fill_accept(), SHM_IS_DEAD, SHM_nattach(), and SHMioc::shmbuf.

Referenced by NI_stream_goodcheck(), SHM_readcheck(), SHM_recv(), SHM_send(), and SHM_writecheck().

01095 {
01096    int ii , jj , ct ;
01097    char *bbb ;
01098 
01099    /** check inputs for OK-osity **/
01100 
01101    if( ioc == NULL || ioc->bad == SHM_IS_DEAD ) return -1 ;
01102 
01103    /** if it was good before, then check if it is still good **/
01104 
01105    if( ioc->bad == 0 ){
01106      ct = NI_clock_time() ;
01107      if( ct - ioc->goodcheck_time > 2 ){    /* 23 Nov 2004 */
01108        ii = SHM_alivecheck(ioc->id) ;
01109        ioc->goodcheck_time = ct ;
01110      } else {
01111        ii = 1 ;
01112      }
01113      if( ii <= 0 ){                            /* has died */
01114 #ifdef NIML_DEBUG
01115         NI_dpr("++ Shared memory connection %s has gone bad!\n",
01116                ioc->name ) ;
01117 #endif
01118         shmdt( ioc->shmbuf ) ; ioc->bad = SHM_IS_DEAD ;
01119         shmctl( ioc->id , IPC_RMID , NULL ) ; return -1 ;
01120      }
01121      return 1 ;
01122    }
01123 
01124    /** wasn't good before, so check if that condition has changed **/
01125 
01126    /** shm "r" process waiting for creation by the "w" process **/
01127 
01128    if( ioc->bad == SHM_WAIT_CREATE ){
01129       int dms=0 , ms ;
01130 
01131       if( msec < 0 ) msec = 999999999 ;       /* a long time (11+ days) */
01132       for( ms=0 ; ms < msec ; ms += dms ){
01133         ioc->id = SHM_accept( ioc->name ) ;  /* try to attach to shmem segment */
01134         if( ioc->id >= 0 ) break ;           /* works? break out               */
01135         dms = NEXTDMS(dms) ; dms = MIN(dms,msec-ms) ; NI_sleep(dms) ;
01136       }
01137       if( ioc->id < 0 )                /* one last try? */
01138         ioc->id = SHM_accept( ioc->name ) ;
01139 
01140       if( ioc->id >= 0 ){              /* found it?     */
01141         jj = SHM_fill_accept( ioc ) ;  /* fill struct   */
01142         if( jj < 0 ) return -1 ;       /* this is bad   */
01143         ioc->bad = 0 ;                 /* mark as ready */
01144         return 1 ;
01145       }
01146       return 0 ;
01147    }
01148 
01149    /** shmem "w" process waiting for "r" process to attach */
01150 
01151    else if( ioc->bad == SHM_WAIT_ACCEPT ){
01152      int dms=0 , ms ;
01153 
01154      if( msec < 0 ) msec = 999999999 ;      /* a long time (11+ days) */
01155      for( ms=0 ; ms < msec ; ms += dms ){
01156        if( SHM_nattach(ioc->id) > 1 ){ ioc->bad = 0 ; return 1 ; }
01157        dms = NEXTDMS(dms) ; dms = MIN(dms,msec-ms) ; NI_sleep(dms) ;
01158      }
01159      if( SHM_nattach(ioc->id) > 1 ){ ioc->bad = 0 ; return 1 ; }
01160      return 0 ;
01161    }
01162 
01163    return 0 ;  /* should never be reached */
01164 }

SHMioc* SHM_init char *    name,
char *    mode
[static]
 

Create a SHMioc struct for use as a 2-way I/O channel, and return a pointer to it. NULL is returned if an error occurs.

name = "shm:name:size1+size2" to connect a shared memory segment with buffers of length size1 and size2 bytes. The creator process will write to the size1 buffer and read from the size2 buffer. The acceptor process will reverse this.

  • The size strings can end in 'K' to multiply by 1024, or end in 'M' to multiply by 1024*1024.
  • If neither size is given, a default value is used.
  • If only size1 is given, size2=size1.
mode = "w" to open a new shared memory channel = "r" to log into a channel created by someone else

The input "name" is limited to a maximum of 127 bytes. -----------------------------------------------------------------

Definition at line 927 of file niml_stream.c.

References SHMioc::bad, SHMioc::bend1, SHMioc::bend2, SHMioc::bstart1, SHMioc::bstart2, SHMioc::buf1, SHMioc::buf2, SHMioc::bufsize1, SHMioc::bufsize2, SHMioc::goodcheck_time, SHMioc::id, key, SHMioc::name, name, NI_free, NI_malloc, NI_sleep(), SHM_accept(), SHM_ACCEPTOR, SHM_attach(), SHM_BEND1, SHM_BEND2, SHM_BSTART1, SHM_BSTART2, SHM_create(), SHM_CREATOR, SHM_DEFAULT_SIZE, SHM_fill_accept(), SHM_HSIZE, SHM_nattach(), SHM_SIZE1, SHM_SIZE2, SHMioc::shmbuf, SHMioc::shmhead, and SHMioc::whoami.

Referenced by NI_stream_open().

00928 {
00929    SHMioc *ioc ;
00930    int do_create , do_accept ;
00931    char key[128] , *kend ;
00932    int  size1=SHM_DEFAULT_SIZE , ii , jj , size2=SHM_DEFAULT_SIZE ;
00933 
00934    /** check if inputs are reasonable **/
00935 
00936    if( name                   == NULL ||
00937        strlen(name)           >  127  ||
00938        strncmp(name,"shm:",4) != 0    ||
00939        mode                   == NULL   ) return NULL ;
00940 
00941    do_create = (*mode == 'w') ;  /* writer */
00942    do_accept = (*mode == 'r') ;  /* reader */
00943 
00944    if( !do_create && !do_accept ) return NULL ;
00945 
00946    /** get keystring (after "shm:") **/
00947 
00948    for( ii=4 ; name[ii] != ':' && name[ii] != '\0' ; ii++ )
00949      key[ii-4] = name[ii] ;
00950    key[ii-4] = '\0' ;
00951 
00952    /** get size1 (after "shm:name:"), if we stopped at a ':' **/
00953 
00954    if( do_create && name[ii] == ':' && name[ii+1] != '\0' ){
00955 
00956      size1 = strtol( name+ii+1 , &kend , 10 ) ;
00957      if( size1 <= 0 ) size1 = SHM_DEFAULT_SIZE ;
00958      else {
00959             if( *kend == 'K' || *kend == 'k' ){ size1 *= 1024     ; kend++; }
00960        else if( *kend == 'M' || *kend == 'm' ){ size1 *= 1024*1024; kend++; }
00961      }
00962      size2 = size1 ;  /* 23 Aug 2002 */
00963 
00964      /** get size2, if we stopped at a + **/
00965 
00966      if( *kend == '+' ){
00967        size2 = strtol( kend+1 , &kend , 10 ) ;
00968        if( size2 <= 0 ) size2 = SHM_DEFAULT_SIZE ;
00969        else {
00970               if( *kend == 'K' || *kend == 'k' ){ size2 *= 1024     ; kend++; }
00971          else if( *kend == 'M' || *kend == 'm' ){ size2 *= 1024*1024; kend++; }
00972        }
00973      }
00974    }
00975 
00976    /** initialize SHMioc **/
00977 
00978    ioc = NI_malloc(SHMioc, sizeof(SHMioc) ) ;
00979 
00980    strcpy( ioc->name , key ) ;  /* save the key name  */
00981 
00982    /** attach to existing shmem segment **/
00983 
00984    if( do_accept ){
00985       ioc->whoami = SHM_ACCEPTOR ;
00986       for( ii=0 ; ii < 4 ; ii++ ){      /* try to find segment */
00987          ioc->id = SHM_accept( key ) ;  /* several times       */
00988          if( ioc->id >= 0 ) break ;     /* works? break out    */
00989          NI_sleep(ii+1) ;               /* wait 1 millisecond  */
00990       }
00991       if( ioc->id < 0 )
00992         ioc->id = SHM_accept( key ) ;   /* 1 last try? */
00993 
00994       if( ioc->id < 0 ){                /* failed to find segment? */
00995          ioc->bad = SHM_WAIT_CREATE ;   /* mark for waiting        */
00996          return ioc ;                   /* and we are DONE for now */
00997          ioc->goodcheck_time = -99 ; /* 23 Nov 2004 */
00998 
00999       } else {                          /* found it?   */
01000 
01001          jj = SHM_fill_accept( ioc ) ;  /* fill struct */
01002 
01003          if( jj < 0 ){                  /* this is bad */
01004            NI_free(ioc); return NULL;
01005          }
01006 
01007          return ioc ;                   /** DONE **/
01008          ioc->goodcheck_time = -99 ; /* 23 Nov 2004 */
01009       }
01010    }
01011 
01012    /** create a new shmem segment **/
01013 
01014    if( do_create ){
01015       char *bbb ;
01016 
01017       ioc->whoami = SHM_CREATOR ;
01018       ioc->id = SHM_create( key, size1+size2+SHM_HSIZE+4 ) ; /* create it */
01019       if( ioc->id < 0 ){                                     /* can't? quit */
01020          NI_free(ioc); return NULL;
01021       }
01022       bbb = SHM_attach( ioc->id ) ;                        /* attach it   */
01023       if( bbb == NULL ){                                   /* can't? quit */
01024          NI_free(ioc); return NULL;
01025       }
01026 
01027       ioc->shmbuf   = bbb ;                                /* buffer */
01028       ioc->shmhead  = (int *) bbb ;                        /* buffer as int */
01029 
01030       ioc->bufsize1 = ioc->shmhead[SHM_SIZE1] = size1 ;    /* size of buf 1 */
01031       ioc->bstart1  = ioc->shmhead + SHM_BSTART1 ;         /* start marker 1*/
01032       ioc->bend1    = ioc->shmhead + SHM_BEND1 ;           /* end marker 1  */
01033       ioc->buf1     = ioc->shmbuf  + SHM_HSIZE ;           /* buffer 1      */
01034 
01035       ioc->bufsize2 = ioc->shmhead[SHM_SIZE2] = size2 ;    /* size of buf 2 */
01036       ioc->bstart2  = ioc->shmhead + SHM_BSTART2 ;         /* start marker 2*/
01037       ioc->bend2    = ioc->shmhead + SHM_BEND2 ;           /* end marker 2  */
01038       ioc->buf2     = ioc->buf1    + size1 ;               /* buffer 2      */
01039 
01040       *(ioc->bstart1) = 0 ;                                /* init markers 1*/
01041       *(ioc->bend1)   = size1-1 ;
01042       *(ioc->bstart2) = 0 ;                                /* init markers 2*/
01043       *(ioc->bend2)   = size2-1 ;
01044 
01045       NI_sleep(3) ;
01046       jj = SHM_nattach(ioc->id) ;                          /* # processes */
01047 
01048       if( jj < 2 ){
01049         NI_sleep(3) ; jj = SHM_nattach(ioc->id) ;
01050       }
01051 
01052       if( jj > 2 ){                                        /* should not  */
01053         shmdt( bbb ) ;                                     /* happen ever */
01054         shmctl( ioc->id , IPC_RMID , NULL ) ;
01055         NI_free(ioc); return NULL;
01056       }
01057 
01058       ioc->bad  = (jj < 2)          /* ready if both   */
01059                  ? SHM_WAIT_ACCEPT  /* processes are   */
01060                  : 0 ;              /* attached to shm */
01061       ioc->goodcheck_time = -99 ; /* 23 Nov 2004 */
01062       return ioc ;
01063    }
01064 
01065    return NULL ;  /* should never be reached */
01066 }

int SHM_nattach int    shmid [static]
 

Find the number of attaches to a shmem segment. Returns -1 if an error occurs. -----------------------------------------------------------------

Definition at line 816 of file niml_stream.c.

References calloc, free, getenv(), NI_sleep(), and PERROR.

Referenced by SHM_alivecheck(), SHM_fill_accept(), SHM_goodcheck(), and SHM_init().

00817 {
00818    int ii ;
00819    static struct shmid_ds buf ;
00820    char *eee = getenv( "NIML_DNAME" ) ;
00821 
00822    if( shmid < 0 ) return -1 ;
00823    ii = shmctl( shmid , IPC_STAT , &buf ) ;
00824    if( ii < 0 ){
00825      if( eee != NULL ) fprintf(stderr,"SHM_nattach: trying again!\n") ;
00826      NI_sleep(9) ;
00827      ii = shmctl( shmid , IPC_STAT , &buf ) ;
00828    }
00829    if( ii < 0 ){
00830      char *ppp ;
00831      if( eee != NULL ){
00832        ppp = (char *)calloc(1,strlen(eee)+32) ;
00833        strcpy(ppp,"SHM_nattach (") ;
00834        strcat(ppp,eee) ; strcat(ppp,")") ;
00835      } else {
00836        ppp = strdup("SHM_nattach") ;
00837      }
00838      PERROR(ppp);
00839      fprintf(stderr,"%s: called shmctl(%x,%x,%p), got %d\n",
00840              ppp,(unsigned int)shmid, (unsigned int)IPC_STAT, (void *)&buf,
00841              ii ) ;
00842      free((void *)ppp); return -1;
00843    } else if( eee != NULL ){
00844      fprintf(stderr,"SHM_nattach (%s): called shmctl(%x,%x,%p), got %d\n",
00845              eee,
00846              (unsigned int)shmid, (unsigned int)IPC_STAT, (void *)&buf,
00847              (int)buf.shm_nattch ) ;
00848    }
00849    return (int)buf.shm_nattch ;
00850 }

int SHM_readcheck SHMioc   ioc,
int    msec
[static]
 

Check if the SHMioc is ready to have data read out of it. If not, the routine will wait up to msec milliseconds for data to be available. If msec < 0, this routine will wait indefinitely. For shmem segments, the return value is how many bytes can be read (0 if none are available). -1 will be returned if some unrecoverable error is detected. -----------------------------------------------------------------------------

Definition at line 1192 of file niml_stream.c.

References SHMioc::bad, SHMioc::bend1, SHMioc::bend2, SHMioc::bstart1, SHMioc::bstart2, SHMioc::bufsize1, SHMioc::bufsize2, SHMioc::goodcheck_time, MIN, NEXTDMS, NI_clock_time(), NI_sleep(), SHM_ACCEPTOR, SHM_CREATOR, SHM_goodcheck(), and SHMioc::whoami.

Referenced by NI_stream_readcheck().

01193 {
01194    int ii , ct ;
01195    int nread , dms=0 , ms ;
01196    int *bstart, *bend , bsize ;  /* for the chosen buffer */
01197 
01198    /** check if the SHMioc is good **/
01199 
01200    ct = NI_clock_time() ;
01201    if( ct - ioc->goodcheck_time > 2 ){    /* 23 Nov 2004 */
01202      ii = SHM_goodcheck(ioc,0) ;
01203      ioc->goodcheck_time = ct ;
01204      if( ii <= 0  ){                      /* not good yet */
01205        ii = SHM_goodcheck(ioc,msec) ;     /* so wait for it to get good */
01206        if( ii <= 0 ) return ii ;          /* if still not good, exit */
01207      }
01208    } else if( ioc->bad ) return 0 ;
01209 
01210    /** choose buffer from which to read **/
01211 
01212    switch( ioc->whoami ){
01213 
01214      default: return -1 ;  /* should never happen */
01215 
01216      case SHM_ACCEPTOR:
01217        bstart = ioc->bstart1 ;
01218        bend   = ioc->bend1 ;
01219        bsize  = ioc->bufsize1 ;
01220      break ;
01221 
01222      case SHM_CREATOR:
01223        bstart = ioc->bstart2 ;
01224        bend   = ioc->bend2 ;
01225        bsize  = ioc->bufsize2 ;
01226      break ;
01227    }
01228 
01229    /** must loop and wait **/
01230 
01231    if( msec < 0 ) msec = 999999999 ;      /* a long time (11+ days) */
01232 
01233    /** Compute the number of readable bytes into nread. **/
01234 
01235    for( ms=0 ; ms < msec ; ms += dms ){
01236      nread = (*bend - *bstart + bsize + 1) % bsize ;
01237      if( nread > 0 ) return nread ;
01238      dms = NEXTDMS(dms) ; dms = MIN(dms,msec-ms) ; NI_sleep(dms) ;
01239      ii = SHM_goodcheck(ioc,0) ; if( ii == -1 ) return -1 ;
01240    }
01241    nread = (*bend - *bstart + bsize + 1) % bsize ;
01242    if( nread > 0 ) return nread ;
01243    return 0 ;
01244 }

int SHM_recv SHMioc   ioc,
char *    buffer,
int    nbytes
[static]
 

Read up to nbytes of data from the SHMioc, into buffer. Returns the number of bytes actually read. This may be less than nbytes (may even be 0). If an error occurs, -1 is returned. ------------------------------------------------------------------------------

Definition at line 1416 of file niml_stream.c.

References SHMioc::bad, SHMioc::bend1, SHMioc::bend2, SHMioc::bstart1, SHMioc::bstart2, SHMioc::buf1, SHMioc::buf2, SHMioc::bufsize1, SHMioc::bufsize2, SHM_ACCEPTOR, SHM_CREATOR, SHM_goodcheck(), and SHMioc::whoami.

Referenced by NI_stream_read().

01417 {
01418    int *bstart, *bend , bsize ;  /* for the chosen buffer */
01419    char *buf ;
01420    int nread, sbot,stop , ii ;
01421 
01422    /** check for reasonable inputs **/
01423 
01424    if( ioc    == NULL || ioc->bad   ||
01425        buffer == NULL || nbytes < 0   ) return -1 ;
01426 
01427    if( nbytes == 0 ) return 0 ;
01428 
01429    ii = SHM_goodcheck(ioc,1) ;
01430    if( ii <= 0 ) return ii ;
01431 
01432    /** choose buffer from which to read **/
01433 
01434    switch( ioc->whoami ){
01435 
01436      default: return -1 ;  /* should never happen */
01437 
01438      case SHM_ACCEPTOR:
01439        bstart = ioc->bstart1 ;
01440        bend   = ioc->bend1 ;
01441        bsize  = ioc->bufsize1 ;
01442        buf    = ioc->buf1 ;
01443      break ;
01444 
01445      case SHM_CREATOR:
01446        bstart = ioc->bstart2 ;
01447        bend   = ioc->bend2 ;
01448        bsize  = ioc->bufsize2 ;
01449        buf    = ioc->buf2 ;
01450      break ;
01451    }
01452 
01453    /** read from the circular buffer, starting at bstart **/
01454 
01455    nread = ( *bend - *bstart + bsize + 1 ) % bsize ;    /* readable amount */
01456    if( nread <= 0 ) return 0 ;                          /* nothing!?       */
01457    if( nread > nbytes ) nread = nbytes ;                /* amount to read  */
01458 
01459    sbot = *bstart ; stop = sbot + nread-1 ;             /* from sbot to stop */
01460 
01461    if( stop < bsize ){                                  /* 1 piece to copy */
01462       memcpy( buffer, buf+sbot, nread ) ;               /* copy the data   */
01463       *bstart = (stop+1) % bsize ;                      /* move bstart up  */
01464    } else {                                             /* 2 pieces to copy */
01465       int nn = bsize - sbot ;                           /* size of piece 1  */
01466       memcpy( buffer   , buf + sbot, nn        ) ;      /* copy piece 1     */
01467       memcpy( buffer+nn, buf       , nread-nn  ) ;      /* copy piece 2     */
01468       *bstart = nread-nn ;                              /* move bstart up   */
01469    }
01470    return nread ;
01471 }

int SHM_send SHMioc   ioc,
char *    buffer,
int    nbytes
[static]
 

Send nbytes of data from buffer down the SHMioc. Return value is the number of bytes actually sent, or is -1 if some error occurs. ------------------------------------------------------------------------------

Definition at line 1309 of file niml_stream.c.

References SHMioc::bad, SHMioc::bend1, SHMioc::bend2, SHMioc::bstart1, SHMioc::bstart2, SHMioc::buf1, SHMioc::buf2, SHMioc::bufsize1, SHMioc::bufsize2, SHM_ACCEPTOR, SHM_CREATOR, SHM_goodcheck(), SHM_writecheck(), and SHMioc::whoami.

Referenced by SHM_sendall().

01310 {
01311    int ii ;
01312    int nread,nwrite , ebot,etop ;
01313    int *bstart, *bend , bsize ;  /* for the chosen buffer */
01314    char *buf ;
01315 
01316    /** check for reasonable inputs **/
01317 
01318    if( ioc    == NULL || ioc->bad   ||
01319        buffer == NULL || nbytes < 0   ) return -1 ;
01320 
01321    if( nbytes == 0 ) return 0 ;  /* stupid user */
01322 
01323    ii = SHM_goodcheck(ioc,1) ;   /* can't send if it ain't good */
01324    if( ii <= 0 ) return ii ;
01325 
01326    ii = SHM_writecheck(ioc,1) ;  /* is something is writeable? */
01327    if( ii <= 0 ) return ii ;
01328 
01329    /** choose buffer in which to write **/
01330 
01331    switch( ioc->whoami ){
01332 
01333      default: return -1 ;  /* should never happen */
01334 
01335      case SHM_ACCEPTOR:
01336        bstart = ioc->bstart2 ;
01337        bend   = ioc->bend2 ;
01338        bsize  = ioc->bufsize2 ;
01339        buf    = ioc->buf2 ;
01340      break ;
01341 
01342      case SHM_CREATOR:
01343        bstart = ioc->bstart1 ;
01344        bend   = ioc->bend1 ;
01345        bsize  = ioc->bufsize1 ;
01346        buf    = ioc->buf1 ;
01347      break ;
01348    }
01349 
01350    /** write into the circular buffer, past "bend" **/
01351 
01352    nread  = ( *bend - *bstart + bsize + 1 ) % bsize; /* amount readable  */
01353    nwrite = bsize - 1 - nread ;                      /* amount writeable */
01354    if( nwrite <= 0 ) return 0 ;                      /* can't write!     */
01355 
01356    if( nwrite > nbytes ) nwrite = nbytes ;           /* how much to write */
01357 
01358    ebot = *bend+1 ; if( ebot >= bsize ) ebot = 0 ;   /* start at ebot */
01359    etop = ebot+nwrite-1 ;                            /* end at etop   */
01360 
01361    if( etop < bsize ){                               /* 1 piece to copy  */
01362       memcpy( buf + ebot, buffer, nwrite ) ;         /* copy data        */
01363       *bend = etop ;                                 /* change bend      */
01364    } else {                                          /* 2 pieces to copy */
01365       int nn = bsize - ebot ;                        /* size of piece 1  */
01366       memcpy( buf + ebot, buffer   , nn        ) ;   /* copy piece 1     */
01367       memcpy( buf       , buffer+nn, nwrite-nn ) ;   /* copy piece 2     */
01368       *bend = nwrite-nn-1 ;                          /* change bend      */
01369    }
01370    return nwrite ;
01371 }

int SHM_sendall SHMioc   ioc,
char *    buffer,
int    nbytes
[static]
 

Send (exactly) nbytes of data from the buffer down the SHMioc. The only difference between this and SHM_send is that this function will not return until all the data is sent, even if it takes forever. Under these circumstances, it would be good if the reader process is still working. ------------------------------------------------------------------------------

Definition at line 1381 of file niml_stream.c.

References SHMioc::bad, NEXTDMS, NI_sleep(), and SHM_send().

Referenced by NI_stream_write().

01382 {
01383    int ii , ntot=0 , dms=0 ;
01384 
01385    /** check for reasonable inputs **/
01386 
01387    if( ioc    == NULL || ioc->bad   ||
01388        buffer == NULL || nbytes < 0   ) return -1 ;
01389 
01390    if( nbytes == 0 ) return 0 ;
01391 
01392    while(1){
01393       ii = SHM_send( ioc , buffer+ntot , nbytes-ntot ); /* send what's left */
01394       if( ii == -1 ) return -1 ;                        /* an error!?       */
01395 
01396       if( ii == 0 ){                                    /* nothing sent? */
01397         dms = NEXTDMS(dms) ;
01398       } else {                                          /* sent something!   */
01399         ntot += ii ;                                    /* total sent so far */
01400         if( ntot >= nbytes ) return nbytes ;            /* all done!?        */
01401         dms = 1 ;
01402       }
01403 
01404       NI_sleep(dms) ;                                   /* wait a bit */
01405    }
01406    return -1 ;   /* should never be reached */
01407 }

int SHM_size int    shmid [static]
 

Find the size of a shmem segment. Returns -1 if an error occurs. -----------------------------------------------------------------

Definition at line 800 of file niml_stream.c.

References PERROR.

Referenced by SHM_fill_accept().

00801 {
00802    int ii ;
00803    struct shmid_ds buf ;
00804 
00805    if( shmid < 0 ) return -1 ;
00806    ii = shmctl( shmid , IPC_STAT , &buf ) ;
00807    if( ii < 0 ){ PERROR("SHM_size") ;  return -1 ; }
00808    return buf.shm_segsz ;
00809 }

key_t SHM_string_to_key char *    key_string [static]
 

Convert a string to a key, for IPC operations. -----------------------------------------------------------------

Definition at line 732 of file niml_stream.c.

Referenced by SHM_accept(), and SHM_create().

00733 {
00734    int ii , sum ;
00735    key_t kk ;
00736 
00737    sum = 987654321 ;
00738    if( key_string == NULL ) return (key_t) sum ;
00739 
00740    for( ii=0 ; key_string[ii] != '\0' ; ii++ )
00741       sum += ((int)key_string[ii]) << ((ii%3)*8) ;
00742 
00743    kk = (key_t) sum ;
00744 #ifdef IPC_PRIVATE
00745    if( kk == IPC_PRIVATE || kk <= 0 ) kk = 666 ;
00746 #endif
00747    return kk ;
00748 }

int SHM_writecheck SHMioc   ioc,
int    msec
[static]
 

Check if the SHMioc is ready to have data written into it. If not, the routine will wait up to msec milliseconds for writing to be allowable. If msec < 0, this routine will wait indefinitely. The return value is the number of bytes that can be sent (0 if none, positive if some). -1 will be returned if some unrecoverable error is detected. -----------------------------------------------------------------------------

Definition at line 1255 of file niml_stream.c.

References SHMioc::bend1, SHMioc::bend2, SHMioc::bstart1, SHMioc::bstart2, SHMioc::bufsize1, SHMioc::bufsize2, MIN, NEXTDMS, NI_sleep(), SHM_ACCEPTOR, SHM_CREATOR, SHM_goodcheck(), and SHMioc::whoami.

Referenced by NI_stream_writecheck(), and SHM_send().

01256 {
01257    int ii ;
01258    int nread , dms=0 , ms , nwrite ;
01259    int *bstart, *bend , bsize ;  /* for the chosen buffer */
01260 
01261    /** check if the SHMioc is good **/
01262 
01263    ii = SHM_goodcheck(ioc,0) ;
01264    if( ii == -1 ) return -1 ;        /* some error */
01265    if( ii == 0  ){                   /* not good yet */
01266      ii = SHM_goodcheck(ioc,msec) ;  /* so wait for it to get good */
01267      if( ii <= 0 ) return ii ;       /* if still not good, exit */
01268    }
01269 
01270    /** choose buffer to which to write **/
01271 
01272    switch( ioc->whoami ){
01273 
01274      default: return -1 ;  /* should never happen */
01275 
01276      case SHM_ACCEPTOR:
01277        bstart = ioc->bstart2 ;
01278        bend   = ioc->bend2 ;
01279        bsize  = ioc->bufsize2 ;
01280      break ;
01281 
01282      case SHM_CREATOR:
01283        bstart = ioc->bstart1 ;
01284        bend   = ioc->bend1 ;
01285        bsize  = ioc->bufsize1 ;
01286      break ;
01287    }
01288 
01289    if( msec < 0 ) msec = 999999999 ;      /* a long time (11+ days) */
01290 
01291    for( ms=0 ; ms < msec ; ms += dms ){
01292      nread  = (*bend - *bstart + bsize + 1) % bsize ;
01293      nwrite = bsize - 1 - nread ;
01294      if( nwrite > 0 ) return nwrite ;
01295      dms = NEXTDMS(dms) ; dms = MIN(dms,msec-ms) ; NI_sleep(dms) ;
01296      ii = SHM_goodcheck(ioc,0) ; if( ii == -1 ) return -1 ;
01297    }
01298    nread  = (*bend - *bstart + bsize + 1) % bsize ;
01299    nwrite = bsize - 1 - nread ;
01300    if( nwrite > 0 ) return nwrite ;
01301    return 0 ;
01302 }

int tcp_accept int    sd,
char **    hostname,
char **    hostaddr
[static]
 

Accept incoming connection on a socket.

Return value is the attached socket (which is not the original socket!). If -1 is returned, some error occured. If the accept works, then the original socket is still open and listening for further attachments. Under many circumstances, you will want to close the original socket immediately. This can be done with CLOSEDOWN(sd), where sd is the input socket.

If hostname is not NULL, then the char * it points to will be filled with a pointer to the official name of the host that connected.

If hostaddr is not NULL, then the char * it points to will be filled with a pointer to the Internet address (in 'dot' form) of the host that connected.

Both the char * pointers returned are from NI_malloc(), and should be NI_free()-d when no longer needed. If they aren't needed at all, just pass in NULL for these arguments.

Note that this routine will block until somebody connects. You can use tcp_readcheck(sd,0) to see if anyone is waiting to connect before calling this routine.

However, if someone connects and the IP address isn't on the trusted list, then the connection will be closed immediately. ---------------------------------------------------------------------------

Definition at line 508 of file niml_stream.c.

References CLOSEDOWN, NI_strdup(), NI_trust_host(), PERROR, and tcp_set_cutoff().

00509 {
00510    struct sockaddr_in pin ;
00511    int addrlen , sd_new ;
00512    struct hostent *hostp ;
00513    char *str ;
00514 
00515    /** accept the connection **/
00516 
00517    addrlen = sizeof(pin) ;
00518    sd_new = accept( sd , (struct sockaddr *)&pin , &addrlen ) ;
00519    if( sd_new == -1 ){ PERROR("tcp_accept"); return -1; }
00520 
00521    /** get dotted form address of connector **/
00522 
00523    str = inet_ntoa( pin.sin_addr ) ;
00524 
00525    if( !NI_trust_host(str) ){
00526      fprintf(stderr,"\n** ILLEGAL attempt to connect from host %s\n",str) ;
00527      CLOSEDOWN( sd_new ) ;
00528      return -1 ;
00529    }
00530 
00531    if( hostaddr != NULL ) *hostaddr = NI_strdup(str) ;
00532 
00533    /** get name of connector **/
00534 
00535    if( hostname != NULL ){
00536      hostp = gethostbyaddr( (char *) (&pin.sin_addr) ,
00537                             sizeof(struct in_addr) , AF_INET ) ;
00538 
00539      if( hostp != NULL ) *hostname = NI_strdup(hostp->h_name) ;
00540      else                *hostname = NI_strdup("UNKNOWN") ;  /* bad lookup */
00541    }
00542 
00543    tcp_set_cutoff( sd_new ) ;  /* let it die quickly, we hope */
00544    return sd_new ;
00545 }

int tcp_alivecheck int    sd [static]
 

Check if an already active socket is still alive.

If it is dead, then readcheck will say we can read, but we won't actually get any bytes when we try (using peek mode). Returns 1 if things are OK, 0 if not. ---------------------------------------------------------------------

Definition at line 303 of file niml_stream.c.

References PERROR, tcp_readcheck(), and tcp_recv.

00304 {
00305    int ii ;
00306    char bbb[4] ;
00307 
00308    ii = tcp_readcheck(sd,0) ;                 /* can I read?          */
00309    if( ii == 0 ) return 1 ;                   /* can't read is OK     */
00310    if( ii <  0 ) return 0 ;                   /* some error is bad    */
00311    errno = 0 ;
00312    ii = tcp_recv( sd , bbb , 1 , MSG_PEEK ) ; /* try to read one byte */
00313    if( ii == 1 ) return 1 ;                   /* if we get it, good   */
00314    if( errno ) PERROR("tcp_alivecheck") ;
00315    return 0 ;                                 /* no data ==> death!   */
00316 }

int tcp_connect char *    host,
int    port
[static]
 

Open a socket to the given host, to the given TCP port.

This function is used to "reach out" to a server that is supposed to be listening on the same port. Returns socket id; if -1, some error occured (e.g., nobody listening). --------------------------------------------------------------------------

Definition at line 326 of file niml_stream.c.

References CLOSEDOWN, getenv(), l, NI_dpr(), PERROR, q, socket, SOCKET_BUFSIZE, and tcp_set_cutoff().

00327 {
00328    int sd , l , q,qq ;
00329    struct sockaddr_in sin ;
00330    struct hostent    *hostp ;
00331 
00332    if( host == NULL || port < 1 ) return -1 ;  /* bad inputs */
00333 
00334 #ifdef NIML_DEBUG
00335    NI_dpr("Enter tcp_connect: host=%s port=%d\n",host,port) ;
00336 #endif
00337 
00338    /** open a socket **/
00339 
00340    sd = socket( AF_INET , SOCK_STREAM , 0 ) ;
00341    if( sd == -1 ){ PERROR("tcp_connect(socket)"); return -1; }
00342 
00343    /** set socket options (no delays, large buffers) **/
00344 
00345 #if 0
00346    { char *eee=getenv( "NIML_TCP_NAGLE" ) ;
00347      if( eee == NULL || toupper(*eee) != 'Y' ){
00348        /** disable the Nagle algorithm **/
00349        l = 1;
00350        setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, (void *)&l, sizeof(int)) ;
00351      }
00352    }
00353 #endif
00354 
00355    /* but large buffers are good */
00356 
00357 #ifdef SOCKET_BUFSIZE
00358    q = 0 ; qq = sizeof(int) ;                                 /* 03 Dec 2002:    */
00359    getsockopt(sd, SOL_SOCKET, SO_SNDBUF, (void *)&q, &qq ) ;  /* only modify      */
00360    if( q < SOCKET_BUFSIZE ){                                  /* if current buffer */
00361      l = SOCKET_BUFSIZE ;                                     /* is too small     */
00362      setsockopt(sd, SOL_SOCKET, SO_SNDBUF, (void *)&l, sizeof(int)) ;
00363    }
00364    q = 0 ; qq = sizeof(int) ;
00365    getsockopt(sd, SOL_SOCKET, SO_RCVBUF, (void *)&q, &qq ) ;
00366    if( q < SOCKET_BUFSIZE ){
00367      l = SOCKET_BUFSIZE ;
00368      setsockopt(sd, SOL_SOCKET, SO_RCVBUF, (void *)&l, sizeof(int)) ;
00369    }
00370 #endif
00371 
00372    /** set port on remote computer **/
00373 
00374    memset( &sin , 0 , sizeof(sin) ) ;
00375    sin.sin_family = AF_INET ;
00376    sin.sin_port   = htons(port) ;
00377 
00378    /** set remote computer IP address from its name **/
00379 
00380    hostp = gethostbyname(host) ;
00381    if( hostp == NULL ){
00382       PERROR("tcp_connect(gethostbyname)");
00383 #ifdef NIML_DEBUG
00384    NI_dpr("      tcp_connect: can't gethostbyname(); errno=%d\n",errno);
00385 #endif
00386       CLOSEDOWN(sd); return -1;
00387    }
00388    sin.sin_addr.s_addr = ((struct in_addr *)(hostp->h_addr))->s_addr ;
00389 
00390    errno = 0 ;
00391    if( connect(sd,(struct sockaddr *)&sin,sizeof(sin)) != 0 ){
00392       if( errno != ECONNREFUSED ) PERROR("tcp_connect(connect)") ;
00393 #ifdef NIML_DEBUG
00394    NI_dpr("      tcp_connect: can't connect(); errno=%d\n",errno);
00395 #endif
00396       CLOSEDOWN(sd); return -1;
00397    }
00398 
00399 #ifdef NIML_DEBUG
00400    NI_dpr("      tcp_connect: connected!\n");
00401 #endif
00402 
00403    tcp_set_cutoff( sd ) ;
00404    return sd ;
00405 }

int tcp_listen int    port [static]
 

Set up to listen for a connection on a given port.

This is intended for use by a server, which will wait for some other program to actively connect to this port. There is no security here - connections will be taken from any IP address.

This function does not actually form the connection. That must be done separately. Whether someone is trying to connect can be checked for with the routine "tcp_readcheck" and then accepted with "tcp_accept".

The return value is the descriptor for the listening socket. ----------------------------------------------------------------------------

Definition at line 421 of file niml_stream.c.

References CLOSEDOWN, getenv(), l, PERROR, q, socket, SOCKET_BUFSIZE, and tcp_set_cutoff().

00422 {
00423    int sd , l , q,qq ;
00424    struct sockaddr_in sin ;
00425 
00426    if( port < 1 ) return -1 ; /* bad input */
00427 
00428    /** open a socket **/
00429 
00430    sd = socket( AF_INET , SOCK_STREAM , 0 ) ;
00431    if( sd == -1 ){ PERROR("tcp_listen(socket)"); return -1; }
00432 
00433    /** set socket options (no delays, large buffers) **/
00434 
00435 #if 0
00436    { char *eee=getenv( "NIML_TCP_NAGLE" ) ;
00437      if( eee == NULL || toupper(*eee) != 'Y' ){
00438        /** disable the Nagle algorithm **/
00439        l = 1;
00440        setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, (void *)&l, sizeof(int)) ;
00441      }
00442    }
00443 #endif
00444 
00445 #ifdef SOCKET_BUFSIZE
00446    q = 0 ; qq = sizeof(int) ;
00447    getsockopt(sd, SOL_SOCKET, SO_SNDBUF, (void *)&q, &qq ) ;
00448    if( q < SOCKET_BUFSIZE ){
00449      l = SOCKET_BUFSIZE ;
00450      setsockopt(sd, SOL_SOCKET, SO_SNDBUF, (void *)&l, sizeof(int)) ;
00451    }
00452    q = 0 ; qq = sizeof(int) ;
00453    getsockopt(sd, SOL_SOCKET, SO_RCVBUF, (void *)&q, &qq ) ;
00454    if( q < SOCKET_BUFSIZE ){
00455      l = SOCKET_BUFSIZE ;
00456      setsockopt(sd, SOL_SOCKET, SO_RCVBUF, (void *)&l, sizeof(int)) ;
00457    }
00458 #endif
00459 
00460    /** set port on remote computer **/
00461 
00462    memset( &sin , 0 , sizeof(sin) ) ;
00463    sin.sin_family      = AF_INET ;
00464    sin.sin_port        = htons(port) ;
00465    sin.sin_addr.s_addr = INADDR_ANY ;  /* reader reads from anybody */
00466 
00467    if( bind(sd , (struct sockaddr *)&sin , sizeof(sin)) == -1 ){
00468      PERROR("tcp_listen(bind)"); CLOSEDOWN(sd); return -1;
00469    }
00470 
00471    if( listen(sd,1) == -1 ){
00472      PERROR("tcp_listen(listen)"); CLOSEDOWN(sd); return -1;
00473    }
00474 
00475    tcp_set_cutoff( sd ) ;
00476    return sd ;
00477 }

int tcp_readcheck int    sd,
int    msec
[static]
 

See if the given socket (file descriptor sd) is ready to read.

msec is the number of milliseconds to wait:

  • zero ==> no waiting
  • < 0 ==> wait until something happens (not recommended)
Return values are:
  • -1 = some error occured (socket closed at other end?)
  • 0 = socket is not ready to read
  • 1 = socket has data ---------------------------------------------------------------------

Definition at line 204 of file niml_stream.c.

References PERROR.

00205 {
00206    int ii ;
00207    fd_set rfds ;
00208    struct timeval tv , *tvp ;
00209 
00210    if( sd < 0 ) return -1 ;                     /* bad socket id */
00211 
00212    FD_ZERO(&rfds) ; FD_SET(sd, &rfds) ;         /* check only sd */
00213 
00214    if( msec >= 0 ){                             /* set timer */
00215      tv.tv_sec  = msec/1000 ;
00216      tv.tv_usec = (msec%1000)*1000 ;
00217      tvp        = &tv ;
00218    } else {
00219      tvp        = NULL ;                        /* forever */
00220    }
00221 
00222    ii = select(sd+1, &rfds, NULL, NULL, tvp) ;  /* check it */
00223    if( ii == -1 ) PERROR( "tcp_readcheck(select)" ) ;
00224    return ii ;
00225 }

void tcp_set_cutoff int    sd [static]
 

Set a socket so that it will cutoff quickly when it is closed. See http://www.manualy.sk/sock-faq/unix-socket-faq.html for more information about this stuff. --------------------------------------------------------------------------

Definition at line 269 of file niml_stream.c.

00270 {
00271    if( sd < 0 ) return ;  /* bad input */
00272 
00273 #ifdef SO_LINGER
00274    /* Turn off "lingering". */
00275 
00276    { struct linger lg ;
00277      lg.l_onoff  = 1 ;
00278      lg.l_linger = 0 ;
00279      setsockopt(sd, SOL_SOCKET, SO_LINGER, (void *)&lg, sizeof(struct linger)) ;
00280    }
00281 #endif
00282 
00283 #ifdef SO_REUSEADDR
00284    /* Let the address be reused quickly,
00285       in case of another connection from the same host on the same port. */
00286 
00287    { int optval = 1;
00288      setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval)) ;
00289    }
00290 #endif
00291 
00292    return ;
00293 }

void tcp_sigurg_handler int    sig [static]
 

Signal handler for SIGURG -- for incoming OOB data on a socket. We just close the NI_stream that the socket is attached to. But first we have to find it! --------------------------------------------------------------------

Definition at line 135 of file niml_stream.c.

References NI_stream_type::bad, CLOSEDOWN, MARKED_FOR_DEATH, NI_TCP_TYPE, num_open_streams, NI_stream_type::sd, and NI_stream_type::type.

Referenced by NI_stream_open().

00136 {
00137    int nn = num_open_streams , ii , sd,sdtop ;
00138    NI_stream_type *ns ;
00139    fd_set efds ;
00140    struct timeval tv ;
00141    static volatile int busy=0 ;
00142 
00143    if( sig != SIGURG         ||
00144        busy                  ||
00145        num_open_streams <= 0 || open_streams == NULL ) return ;  /* bad */
00146 
00147    busy = 1 ;  /* prevent recursion! */
00148 
00149    /* find largest socket descriptor in list of streams,
00150       and make list of all open socket descriptors in streams */
00151 
00152    FD_ZERO(&efds) ; sdtop = -1 ;
00153    for( ii=0 ; ii < nn ; ii++ ){
00154      if( open_streams[ii]       != NULL             &&
00155          open_streams[ii]->bad  != MARKED_FOR_DEATH &&
00156          open_streams[ii]->type == NI_TCP_TYPE      &&
00157          open_streams[ii]->sd   >= 0                  ){
00158 
00159        FD_SET( open_streams[ii]->sd , &efds ) ;
00160        if( open_streams[ii]->sd > sdtop ) sdtop = open_streams[ii]->sd;
00161      }
00162    }
00163    if( sdtop < 0 ){ busy=0 ; return; }   /* no sockets found? */
00164 
00165    /* do a select to find which socket has an exceptional condition */
00166 
00167    tv.tv_sec  = 0 ;
00168    tv.tv_usec = 666 ;
00169    ii = select(sdtop+1, NULL, NULL, &efds, &tv) ;  /* check it */
00170    if( ii <= 0 ){ busy=0 ; return; }   /* no sockets found? */
00171 
00172    /* loop over found sockets and close their streams */
00173 
00174    for( ii=0 ; ii < nn ; ii++ ){
00175      if( open_streams[ii] != NULL && open_streams[ii]->type == NI_TCP_TYPE ){
00176        if( FD_ISSET( open_streams[ii]->sd , &efds ) ){
00177          CLOSEDOWN( open_streams[ii]->sd ) ;
00178          open_streams[ii]->bad = MARKED_FOR_DEATH ;
00179        }
00180      }
00181    }
00182 
00183    busy=0 ; return ;
00184 }

int tcp_writecheck int    sd,
int    msec
[static]
 

See if the given socket (file descriptor sd) is ready to write.

msec = max amount of time to wait, in milliseconds.

  • zero ==> no waiting
  • < 0 ==> wait until something happens (not recommended)
Return values are
  • -1 = some error occured (socket closed at other end?)
  • 0 = socket is not ready to write
  • 1 = OK to write to socket ---------------------------------------------------------------------

Definition at line 240 of file niml_stream.c.

References PERROR.

00241 {
00242    int ii ;
00243    fd_set wfds ;
00244    struct timeval tv , *tvp ;
00245 
00246    if( sd < 0 ) return -1 ;                     /* bad socket id */
00247 
00248    FD_ZERO(&wfds) ; FD_SET(sd, &wfds) ;         /* check only sd */
00249 
00250    if( msec >= 0 ){                             /* set timer */
00251      tv.tv_sec  = msec/1000 ;
00252      tv.tv_usec = (msec%1000)*1000 ;
00253      tvp        = &tv ;
00254    } else {
00255      tvp        = NULL ;                        /* forever */
00256    }
00257 
00258    ii = select(sd+1, NULL , &wfds, NULL, tvp);  /* check it */
00259    if( ii == -1 ) PERROR( "tcp_writecheck(select)" ) ;
00260    return ii ;
00261 }

Variable Documentation

int atexit_is_setup = 0 [static]
 

Variable to indicate that the atexit() call has/hasn't been made

Definition at line 127 of file niml_stream.c.

Referenced by NI_stream_open().

volatile int doing_atexit = 0 [static]
 

Signal that we are doing atexit() stuff.

Definition at line 74 of file niml_stream.c.

Referenced by atexit_open_streams(), and remove_open_stream().

char** host_list = NULL [static]
 

IP addresses in dotted form.

Definition at line 552 of file niml_stream.c.

Referenced by add_trusted_host(), init_trusted_list(), and NI_trust_host().

int host_num = 0 [static]
 

Number of trusted hosts.

Definition at line 551 of file niml_stream.c.

Referenced by add_trusted_host(), init_trusted_list(), NI_add_trusted_host(), and NI_trust_host().

char* init_hosts[] [static]
 

Initial value:

 {  
    "127.0.0.1"    ,           
    "192.168."     ,           
    "128.231.21"               
}

Definition at line 554 of file niml_stream.c.

Referenced by init_trusted_list().

int nosigpipe = 0 [static]
 

For tcp - indicates that SIGPIPE is ignored; will be set the first time tcp_send is called.

Definition at line 23 of file niml_stream.c.

Referenced by NI_stream_write().

int num_open_streams = 0 [static]
 

Number of entries on the list of currently open streams.

This list is needed so we can deal with the SIGURG signal, which we use as a message to shut a socket down. The signal call itself doesn't tell us which socket was the trigger, so we have to search all the open sockets for a match: hence, this list of open streams. ---------------------------------------------------------------------

Definition at line 66 of file niml_stream.c.

Referenced by add_open_stream(), atexit_open_streams(), remove_open_stream(), and tcp_sigurg_handler().

NI_stream_type** open_streams = NULL [static]
 

The actual array of open NIML streams.

Definition at line 70 of file niml_stream.c.

int sigurg = 0 [static]
 

For tcp - indicates that the SIGURG handler is installed; will be set the first time a TCP socket is created.

Definition at line 28 of file niml_stream.c.

Referenced by NI_stream_open().

 

Powered by Plone

This site conforms to the following standards: