New library and PV dump programs for IOC and client workstation
This commit is contained in:
987
src/dbtools/BSlib.c
Normal file
987
src/dbtools/BSlib.c
Normal file
@@ -0,0 +1,987 @@
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "BSlib.h"
|
||||
|
||||
#ifdef linux
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
#ifdef vxWorks
|
||||
#include <vxWorks.h>
|
||||
#include <in.h>
|
||||
#include <ioctl.h>
|
||||
#include <inetLib.h>
|
||||
#include <taskLib.h>
|
||||
#include <ioLib.h>
|
||||
#include <sockLib.h>
|
||||
#include <selectLib.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#include <netdb.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#ifdef SOLARIS
|
||||
#define BSD_COMP
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <net/if.h>
|
||||
|
||||
|
||||
static long BSgetBroadcastAddr(int soc, struct sockaddr* sin);
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* server mode functions */
|
||||
|
||||
#ifndef vxWorks /* server mode functions */
|
||||
static char* filename=(char*)NULL;
|
||||
|
||||
/* ----------------------------- */
|
||||
/* signal catcher for the server */
|
||||
/* ----------------------------- */
|
||||
static void catch_sig(int sig)
|
||||
{
|
||||
fprintf(stderr,"\nbdt server exiting\n");
|
||||
unlink(filename);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* -------------------------------- */
|
||||
/* child reaper for the server mode */
|
||||
/* -------------------------------- */
|
||||
static void get_child(int sig)
|
||||
{
|
||||
#ifdef SOLARIS
|
||||
while(waitpid(-1,(int*)NULL,WNOHANG)>0);
|
||||
#else
|
||||
while(wait3((int *)NULL,WNOHANG,(struct rusage *)NULL)>0);
|
||||
#endif
|
||||
|
||||
#if defined linux || defined SOLARIS
|
||||
signal(SIGCHLD,get_child); /* for reaping children */
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ------------------------------- */
|
||||
/* Clear the signals for a process */
|
||||
/* ------------------------------- */
|
||||
int BSserverClearSignals()
|
||||
{
|
||||
signal(SIGCHLD,SIG_DFL);
|
||||
signal(SIGHUP,SIG_DFL);
|
||||
signal(SIGINT,SIG_DFL);
|
||||
signal(SIGTERM,SIG_DFL);
|
||||
signal(SIGQUIT,SIG_DFL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------- */
|
||||
/* Make a unix process into a generic background process */
|
||||
/* ----------------------------------------------------- */
|
||||
int BSmakeServer(char** argv)
|
||||
{
|
||||
FILE* fd;
|
||||
|
||||
if(filename) return -1;
|
||||
|
||||
/* set up signal handling for the server */
|
||||
signal(SIGCHLD,get_child); /* for reaping children */
|
||||
signal(SIGHUP,catch_sig);
|
||||
signal(SIGINT,catch_sig);
|
||||
signal(SIGTERM,catch_sig);
|
||||
signal(SIGQUIT,catch_sig);
|
||||
|
||||
/* disconnect from parent */
|
||||
switch(fork())
|
||||
{
|
||||
case -1: /* error */
|
||||
perror("Cannot fork");
|
||||
return -1;
|
||||
case 0: /* child */
|
||||
#if defined linux || defined SOLARIS
|
||||
setpgrp();
|
||||
#else
|
||||
setpgrp(0,0);
|
||||
#endif
|
||||
setsid();
|
||||
break;
|
||||
default: /* parent goes away */
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* save process ID */
|
||||
filename=(char*)malloc(strlen(argv[0])+10);
|
||||
sprintf(filename,"%s.%d",argv[0],getpid());
|
||||
fd=fopen(filename,"w");
|
||||
fprintf(fd,"%d",getpid());
|
||||
fprintf(stderr,"\npv server pid: %d\n",getpid());
|
||||
fclose(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* server mode functions */
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
/* open a bulk data socket to a server given the server IP address */
|
||||
/* --------------------------------------------------------------- */
|
||||
|
||||
BS* BSipOpen(char* address, int Port)
|
||||
{
|
||||
struct hostent* pHostent;
|
||||
unsigned long addr;
|
||||
BSDATA info;
|
||||
struct sockaddr_in* tsin;
|
||||
|
||||
tsin=(struct sockaddr_in*)&(info.sin);
|
||||
|
||||
#ifndef vxWorks
|
||||
/* Deal with the name -vs- IP number issue. */
|
||||
if (isdigit(address[0]))
|
||||
{
|
||||
#endif
|
||||
addr=inet_addr(address);
|
||||
#ifndef vxWorks
|
||||
}
|
||||
else
|
||||
{
|
||||
if((pHostent=gethostbyname(address))==NULL) return NULL;
|
||||
memcpy((char*)&addr,pHostent->h_addr,sizeof(addr));
|
||||
}
|
||||
#endif
|
||||
|
||||
tsin->sin_port=htons(Port);
|
||||
tsin->sin_family=AF_INET;
|
||||
memcpy((char*)&(tsin->sin_addr),(char*)&addr,sizeof(addr));
|
||||
|
||||
return BSipOpenData(&info);
|
||||
}
|
||||
|
||||
BS* BSipOpenData(BSDATA* info)
|
||||
{
|
||||
struct sockaddr_in tsin;
|
||||
int osoc;
|
||||
BS* bdt;
|
||||
|
||||
tsin.sin_port=0;
|
||||
tsin.sin_family=AF_INET;
|
||||
tsin.sin_addr.s_addr=htonl(INADDR_ANY);
|
||||
|
||||
if((osoc=socket(AF_INET,SOCK_STREAM,BS_TCP))<0)
|
||||
{
|
||||
perror("BSipOpen: create socket failed");
|
||||
return (BS*)NULL;
|
||||
}
|
||||
|
||||
if((bind(osoc,(struct sockaddr*)&tsin,sizeof(tsin)))<0)
|
||||
{
|
||||
perror("BSipOpen: local address bind failed");
|
||||
return (BS*)NULL;
|
||||
}
|
||||
|
||||
if(connect(osoc,(struct sockaddr*)&(info->sin),sizeof(info->sin))<0)
|
||||
{
|
||||
perror("BSipOpen: connect failed");
|
||||
close(osoc);
|
||||
return (BS*)NULL;
|
||||
}
|
||||
|
||||
bdt=(BS*)malloc(sizeof(BS));
|
||||
bdt->soc=osoc;
|
||||
bdt->remaining_send=0;
|
||||
bdt->remaining_recv=0;
|
||||
bdt->state=BSidle;
|
||||
|
||||
#ifndef vxWorks
|
||||
{
|
||||
int j;
|
||||
j = fcntl(bdt->soc, F_GETFL, 0);
|
||||
fcntl(bdt->soc, F_SETFL, j|O_NDELAY);
|
||||
}
|
||||
#endif
|
||||
/* now connected to the bulk data socket on the IOC */
|
||||
return bdt;
|
||||
}
|
||||
|
||||
/* -------------------------------------- */
|
||||
/* write size bytes from buffer to socket */
|
||||
/* -------------------------------------- */
|
||||
int BSwrite(int soc,void* buffer,int size)
|
||||
{
|
||||
int rc;
|
||||
int total;
|
||||
unsigned char* data;
|
||||
fd_set fds;
|
||||
struct timeval to;
|
||||
|
||||
data=(unsigned char*)buffer;
|
||||
total=size;
|
||||
|
||||
to.tv_sec = 5;
|
||||
to.tv_usec = 0;
|
||||
|
||||
do
|
||||
{
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(soc, &fds);
|
||||
if(select(FD_SETSIZE,NULL,&fds,NULL,&to) != 1)
|
||||
{
|
||||
printf("BSwrite: timeout waiting to write data\n");
|
||||
return -1;
|
||||
}
|
||||
/* send block of data */
|
||||
if((rc=send(soc,(char*)&data[size-total],total,0))<0)
|
||||
{
|
||||
if(errno == EINTR)
|
||||
rc = 0;
|
||||
else
|
||||
perror("BSwrite: Send to remote failed");
|
||||
}
|
||||
else
|
||||
total-=rc;
|
||||
}
|
||||
while(rc>0 && total>0);
|
||||
|
||||
return (rc<=0)?-1:0;
|
||||
}
|
||||
|
||||
/* --------------------------------------- */
|
||||
/* send a message header down a BS socket */
|
||||
/* --------------------------------------- */
|
||||
int BSsendHeader(BS* bdt,unsigned short verb,int size)
|
||||
{
|
||||
BSmsgHead buf;
|
||||
|
||||
if(bdt->state!=BSidle)
|
||||
{
|
||||
fprintf(stderr,"BSsendHeader: Interface not idle\n");
|
||||
bdt->state=BSbad;
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf.verb=htons(verb);
|
||||
buf.size=htonl((unsigned long)size);
|
||||
|
||||
if(BSwrite(bdt->soc,&buf.verb, sizeof(buf.verb))<0)
|
||||
{
|
||||
fprintf(stderr,"BSsendHeader: write to remote failed");
|
||||
return -1;
|
||||
}
|
||||
if(BSwrite(bdt->soc,&buf.size, sizeof(buf.size))<0)
|
||||
{
|
||||
fprintf(stderr,"BSsendHeader: write to remote failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* don't wait for response if data must go out */
|
||||
if(size)
|
||||
{
|
||||
bdt->remaining_send=size;
|
||||
bdt->state=BSsData;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------- */
|
||||
/* send a message data chunk down a BS socket */
|
||||
/* ------------------------------------------- */
|
||||
int BSsendData(BS* bdt,void* buffer,int size)
|
||||
{
|
||||
int len;
|
||||
int remaining;
|
||||
int rc;
|
||||
|
||||
if(bdt->state!=BSsData)
|
||||
{
|
||||
fprintf(stderr,"BSsendData: Interface not in send data mode\n");
|
||||
bdt->state=BSbad;
|
||||
return -1;
|
||||
}
|
||||
|
||||
remaining=bdt->remaining_send-size;
|
||||
|
||||
if(remaining<0)
|
||||
{
|
||||
fprintf(stderr,"WARNING -- BSsendData: To much data to send\n");
|
||||
len=bdt->remaining_send;
|
||||
}
|
||||
else
|
||||
len=size;
|
||||
|
||||
if (BSwrite(bdt->soc, buffer, len) < 0)
|
||||
return -1;
|
||||
|
||||
bdt->remaining_send-=len;
|
||||
|
||||
if(bdt->remaining_send<0)
|
||||
{
|
||||
fprintf(stderr,"BSsendData: To much data Sent\n");
|
||||
bdt->remaining_send=0;
|
||||
}
|
||||
|
||||
if(bdt->remaining_send==0)
|
||||
bdt->state=BSidle;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int BSflushOutput(BS* bdt)
|
||||
{
|
||||
#ifdef vxWorks
|
||||
ioctl(bdt->soc, FIOWFLUSH, 0);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------- */
|
||||
/* Read exactly size bytes from remote */
|
||||
/* ------------------------------------- */
|
||||
int BSread(int soc,void* buffer,int size)
|
||||
{
|
||||
int rc,total;
|
||||
unsigned char* data;
|
||||
fd_set fds;
|
||||
struct timeval to;
|
||||
|
||||
to.tv_sec = 5;
|
||||
to.tv_usec = 0;
|
||||
|
||||
data=(unsigned char*)buffer;
|
||||
total=size;
|
||||
|
||||
do
|
||||
{
|
||||
#if 1
|
||||
/* wait for data chunk */
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(soc, &fds);
|
||||
if (select(soc+1, &fds, NULL, NULL, &to) != 1)
|
||||
{
|
||||
printf("BSread: timeout waiting for data\n");
|
||||
return(-1);
|
||||
}
|
||||
#endif
|
||||
if((rc=recv(soc,(char*)&data[size-total],total,0))<0)
|
||||
{
|
||||
if(errno==EINTR)
|
||||
{
|
||||
printf("BSread: EINTR");
|
||||
rc=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
perror("BSread: Receive data chunk failed");
|
||||
}
|
||||
}
|
||||
else
|
||||
total-=rc;
|
||||
}
|
||||
while(rc>0 && total>0);
|
||||
|
||||
return (rc<=0)?-1:0;
|
||||
}
|
||||
|
||||
/* ------------------------------------- */
|
||||
/* wait for a message header from remote */
|
||||
/* ------------------------------------- */
|
||||
int BSreceiveHeader(BS* bdt,int* verb,int* size)
|
||||
{
|
||||
BSmsgHead buf;
|
||||
|
||||
/* can only receive header when in the idle state */
|
||||
if (bdt->state == BSeof)
|
||||
return -1;
|
||||
|
||||
if(bdt->state != BSidle)
|
||||
{
|
||||
fprintf(stderr,"BSreceiveHeader: Interface not idle\n");
|
||||
bdt->state=BSbad;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(BSread(bdt->soc,&buf.verb,sizeof(buf.verb))<0)
|
||||
{
|
||||
fprintf(stderr,"BSreceiveHeader: Read failed\n");
|
||||
return -1;
|
||||
}
|
||||
if(BSread(bdt->soc,&buf.size,sizeof(buf.size))<0)
|
||||
{
|
||||
fprintf(stderr,"BSreceiveHeader: Read failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* copy message data to user */
|
||||
*verb=ntohs(buf.verb);
|
||||
*size=ntohl(buf.size);
|
||||
|
||||
if(*size)
|
||||
bdt->state=BSrData;
|
||||
|
||||
bdt->remaining_recv=*size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
Wait for a chunk of data from remote.
|
||||
User can continually call this with a maximum size until it return 0.
|
||||
------------------------------------------------------------------------ */
|
||||
int BSreceiveData(BS* bdt,void* buffer,int size)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* can only receive data when in the receive data state */
|
||||
switch(bdt->state)
|
||||
{
|
||||
case BSrData: break;
|
||||
case BSidle: return 0;
|
||||
default:
|
||||
fprintf(stderr,"BSreceiveData: bad receive state\n");
|
||||
bdt->state=BSbad;
|
||||
break;
|
||||
}
|
||||
|
||||
if (bdt->remaining_recv < size)
|
||||
size = bdt->remaining_recv;
|
||||
|
||||
if(BSread(bdt->soc,buffer,size)<0)
|
||||
{
|
||||
fprintf(stderr,"BSreceiveData: Read failed\n");
|
||||
bdt->state = BSeof;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bdt->remaining_recv-=size;
|
||||
|
||||
if(bdt->remaining_recv<0)
|
||||
{
|
||||
fprintf(stderr,"BSreceiveData: To much data received\n");
|
||||
bdt->remaining_recv=0;
|
||||
}
|
||||
|
||||
if(bdt->remaining_recv==0)
|
||||
bdt->state=BSidle;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/* -------------------- */
|
||||
/* close the connection */
|
||||
/* -------------------- */
|
||||
int BSclose(BS* bdt)
|
||||
{
|
||||
int verb,size,done;
|
||||
|
||||
/* send a close message out */
|
||||
if(BSsendHeader(bdt,BS_Close,0)<0)
|
||||
{
|
||||
fprintf(stderr,"BSclose: Cannot send close message\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
done=0;
|
||||
|
||||
do
|
||||
{
|
||||
/* check response */
|
||||
if(BSreceiveHeader(bdt,&verb,&size)<0)
|
||||
{
|
||||
fprintf(stderr,"BSclose: Close message response error\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch(verb)
|
||||
{
|
||||
case BS_Ok:
|
||||
done=1;
|
||||
break;
|
||||
case BS_Error:
|
||||
fprintf(stderr,"BSclose: Close rejected\n");
|
||||
return -1;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
while(done==0);
|
||||
|
||||
BSfreeBS(bdt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------- */
|
||||
/* make a listener socket for UDP - simple */
|
||||
/* --------------------------------------- */
|
||||
int BSopenListenerUDP(int Port)
|
||||
{
|
||||
int nsoc;
|
||||
struct sockaddr_in tsin;
|
||||
|
||||
tsin.sin_port=htons(Port);
|
||||
tsin.sin_family=AF_INET;
|
||||
tsin.sin_addr.s_addr=htonl(INADDR_ANY);
|
||||
|
||||
if((nsoc=socket(AF_INET,SOCK_DGRAM,BS_UDP))<0)
|
||||
{
|
||||
perror("BSopenListenerUDP: open socket failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if((bind(nsoc,(struct sockaddr*)&tsin,sizeof(tsin)))<0)
|
||||
{
|
||||
perror("BSopenListenerUDP: local bind failed");
|
||||
close(nsoc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return nsoc;
|
||||
}
|
||||
|
||||
/* --------------------------------------- */
|
||||
/* make a listener socket for TCP - simple */
|
||||
/* --------------------------------------- */
|
||||
int BSopenListenerTCP(int Port)
|
||||
{
|
||||
int nsoc;
|
||||
struct sockaddr_in tsin;
|
||||
|
||||
memset (&tsin, 0, sizeof(struct sockaddr_in));
|
||||
tsin.sin_port=htons(Port);
|
||||
tsin.sin_family=htons(AF_INET);
|
||||
tsin.sin_addr.s_addr=htonl(INADDR_ANY);
|
||||
|
||||
if((nsoc=socket(AF_INET,SOCK_STREAM,BS_TCP))<0)
|
||||
{
|
||||
perror("BSopenListenerTCP: open socket failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if((bind(nsoc,(struct sockaddr*)&tsin,sizeof(tsin)))<0)
|
||||
{
|
||||
perror("BSopenListenerTCP: local bind failed");
|
||||
close(nsoc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
listen(nsoc,5);
|
||||
return nsoc;
|
||||
}
|
||||
|
||||
/* ------------------------------- */
|
||||
/* make BS from a socket - simple */
|
||||
/* ------------------------------- */
|
||||
BS* BSmakeBS(int soc)
|
||||
{
|
||||
BS* bdt;
|
||||
bdt=(BS*)malloc(sizeof(BS));
|
||||
bdt->soc=soc;
|
||||
bdt->remaining_send=0;
|
||||
bdt->remaining_recv=0;
|
||||
bdt->state=BSidle;
|
||||
return bdt;
|
||||
}
|
||||
|
||||
/* --------------------------- */
|
||||
/* free a BS and close socket */
|
||||
/* --------------------------- */
|
||||
int BSfreeBS(BS* bdt)
|
||||
{
|
||||
close(bdt->soc);
|
||||
free(bdt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/*
|
||||
Next three function adjust the fields of the BSDATA structure.
|
||||
*/
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
int BSgetAddressPort(BSDATA* info, char* ip_addr, int* dest_port)
|
||||
{
|
||||
char* name;
|
||||
struct sockaddr_in* sin = (struct sockaddr_in*)&(info->sin);
|
||||
|
||||
*dest_port=sin->sin_port;
|
||||
name=inet_ntoa(sin->sin_addr);
|
||||
strcpy(ip_addr,name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BSsetAddressPort(BSDATA* info, char* ip_addr, int dest_port)
|
||||
{
|
||||
BSsetPort(info, dest_port);
|
||||
return BSsetAddress(info, ip_addr);
|
||||
}
|
||||
|
||||
int BSsetPort(BSDATA* info, int dest_port)
|
||||
{
|
||||
struct sockaddr_in* sin = (struct sockaddr_in*)&(info->sin);
|
||||
sin->sin_family=AF_INET;
|
||||
sin->sin_port=htons(dest_port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BSsetAddress(BSDATA* info, char* ip_addr)
|
||||
{
|
||||
struct hostent *pHostent;
|
||||
struct sockaddr_in* sin = (struct sockaddr_in*)&(info->sin);
|
||||
unsigned long addr;
|
||||
|
||||
sin->sin_family=AF_INET;
|
||||
|
||||
#ifndef vxWorks
|
||||
/* Deal with the name -vs- IP number issue. */
|
||||
if (isdigit(ip_addr[0]))
|
||||
{
|
||||
#endif
|
||||
if((addr=inet_addr(ip_addr))==-1)
|
||||
return -1;
|
||||
else
|
||||
memcpy((char*)&(sin->sin_addr),(char*)&addr,sizeof(addr));
|
||||
#ifndef vxWorks
|
||||
}
|
||||
else
|
||||
{
|
||||
if((pHostent=gethostbyname(ip_addr))==NULL) return -1;
|
||||
memcpy((char*)&addr,pHostent->h_addr,sizeof(addr));
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
/*
|
||||
All this function does is send a broadcast message and return the
|
||||
addressing info to the caller of a responder to the broadcast.
|
||||
|
||||
arguments:
|
||||
soc - broadcast socket to use for sending data
|
||||
trys - number of times to send if no response
|
||||
o_info - outgoing BSDATA, address/port info
|
||||
i_info - incoming BSDATA, address/port where response came from
|
||||
omsg/osize - outgoing message and size
|
||||
imsg/isize - incoming message and buffer size
|
||||
|
||||
Returns the number of bytes read.
|
||||
*/
|
||||
/* ----------------------------------------------------------------- */
|
||||
|
||||
int BSbroadcastTrans(int soc,int trys,BSDATA* o_info,BSDATA* i_info,
|
||||
void* omsg,int osize,void* imsg,int isize)
|
||||
{
|
||||
int i;
|
||||
int rc=0;
|
||||
|
||||
for(i=0;rc==0 && i<trys;i++)
|
||||
{
|
||||
/* send out the message */
|
||||
rc=BSwriteUDP(soc,o_info,omsg,osize);
|
||||
if(rc<0) return rc;
|
||||
|
||||
/* wait for a response */
|
||||
rc=BSreadUDP(soc,i_info,1,imsg,isize);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int BSbroadcast(int soc,BSDATA* o_info, void* omsg,int osize)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* send out the message */
|
||||
rc=BSwriteUDP(soc,o_info,omsg,osize);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/*
|
||||
This function waits for a message and sends out an ACK when it gets one.
|
||||
addressing info to the caller of a responder to the broadcast.
|
||||
|
||||
Lots of arguments:
|
||||
|
||||
soc - The socket to send the message down.
|
||||
info - The socket information telling where the data read came from
|
||||
(returned to the user).
|
||||
tout - Timeout for read in seconds. 0=no wait, -1=wait forever.
|
||||
buf - Buffer to populate with read data.
|
||||
size - Size of the buf.
|
||||
|
||||
returns the length the read message, 0 is timeout, -1 is error
|
||||
*/
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
int BSreadUDP(int soc,BSDATA* info,BS_ULONG tout,void* buf,int size)
|
||||
{
|
||||
int mlen,rc;
|
||||
fd_set fds;
|
||||
struct timeval to;
|
||||
int error=0;
|
||||
|
||||
do
|
||||
{
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(soc, &fds);
|
||||
|
||||
if(tout==-1)
|
||||
rc=select(FD_SETSIZE,&fds,NULL,NULL,NULL);
|
||||
else
|
||||
{
|
||||
to.tv_sec=tout;
|
||||
to.tv_usec=0;
|
||||
rc=select(FD_SETSIZE,&fds,NULL,NULL,&to);
|
||||
}
|
||||
|
||||
switch(rc)
|
||||
{
|
||||
case -1: /* bad */
|
||||
switch(errno)
|
||||
{
|
||||
case EINTR: break;
|
||||
default: error=-1; break;
|
||||
}
|
||||
break;
|
||||
case 0: /* timeout */
|
||||
break;
|
||||
default: /* data ready */
|
||||
break;
|
||||
}
|
||||
}
|
||||
while(rc<0 && error==0);
|
||||
|
||||
error=0;
|
||||
|
||||
if(rc>0)
|
||||
{
|
||||
error=0;
|
||||
do
|
||||
{
|
||||
info->len=sizeof(info->sin);
|
||||
mlen=recvfrom(soc,(char*)buf,size,0, &info->sin,&info->len);
|
||||
|
||||
if(mlen<0)
|
||||
{
|
||||
switch(errno)
|
||||
{
|
||||
case EINTR: break;
|
||||
default: error=-1; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
while(mlen<0 && error==0);
|
||||
|
||||
if(mlen<0)
|
||||
rc=-1;
|
||||
else
|
||||
rc=mlen;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/*
|
||||
Write a chuck of data to a UDP socket at an internet address
|
||||
*/
|
||||
/*-----------------------------------------------------------------------*/
|
||||
int BSwriteDataUDP(int soc,int dest_port,char* ip_addr,void* buf,int size)
|
||||
{
|
||||
BSDATA data;
|
||||
|
||||
BSsetAddress(&data,ip_addr);
|
||||
BSsetPort(&data,dest_port);
|
||||
|
||||
return BSwriteUDP(soc,&data,buf,size);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/*
|
||||
Write a chunk of data to a UDP socket using BSDATA.
|
||||
Arguments:
|
||||
*/
|
||||
/*-----------------------------------------------------------------------*/
|
||||
int BSwriteUDP(int soc,BSDATA* info,void* obuf,int osize)
|
||||
{
|
||||
int mlen;
|
||||
|
||||
mlen=sendto(soc,(char*)obuf,osize,0,&info->sin,sizeof(info->sin));
|
||||
|
||||
return mlen;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/*
|
||||
Write/Read a chuck of data to a UDP socket using BSDATA.
|
||||
Arguments:
|
||||
soc - socket to send message down and read from
|
||||
info - address/port to send message to
|
||||
obuf/osize - outgoing message and size of it.
|
||||
ibuf/isize - incoming message and size of the buffer.
|
||||
|
||||
Returns the number of bytes read, -1 for error.
|
||||
*/
|
||||
/*-----------------------------------------------------------------------*/
|
||||
int BStransUDP(int soc,BSDATA* info,void* obuf,int osize,void* ibuf,int isize)
|
||||
{
|
||||
int done,i,mlen,flen;
|
||||
struct sockaddr fromsin;
|
||||
fd_set fds;
|
||||
struct timeval tout;
|
||||
|
||||
done=0;
|
||||
mlen=0;
|
||||
|
||||
for(i=0;i<BS_RETRY_COUNT && done==0;i++)
|
||||
{
|
||||
mlen=sendto(soc,(char*)obuf,osize,0,&(info->sin),sizeof(info->sin));
|
||||
if(mlen<0)
|
||||
{
|
||||
printf("send failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tout.tv_sec=0;
|
||||
tout.tv_usec=200000;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(soc,&fds);
|
||||
|
||||
switch(select(FD_SETSIZE,&fds,(fd_set*)0,(fd_set*)0,&tout))
|
||||
{
|
||||
case 0: /* timeout */ break;
|
||||
case -1: /* error */
|
||||
printf("select failed\n");
|
||||
return -1;
|
||||
default: /* data ready */
|
||||
flen=sizeof(fromsin);
|
||||
mlen=recvfrom(soc,(char*)ibuf,isize,0,&fromsin,&flen);
|
||||
if(mlen<0) return -1;
|
||||
done=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(i>=BS_RETRY_COUNT) return 0;
|
||||
|
||||
return mlen;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/*
|
||||
Open a broadcast socket and set port to a default.
|
||||
*/
|
||||
/*-----------------------------------------------------------------------*/
|
||||
int BSipBroadcastOpen(BSDATA* info, int default_dest_port)
|
||||
{
|
||||
struct sockaddr_in* sin;
|
||||
int soc;
|
||||
|
||||
sin=(struct sockaddr_in*)&(info->sin);
|
||||
|
||||
if( (soc=BSgetBroadcastSocket(0,sin)) <0) return -1;
|
||||
|
||||
sin->sin_port=htons(default_dest_port);
|
||||
|
||||
return soc;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/*
|
||||
BSgetBroadcastSocket() - return a broadcast socket for a port, return
|
||||
a sockaddr also.
|
||||
*/
|
||||
/*-----------------------------------------------------------------------*/
|
||||
int BSgetBroadcastSocket(int port, struct sockaddr_in* sin)
|
||||
{
|
||||
int on=1;
|
||||
int soc;
|
||||
BS bs;
|
||||
|
||||
sin->sin_port=htons(port);
|
||||
sin->sin_family=AF_INET;
|
||||
sin->sin_addr.s_addr=htonl(INADDR_ANY);
|
||||
|
||||
if( (soc=socket(AF_INET,SOCK_DGRAM,BS_UDP)) < 0 )
|
||||
{
|
||||
perror("socket create failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
setsockopt(soc,SOL_SOCKET,SO_BROADCAST,(char*)&on,sizeof(on));
|
||||
|
||||
if( bind(soc,(struct sockaddr*)sin,sizeof(struct sockaddr_in)) < 0 )
|
||||
{
|
||||
perror("socket bind failed");
|
||||
close(soc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( BSgetBroadcastAddr(soc,(struct sockaddr*)sin) < 0 )
|
||||
return -1;
|
||||
|
||||
return soc;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/*
|
||||
BSgetBroadcastAddr() - Determine the broadcast address, this is
|
||||
directly from the Sun Network Programmer's guide.
|
||||
*/
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static long BSgetBroadcastAddr(int soc, struct sockaddr* sin)
|
||||
{
|
||||
struct ifconf ifc;
|
||||
struct ifreq* ifr;
|
||||
struct ifreq* save;
|
||||
char buf[BUFSIZ];
|
||||
int tot,i;
|
||||
|
||||
ifc.ifc_len = sizeof(buf);
|
||||
ifc.ifc_buf = buf;
|
||||
if(ioctl(soc,SIOCGIFCONF,(int)&ifc) < 0)
|
||||
{ perror("ioctl SIOCGIFCONF failed"); return -1; }
|
||||
|
||||
ifr = ifc.ifc_req;
|
||||
tot = ifc.ifc_len/sizeof(struct ifreq);
|
||||
save=(struct ifreq*)NULL;
|
||||
i=0;
|
||||
|
||||
do
|
||||
{
|
||||
if(ifr[i].ifr_addr.sa_family==AF_INET)
|
||||
{
|
||||
if(ioctl(soc,SIOCGIFFLAGS,(int)&ifr[i])<0)
|
||||
{ perror("ioctl SIOCGIFFLAGS failed"); return -1; }
|
||||
|
||||
if( (ifr[i].ifr_flags&IFF_UP) &&
|
||||
!(ifr[i].ifr_flags&IFF_LOOPBACK) &&
|
||||
(ifr[i].ifr_flags&IFF_BROADCAST))
|
||||
{ save=&ifr[i]; }
|
||||
}
|
||||
} while( !save && ++i<tot );
|
||||
|
||||
if(save)
|
||||
{
|
||||
if(ioctl(soc,SIOCGIFBRDADDR,(int)save)<0)
|
||||
{ perror("ioctl SIOCGIFBRDADDR failed"); return -1; }
|
||||
|
||||
memcpy((char*)sin,(char*)&save->ifr_broadaddr,
|
||||
sizeof(save->ifr_broadaddr));
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
187
src/dbtools/BSlib.h
Normal file
187
src/dbtools/BSlib.h
Normal file
@@ -0,0 +1,187 @@
|
||||
#ifndef ___BS_H
|
||||
#define ___BS_H
|
||||
|
||||
/*
|
||||
* $Log$
|
||||
*/
|
||||
|
||||
/*
|
||||
Author: Jim Kowalkowski
|
||||
Date: 9/1/95
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
/* got from protocols(5) (cheated) or /etc/protocols */
|
||||
#define BS_UDP 17
|
||||
#define BS_TCP 6
|
||||
|
||||
/* server ports - in the user reserved area - above 50000 */
|
||||
#define BS_UDP_PORT 50296
|
||||
#define BS_TCP_PORT 50297
|
||||
|
||||
/* message types */
|
||||
#define BS_Ok 0
|
||||
#define BS_Error 1
|
||||
#define BS_Close 2
|
||||
#define BS_Ping 3
|
||||
|
||||
#define BS_LAST_VERB 3
|
||||
#define BS_RETRY_COUNT 3
|
||||
|
||||
/* protocol states */
|
||||
typedef enum { BSidle,BSunbound,BSsData,BSrData,BSbad,BSeof } BSstate;
|
||||
|
||||
struct bs
|
||||
{
|
||||
int soc;
|
||||
int remaining_send;
|
||||
int remaining_recv;
|
||||
BSstate state;
|
||||
};
|
||||
typedef struct bs BS;
|
||||
|
||||
struct bs_udp_data
|
||||
{
|
||||
struct sockaddr sin;
|
||||
int len;
|
||||
};
|
||||
typedef struct bs_udp_data BSDATA;
|
||||
|
||||
struct BSmsgHead
|
||||
{
|
||||
unsigned short verb;
|
||||
unsigned long size;
|
||||
};
|
||||
typedef struct BSmsgHead BSmsgHead;
|
||||
|
||||
typedef unsigned long BS_ULONG;
|
||||
|
||||
#define BSgetSocket(BS) (BS->soc)
|
||||
#define BSgetResidualWrite(BS) (BS->remaining_send)
|
||||
#define BSgetResidualRead(BS) (BS->remaining_recv)
|
||||
#define BSgetProtoState(BS) (BS->state)
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
Server functions:
|
||||
|
||||
BSopenListenerTCP:
|
||||
Open a socket locally bound to the bulk data transfer TCP server port.
|
||||
Set the socket up as a listener. Return the open socket.
|
||||
|
||||
BSopenListenerUDP:
|
||||
Open a socket locally bound to the bulk data transfer UDP server port.
|
||||
Return the open socket.
|
||||
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
int BSopenListenerTCP(int Port);
|
||||
int BSopenListenerUDP(int Port);
|
||||
int BSopenTCP(BSDATA*);
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
Utilities functions:
|
||||
|
||||
BSmakeServer:
|
||||
Available under unix only. Put process in the background, disassociate
|
||||
process from controlling terminal and parent process, and prepare
|
||||
signals for reaping children spawned by the process.
|
||||
|
||||
BSserverClearSignals:
|
||||
Clear the signal handlers for a process, set them to default.
|
||||
|
||||
BSmakeBS:
|
||||
Allocate and initialize a BS from a socket.
|
||||
|
||||
BSfreeBS:
|
||||
Close the open socket and free the memory for the BS.
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
#ifndef vxWorks
|
||||
int BSmakeServer(char** argv);
|
||||
int BSserverClearSignals();
|
||||
#endif
|
||||
|
||||
BS* BSmakeBS(int socket); /* make a BS from a socket */
|
||||
int BSfreeBS(BS* bdt); /* free a BS */
|
||||
|
||||
int BSgetBroadcastSocket(int port, struct sockaddr_in* sin);
|
||||
int BSipBroadcastOpen(BSDATA* info, int default_dest_port);
|
||||
int BSgetAddressPort(BSDATA* info,char* ip_addr, int* dest_port);
|
||||
int BSsetAddressPort(BSDATA* info,char* ip_addr, int dest_port);
|
||||
int BSsetAddress(BSDATA* info,char* ip_addr);
|
||||
int BSsetPort(BSDATA* info,int dest_port);
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
UDP functions:
|
||||
------------------------------------------------------------------------ */
|
||||
int BStransUDP(int soc,BSDATA* info,void* obuf,int osize,void* ibuf,int isize);
|
||||
int BSwriteUDP(int soc,BSDATA* info,void* obuf,int osize);
|
||||
int BSwriteDataUDP(int soc,int dest_port, char* ip_addr,void* obuf,int osize);
|
||||
int BSreadUDP(int soc,BSDATA* info,BS_ULONG tout,void* buf,int size);
|
||||
int BSbroadcast(int soc,BSDATA* info,void* buf,int size);
|
||||
int BSbroadcastTrans(int soc,int trys,BSDATA* o_info,BSDATA* i_info,
|
||||
void* obuf,int osize,void* ibuf,int isize);
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
Client functions:
|
||||
|
||||
BSipOpen:
|
||||
Open a connection to an bulk data transfer given the IP address of the
|
||||
machine where the server exists. The returned BS is returned unbound,
|
||||
a connect must be issued before data transactions can take place.
|
||||
|
||||
BSclose:
|
||||
Completely close a connection to a server and free the BS.
|
||||
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
BS* BSipOpen(char* address, int port);
|
||||
BS* BSipOpenData(BSDATA* info);
|
||||
int BSclose(BS* bdt);
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
Client and Server shared functions:
|
||||
|
||||
BSsendHeader:
|
||||
Send a message header out to a connect BS with command and message body
|
||||
size information.
|
||||
|
||||
BSsendData:
|
||||
Send a portion or all the message body out a connected BS. A header
|
||||
must have previously been sent with length information. The interface
|
||||
will only allow the amount of data specified in the header to be sent.
|
||||
|
||||
BSwrite:
|
||||
This call will block until all the data specified in the size parameter
|
||||
are sent down the socket.
|
||||
|
||||
BSread:
|
||||
This call will block until all the data specified in the size parameter
|
||||
is read from the socket.
|
||||
|
||||
BSreceiveHeader:
|
||||
Wait until a message header appears at the BS, return the action and
|
||||
remaining message body size.
|
||||
|
||||
BSreceiveData:
|
||||
Wait for a chunk or the entire body of a message to appear at the BS.
|
||||
Put the data into the buffer for a maximum size. Return the amount of
|
||||
data actually received, or zero if there is no data remaining for the
|
||||
current message.
|
||||
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
int BSsendHeader(BS* bdt, unsigned short verb, int size);
|
||||
int BSsendData(BS* bdt, void* buffer, int size);
|
||||
int BSreceiveHeader(BS* bdt, int* verb, int* size);
|
||||
int BSreceiveData(BS* bdt, void* buffer, int size);
|
||||
int BSread(int socket, void* buffer, int size);
|
||||
int BSwrite(int socket, void* buffer, int size);
|
||||
int BSflushOutput(BS* bdt);
|
||||
|
||||
#endif
|
||||
|
||||
18
src/dbtools/PVS.h
Normal file
18
src/dbtools/PVS.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef __PVS_H
|
||||
#define __PVS_H
|
||||
|
||||
#include "BSlib.h"
|
||||
|
||||
#define PVS_RETRY_COUNT 4
|
||||
#define PVS_TRANSFER_SIZE 1024
|
||||
#define PVS_UDP 17
|
||||
#define PVS_TCP 6
|
||||
#define PVS_UDP_PORT 50298
|
||||
#define PVS_TCP_PORT 50299
|
||||
#define PVS_UDP_CPORT 50300
|
||||
|
||||
#define PVS_Request (BS_LAST_VERB+1)
|
||||
#define PVS_Data (BS_LAST_VERB+2)
|
||||
#define PVS_Alive (BS_LAST_VERB+3)
|
||||
|
||||
#endif
|
||||
88
src/dbtools/PVSget.c
Normal file
88
src/dbtools/PVSget.c
Normal file
@@ -0,0 +1,88 @@
|
||||
|
||||
/* only runable on work station now */
|
||||
|
||||
#include "PVS.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc,char** argv)
|
||||
{
|
||||
BS* bs;
|
||||
int verb,size,done,len,i;
|
||||
char* buffer;
|
||||
BSDATA info;
|
||||
|
||||
if(argc<2)
|
||||
{
|
||||
printf("Enter IOC name on command line\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
done=0;
|
||||
buffer=(char*)malloc(PVS_TRANSFER_SIZE);
|
||||
|
||||
if(BSsetAddressPort(&info,argv[1],PVS_TCP_PORT)<0)
|
||||
{
|
||||
printf("Failed to locate IOC host name\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if((bs=BSipOpenData(&info))==NULL)
|
||||
{
|
||||
printf("open of socket to IOC failed\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
while(done==0)
|
||||
{
|
||||
printf("Begin----------\n");
|
||||
/* read messages until close received */
|
||||
if(BSreceiveHeader(bs,&verb,&size)<0)
|
||||
{
|
||||
printf("receive failed from socket\n");
|
||||
done=-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(verb)
|
||||
{
|
||||
case PVS_Data: /* read a block of names */
|
||||
printf("got PVS_Data msg, size=%d\n",size);
|
||||
|
||||
if((len=BSreceiveData(bs,buffer,size))<0)
|
||||
{
|
||||
printf("receive data failed\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i=0;i<len;i++)
|
||||
{
|
||||
if(buffer[i]!=' ')
|
||||
putchar(buffer[i]);
|
||||
else
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
putchar('\n');
|
||||
break;
|
||||
case BS_Close: /* transfers complete */
|
||||
printf("got BS_Close\n");
|
||||
BSsendHeader(bs,BS_Ok,0);
|
||||
done=-1;
|
||||
break;
|
||||
default:
|
||||
printf("unknown message type received from remote\n");
|
||||
if(size>0) done=-1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("Closing connection\n");
|
||||
BSfreeBS(bs);
|
||||
}
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
214
src/dbtools/PVSserver.c
Normal file
214
src/dbtools/PVSserver.c
Normal file
@@ -0,0 +1,214 @@
|
||||
|
||||
/* only runable on work station now */
|
||||
|
||||
#include "PVS.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct PVSnode
|
||||
{
|
||||
BSDATA info;
|
||||
int alive;
|
||||
struct PVSnode* next;
|
||||
};
|
||||
typedef struct PVSnode PVSNODE;
|
||||
|
||||
static PVSNODE* ioc_list = (PVSNODE*)NULL;
|
||||
|
||||
static int read_pvs(BSDATA* info);
|
||||
|
||||
int main(int argc,char** argv)
|
||||
{
|
||||
int soc,mlen;
|
||||
unsigned short buf,in_buf,ping;
|
||||
BSDATA info;
|
||||
PVSNODE* node;
|
||||
|
||||
if(BSmakeServer(argv)<0)
|
||||
{
|
||||
fprintf(stderr,"Cannot make into a server\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if((soc=BSopenListenerUDP(PVS_UDP_PORT))<0)
|
||||
{
|
||||
fprintf(stderr,"Open of UDP listener socket failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf=htons(BS_Ok); /* always sends this out */
|
||||
ping=htons(BS_Ping); /* always sends this out */
|
||||
|
||||
while(1)
|
||||
{
|
||||
/* wait forever until a message comes in */
|
||||
|
||||
mlen=BSreadUDP(soc,&info,7,&in_buf,sizeof(in_buf));
|
||||
|
||||
/* check for errors */
|
||||
switch(mlen)
|
||||
{
|
||||
case 0: /* timeout */
|
||||
printf("Why did a timeout occur?\n");
|
||||
/* send out a ping to each of the IOCs in the ioc_list */
|
||||
for(node=ioc_list;node;node=node->next)
|
||||
{
|
||||
mlen=BStransUDP(soc,&(node->info),&ping,sizeof(ping),
|
||||
&in_buf,sizeof(in_buf));
|
||||
|
||||
/* check for errors */
|
||||
switch(mlen)
|
||||
{
|
||||
case 0: /* timeout */
|
||||
printf("IOC dead\n");
|
||||
node->alive=0;
|
||||
break;
|
||||
case -1: /* error */
|
||||
printf("Communications failed\n");
|
||||
break;
|
||||
default: /* ok */
|
||||
if(node->alive==0)
|
||||
{
|
||||
switch(fork())
|
||||
{
|
||||
case -1: /* error */
|
||||
perror("fork failure");
|
||||
break;
|
||||
case 0: /* child */
|
||||
close(soc);
|
||||
BSserverClearSignals();
|
||||
sleep(1);
|
||||
if(read_pvs(&(node->info))==0)
|
||||
node->alive=1;
|
||||
default: /* parent */
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case -1: /* error */
|
||||
fprintf(stderr,"Communications failure\n");
|
||||
break;
|
||||
default: /* ok */
|
||||
if(BSwriteUDP(soc,&info,&buf,sizeof(buf))<0)
|
||||
fprintf(stderr,"respone send failed\n");
|
||||
else
|
||||
{
|
||||
node=(PVSNODE*)malloc(sizeof(PVSNODE));
|
||||
node->alive=1;
|
||||
node->info=info;
|
||||
BSsetPort(&(node->info),PVS_UDP_CPORT);
|
||||
node->next=ioc_list;
|
||||
ioc_list=node;
|
||||
|
||||
switch(fork())
|
||||
{
|
||||
case -1: /* error */
|
||||
perror("fork failure");
|
||||
break;
|
||||
case 0: /* child */
|
||||
close(soc);
|
||||
BSserverClearSignals();
|
||||
sleep(1);
|
||||
return read_pvs(&info);
|
||||
default: /* parent */
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
close(soc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_pvs(BSDATA* info)
|
||||
{
|
||||
BS* bs;
|
||||
int verb,size,done,len,i,port;
|
||||
char* buffer;
|
||||
char ip_from[40];
|
||||
FILE* fd;
|
||||
|
||||
BSgetAddressPort(info,ip_from,&port);
|
||||
|
||||
printf("IOC %s starting\n",ip_from);
|
||||
|
||||
/* verify ioc not already added */
|
||||
if(access(ip_from,F_OK)==0)
|
||||
{
|
||||
/* delete the existing file for this IOC */
|
||||
unlink(ip_from);
|
||||
}
|
||||
|
||||
buffer=(char*)malloc(PVS_TRANSFER_SIZE+2);
|
||||
done=0;
|
||||
BSsetPort(info,PVS_TCP_PORT);
|
||||
|
||||
if((bs=BSipOpenData(info))==NULL)
|
||||
{
|
||||
fprintf(stderr,"Open of socket to IOC failed\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if((fd=fopen(ip_from,"w"))==(FILE*)NULL)
|
||||
{
|
||||
fprintf(stderr,"Open of name file failed\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
while(done==0)
|
||||
{
|
||||
/* read messages until close received */
|
||||
if(BSreceiveHeader(bs,&verb,&size)<0)
|
||||
{
|
||||
fprintf(stderr,"Receive header failed\n");
|
||||
done=-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(verb)
|
||||
{
|
||||
case PVS_Data: /* read a block of names */
|
||||
if((len=BSreceiveData(bs,buffer,size))<0)
|
||||
{
|
||||
fprintf(stderr,"Receive data failed\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i=0;i<len;i++)
|
||||
{
|
||||
if(buffer[i]==' ') buffer[i]='\n';
|
||||
}
|
||||
buffer[len]='\n';
|
||||
buffer[len+1]='\0';
|
||||
|
||||
fputs(buffer,fd);
|
||||
}
|
||||
break;
|
||||
case BS_Close: /* transfers complete */
|
||||
if(BSsendHeader(bs,BS_Ok,0)<0)
|
||||
{
|
||||
fprintf(stderr,"ACK Header send failed\n");
|
||||
}
|
||||
done=-1;
|
||||
break;
|
||||
default:
|
||||
if(size>0) done=-1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(fd);
|
||||
}
|
||||
BSfreeBS(bs);
|
||||
}
|
||||
free(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
232
src/dbtools/PVSvx.c
Normal file
232
src/dbtools/PVSvx.c
Normal file
@@ -0,0 +1,232 @@
|
||||
|
||||
#include "PVS.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef vxWorks
|
||||
#include <vxWorks.h>
|
||||
#include <iv.h>
|
||||
#include <taskLib.h>
|
||||
#include <dbStaticLib.h>
|
||||
|
||||
extern struct dbBase *pdbBase;
|
||||
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
static void PVSserver(int want_annouce,char* name);
|
||||
static int PVSannouce(int want_annouce,char* name);
|
||||
|
||||
#ifdef vxWorks
|
||||
int PVSstart(int want_annouce, char* name)
|
||||
#else
|
||||
int main(int argc,char** argv)
|
||||
#endif
|
||||
{
|
||||
#ifndef vxWorks
|
||||
char* name;
|
||||
int want_annouce;
|
||||
#endif
|
||||
|
||||
#ifndef vxWorks
|
||||
if(argc<3)
|
||||
{
|
||||
fprintf(stderr,"bad args\n");
|
||||
fprintf(stderr," usage: %s a_flag host_name\n",
|
||||
argv[0]);
|
||||
fprintf(stderr," where\n");
|
||||
fprintf(stderr," a_flag=0(want),1(don't want) to annouce boot\n");
|
||||
fprintf(stderr," host_name=PV master host (if one exists)\n");
|
||||
return -1;
|
||||
}
|
||||
name=argv[2];
|
||||
if(sscanf(argv[1],"%d",&want_annouce)<1)
|
||||
{
|
||||
fprintf(stderr,"bad a_flag\n");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef vxWorks
|
||||
taskSpawn("PVS",150,VX_FP_TASK|VX_STDIO,5000,
|
||||
(FUNCPTR)PVSserver,want_annouce,(int)name,0,0,0,0,0,0,0,0);
|
||||
#else
|
||||
PVSserver(want_annouce,name);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int PVSannouce(int want_annouce,char* name)
|
||||
{
|
||||
int soc,mlen;
|
||||
unsigned short buf,in_buf;
|
||||
BSDATA info,in_info;
|
||||
|
||||
if(want_annouce==0 && name)
|
||||
{
|
||||
if((soc=BSopenListenerUDP(0))<0)
|
||||
{
|
||||
printf("Open of UDP socket failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(BSsetAddressPort(&info,name,PVS_UDP_PORT)<0)
|
||||
{
|
||||
printf("Set send port failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf=htons(PVS_Alive);
|
||||
mlen=BStransUDP(soc,&info,&buf,sizeof(buf),&in_buf,sizeof(in_buf));
|
||||
|
||||
/* check for errors */
|
||||
switch(mlen)
|
||||
{
|
||||
case 0: /* timeout */
|
||||
printf("No server running on host\n");
|
||||
break;
|
||||
case -1: /* error */
|
||||
printf("Communications failed\n");
|
||||
break;
|
||||
default: /* ok */
|
||||
break;
|
||||
}
|
||||
|
||||
close(soc);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void PVSserver(int want_annouce,char* name)
|
||||
{
|
||||
fd_set fds,rfds;
|
||||
int tsoc,usoc,nsoc,len,s;
|
||||
unsigned short buf;
|
||||
unsigned long names_len,nl;
|
||||
struct sockaddr stemp;
|
||||
int stemp_len;
|
||||
char* names;
|
||||
char* n;
|
||||
BSDATA info;
|
||||
BS* bs;
|
||||
long rc;
|
||||
#ifdef vxWorks
|
||||
DBENTRY db;
|
||||
#endif
|
||||
|
||||
bs=(BS*)NULL;
|
||||
names=(char*)malloc(PVS_TRANSFER_SIZE);
|
||||
|
||||
if((tsoc=BSopenListenerTCP(PVS_TCP_PORT))<0)
|
||||
{
|
||||
printf("PVSserver: Open of TCP listener socket failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if((usoc=BSopenListenerUDP(PVS_UDP_CPORT))<0)
|
||||
{
|
||||
printf("PVSserver: Open of UDP listener socket failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(tsoc,&fds);
|
||||
FD_SET(usoc,&fds);
|
||||
|
||||
PVSannouce(want_annouce,name);
|
||||
|
||||
while(1)
|
||||
{
|
||||
rfds=fds;
|
||||
if(select(FD_SETSIZE,&rfds,(fd_set*)NULL,(fd_set*)NULL,
|
||||
(struct timeval*)NULL)<0)
|
||||
{
|
||||
printf("PVSserver: Select failure\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(FD_ISSET(tsoc,&rfds))
|
||||
{
|
||||
/* only requests for PVs will come in here for now */
|
||||
/* handle the request here - single threaded server */
|
||||
|
||||
stemp_len=sizeof(stemp);
|
||||
if((nsoc=accept(tsoc,&stemp,&stemp_len))<0)
|
||||
printf("PVSserver: Bad accept\n");
|
||||
else
|
||||
{
|
||||
bs=BSmakeBS(nsoc);
|
||||
#ifdef vxWorks
|
||||
dbInitEntry(pdbBase,&db);
|
||||
names_len=0;
|
||||
for(rc=dbFirstRecdes(&db);rc==0;rc=dbNextRecdes(&db))
|
||||
{
|
||||
for(rc=dbFirstRecord(&db);rc==0;rc=dbNextRecord(&db))
|
||||
{
|
||||
/* collect the names util we excede the max */
|
||||
n=dbGetRecordName(&db);
|
||||
s=strlen(n);
|
||||
if((names_len+s)>PVS_TRANSFER_SIZE)
|
||||
{
|
||||
names[names_len++]='\0';
|
||||
if(BSsendHeader(bs,PVS_Data,names_len)<0)
|
||||
printf("PVSserver: data cmd failed\n");
|
||||
else
|
||||
{
|
||||
if(BSsendData(bs,names,names_len)<0)
|
||||
printf("PVSserver: data send failed\n");
|
||||
}
|
||||
names_len=0;
|
||||
}
|
||||
memcpy(&names[names_len],n,s);
|
||||
names_len+=s;
|
||||
names[names_len++]=' ';
|
||||
}
|
||||
}
|
||||
if(names_len>0)
|
||||
{
|
||||
names[names_len++]='\0';
|
||||
if(BSsendHeader(bs,PVS_Data,names_len)<0)
|
||||
printf("PVSserver: data cmd failed\n");
|
||||
else
|
||||
{
|
||||
if(BSsendData(bs,names,names_len)<0)
|
||||
printf("PVSserver: data send failed\n");
|
||||
}
|
||||
}
|
||||
#else
|
||||
strcpy(names,"jim Kowalkowski");
|
||||
names_len=strlen("jim kowalkowski")+1;
|
||||
if(BSsendHeader(bs,PVS_Data,names_len)<0)
|
||||
printf("BSsendHeader failed\n");
|
||||
else
|
||||
{
|
||||
if(BSsendData(bs,names,names_len)<0)
|
||||
printf("BSsendData failed\n");
|
||||
}
|
||||
#endif
|
||||
BSclose(bs);
|
||||
}
|
||||
}
|
||||
if(FD_ISSET(usoc,&rfds))
|
||||
{
|
||||
/* only pings will come in here for now */
|
||||
len=BSreadUDP(usoc,&info,0,&buf,sizeof(buf));
|
||||
if(len<=0)
|
||||
printf("PVSserver: UDP listener read failure\n");
|
||||
else
|
||||
{
|
||||
if(BSwriteUDP(usoc,&info,&buf,sizeof(buf))<0)
|
||||
printf("PVSserver: UDP listener ping write failure\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user