Initial revision
This commit is contained in:
37
src/ca/lookup_addr_test.c
Normal file
37
src/ca/lookup_addr_test.c
Normal file
@@ -0,0 +1,37 @@
|
||||
#include <types.h>
|
||||
#include <socket.h>
|
||||
#include <in.h>
|
||||
#include <netdb.h>
|
||||
#include <inet.h>
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
struct in_addr net_addr;
|
||||
struct hostent *ent;
|
||||
struct hostent *gethostbyaddr();
|
||||
|
||||
unsigned long net;
|
||||
unsigned long addr;
|
||||
|
||||
if(argc != 2){
|
||||
printf("test <inet addr with dots>\n");
|
||||
exit();
|
||||
}
|
||||
printf("%s\n",argv[1]);
|
||||
net = inet_network(argv[1]);
|
||||
addr = inet_addr(argv[1]);
|
||||
printf("%x %x\n", addr, net);
|
||||
net_addr = inet_makeaddr(net, addr);
|
||||
printf("%x\n", net_addr.s_addr);
|
||||
|
||||
|
||||
|
||||
/* the above seems to be broken ? */
|
||||
ent = gethostbyaddr(&net, sizeof(net_addr), AF_INET);
|
||||
if(ent)
|
||||
printf("%s\n", ent->h_name);
|
||||
|
||||
|
||||
}
|
||||
152
src/ca/os_depen.h
Normal file
152
src/ca/os_depen.h
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* O S _ D E P E N . H
|
||||
*
|
||||
*
|
||||
* OS dependent stuff for channel access
|
||||
* Author Jeffrey O. Hill
|
||||
*
|
||||
* History
|
||||
* .01 joh 110190 Moved to this file
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef INCos_depenh
|
||||
#define INCos_depenh
|
||||
|
||||
#ifdef vxWorks
|
||||
# ifndef INCfast_lockh
|
||||
# include <fast_lock.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/************************************************************************/
|
||||
/* Provided to enforce one thread at a time code sections */
|
||||
/* independent of a particular operating system */
|
||||
/************************************************************************/
|
||||
#ifdef VMS
|
||||
/* provides for data structure mutal exclusive lock out */
|
||||
/* in the VMS AST environment. */
|
||||
/* note: the following must allways be used together */
|
||||
# define LOCK\
|
||||
{register long astenblwas;\
|
||||
astenblwas = sys$setast(FALSE);
|
||||
# define UNLOCK\
|
||||
if(astenblwas == SS$_WASSET)sys$setast(TRUE);}
|
||||
#endif
|
||||
|
||||
#ifdef vxWorks
|
||||
# define LOCK FASTLOCK(&client_lock);
|
||||
# define UNLOCK FASTUNLOCK(&client_lock);
|
||||
#endif
|
||||
|
||||
#ifdef UNIX
|
||||
# define LOCK
|
||||
# define UNLOCK
|
||||
#endif
|
||||
|
||||
#ifdef vxWorks
|
||||
#define VXTHISTASKID taskIdCurrent
|
||||
extern int taskIdCurrent;
|
||||
#define abort() taskSuspend(VXTHISTASKID);
|
||||
#endif
|
||||
|
||||
#ifdef vxWorks
|
||||
# define memcpy(D,S,N) bcopy(S,D,N)
|
||||
# define memset(D,V,N) bfill(D,N,V)
|
||||
# define printf logMsg
|
||||
#endif
|
||||
|
||||
#ifdef VMS
|
||||
#ifdef WINTCP /* Wallangong */
|
||||
/* (the VAXC runtime lib has its own close */
|
||||
# define socket_close(S) netclose(S)
|
||||
# define socket_ioctl(A,B,C) ioctl(A,B,C)
|
||||
#else
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef UNIX
|
||||
# define socket_close(S) close(S)
|
||||
# define socket_ioctl(A,B,C) ioctl(A,B,C)
|
||||
#endif
|
||||
|
||||
#ifdef vxWorks
|
||||
# define socket_close(S) close(S)
|
||||
# define socket_ioctl(A,B,C) ioctl(A,B,C)
|
||||
#endif
|
||||
|
||||
#ifdef VMS
|
||||
#ifdef WINTCP
|
||||
extern int uerrno; /* Wallongong errno is uerrno */
|
||||
# define MYERRNO uerrno
|
||||
#else
|
||||
extern volatile int noshare socket_errno;
|
||||
# define MYERRNO socket_errno
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef vxWorks
|
||||
# define MYERRNO (errnoGet()&0xffff)
|
||||
#endif
|
||||
|
||||
#ifdef UNIX
|
||||
extern int errno;
|
||||
# define MYERRNO errno
|
||||
#endif
|
||||
|
||||
#ifdef VMS
|
||||
struct iosb{
|
||||
short status;
|
||||
unsigned short count;
|
||||
void *device;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct timeval{
|
||||
unsigned long tv_sec;
|
||||
unsigned long tv_usec;
|
||||
};
|
||||
|
||||
#ifdef vxWorks
|
||||
# define POST_IO_EV vrtxPost(&io_done_flag, TRUE)
|
||||
#endif
|
||||
#ifdef VMS
|
||||
# define POST_IO_EV sys$setef(io_done_flag)
|
||||
#endif
|
||||
#ifdef UNIX
|
||||
# define POST_IO_EV
|
||||
#endif
|
||||
|
||||
/* 50 mS delay for TCP to finish transmitting */
|
||||
/* select wakes you if message is only partly here */
|
||||
/* so this wait free's up the processor until it completely arrives */
|
||||
/* NOTE: DELAYVAL must be less than 1.0 */
|
||||
#define DELAYVAL 0.250 /* 250 mS */
|
||||
|
||||
#ifdef VMS
|
||||
# define SYSFREQ 10000000 /* 10 MHz */
|
||||
# define TCPDELAY\
|
||||
{float delay = DELAYVAL; static int ef=NULL;\
|
||||
int status; int systim[2]={-SYSFREQ*DELAYVAL,~0};\
|
||||
if(!ef)ef= lib$get_ef(&ef);\
|
||||
status = sys$setimr(ef,systim,NULL,MYTIMERID,NULL);\
|
||||
if(~status&STS$M_SUCCESS)lib$signal(status);\
|
||||
status = sys$waitfr(ef);\
|
||||
if(~status&STS$M_SUCCESS)lib$signal(status);\
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef vxWorks
|
||||
# define SYSFREQ sysClkRateGet() /* 60 Hz */
|
||||
# define TCPDELAY taskDelay((unsigned int)DELAYVAL*SYSFREQ);
|
||||
# define time(A) (tickGet()/sysfreq)
|
||||
#endif
|
||||
|
||||
#ifdef UNIX
|
||||
# define SYSFREQ 1000000 /* 1 MHz */
|
||||
# define TCPDELAY {if(select(0,NULL,NULL,NULL,&tcpdelayval)<0)abort();}
|
||||
static struct timeval tcpdelayval = {0,(unsigned int)DELAYVAL*SYSFREQ};
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
265
src/ca/repeater.c
Normal file
265
src/ca/repeater.c
Normal file
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* REPEATER.C
|
||||
*
|
||||
* CA broadcast repeater
|
||||
*
|
||||
* Author: Jeff Hill
|
||||
* Date: 3-27-90
|
||||
*
|
||||
* Control System Software for the GTA Project
|
||||
*
|
||||
* Copyright 1988, 1989, the Regents of the University of California.
|
||||
*
|
||||
* This software was produced under a U.S. Government contract
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory, which is
|
||||
* operated by the University of California for the U.S. Department
|
||||
* of Energy.
|
||||
*
|
||||
* Developed by the Controls and Automation Group (AT-8)
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Direct inqueries to:
|
||||
* Andy Kozubal, AT-8, Mail Stop H820
|
||||
* Los Alamos National Laboratory
|
||||
* Los Alamos, New Mexico 87545
|
||||
* Phone: (505) 667-6508
|
||||
* E-mail: kozubal@k2.lanl.gov
|
||||
*
|
||||
* PURPOSE:
|
||||
* Broadcasts fan out over the LAN, but UDP does not allow
|
||||
* two processes on the same machine to get the same broadcast.
|
||||
* This code takes extends the broadcast model from the net to within
|
||||
* the OS.
|
||||
*
|
||||
* NOTES:
|
||||
*
|
||||
* This server does not gaurantee the reliability of
|
||||
* fanned out broadcasts in keeping with the nature of
|
||||
* broadcasts. Therefore, CA provides a backup.
|
||||
*
|
||||
* UDP datagrams delivered between two processes on the same
|
||||
* machine dont travel over the LAN.
|
||||
*
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <lstLib.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <types.h>
|
||||
#include <socket.h>
|
||||
#include <in.h>
|
||||
#include <ioctl.h>
|
||||
|
||||
#include <iocmsg.h>
|
||||
#include <os_depen.h>
|
||||
struct sockaddr_in *local_addr();
|
||||
|
||||
/*
|
||||
these can be external since there is only one instance
|
||||
per machine so we dont care about reentrancy
|
||||
*/
|
||||
struct one_client{
|
||||
NODE node;
|
||||
struct sockaddr_in from;
|
||||
};
|
||||
|
||||
static
|
||||
LIST client_list;
|
||||
|
||||
static
|
||||
char buf[MAX_UDP]; /* bigger than max TCP */
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Fan out broadcasts to several processor local tasks
|
||||
*
|
||||
*
|
||||
*/
|
||||
#ifdef VMS
|
||||
main()
|
||||
#else
|
||||
ca_repeater_task()
|
||||
#endif
|
||||
{
|
||||
int status;
|
||||
int size;
|
||||
int sock;
|
||||
struct sockaddr_in from;
|
||||
struct sockaddr_in bd;
|
||||
struct sockaddr_in local;
|
||||
int from_size = sizeof from;
|
||||
struct one_client *pclient;
|
||||
struct one_client *pnxtclient;
|
||||
unsigned *pcount = (unsigned *)buf;
|
||||
|
||||
|
||||
lstInit(&client_list);
|
||||
|
||||
/* allocate a socket */
|
||||
sock = socket( AF_INET, /* domain */
|
||||
SOCK_DGRAM, /* type */
|
||||
0); /* deflt proto */
|
||||
if(sock == ERROR)
|
||||
abort();
|
||||
|
||||
memset(&bd,0,sizeof bd);
|
||||
bd.sin_family = AF_INET;
|
||||
bd.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
bd.sin_port = htons(CA_CLIENT_PORT);
|
||||
status = bind(sock, &bd, sizeof bd);
|
||||
if(status<0)
|
||||
if(MYERRNO == EADDRINUSE){
|
||||
printf("Only one CA repeater thread per host\n");
|
||||
exit();
|
||||
}
|
||||
else
|
||||
abort();
|
||||
|
||||
local = *local_addr(sock);
|
||||
|
||||
while(TRUE){
|
||||
|
||||
size = recvfrom(
|
||||
sock,
|
||||
buf,
|
||||
sizeof buf,
|
||||
0,
|
||||
&from,
|
||||
&from_size);
|
||||
|
||||
if(size > 0){
|
||||
if(size != ntohl(*pcount))
|
||||
printf("ca repeater: corrupt msg ignored\n");
|
||||
else if(from.sin_addr.s_addr != local.sin_addr.s_addr)
|
||||
for( pclient = (struct one_client *)
|
||||
client_list.node.next;
|
||||
pclient;
|
||||
pclient = (struct one_client *)
|
||||
pclient->node.next){
|
||||
|
||||
status = sendto(
|
||||
sock,
|
||||
buf,
|
||||
size,
|
||||
0,
|
||||
&pclient->from,
|
||||
sizeof pclient->from);
|
||||
if(status < 0)
|
||||
abort();
|
||||
#ifdef DEBUG
|
||||
printf("Sent\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if(size == 0){
|
||||
struct {
|
||||
unsigned length;
|
||||
struct extmsg extmsg;
|
||||
}confirm;
|
||||
|
||||
/*
|
||||
* If this is a processor local message then add to
|
||||
* the list of clients to repeat to if not there
|
||||
* allready
|
||||
*/
|
||||
for( pclient = (struct one_client *)
|
||||
client_list.node.next;
|
||||
pclient;
|
||||
pclient = (struct one_client *)
|
||||
pclient->node.next)
|
||||
if(from.sin_port == pclient->from.sin_port)
|
||||
break;
|
||||
|
||||
if(!pclient){
|
||||
pclient = (struct one_client *)
|
||||
malloc(sizeof *pclient);
|
||||
if(pclient){
|
||||
pclient->from = from;
|
||||
lstAdd(&client_list, pclient);
|
||||
#ifdef DEBUG
|
||||
printf("Added %x %d\n", from.sin_port, size);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
memset(&confirm, NULL, sizeof confirm);
|
||||
confirm.length = htonl(sizeof confirm);
|
||||
confirm.extmsg.m_cmmd = htons(REPEATER_CONFIRM);
|
||||
confirm.extmsg.m_available = local.sin_addr.s_addr;
|
||||
status = sendto(
|
||||
sock,
|
||||
&confirm,
|
||||
sizeof confirm,
|
||||
0,
|
||||
&from, /* reflect back to sender */
|
||||
sizeof from);
|
||||
if(status != sizeof confirm)
|
||||
abort();
|
||||
}else
|
||||
abort();
|
||||
|
||||
/* remove any dead wood prior to pending */
|
||||
for( pclient = (struct one_client *)
|
||||
client_list.node.next;
|
||||
pclient;
|
||||
pclient = pnxtclient){
|
||||
/* do it now in case item deleted */
|
||||
pnxtclient = (struct one_client *)
|
||||
pclient->node.next;
|
||||
clean_client(pclient);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* check to see if this client is still around
|
||||
*
|
||||
*/
|
||||
clean_client(pclient)
|
||||
struct one_client *pclient;
|
||||
{
|
||||
int port = pclient->from.sin_port;
|
||||
int sock;
|
||||
struct sockaddr_in bd;
|
||||
int status;
|
||||
int present = FALSE;
|
||||
|
||||
/* allocate a socket */
|
||||
sock = socket( AF_INET, /* domain */
|
||||
SOCK_DGRAM, /* type */
|
||||
0); /* deflt proto */
|
||||
if(sock == ERROR)
|
||||
abort();
|
||||
|
||||
memset(&bd,0,sizeof bd);
|
||||
bd.sin_family = AF_INET;
|
||||
bd.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
bd.sin_port = port;
|
||||
status = bind(sock, &bd, sizeof bd);
|
||||
if(status<0){
|
||||
if(MYERRNO == EADDRINUSE)
|
||||
present = TRUE;
|
||||
else
|
||||
abort();
|
||||
}
|
||||
close(sock);
|
||||
|
||||
if(!present){
|
||||
lstDelete(&client_list, pclient);
|
||||
if(free(pclient)<0)
|
||||
abort();
|
||||
#ifdef DEBUG
|
||||
printf("Deleted\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
Reference in New Issue
Block a user