sun4 support added
This commit is contained in:
2441
src/ca/access.c
2441
src/ca/access.c
File diff suppressed because it is too large
Load Diff
@@ -13,16 +13,15 @@
|
||||
#include <cadef.h>
|
||||
#include <db_access.h>
|
||||
|
||||
/*
|
||||
#define CA_TEST_CHNL "AI_T2000"
|
||||
*/
|
||||
#define CA_TEST_CHNL "ca:ai_2000"
|
||||
#define CA_TEST_CHNL4 "ca:ai_2000"
|
||||
#define CA_TEST_CHNL4 "ca:bo_000"
|
||||
|
||||
#define EVENT_ROUTINE null_event
|
||||
/*
|
||||
#define EVENT_ROUTINE ca_test_event
|
||||
#define CONN_ROUTINE NULL
|
||||
*/
|
||||
#define EVENT_ROUTINE null_event
|
||||
#define CONN_ROUTINE conn
|
||||
|
||||
#define NUM 1
|
||||
|
||||
@@ -50,6 +49,7 @@ main()
|
||||
void ca_test_event();
|
||||
void null_event();
|
||||
struct dbr_gr_float *ptr;
|
||||
struct dbr_gr_float *pgrfloat;
|
||||
float delay = .003;
|
||||
|
||||
long status;
|
||||
@@ -60,6 +60,7 @@ main()
|
||||
char string[41];
|
||||
float value;
|
||||
float *pfloat;
|
||||
double *pdouble;
|
||||
struct dbr_ctrl_float *pctrl;
|
||||
char pstring[NUM][MAX_STRING_SIZE];
|
||||
void write_event();
|
||||
@@ -92,7 +93,7 @@ main()
|
||||
0,
|
||||
&chix4,
|
||||
NULL,
|
||||
conn,
|
||||
CONN_ROUTINE,
|
||||
NULL),NULL);
|
||||
SEVCHK(ca_build_and_connect(
|
||||
CA_TEST_CHNL,
|
||||
@@ -100,7 +101,7 @@ main()
|
||||
0,
|
||||
&chix2,
|
||||
NULL,
|
||||
conn,
|
||||
CONN_ROUTINE,
|
||||
NULL),NULL);
|
||||
SEVCHK(ca_build_and_connect(
|
||||
CA_TEST_CHNL,
|
||||
@@ -108,7 +109,7 @@ main()
|
||||
0,
|
||||
&chix1,
|
||||
NULL,
|
||||
conn,
|
||||
CONN_ROUTINE,
|
||||
NULL),NULL);
|
||||
status = ca_pend_io(10.0);
|
||||
SEVCHK(status,NULL);
|
||||
@@ -137,7 +138,7 @@ main()
|
||||
0,
|
||||
&chix4,
|
||||
NULL,
|
||||
conn,
|
||||
CONN_ROUTINE,
|
||||
NULL),NULL);
|
||||
SEVCHK(ca_build_and_connect(
|
||||
CA_TEST_CHNL,
|
||||
@@ -145,7 +146,7 @@ main()
|
||||
0,
|
||||
&chix2,
|
||||
NULL,
|
||||
conn,
|
||||
CONN_ROUTINE,
|
||||
NULL),NULL);
|
||||
SEVCHK(ca_build_and_connect(
|
||||
CA_TEST_CHNL,
|
||||
@@ -153,10 +154,10 @@ main()
|
||||
0,
|
||||
&chix1,
|
||||
NULL,
|
||||
conn,
|
||||
CONN_ROUTINE,
|
||||
NULL),NULL);
|
||||
|
||||
status = ca_pend_io(1.0);
|
||||
status = ca_pend_io(10.0);
|
||||
SEVCHK(status,NULL);
|
||||
|
||||
if(INVALID_DB_REQ(chix1->type))
|
||||
@@ -190,6 +191,8 @@ main()
|
||||
status = ca_add_event(DBR_FLOAT, chix4, EVENT_ROUTINE, 0xaaaaaaaa, &monix);
|
||||
SEVCHK(status,NULL);
|
||||
SEVCHK(ca_clear_event(monix),NULL);
|
||||
status = ca_add_event(DBR_FLOAT, chix4, EVENT_ROUTINE, 0xaaaaaaaa, &monix);
|
||||
SEVCHK(status,NULL);
|
||||
}
|
||||
if(VALID_DB_REQ(chix4->type)){
|
||||
status = ca_add_event(DBR_FLOAT, chix4, EVENT_ROUTINE, 0xaaaaaaaa, &monix);
|
||||
@@ -206,6 +209,8 @@ main()
|
||||
|
||||
|
||||
pfloat = (float *) malloc(sizeof(float)*NUM);
|
||||
pdouble = (double *) malloc(sizeof(double)*NUM);
|
||||
pgrfloat = (struct dbr_gr_float *) malloc(sizeof(*pgrfloat)*NUM);
|
||||
|
||||
|
||||
if(VALID_DB_REQ(chix1->type))
|
||||
@@ -215,6 +220,8 @@ main()
|
||||
sprintf(&pstring[j][0],"%d",j+100);
|
||||
SEVCHK(ca_array_put(DBR_STRING,NUM,chix1,pstring),NULL)
|
||||
SEVCHK(ca_array_get(DBR_FLOAT,NUM,chix1,pfloat),NULL)
|
||||
SEVCHK(ca_array_get(DBR_DOUBLE,NUM,chix1,pdouble),NULL)
|
||||
SEVCHK(ca_array_get(DBR_GR_FLOAT,NUM,chix1,pgrfloat),NULL)
|
||||
}
|
||||
else
|
||||
abort();
|
||||
@@ -224,18 +231,22 @@ main()
|
||||
# ifdef VMS
|
||||
lib$show_timer();
|
||||
# endif
|
||||
for(i=0;i<NUM;i++)
|
||||
printf("Value Returned from put/get %f\n",pfloat[i]);
|
||||
for(i=0;i<NUM;i++){
|
||||
printf("Float value Returned from put/get %f\n",pfloat[i]);
|
||||
printf("Double value Returned from put/get %f\n",pdouble[i]);
|
||||
printf("GR Float value Returned from put/get %f\n",pgrfloat[i].value);
|
||||
}
|
||||
|
||||
for(i=0;i<10;i++)
|
||||
ca_get_callback(DBR_FLOAT, chix1, ca_test_event, NULL);
|
||||
ca_get_callback(DBR_GR_FLOAT, chix1, ca_test_event, NULL);
|
||||
|
||||
printf("-- Put/Gets done- waiting for Events --\n");
|
||||
status = ca_pend_event(500.0);
|
||||
status = ca_pend_event(60.0);
|
||||
if(status == ECA_TIMEOUT){
|
||||
|
||||
free(ptr);
|
||||
free(pfloat);
|
||||
free(pgrfloat);
|
||||
|
||||
exit();
|
||||
}else
|
||||
@@ -251,8 +262,8 @@ void null_event()
|
||||
{
|
||||
static int i;
|
||||
|
||||
if(i++>100){
|
||||
printf("100 occured\n");
|
||||
if(i++>1000){
|
||||
printf("1000 occured\n");
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
154
src/ca/conn.c
154
src/ca/conn.c
@@ -9,17 +9,15 @@
|
||||
/* */
|
||||
/* History */
|
||||
/* ------- */
|
||||
/* */
|
||||
/* Date Programmer Comments */
|
||||
/* ---- ---------- -------- */
|
||||
/* 6/89 Jeff Hill Init Release */
|
||||
/* .00 06xx89 joh Init Release */
|
||||
/* .01 060591 joh delinting */
|
||||
/* */
|
||||
/*_begin */
|
||||
/************************************************************************/
|
||||
/* */
|
||||
/* Title: IOC connection automation */
|
||||
/* File: atcs:[ca]conn.c */
|
||||
/* Environment: VMS, UNIX, VRTX */
|
||||
/* Environment: VMS, UNIX, vxWorks */
|
||||
/* Equipment: VAX, SUN, VME */
|
||||
/* */
|
||||
/* */
|
||||
@@ -36,10 +34,11 @@
|
||||
#include <iocmsg.h>
|
||||
#include <iocinf.h>
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* CHID_RETRY
|
||||
* MANAGE_CONN
|
||||
*
|
||||
* retry disconnected channels
|
||||
*
|
||||
@@ -47,29 +46,45 @@
|
||||
* NOTES:
|
||||
* Lock must be applied while in this routine
|
||||
*/
|
||||
chid_retry(silent)
|
||||
void manage_conn(silent)
|
||||
char silent;
|
||||
{
|
||||
register chid chix;
|
||||
register unsigned int retry_cnt = 0;
|
||||
register unsigned int keepalive_cnt = 0;
|
||||
unsigned int retry_cnt_no_handler = 0;
|
||||
char string[100];
|
||||
char string[128];
|
||||
ca_time current;
|
||||
int i;
|
||||
int search_type;
|
||||
|
||||
/*
|
||||
* CASTTMO+pndrecvcnt*LKUPTMO)/DELAYVAL + 1
|
||||
*/
|
||||
#define CASTTMO 0.150 /* 150 mS */
|
||||
#define LKUPTMO 0.015 /* 15 mS */
|
||||
current = time(NULL);
|
||||
|
||||
for(i=0; i< nxtiiu; i++){
|
||||
if(i != BROADCAST_IIU && iiu[i].conn_up)
|
||||
int search_type;
|
||||
|
||||
if(iiu[i].next_retry > current)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* periodic keepalive on unused channels
|
||||
*/
|
||||
if(i != BROADCAST_IIU && iiu[i].conn_up){
|
||||
|
||||
/*
|
||||
* reset of delay to the next keepalive
|
||||
* occurs when the message is sent
|
||||
*/
|
||||
noop_msg(&iiu[i]);
|
||||
keepalive_cnt++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(iiu[i].nconn_tries++ > MAXCONNTRIES)
|
||||
continue;
|
||||
|
||||
iiu[i].retry_delay += iiu[i].retry_delay;
|
||||
iiu[i].next_retry = current + iiu[i].retry_delay;
|
||||
|
||||
search_type = (i==BROADCAST_IIU? DONTREPLY: DOREPLY);
|
||||
|
||||
chix = (chid) &iiu[i].chidlist;
|
||||
@@ -80,14 +95,13 @@ char silent;
|
||||
retry_cnt++;
|
||||
|
||||
if(!(silent || chix->connection_func)){
|
||||
ca_signal(ECA_CHIDNOTFND, chix+1);
|
||||
ca_signal(ECA_CHIDNOTFND, chix+1);
|
||||
retry_cnt_no_handler++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(retry_cnt){
|
||||
send_msg();
|
||||
printf("<Trying> ");
|
||||
#ifdef UNIX
|
||||
fflush(stdout);
|
||||
@@ -99,7 +113,10 @@ char silent;
|
||||
}
|
||||
}
|
||||
|
||||
return ECA_NORMAL;
|
||||
if(keepalive_cnt|retry_cnt){
|
||||
cac_send_msg();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -115,49 +132,96 @@ char silent;
|
||||
*
|
||||
*/
|
||||
void
|
||||
mark_server_available(net_addr)
|
||||
struct in_addr net_addr;
|
||||
mark_server_available(pnet_addr)
|
||||
struct in_addr *pnet_addr;
|
||||
{
|
||||
int i;
|
||||
void noop_msg();
|
||||
unsigned port;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* if timers have expired take care of them
|
||||
* before they are reset
|
||||
*/
|
||||
manage_conn(TRUE);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("<%s> ",host_from_addr(pnet_addr));
|
||||
#ifdef UNIX
|
||||
fflush(stdout);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
for(i=0;i<nxtiiu;i++)
|
||||
if( (net_addr.s_addr ==
|
||||
if( (pnet_addr->s_addr ==
|
||||
iiu[i].sock_addr.sin_addr.s_addr)){
|
||||
|
||||
/*
|
||||
* reset the retry count out
|
||||
*
|
||||
*/
|
||||
iiu[i].nconn_tries = 0;
|
||||
|
||||
/*
|
||||
* Check if the conn is down but TCP
|
||||
* has not informed me by sending a NULL msg
|
||||
*/
|
||||
if(iiu[i].conn_up){
|
||||
/*
|
||||
* Check if the conn is down but TCP
|
||||
* has not informed me by sending a NULL msg
|
||||
*/
|
||||
noop_msg(&iiu[i]);
|
||||
send_msg();
|
||||
cac_send_msg();
|
||||
}
|
||||
else{
|
||||
/*
|
||||
* reset the delay to the next retry
|
||||
*/
|
||||
iiu[i].next_retry = CA_CURRENT_TIME;
|
||||
iiu[i].nconn_tries = 0;
|
||||
iiu[i].retry_delay = 1;
|
||||
manage_conn(TRUE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Not on a known IOC so try a directed UDP
|
||||
* never connected to this IOC before
|
||||
*
|
||||
* We end up here when the client starts before the server
|
||||
*
|
||||
* It would be best if this used a directed UDP
|
||||
* reply rather than a broadcast
|
||||
*/
|
||||
/*
|
||||
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
This connects when the client starts before the server
|
||||
1) uses a broadcast- should use a directed UDP messaage
|
||||
2) many clients with nonexsistent channels could
|
||||
cause a flood here
|
||||
|
||||
|
||||
/*
|
||||
* reset the retry cnt to 3
|
||||
*/
|
||||
iiu[BROADCAST_IIU].nconn_tries = MAXCONNTRIES-3;
|
||||
|
||||
/*
|
||||
* This part is very important since many machines
|
||||
* could have channels in a disconnected state which
|
||||
* dont exist anywhere on the network. This insures
|
||||
* that we dont have many CA clients synchronously
|
||||
* flooding the network with broadcasts.
|
||||
*
|
||||
* I fetch the local port number and use the low order bits
|
||||
* as a pseudo random delay to prevent every one
|
||||
* from replying at once.
|
||||
*/
|
||||
{
|
||||
struct sockaddr_in saddr;
|
||||
unsigned saddr_length = sizeof(saddr);
|
||||
int status;
|
||||
|
||||
status = getsockname(
|
||||
iiu[BROADCAST_IIU].sock_chan,
|
||||
&saddr,
|
||||
&saddr_length);
|
||||
if(status<0)
|
||||
abort();
|
||||
port = saddr.sin_port;
|
||||
}
|
||||
|
||||
iiu[BROADCAST_IIU].retry_delay = (port&0xf) + 1;
|
||||
iiu[BROADCAST_IIU].next_retry = time(NULL) + iiu[BROADCAST_IIU].retry_delay;
|
||||
#ifdef DEBUG
|
||||
printf("<Trying ukn online after pseudo random delay=%d sec> ",
|
||||
iiu[BROADCAST_IIU].retry_delay);
|
||||
#ifdef UNIX
|
||||
fflush(stdout);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
iiu[BROADCAST_IIU].nconn_tries = MAXCONNTRIES-1;
|
||||
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -9,10 +9,8 @@
|
||||
/* */
|
||||
/* History */
|
||||
/* ------- */
|
||||
/* */
|
||||
/* Date Programmer Comments */
|
||||
/* ---- ---------- -------- */
|
||||
/* 6/89 Jeff Hill Init Release */
|
||||
/* 06xx89 joh First Release */
|
||||
/* 060591 joh delinting */
|
||||
/* */
|
||||
/*_begin */
|
||||
/************************************************************************/
|
||||
@@ -47,38 +45,46 @@
|
||||
#include <iocmsg.h>
|
||||
#include <iocinf.h>
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Keep track of how many times messages have come with out a break in between
|
||||
*/
|
||||
* FLOW CONTROL
|
||||
*
|
||||
* Keep track of how many times messages have
|
||||
* come with out a break in between and
|
||||
* suppress monitors if we are behind
|
||||
* (an update is sent when we catch up)
|
||||
*/
|
||||
void
|
||||
flow_control(piiu)
|
||||
struct ioc_in_use *piiu;
|
||||
{
|
||||
unsigned nbytes;
|
||||
register int status;
|
||||
register int busy = piiu->client_busy;
|
||||
struct ioc_in_use *piiu;
|
||||
{
|
||||
unsigned nbytes;
|
||||
register int status;
|
||||
register int busy = piiu->client_busy;
|
||||
|
||||
status = socket_ioctl( piiu->sock_chan,
|
||||
FIONREAD,
|
||||
&nbytes);
|
||||
if(status < 0)
|
||||
return ERROR;
|
||||
status = socket_ioctl(piiu->sock_chan,
|
||||
FIONREAD,
|
||||
&nbytes);
|
||||
if (status < 0) {
|
||||
close_ioc(piiu);
|
||||
return;
|
||||
}
|
||||
|
||||
if(nbytes){
|
||||
piiu->contiguous_msg_count++;
|
||||
if(!busy)
|
||||
if(piiu->contiguous_msg_count > MAX_CONTIGUOUS_MSG_COUNT){
|
||||
piiu->client_busy = TRUE;
|
||||
ca_busy_message(piiu);
|
||||
}
|
||||
}
|
||||
else{
|
||||
piiu->contiguous_msg_count=0;
|
||||
if(busy){
|
||||
ca_ready_message(piiu);
|
||||
piiu->client_busy = FALSE;
|
||||
}
|
||||
}
|
||||
if (nbytes) {
|
||||
piiu->contiguous_msg_count++;
|
||||
if (!busy)
|
||||
if (piiu->contiguous_msg_count >
|
||||
MAX_CONTIGUOUS_MSG_COUNT) {
|
||||
piiu->client_busy = TRUE;
|
||||
ca_busy_message(piiu);
|
||||
}
|
||||
} else {
|
||||
piiu->contiguous_msg_count = 0;
|
||||
if (busy) {
|
||||
ca_ready_message(piiu);
|
||||
piiu->client_busy = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
1353
src/ca/iocinf.c
1353
src/ca/iocinf.c
File diff suppressed because it is too large
Load Diff
@@ -9,11 +9,9 @@
|
||||
/* */
|
||||
/* History */
|
||||
/* ------- */
|
||||
/* */
|
||||
/* Date Programmer Comments */
|
||||
/* ---- ---------- -------- */
|
||||
/* 8/87 Jeff Hill Init Release */
|
||||
/* 1/90 Jeff Hill fd_set in the UNIX version only */
|
||||
/* .01 08xx87 joh Init Release */
|
||||
/* .02 01xx90 joh fd_set in the UNIX version only */
|
||||
/* .03 060691 joh Rearanged buffer struct for SPARC port */
|
||||
/* */
|
||||
/*_begin */
|
||||
/************************************************************************/
|
||||
@@ -60,7 +58,6 @@
|
||||
# include <os_depen.h>
|
||||
#endif
|
||||
|
||||
void send_msg();
|
||||
|
||||
/* throw out requests prior to last ECA_TIMEOUT from ca_pend */
|
||||
#define VALID_MSG(PIIU) (piiu->read_seq == piiu->cur_read_seq)
|
||||
@@ -87,25 +84,13 @@ enum channel_state{cs_never_conn, cs_prev_conn, cs_conn, closed};
|
||||
#define SETPENDRECV {pndrecvcnt++;}
|
||||
#define CLRPENDRECV {if(--pndrecvcnt<1){IODONESUB; POST_IO_EV;}}
|
||||
|
||||
/* size of object in bytes rounded up to nearest long word */
|
||||
#define QUAD_ROUND(A) (((A)+3)>>2)
|
||||
#define QUAD_SIZEOF(A) (QUAD_ROUND(sizeof(A)))
|
||||
|
||||
/* size of object in bytes rounded up to nearest short word */
|
||||
#define BI_ROUND(A) (((A)+1)>>1)
|
||||
#define BI_SIZEOF(A) (QUAD_ROUND(sizeof(A)))
|
||||
/*
|
||||
#define MAX(A,B) (((A)>(B))?(A):(B))
|
||||
#define MIN(A,B) (((A)>(B))?(B):(A))
|
||||
*/
|
||||
/************************************************************************/
|
||||
/* Structures */
|
||||
/************************************************************************/
|
||||
|
||||
/* stk must be above and contiguous with buf ! */
|
||||
struct buffer{
|
||||
unsigned long stk;
|
||||
char buf[MAX_MSG_SIZE]; /* from iocmsg.h */
|
||||
unsigned long stk;
|
||||
};
|
||||
|
||||
|
||||
@@ -121,6 +106,9 @@ struct pending_io_event{
|
||||
void *io_done_arg;
|
||||
};
|
||||
|
||||
typedef unsigned long ca_time;
|
||||
#define CA_RETRY_PERIOD 5 /* sec to next keepalive */
|
||||
#define CA_CURRENT_TIME 0
|
||||
|
||||
#define MAX_CONTIGUOUS_MSG_COUNT 2
|
||||
|
||||
@@ -148,15 +136,16 @@ struct pending_io_event{
|
||||
#define io_done_flag (ca_static->ca_io_done_flag)
|
||||
#define evuser (ca_static->ca_evuser)
|
||||
#define client_lock (ca_static->ca_client_lock)
|
||||
#define event_buf (ca_static->ca_event_buf)
|
||||
#define event_buf_size (ca_static->ca_event_buf_size)
|
||||
#define local_chidlist (ca_static->ca_local_chidlist)
|
||||
#define dbfree_ev_list (ca_static->ca_dbfree_ev_list)
|
||||
#define lcl_buff_list (ca_static->ca_lcl_buff_list)
|
||||
#endif
|
||||
#ifdef VMS
|
||||
#define io_done_flag (ca_static->ca_io_done_flag)
|
||||
#define peek_ast_buf (ca_static->ca_peek_ast_buf)
|
||||
#endif
|
||||
|
||||
|
||||
struct ca_static{
|
||||
unsigned short ca_nxtiiu;
|
||||
long ca_pndrecvcnt;
|
||||
@@ -166,7 +155,7 @@ struct ca_static{
|
||||
void (*ca_connection_func)();
|
||||
void *ca_connection_arg;
|
||||
void (*ca_fd_register_func)();
|
||||
void (*ca_fd_register_arg)();
|
||||
void *ca_fd_register_arg;
|
||||
short ca_exit_in_progress;
|
||||
unsigned short ca_post_msg_active;
|
||||
LIST ca_free_event_list;
|
||||
@@ -177,16 +166,16 @@ struct ca_static{
|
||||
#endif
|
||||
#ifdef VMS
|
||||
int ca_io_done_flag;
|
||||
char ca_peek_ast_buf;
|
||||
#endif
|
||||
#ifdef vxWorks
|
||||
int ca_io_done_flag;
|
||||
void *ca_evuser;
|
||||
FAST_LOCK ca_client_lock;
|
||||
void *ca_event_buf;
|
||||
unsigned ca_event_buf_size;
|
||||
int ca_tid;
|
||||
LIST ca_local_chidlist;
|
||||
LIST ca_dbfree_ev_list;
|
||||
LIST ca_lcl_buff_list;
|
||||
#endif
|
||||
struct ioc_in_use{
|
||||
unsigned contiguous_msg_count;
|
||||
@@ -200,10 +189,10 @@ struct ca_static{
|
||||
unsigned read_seq;
|
||||
unsigned cur_read_seq;
|
||||
LIST chidlist; /* chans on this connection */
|
||||
unsigned nconn_wait; /* number delays before try */
|
||||
unsigned nconn_tries; /* number of times conn was tried */
|
||||
int conn_up; /* boolean: T-conn /F-disconn */
|
||||
unsigned count_to_refresh; /* ndelays to conn retry */
|
||||
unsigned nconn_tries;
|
||||
ca_time next_retry;
|
||||
ca_time retry_delay;
|
||||
#define MAXCONNTRIES 3
|
||||
#ifdef VMS /* for qio ASTs */
|
||||
struct sockaddr_in recvfrom;
|
||||
@@ -236,12 +225,21 @@ struct ca_static{
|
||||
GLBLTYPE
|
||||
struct ca_static *ca_static;
|
||||
|
||||
#ifdef VMS
|
||||
GLBLTYPE
|
||||
char ca_unique_address;
|
||||
# define MYTIMERID (&ca_unique_address)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* CA internal functions
|
||||
*
|
||||
*/
|
||||
void cac_send_msg();
|
||||
void build_msg();
|
||||
struct in_addr broadcast_addr();
|
||||
void manage_conn();
|
||||
void noop_msg();
|
||||
void ca_busy_message();
|
||||
void ca_ready_message();
|
||||
void flow_control();
|
||||
char *host_from_addr();
|
||||
int ca_repeater_task();
|
||||
void close_ioc();
|
||||
void recv_msg_select();
|
||||
void mark_server_available();
|
||||
#endif
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
#ifndef __IOCMSG__
|
||||
/*
|
||||
History
|
||||
1/90 joh removed status field in favor of a seperate command-
|
||||
saves space on every successful operation
|
||||
|
||||
4-13-90 joh moved server ports to above IPPORT_USERRESERVED
|
||||
see in.h
|
||||
|
||||
*/
|
||||
* History
|
||||
* .01 01xx90 joh removed status field in favor of a independent m_cmmd-
|
||||
* saves space on every successful operation
|
||||
*
|
||||
* .02 041390 joh moved server ports to above IPPORT_USERRESERVED
|
||||
* see in.h
|
||||
*
|
||||
* .03 060391 joh Bumped protocol version to 4 to support changes for
|
||||
* SPARC alignment in db_access.h
|
||||
*
|
||||
*/
|
||||
|
||||
#define __IOCMSG__
|
||||
|
||||
/* TCP/UDP port number (bumped each protocol change) */
|
||||
#define CA_PROTOCOL_VERSION 3
|
||||
#define CA_PROTOCOL_VERSION 4
|
||||
#define CA_PORT_BASE IPPORT_USERRESERVED + 56
|
||||
#define CA_SERVER_PORT (CA_PORT_BASE+CA_PROTOCOL_VERSION*2)
|
||||
#define CA_CLIENT_PORT (CA_PORT_BASE+CA_PROTOCOL_VERSION*2+1)
|
||||
@@ -23,7 +26,6 @@
|
||||
|
||||
|
||||
/* values for m_cmmd */
|
||||
|
||||
#define IOC_NOOP 0 /* do nothing, but verify TCP */
|
||||
#define IOC_EVENT_ADD 1 /* add an event */
|
||||
#define IOC_EVENT_CANCEL 2 /* cancel an event */
|
||||
@@ -45,20 +47,42 @@
|
||||
#define IOC_READ_BUILD 16 /* read accompanying a build */
|
||||
#define REPEATER_CONFIRM 17 /* registration confirmation */
|
||||
|
||||
/*
|
||||
for use with build and search and not_found
|
||||
(if search fails and its not a broadcast tell
|
||||
the client to look elesewhere)
|
||||
*/
|
||||
/*
|
||||
* for use with build and search and not_found (if search fails and
|
||||
* its not a broadcast tell the client to look elesewhere)
|
||||
*/
|
||||
#define DOREPLY 10
|
||||
#define DONTREPLY 5
|
||||
|
||||
|
||||
/* extmsg - the nonvariant part of each message sent/recv
|
||||
by the request server.
|
||||
*/
|
||||
/* size of object in bytes rounded up to nearest oct word */
|
||||
#define OCT_ROUND(A) (((A)+7)>>3)
|
||||
#define OCT_SIZEOF(A) (OCT_ROUND(sizeof(A)))
|
||||
|
||||
/* size of object in bytes rounded up to nearest long word */
|
||||
#define QUAD_ROUND(A) (((A)+3)>>2)
|
||||
#define QUAD_SIZEOF(A) (QUAD_ROUND(sizeof(A)))
|
||||
|
||||
/* size of object in bytes rounded up to nearest short word */
|
||||
#define BI_ROUND(A) (((A)+1)>>1)
|
||||
#define BI_SIZEOF(A) (BI_ROUND(sizeof(A)))
|
||||
|
||||
/*
|
||||
* Required Message Alignment
|
||||
*
|
||||
* Determined by the architecture with the most restrictive
|
||||
* alignment requirements (currently the SPARC).
|
||||
*
|
||||
* octal rounding
|
||||
*
|
||||
* NOTE: all structures declared in this file must have a
|
||||
* byte count which is evenly divisible by 8 for the SPARC.
|
||||
*/
|
||||
#define CA_MESSAGE_ALIGN(A) (OCT_ROUND(A)<<3)
|
||||
|
||||
/*
|
||||
* the common part of each message sent/recv by the
|
||||
* CA server.
|
||||
*/
|
||||
struct extmsg {
|
||||
unsigned short m_cmmd; /* operation to be performed */
|
||||
unsigned short m_postsize; /* size of message extension */
|
||||
@@ -70,7 +94,9 @@ struct extmsg {
|
||||
};
|
||||
|
||||
|
||||
/* for monitor (event) message extension */
|
||||
/*
|
||||
* for monitor (event) message extension
|
||||
*/
|
||||
struct mon_info{
|
||||
float m_lval; /* low delta */
|
||||
float m_hval; /* high delta */
|
||||
|
||||
@@ -96,15 +96,17 @@ extern int taskIdCurrent;
|
||||
|
||||
#ifdef VMS
|
||||
struct iosb{
|
||||
short status;
|
||||
unsigned short count;
|
||||
void *device;
|
||||
short status;
|
||||
unsigned short count;
|
||||
void *device;
|
||||
};
|
||||
static char ca_unique_address;
|
||||
#define MYTIMERID (&ca_unique_address)
|
||||
#endif
|
||||
|
||||
struct timeval{
|
||||
unsigned long tv_sec;
|
||||
unsigned long tv_usec;
|
||||
unsigned long tv_sec;
|
||||
unsigned long tv_usec;
|
||||
};
|
||||
|
||||
#ifdef vxWorks
|
||||
@@ -137,15 +139,19 @@ struct timeval{
|
||||
#endif
|
||||
|
||||
#ifdef vxWorks
|
||||
# define SYSFREQ sysClkRateGet() /* 60 Hz */
|
||||
# define TCPDELAY taskDelay((unsigned int)DELAYVAL*SYSFREQ);
|
||||
# define time(A) (tickGet()/sysfreq)
|
||||
# define SYSFREQ sysClkRateGet() /* usually 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};
|
||||
# define SYSFREQ 1000000 /* 1 MHz */
|
||||
# define TCPDELAY {if(select(0,NULL,NULL,NULL,&tcpdelayval)<0)abort();}
|
||||
# ifndef CA_GLBLSOURCE
|
||||
extern struct timeval tcpdelayval;
|
||||
# else
|
||||
struct timeval tcpdelayval = {0,(unsigned int)DELAYVAL*SYSFREQ};
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -36,18 +36,24 @@
|
||||
*
|
||||
* This server does not gaurantee the reliability of
|
||||
* fanned out broadcasts in keeping with the nature of
|
||||
* broadcasts. Therefore, CA provides a backup.
|
||||
* broadcasts. Therefore, CA retransmitts lost msgs.
|
||||
*
|
||||
* UDP datagrams delivered between two processes on the same
|
||||
* machine dont travel over the LAN.
|
||||
*
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .01 060691 joh Took out 4 byte count at message begin to
|
||||
* in preparation for SPARC alignment
|
||||
*
|
||||
*/
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <lstLib.h>
|
||||
#ifdef VMS
|
||||
#include <stsdef.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <types.h>
|
||||
@@ -60,9 +66,9 @@
|
||||
struct sockaddr_in *local_addr();
|
||||
|
||||
/*
|
||||
these can be external since there is only one instance
|
||||
per machine so we dont care about reentrancy
|
||||
*/
|
||||
* 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;
|
||||
@@ -72,9 +78,13 @@ static
|
||||
LIST client_list;
|
||||
|
||||
static
|
||||
char buf[MAX_UDP]; /* bigger than max TCP */
|
||||
char buf[MAX_UDP];
|
||||
|
||||
int ca_repeater();
|
||||
|
||||
#define NTRIES 100
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Fan out broadcasts to several processor local tasks
|
||||
@@ -86,6 +96,38 @@ main()
|
||||
#else
|
||||
ca_repeater_task()
|
||||
#endif
|
||||
{
|
||||
unsigned i,j;
|
||||
|
||||
/*
|
||||
*
|
||||
* This allows the system inet support to takes it
|
||||
* time releasing the bind I used to test if the repeater
|
||||
* is up.
|
||||
*
|
||||
*/
|
||||
for(i=0; i<NTRIES; i++){
|
||||
ca_repeater();
|
||||
for(j=0; j<100; j++)
|
||||
TCPDELAY;
|
||||
#ifdef DEBUG
|
||||
printf("CA: retiring the repeater\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
printf("CA: Only one CA repeater thread per host\n");
|
||||
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* ca_repeater()
|
||||
*
|
||||
*
|
||||
*/
|
||||
ca_repeater()
|
||||
{
|
||||
int status;
|
||||
int size;
|
||||
@@ -96,7 +138,6 @@ ca_repeater_task()
|
||||
int from_size = sizeof from;
|
||||
struct one_client *pclient;
|
||||
struct one_client *pnxtclient;
|
||||
unsigned *pcount = (unsigned *)buf;
|
||||
|
||||
|
||||
lstInit(&client_list);
|
||||
@@ -106,23 +147,28 @@ ca_repeater_task()
|
||||
SOCK_DGRAM, /* type */
|
||||
0); /* deflt proto */
|
||||
if(sock == ERROR)
|
||||
abort();
|
||||
return FALSE;
|
||||
|
||||
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();
|
||||
if(status<0){
|
||||
if(MYERRNO != EADDRINUSE){
|
||||
printf("CA REepeater: unexpected bind fail %d\n",
|
||||
MYERRNO);
|
||||
}
|
||||
else
|
||||
abort();
|
||||
socket_close(sock);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
local = *local_addr(sock);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("CA Repeater: Attached and initialized\n");
|
||||
#endif
|
||||
|
||||
while(TRUE){
|
||||
|
||||
size = recvfrom(
|
||||
@@ -134,9 +180,7 @@ ca_repeater_task()
|
||||
&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)
|
||||
if(from.sin_addr.s_addr != local.sin_addr.s_addr)
|
||||
for( pclient = (struct one_client *)
|
||||
client_list.node.next;
|
||||
pclient;
|
||||
@@ -150,18 +194,17 @@ ca_repeater_task()
|
||||
0,
|
||||
&pclient->from,
|
||||
sizeof pclient->from);
|
||||
if(status < 0)
|
||||
abort();
|
||||
if(status < 0){
|
||||
printf("CA Repeater: fanout err %d\n",
|
||||
MYERRNO);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("Sent\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if(size == 0){
|
||||
struct {
|
||||
unsigned length;
|
||||
struct extmsg extmsg;
|
||||
}confirm;
|
||||
struct extmsg confirm;
|
||||
|
||||
/*
|
||||
* If this is a processor local message then add to
|
||||
@@ -189,9 +232,8 @@ ca_repeater_task()
|
||||
}
|
||||
|
||||
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;
|
||||
confirm.m_cmmd = htons(REPEATER_CONFIRM);
|
||||
confirm.m_available = local.sin_addr.s_addr;
|
||||
status = sendto(
|
||||
sock,
|
||||
&confirm,
|
||||
@@ -199,10 +241,15 @@ ca_repeater_task()
|
||||
0,
|
||||
&from, /* reflect back to sender */
|
||||
sizeof from);
|
||||
if(status != sizeof confirm)
|
||||
abort();
|
||||
}else
|
||||
abort();
|
||||
if(status != sizeof confirm){
|
||||
printf("CA Repeater: confirm err %d\n",
|
||||
MYERRNO);
|
||||
}
|
||||
}
|
||||
else{
|
||||
printf("CA Repeater: recv err %d\n",
|
||||
MYERRNO);
|
||||
}
|
||||
|
||||
/* remove any dead wood prior to pending */
|
||||
for( pclient = (struct one_client *)
|
||||
@@ -217,7 +264,7 @@ ca_repeater_task()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* check to see if this client is still around
|
||||
@@ -236,8 +283,11 @@ struct one_client *pclient;
|
||||
sock = socket( AF_INET, /* domain */
|
||||
SOCK_DGRAM, /* type */
|
||||
0); /* deflt proto */
|
||||
if(sock == ERROR)
|
||||
abort();
|
||||
if(sock == ERROR){
|
||||
printf("CA Repeater: no socket err %d\n",
|
||||
MYERRNO);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
memset(&bd,0,sizeof bd);
|
||||
bd.sin_family = AF_INET;
|
||||
@@ -247,10 +297,12 @@ struct one_client *pclient;
|
||||
if(status<0){
|
||||
if(MYERRNO == EADDRINUSE)
|
||||
present = TRUE;
|
||||
else
|
||||
abort();
|
||||
else{
|
||||
printf("CA Repeater: client cleanup err %d\n",
|
||||
MYERRNO);
|
||||
}
|
||||
}
|
||||
close(sock);
|
||||
socket_close(sock);
|
||||
|
||||
if(!present){
|
||||
lstDelete(&client_list, pclient);
|
||||
|
||||
897
src/ca/service.c
897
src/ca/service.c
@@ -10,11 +10,17 @@
|
||||
/* History */
|
||||
/* ------- */
|
||||
/* */
|
||||
/* Date Programmer Comments */
|
||||
/* ---- ---------- -------- */
|
||||
/* 8/87 Jeff Hill Init Release */
|
||||
/* 1/90 Jeff Hill Made cmmd for errors which */
|
||||
/* Date Person Comments */
|
||||
/* ---- ------ -------- */
|
||||
/* 8/87 joh Init Release */
|
||||
/* 1/90 joh Made cmmd for errors which */
|
||||
/* eliminated the status field */
|
||||
/* 030791 joh Fixed problem where pend count was decremented */
|
||||
/* prior to connecting chan (setting the type). */
|
||||
/* 041591 joh added call to channel exsits routine */
|
||||
/* 060491 joh fixed structure pass for SPARC cc */
|
||||
/* 060691 jow reworked to remove 4 byte count before each */
|
||||
/* macro message */
|
||||
/* */
|
||||
/*_begin */
|
||||
/************************************************************************/
|
||||
@@ -55,420 +61,477 @@
|
||||
#include <iocinf.h>
|
||||
|
||||
void reconnect_channel();
|
||||
#define BUFSTAT printf("expected %d left %d\n",msgcnt,*pbufcnt);
|
||||
|
||||
void post_msg(hdrptr,bufcnt,net_addr,piiu)
|
||||
register struct extmsg *hdrptr;
|
||||
register long bufcnt;
|
||||
struct in_addr net_addr;
|
||||
struct ioc_in_use *piiu;
|
||||
|
||||
|
||||
/*
|
||||
* post_msg()
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
void
|
||||
post_msg(hdrptr, pbufcnt, pnet_addr, piiu)
|
||||
register struct extmsg *hdrptr;
|
||||
register unsigned long *pbufcnt;
|
||||
struct in_addr *pnet_addr;
|
||||
struct ioc_in_use *piiu;
|
||||
{
|
||||
evid monix;
|
||||
long msgcnt;
|
||||
long tmp;
|
||||
evid monix;
|
||||
long msgcnt;
|
||||
|
||||
register void * t_available;
|
||||
register unsigned short t_postsize;
|
||||
register unsigned short t_cmmd;
|
||||
register chtype t_type;
|
||||
register unsigned short t_count;
|
||||
register unsigned short t_size;
|
||||
int status;
|
||||
register void *t_available;
|
||||
register unsigned short t_postsize;
|
||||
register unsigned short t_cmmd;
|
||||
register chtype t_type;
|
||||
register unsigned short t_count;
|
||||
int status;
|
||||
|
||||
|
||||
# define BUFSTAT\
|
||||
printf("expected %d left %d\n",msgcnt,bufcnt);
|
||||
|
||||
post_msg_active++;
|
||||
post_msg_active++;
|
||||
|
||||
|
||||
while(bufcnt>0){
|
||||
# ifdef DEBUG
|
||||
printf( "processing message- bytes left %d, pending msgcnt %d\n",
|
||||
bufcnt,
|
||||
pndrecvcnt);
|
||||
# endif
|
||||
|
||||
/* byte swap the message up front */
|
||||
t_available = (void *) hdrptr->m_available;
|
||||
t_postsize = ntohs(hdrptr->m_postsize);
|
||||
t_cmmd = ntohs(hdrptr->m_cmmd);
|
||||
t_type = ntohs(hdrptr->m_type);
|
||||
t_count = ntohs(hdrptr->m_count);
|
||||
t_size = dbr_size[t_type];
|
||||
|
||||
# ifdef DEBUG
|
||||
printf( "MSG: cmd:%d type:%d cnt:%d size:%d npost:%d avail:%x\n",
|
||||
t_cmmd,
|
||||
t_type,
|
||||
t_count,
|
||||
t_size,
|
||||
t_postsize,
|
||||
t_available
|
||||
);
|
||||
# endif
|
||||
|
||||
msgcnt = sizeof(*hdrptr) + t_postsize;
|
||||
if(bufcnt-msgcnt < 0){
|
||||
printf(
|
||||
"post_msg(): expected msg size larger than actual msg %d %d\n",
|
||||
bufcnt,
|
||||
msgcnt);
|
||||
post_msg_active--;
|
||||
return;
|
||||
}
|
||||
|
||||
switch(t_cmmd){
|
||||
|
||||
case IOC_READ_NOTIFY:
|
||||
{
|
||||
/* run the user's event handler */
|
||||
/* m_available points to event descriptor */
|
||||
struct event_handler_args args;
|
||||
|
||||
monix = (evid) t_available;
|
||||
|
||||
|
||||
/*
|
||||
* Currently only the VAXs need data conversion
|
||||
*/
|
||||
# ifdef VAX
|
||||
(*cvrt[t_type])( hdrptr+1, hdrptr+1, FALSE, t_count);
|
||||
# endif
|
||||
|
||||
/*
|
||||
* Orig version of CA didnt use this strucure.
|
||||
* This would run faster if I had decided to
|
||||
* pass a pointer to this structure rather
|
||||
* than the structure itself early on.
|
||||
*
|
||||
* Pumping the arguments on the stack explicitly
|
||||
* could cause problems if a small item is in
|
||||
* the structure and we are on a SPARC processor.
|
||||
*
|
||||
* call handler, only if they did not clear the chid
|
||||
* in the interim
|
||||
*/
|
||||
if(*monix->usr_func){
|
||||
args.usr = monix->usr_arg;
|
||||
args.chid = monix->chan;
|
||||
args.type = t_type;
|
||||
args.count = t_count;
|
||||
args.dbr = (void *) (hdrptr+1);
|
||||
|
||||
(*monix->usr_func)(args);
|
||||
}
|
||||
|
||||
LOCK;
|
||||
lstDelete(&pend_read_list, monix);
|
||||
lstAdd(&free_event_list, monix);
|
||||
UNLOCK;
|
||||
|
||||
break;
|
||||
}
|
||||
case IOC_EVENT_ADD:
|
||||
{
|
||||
/* run the user's event handler */
|
||||
/* m_available points to event descriptor */
|
||||
struct event_handler_args args;
|
||||
|
||||
monix = (evid) t_available;
|
||||
|
||||
|
||||
/* m_postsize = 0 is a confirmation of a monitor cancel */
|
||||
if( !t_postsize ){
|
||||
LOCK;
|
||||
lstDelete(&monix->chan->eventq, monix);
|
||||
lstAdd(&free_event_list, monix);
|
||||
UNLOCK;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* only call if not disabled */
|
||||
if(!monix->usr_func)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Currently only the VAXs need data conversion
|
||||
*/
|
||||
# ifdef VAX
|
||||
(*cvrt[t_type])( hdrptr+1, hdrptr+1, FALSE, t_count);
|
||||
# endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Orig version of CA didnt use this strucure.
|
||||
* This would run faster if I had decided to
|
||||
* pass a pointer to this structure rather
|
||||
* than the structure itself early on.
|
||||
*
|
||||
* Pumping the arguments on the stack explicitly
|
||||
* could cause problems if a small item is in
|
||||
* the structure and we are on a SPARC processor.
|
||||
*
|
||||
*/
|
||||
args.usr = monix->usr_arg;
|
||||
args.chid = monix->chan;
|
||||
args.type = t_type;
|
||||
args.count = t_count;
|
||||
args.dbr = (void *) (hdrptr+1);
|
||||
|
||||
/* call their handler */
|
||||
(*monix->usr_func)(args);
|
||||
|
||||
break;
|
||||
}
|
||||
case IOC_READ:
|
||||
case IOC_READ_BUILD:
|
||||
{
|
||||
chid chan = (chid) hdrptr->m_pciu;
|
||||
|
||||
/* only count get returns if from the current read seq */
|
||||
if(!VALID_MSG(piiu))
|
||||
break;
|
||||
|
||||
if(t_postsize > (t_count-1) * dbr_value_size[t_type] + dbr_size[t_type])
|
||||
SEVCHK(ECA_INTERNAL,"about to violate user's buffer");
|
||||
|
||||
/*
|
||||
* Currently only the VAXs need data conversion
|
||||
*/
|
||||
# ifdef VAX
|
||||
(*cvrt[t_type])( hdrptr+1, t_available, FALSE, t_count);
|
||||
# else
|
||||
/* in line is a little faster */
|
||||
if(t_postsize<=sizeof(int)){
|
||||
if(t_postsize==sizeof(long))
|
||||
*(long *)t_available = *(long *)(hdrptr+1);
|
||||
else if(t_postsize==sizeof(short))
|
||||
*(short *)t_available = *(short *)(hdrptr+1);
|
||||
else if(t_postsize==sizeof(char))
|
||||
*(char *)t_available = *(char *)(hdrptr+1);
|
||||
}else
|
||||
memcpy(
|
||||
t_available,
|
||||
hdrptr+1,
|
||||
t_postsize);
|
||||
# endif
|
||||
|
||||
/*
|
||||
* decrement the outstanding IO count
|
||||
*
|
||||
* This relies on the IOC_READ_BUILD msg returning prior to the
|
||||
* IOC_BUILD msg.
|
||||
*/
|
||||
if( t_cmmd != IOC_READ_BUILD ||
|
||||
(chan->connection_func == NULL && chan->state==cs_never_conn))
|
||||
CLRPENDRECV;
|
||||
|
||||
break;
|
||||
}
|
||||
case IOC_SEARCH:
|
||||
case IOC_BUILD:
|
||||
{
|
||||
chid chan = (chid) t_available;
|
||||
struct ioc_in_use *chpiiu = &iiu[chan->iocix];
|
||||
|
||||
if( chan->paddr ){
|
||||
|
||||
if(chpiiu->sock_addr.sin_addr.s_addr==net_addr.s_addr){
|
||||
printf("burp ");
|
||||
#ifdef UNIX
|
||||
fflush(stdout);
|
||||
while (*pbufcnt >= sizeof(*hdrptr)) {
|
||||
#ifdef DEBUG
|
||||
printf("bytes left %d, pending msgcnt %d\n",
|
||||
*pbufcnt,
|
||||
pndrecvcnt);
|
||||
#endif
|
||||
}
|
||||
else{
|
||||
char msg[256];
|
||||
char acc[64];
|
||||
char rej[64];
|
||||
|
||||
sprintf(acc,"%s",
|
||||
host_from_addr(chpiiu->sock_addr.sin_addr));
|
||||
sprintf(rej,"%s",host_from_addr(net_addr));
|
||||
sprintf(
|
||||
msg,
|
||||
/* byte swap the message up front */
|
||||
t_available = (void *) hdrptr->m_available;
|
||||
t_postsize = ntohs(hdrptr->m_postsize);
|
||||
t_cmmd = ntohs(hdrptr->m_cmmd);
|
||||
t_type = ntohs(hdrptr->m_type);
|
||||
t_count = ntohs(hdrptr->m_count);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("MSG: cmd:%d type:%d cnt:%d npost:%d avail:%x\n",
|
||||
t_cmmd,
|
||||
t_type,
|
||||
t_count,
|
||||
t_postsize,
|
||||
t_available
|
||||
);
|
||||
#endif
|
||||
|
||||
msgcnt = sizeof(*hdrptr) + t_postsize;
|
||||
if (*pbufcnt < msgcnt) {
|
||||
post_msg_active--;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (t_cmmd) {
|
||||
|
||||
case IOC_READ_NOTIFY:
|
||||
{
|
||||
/*
|
||||
* run the user's event handler
|
||||
* m_available points to event descriptor
|
||||
*/
|
||||
struct event_handler_args args;
|
||||
|
||||
monix = (evid) t_available;
|
||||
|
||||
|
||||
/*
|
||||
* Currently only the VAXs need data
|
||||
* conversion
|
||||
*/
|
||||
#ifdef VAX
|
||||
(*cvrt[t_type]) (
|
||||
hdrptr + 1,
|
||||
hdrptr + 1,
|
||||
FALSE,
|
||||
t_count);
|
||||
#endif
|
||||
|
||||
/*
|
||||
*
|
||||
* call handler, only if they did not clear the
|
||||
* chid in the interim
|
||||
*/
|
||||
if (*monix->usr_func) {
|
||||
args.usr = monix->usr_arg;
|
||||
args.chid = monix->chan;
|
||||
args.type = t_type;
|
||||
args.count = t_count;
|
||||
args.dbr = (void *) (hdrptr + 1);
|
||||
|
||||
(*monix->usr_func) (args);
|
||||
}
|
||||
LOCK;
|
||||
lstDelete(&pend_read_list, monix);
|
||||
lstAdd(&free_event_list, monix);
|
||||
UNLOCK;
|
||||
|
||||
break;
|
||||
}
|
||||
case IOC_EVENT_ADD:
|
||||
{
|
||||
struct event_handler_args args;
|
||||
|
||||
/*
|
||||
* run the user's event handler m_available
|
||||
* points to event descriptor
|
||||
*/
|
||||
monix = (evid) t_available;
|
||||
|
||||
|
||||
/*
|
||||
* m_postsize = 0 is a confirmation of a
|
||||
* monitor cancel
|
||||
*/
|
||||
if (!t_postsize) {
|
||||
LOCK;
|
||||
lstDelete(&monix->chan->eventq, monix);
|
||||
lstAdd(&free_event_list, monix);
|
||||
UNLOCK;
|
||||
|
||||
break;
|
||||
}
|
||||
/* only call if not disabled */
|
||||
if (!monix->usr_func)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Currently only the VAXs need data
|
||||
* conversion
|
||||
*/
|
||||
#ifdef VAX
|
||||
(*cvrt[t_type]) (
|
||||
hdrptr + 1,
|
||||
hdrptr + 1,
|
||||
FALSE,
|
||||
t_count);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Orig version of CA didnt use this
|
||||
* strucure. This would run faster if I had
|
||||
* decided to pass a pointer to this
|
||||
* structure rather than the structure itself
|
||||
* early on.
|
||||
*
|
||||
* Pumping the arguments on the stack explicitly
|
||||
* could cause problems if a small item is in
|
||||
* the structure.
|
||||
*
|
||||
*/
|
||||
args.usr = monix->usr_arg;
|
||||
args.chid = monix->chan;
|
||||
args.type = t_type;
|
||||
args.count = t_count;
|
||||
args.dbr = (void *) (hdrptr + 1);
|
||||
|
||||
/* call their handler */
|
||||
(*monix->usr_func) (args);
|
||||
|
||||
break;
|
||||
}
|
||||
case IOC_READ:
|
||||
case IOC_READ_BUILD:
|
||||
{
|
||||
chid chan = (chid) hdrptr->m_pciu;
|
||||
unsigned size;
|
||||
|
||||
/*
|
||||
* only count get returns if from the current
|
||||
* read seq
|
||||
*/
|
||||
if (!VALID_MSG(piiu))
|
||||
break;
|
||||
|
||||
size = dbr_size_n(t_type, t_count);
|
||||
|
||||
/*
|
||||
* Currently only the VAXs need data
|
||||
* conversion
|
||||
*/
|
||||
#ifdef VAX
|
||||
(*cvrt[t_type]) (
|
||||
hdrptr + 1,
|
||||
t_available,
|
||||
FALSE,
|
||||
t_count);
|
||||
#else
|
||||
/*
|
||||
* in line is a little faster
|
||||
*/
|
||||
switch(size){
|
||||
case sizeof(char):
|
||||
*(char *) t_available =
|
||||
*(char *) (hdrptr + 1);
|
||||
break;
|
||||
case sizeof(short):
|
||||
*(short *) t_available =
|
||||
*(short *) (hdrptr + 1);
|
||||
break;
|
||||
case sizeof(long):
|
||||
*(long *) t_available =
|
||||
*(long *) (hdrptr + 1);
|
||||
break;
|
||||
case sizeof(double):
|
||||
*(double *) t_available =
|
||||
*(double *) (hdrptr + 1);
|
||||
break;
|
||||
default:
|
||||
memcpy(
|
||||
t_available,
|
||||
hdrptr + 1,
|
||||
size);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* decrement the outstanding IO count
|
||||
*
|
||||
* This relies on the IOC_READ_BUILD msg
|
||||
* returning prior to the IOC_BUILD msg.
|
||||
*/
|
||||
if (t_cmmd != IOC_READ_BUILD ||
|
||||
(chan->connection_func == NULL &&
|
||||
chan->state == cs_never_conn))
|
||||
CLRPENDRECV;
|
||||
|
||||
break;
|
||||
}
|
||||
case IOC_SEARCH:
|
||||
case IOC_BUILD:
|
||||
{
|
||||
chid chan = (chid) t_available;
|
||||
struct ioc_in_use *chpiiu;
|
||||
|
||||
/*
|
||||
* ignore broadcast replies for deleted channels
|
||||
*
|
||||
*/
|
||||
LOCK;
|
||||
status = client_channel_exists(chan);
|
||||
UNLOCK;
|
||||
|
||||
if (!status) {
|
||||
char msg[64];
|
||||
|
||||
sprintf(
|
||||
msg,
|
||||
"Search reply from %s",
|
||||
host_from_addr(pnet_addr));
|
||||
ca_signal(ECA_NOCHANMSG,msg);
|
||||
break;
|
||||
}
|
||||
|
||||
chpiiu = &iiu[chan->iocix];
|
||||
|
||||
if (chan->paddr) {
|
||||
|
||||
if (chpiiu->sock_addr.sin_addr.s_addr ==
|
||||
pnet_addr->s_addr) {
|
||||
printf("<Extra> ");
|
||||
#ifdef UNIX
|
||||
fflush(stdout);
|
||||
#endif
|
||||
} else {
|
||||
char msg[256];
|
||||
char acc[64];
|
||||
char rej[64];
|
||||
|
||||
sprintf(acc,
|
||||
"%s",
|
||||
host_from_addr(
|
||||
&chpiiu->sock_addr.sin_addr));
|
||||
sprintf(rej,
|
||||
"%s",
|
||||
host_from_addr(pnet_addr));
|
||||
sprintf(
|
||||
msg,
|
||||
"Channel: %s Accepted: %s Rejected: %s ",
|
||||
chan+1,
|
||||
acc,
|
||||
rej);
|
||||
ca_signal(ECA_DBLCHNL, msg);
|
||||
chan + 1,
|
||||
acc,
|
||||
rej);
|
||||
ca_signal(ECA_DBLCHNL, msg);
|
||||
}
|
||||
|
||||
/*
|
||||
* IOC_BUILD messages allways have a
|
||||
* IOC_READ msg following. (IOC_BUILD
|
||||
* messages are sometimes followed by
|
||||
* error messages which are ignored
|
||||
* on double replies)
|
||||
*/
|
||||
if (t_cmmd == IOC_BUILD)
|
||||
msgcnt += sizeof(struct extmsg) +
|
||||
(hdrptr + 1)->m_postsize;
|
||||
|
||||
break;
|
||||
}
|
||||
reconnect_channel(hdrptr, pnet_addr);
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case IOC_READ_SYNC:
|
||||
piiu->read_seq++;
|
||||
break;
|
||||
|
||||
case IOC_RSRV_IS_UP:
|
||||
LOCK;
|
||||
{
|
||||
struct in_addr ina;
|
||||
|
||||
ina.s_addr = (long) t_available;
|
||||
mark_server_available(&ina);
|
||||
}
|
||||
UNLOCK;
|
||||
break;
|
||||
|
||||
case REPEATER_CONFIRM:
|
||||
ca_static->ca_repeater_contacted = TRUE;
|
||||
#ifdef DEBUG
|
||||
printf("repeater confirmation recv\n");
|
||||
#endif
|
||||
break;
|
||||
|
||||
case IOC_NOT_FOUND:
|
||||
{
|
||||
chid chix = (chid) t_available;
|
||||
struct ioc_in_use *piiu = &iiu[chix->iocix];
|
||||
|
||||
LOCK;
|
||||
lstDelete(&piiu->chidlist, chix);
|
||||
lstAdd(&iiu[BROADCAST_IIU].chidlist, chix);
|
||||
chix->iocix = BROADCAST_IIU;
|
||||
if (!piiu->chidlist.count)
|
||||
close_ioc(piiu);
|
||||
|
||||
/*
|
||||
* reset the delay to the next retry or keepalive
|
||||
*/
|
||||
piiu->next_retry = CA_CURRENT_TIME;
|
||||
piiu->nconn_tries = 0;
|
||||
|
||||
manage_conn(TRUE);
|
||||
UNLOCK;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* IOC_BUILD messages allways have a IOC_READ msg following.
|
||||
* (IOC_BUILD messages are sometimes followed by error
|
||||
* messages which are ignored on double replies)
|
||||
*/
|
||||
if(t_cmmd == IOC_BUILD)
|
||||
msgcnt += sizeof(struct extmsg) +
|
||||
(hdrptr+1)->m_postsize;
|
||||
|
||||
break;
|
||||
}
|
||||
case IOC_CLEAR_CHANNEL:
|
||||
{
|
||||
chid chix = (chid) t_available;
|
||||
struct ioc_in_use *piiu = &iiu[chix->iocix];
|
||||
register evid monix;
|
||||
|
||||
|
||||
LOCK;
|
||||
/*
|
||||
* remove any orphaned get callbacks for this
|
||||
* channel
|
||||
*/
|
||||
for (monix = (evid) pend_read_list.node.next;
|
||||
monix;
|
||||
monix = (evid) monix->node.next)
|
||||
if (monix->chan == chix) {
|
||||
lstDelete(&pend_read_list, monix);
|
||||
lstAdd(&free_event_list, monix);
|
||||
}
|
||||
lstConcat(&free_event_list, &chix->eventq);
|
||||
lstDelete(&piiu->chidlist, chix);
|
||||
if (free(chix) < 0)
|
||||
abort();
|
||||
if (!piiu->chidlist.count)
|
||||
close_ioc(piiu);
|
||||
UNLOCK;
|
||||
break;
|
||||
}
|
||||
case IOC_ERROR:
|
||||
{
|
||||
char context[255];
|
||||
char *name;
|
||||
struct extmsg *req = hdrptr + 1;
|
||||
int op;
|
||||
struct exception_handler_args args;
|
||||
|
||||
|
||||
/*
|
||||
* dont process the message if they have
|
||||
* disable notification
|
||||
*/
|
||||
if (!ca_static->ca_exception_func){
|
||||
break;
|
||||
}
|
||||
|
||||
name = (char *) host_from_addr(pnet_addr);
|
||||
if (!name){
|
||||
name = "an unregistered IOC";
|
||||
}
|
||||
|
||||
if (t_postsize > sizeof(struct extmsg)){
|
||||
sprintf(context,
|
||||
"detected by: %s for: %s",
|
||||
name,
|
||||
hdrptr + 2);
|
||||
}
|
||||
else{
|
||||
sprintf(context, "detected by: %s", name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Map internal op id to external op id so I
|
||||
* can freely change the protocol in the
|
||||
* future. This is quite wasteful of space
|
||||
* however.
|
||||
*/
|
||||
switch (ntohs(req->m_cmmd)) {
|
||||
case IOC_READ_NOTIFY:
|
||||
case IOC_READ:
|
||||
op = CA_OP_GET;
|
||||
break;
|
||||
case IOC_WRITE:
|
||||
op = CA_OP_PUT;
|
||||
break;
|
||||
case IOC_SEARCH:
|
||||
case IOC_BUILD:
|
||||
op = CA_OP_SEARCH;
|
||||
break;
|
||||
case IOC_EVENT_ADD:
|
||||
op = CA_OP_ADD_EVENT;
|
||||
break;
|
||||
case IOC_EVENT_CANCEL:
|
||||
op = CA_OP_CLEAR_EVENT;
|
||||
break;
|
||||
default:
|
||||
op = CA_OP_OTHER;
|
||||
break;
|
||||
}
|
||||
|
||||
args.usr = ca_static->ca_exception_arg;
|
||||
args.chid = (chid) hdrptr->m_pciu;
|
||||
args.type = ntohs(req->m_type);
|
||||
args.count = ntohs(req->m_count);
|
||||
args.addr = (void *) (req->m_available);
|
||||
args.stat = ntohl((int) t_available); args.op = op;
|
||||
args.ctx = context;
|
||||
(*ca_static->ca_exception_func) (args);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
printf("post_msg(): Corrupt Cmd in msg %x\n",
|
||||
t_cmmd);
|
||||
abort();
|
||||
}
|
||||
|
||||
*pbufcnt -= msgcnt;
|
||||
hdrptr = (struct extmsg *) (msgcnt + (char *) hdrptr);
|
||||
|
||||
if(!chan->connection_func && chan->state==cs_never_conn){
|
||||
/* decrement the outstanding IO count */
|
||||
CLRPENDRECV;
|
||||
}
|
||||
|
||||
LOCK;
|
||||
reconnect_channel(hdrptr,net_addr,piiu);
|
||||
UNLOCK;
|
||||
|
||||
if(chan->connection_func){
|
||||
struct connection_handler_args args;
|
||||
post_msg_active--;
|
||||
|
||||
args.chid = chan;
|
||||
args.op = CA_OP_CONN_UP;
|
||||
(*chan->connection_func)(args);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case IOC_READ_SYNC:
|
||||
piiu->read_seq++;
|
||||
break;
|
||||
|
||||
case IOC_RSRV_IS_UP:
|
||||
# ifdef DEBUG
|
||||
printf( "IOC on line ->[%s]\n",
|
||||
host_from_addr(t_available));
|
||||
# endif
|
||||
LOCK;
|
||||
mark_server_available(t_available);
|
||||
chid_retry(TRUE);
|
||||
UNLOCK;
|
||||
break;
|
||||
|
||||
case REPEATER_CONFIRM:
|
||||
ca_static->ca_repeater_contacted = TRUE;
|
||||
# ifdef DEBUG
|
||||
printf("repeater confirmation\n");
|
||||
# endif
|
||||
break;
|
||||
|
||||
case IOC_NOT_FOUND:
|
||||
{
|
||||
chid chix = (chid) t_available;
|
||||
struct ioc_in_use *piiu = &iiu[chix->iocix];
|
||||
|
||||
LOCK;
|
||||
lstDelete(&piiu->chidlist, chix);
|
||||
lstAdd(&iiu[BROADCAST_IIU].chidlist, chix);
|
||||
chix->iocix = BROADCAST_IIU;
|
||||
if(!piiu->chidlist.count)
|
||||
close_ioc(piiu);
|
||||
iiu[BROADCAST_IIU].nconn_tries = 0;
|
||||
chid_retry(TRUE);
|
||||
UNLOCK;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case IOC_CLEAR_CHANNEL:
|
||||
{
|
||||
chid chix = (chid) t_available;
|
||||
struct ioc_in_use *piiu = &iiu[chix->iocix];
|
||||
register evid monix;
|
||||
|
||||
|
||||
LOCK;
|
||||
/* remove any orphaned get callbacks for this channel */
|
||||
for( monix = (evid) pend_read_list.node.next;
|
||||
monix;
|
||||
monix = (evid) monix->node.next)
|
||||
if(monix->chan == chix){
|
||||
lstDelete(&pend_read_list, monix);
|
||||
lstAdd(&free_event_list, monix);
|
||||
}
|
||||
|
||||
lstConcat(&free_event_list, &chix->eventq);
|
||||
lstDelete(&piiu->chidlist, chix);
|
||||
if(free(chix)<0)
|
||||
abort();
|
||||
if(!piiu->chidlist.count)
|
||||
close_ioc(piiu);
|
||||
UNLOCK;
|
||||
break;
|
||||
}
|
||||
case IOC_ERROR:
|
||||
{
|
||||
char context[255];
|
||||
char *name;
|
||||
struct extmsg *req = hdrptr+1;
|
||||
int op;
|
||||
struct exception_handler_args args;
|
||||
|
||||
|
||||
/*
|
||||
* dont process the message if they have disable notification
|
||||
*/
|
||||
if(!ca_static->ca_exception_func)
|
||||
break;
|
||||
|
||||
name = (char *) host_from_addr(net_addr);
|
||||
if(!name)
|
||||
name = "an unregistered IOC";
|
||||
|
||||
if(t_postsize>sizeof(struct extmsg))
|
||||
sprintf(context, "detected by: %s for: %s", name, hdrptr+2);
|
||||
else
|
||||
sprintf(context, "detected by: %s", name);
|
||||
|
||||
/*
|
||||
* Map internal op id to external op id so I can freely change the
|
||||
* protocol in the future. This is quite wasteful of space however.
|
||||
*/
|
||||
switch(ntohs(req->m_cmmd)){
|
||||
case IOC_READ_NOTIFY:
|
||||
case IOC_READ:
|
||||
op = CA_OP_GET;
|
||||
break;
|
||||
case IOC_WRITE:
|
||||
op = CA_OP_PUT;
|
||||
break;
|
||||
case IOC_SEARCH:
|
||||
case IOC_BUILD:
|
||||
op = CA_OP_SEARCH;
|
||||
break;
|
||||
case IOC_EVENT_ADD:
|
||||
op = CA_OP_ADD_EVENT;
|
||||
break;
|
||||
case IOC_EVENT_CANCEL:
|
||||
op = CA_OP_CLEAR_EVENT;
|
||||
break;
|
||||
default:
|
||||
op = CA_OP_OTHER;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
args.usr = ca_static->ca_exception_arg; /* user arg */
|
||||
args.chid = hdrptr->m_pciu; /* the chid if appropriate */
|
||||
args.type = ntohs(req->m_type); /* req type if approp */
|
||||
args.count = ntohs(req->m_count); /* req count if approp */
|
||||
args.addr = (void *) (req->m_available);/* req user addr if approp */
|
||||
args.stat = ntohl((int)t_available); /* the CA message code */
|
||||
args.op = op; /* the CA operation */
|
||||
args.ctx = context; /* context string */
|
||||
(*ca_static->ca_exception_func)(args);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
printf("post_msg(): Corrupt Cmd in msg %x\n",t_cmmd);
|
||||
abort();
|
||||
}
|
||||
|
||||
bufcnt -= msgcnt;
|
||||
hdrptr = (struct extmsg *) (msgcnt + (char *) hdrptr);
|
||||
|
||||
}
|
||||
|
||||
|
||||
post_msg_active--;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@@ -477,10 +540,9 @@ if(t_postsize > (t_count-1) * dbr_value_size[t_type] + dbr_size[t_type])
|
||||
* LOCK must be on
|
||||
*
|
||||
*/
|
||||
void reconnect_channel(hdrptr,net_addr,piiu)
|
||||
static void reconnect_channel(hdrptr,pnet_addr)
|
||||
register struct extmsg *hdrptr;
|
||||
struct in_addr net_addr;
|
||||
struct ioc_in_use *piiu;
|
||||
struct in_addr *pnet_addr;
|
||||
{
|
||||
chid chan = (chid) hdrptr->m_available;
|
||||
unsigned short newiocix;
|
||||
@@ -489,15 +551,17 @@ struct ioc_in_use *piiu;
|
||||
|
||||
void ca_request_event();
|
||||
|
||||
|
||||
LOCK;
|
||||
status = alloc_ioc (
|
||||
net_addr,
|
||||
pnet_addr,
|
||||
IPPROTO_TCP,
|
||||
&newiocix
|
||||
);
|
||||
if(status != ECA_NORMAL){
|
||||
printf("... %s ...\n", ca_message(status));
|
||||
printf("for %s on %s\n", chan+1, host_from_addr(net_addr));
|
||||
printf("ignored broadcast reply- proceeding\n");
|
||||
printf("for %s on %s\n", chan+1, host_from_addr(pnet_addr));
|
||||
printf("ignored search reply- proceeding\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -531,7 +595,7 @@ struct ioc_in_use *piiu;
|
||||
pevent = (evid) pevent->node.next)
|
||||
if(pevent->chan == chan){
|
||||
issue_get_callback(pevent);
|
||||
send_msg();
|
||||
cac_send_msg();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -542,8 +606,23 @@ struct ioc_in_use *piiu;
|
||||
pevent;
|
||||
pevent = (evid)pevent->node.next)
|
||||
ca_request_event(pevent);
|
||||
send_msg();
|
||||
cac_send_msg();
|
||||
}
|
||||
|
||||
UNLOCK;
|
||||
|
||||
if(chan->connection_func){
|
||||
struct connection_handler_args args;
|
||||
|
||||
args.chid = chan;
|
||||
args.op = CA_OP_CONN_UP;
|
||||
(*chan->connection_func)(args);
|
||||
}
|
||||
else if(chan->state==cs_never_conn){
|
||||
/* decrement the outstanding IO count */
|
||||
CLRPENDRECV;
|
||||
}
|
||||
|
||||
chan->state = cs_conn;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
*
|
||||
* T E S T _ E V E N T . C
|
||||
* Author: Jeffrey O. Hill
|
||||
* simple stub for testing monitors
|
||||
*
|
||||
*
|
||||
* History
|
||||
* joh 031891 printed type in decimanl instead of hex
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/* System includes */
|
||||
|
||||
#include <cadef.h>
|
||||
@@ -8,22 +23,33 @@ void
|
||||
ca_test_event(args)
|
||||
struct event_handler_args args;
|
||||
{
|
||||
|
||||
printf("~~~### in test event for [%s] ###~~~\n",args.chid+1);
|
||||
printf("User argument\t%x\n", args.usr);
|
||||
printf("Native channel data type\t%x\n", args.chid->type);
|
||||
printf("Monitor data type\t%x\n", args.type);
|
||||
printf("Native channel data type\t%d\n", args.chid->type);
|
||||
printf("Monitor data type\t%d\n", args.type);
|
||||
switch(args.type){
|
||||
case DBR_STRING:
|
||||
printf("Value:\t<%s>\n",args.dbr);
|
||||
break;
|
||||
case DBR_CHAR:
|
||||
printf("Value:\t<%d>\n",*(char *)args.dbr);
|
||||
break;
|
||||
#if DBR_INT != DBR_SHORT
|
||||
case DBR_INT:
|
||||
#endif
|
||||
case DBR_SHORT:
|
||||
case DBR_ENUM:
|
||||
printf("Value:\t<%d>\n",*(int *)args.dbr);
|
||||
printf("Value:\t<%d>\n",*(short *)args.dbr);
|
||||
break;
|
||||
case DBR_LONG:
|
||||
printf("Value:\t<%d>\n",*(long *)args.dbr);
|
||||
break;
|
||||
case DBR_FLOAT:
|
||||
printf("Value:\t<%f>\n",*(float *)args.dbr);
|
||||
break;
|
||||
case DBR_DOUBLE:
|
||||
printf("Value:\t<%f>\n",*(double *)args.dbr);
|
||||
break;
|
||||
case DBR_STS_STRING:
|
||||
printf("Value:\t<%s>\n",((struct dbr_sts_string *)args.dbr)->value);
|
||||
break;
|
||||
@@ -39,7 +65,6 @@ struct event_handler_args args;
|
||||
case DBR_GR_FLOAT:
|
||||
printf("Value:\t<%f>\n",((struct dbr_gr_float *)args.dbr)->value);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf( "Sorry test_event does not handle data type %d yet\n",
|
||||
args.type);
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .01 mm-dd-yy iii Comment
|
||||
* .01 06-25-91 joh inserted the RISC aligned db_access.h structures
|
||||
*/
|
||||
|
||||
|
||||
@@ -110,28 +110,16 @@
|
||||
|
||||
/* function declarations */
|
||||
|
||||
/*
|
||||
* database access address structure
|
||||
*/
|
||||
#include <db_addr.h>
|
||||
|
||||
/* database access address structure (removed from db_access.h and put here) */
|
||||
struct db_addr{
|
||||
char *precord; /* record number of specified type */
|
||||
char *pfield; /* offset from the record origin */
|
||||
char *pad0; /* not used by old */
|
||||
short pad1; /*not used by old */
|
||||
short no_elements; /* number of elements in arrays of data */
|
||||
short record_type; /* type of record being accessed */
|
||||
short pad2; /* not used by old */
|
||||
short field_size; /* size of the field being accessed */
|
||||
/* from database for values of waveforms */
|
||||
short special; /* special processing */
|
||||
short choice_set; /* index of choiceSet GBLCHOICE & RECCHOICE*/
|
||||
short field_type; /* field type as seen by database request*/
|
||||
/*DBR_STRING,...,DBR_ENUM,DBR_NOACCESS*/
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* structures for old database access */
|
||||
#ifndef MAX_STRING_SIZE
|
||||
#define MAX_STRING_SIZE 40
|
||||
#endif
|
||||
|
||||
|
||||
/* VALUES WITH STATUS STRUCTURES */
|
||||
|
||||
/* structure for a string status field */
|
||||
@@ -169,9 +157,10 @@ struct dbr_sts_enum{
|
||||
|
||||
/* structure for a char status field */
|
||||
struct dbr_sts_char{
|
||||
short status; /* status of value */
|
||||
short severity; /* severity of alarm */
|
||||
unsigned char value; /* current value */
|
||||
short status; /* status of value */
|
||||
short severity; /* severity of alarm */
|
||||
char RISC_pad; /* RISC alignment */
|
||||
unsigned char value; /* current value */
|
||||
};
|
||||
|
||||
/* structure for a long status field */
|
||||
@@ -185,6 +174,7 @@ struct dbr_sts_long{
|
||||
struct dbr_sts_double{
|
||||
short status; /* status of value */
|
||||
short severity; /* severity of alarm */
|
||||
long RISC_pad; /* RISC alignment */
|
||||
double value; /* current value */
|
||||
};
|
||||
|
||||
@@ -203,6 +193,7 @@ struct dbr_time_short{
|
||||
short status; /* status of value */
|
||||
short severity; /* severity of alarm */
|
||||
TS_STAMP stamp; /* time stamp */
|
||||
short RISC_pad; /* RISC alignment */
|
||||
short value; /* current value */
|
||||
};
|
||||
|
||||
@@ -219,6 +210,7 @@ struct dbr_time_enum{
|
||||
short status; /* status of value */
|
||||
short severity; /* severity of alarm */
|
||||
TS_STAMP stamp; /* time stamp */
|
||||
short RISC_pad; /* RISC alignment */
|
||||
short value; /* current value */
|
||||
};
|
||||
|
||||
@@ -227,6 +219,8 @@ struct dbr_time_char{
|
||||
short status; /* status of value */
|
||||
short severity; /* severity of alarm */
|
||||
TS_STAMP stamp; /* time stamp */
|
||||
short RISC_pad0; /* RISC alignment */
|
||||
char RISC_pad1; /* RISC alignment */
|
||||
unsigned char value; /* current value */
|
||||
};
|
||||
|
||||
@@ -243,6 +237,7 @@ struct dbr_time_double{
|
||||
short status; /* status of value */
|
||||
short severity; /* severity of alarm */
|
||||
TS_STAMP stamp; /* time stamp */
|
||||
long RISC_pad; /* RISC alignment */
|
||||
double value; /* current value */
|
||||
};
|
||||
|
||||
@@ -282,6 +277,7 @@ struct dbr_gr_float{
|
||||
short status; /* status of value */
|
||||
short severity; /* severity of alarm */
|
||||
short precision; /* number of decimal places */
|
||||
short RISC_pad0; /* RISC alignment */
|
||||
char units[8]; /* units of value */
|
||||
float upper_disp_limit; /* upper limit of graph */
|
||||
float lower_disp_limit; /* lower limit of graph */
|
||||
@@ -303,16 +299,17 @@ struct dbr_gr_enum{
|
||||
|
||||
/* structure for a graphic char field */
|
||||
struct dbr_gr_char{
|
||||
short status; /* status of value */
|
||||
short severity; /* severity of alarm */
|
||||
char units[8]; /* units of value */
|
||||
unsigned char upper_disp_limit; /* upper limit of graph */
|
||||
unsigned char lower_disp_limit; /* lower limit of graph */
|
||||
unsigned char upper_alarm_limit;
|
||||
unsigned char upper_warning_limit;
|
||||
unsigned char lower_warning_limit;
|
||||
unsigned char lower_alarm_limit;
|
||||
unsigned char value; /* current value */
|
||||
short status; /* status of value */
|
||||
short severity; /* severity of alarm */
|
||||
char units[8]; /* units of value */
|
||||
unsigned char upper_disp_limit; /* upper limit of graph */
|
||||
unsigned char lower_disp_limit; /* lower limit of graph */
|
||||
unsigned char upper_alarm_limit;
|
||||
unsigned char upper_warning_limit;
|
||||
unsigned char lower_warning_limit;
|
||||
unsigned char lower_alarm_limit;
|
||||
char RISC_pad; /* RISC alignment */
|
||||
unsigned char value; /* current value */
|
||||
};
|
||||
|
||||
/* structure for a graphic long field */
|
||||
@@ -334,6 +331,7 @@ struct dbr_gr_double{
|
||||
short status; /* status of value */
|
||||
short severity; /* severity of alarm */
|
||||
short precision; /* number of decimal places */
|
||||
short RISC_pad0; /* RISC alignment */
|
||||
char units[8]; /* units of value */
|
||||
double upper_disp_limit; /* upper limit of graph */
|
||||
double lower_disp_limit; /* lower limit of graph */
|
||||
@@ -384,6 +382,7 @@ struct dbr_ctrl_float{
|
||||
short status; /* status of value */
|
||||
short severity; /* severity of alarm */
|
||||
short precision; /* number of decimal places */
|
||||
short RISC_pad; /* RISC alignment */
|
||||
char units[8]; /* units of value */
|
||||
float upper_disp_limit; /* upper limit of graph */
|
||||
float lower_disp_limit; /* lower limit of graph */
|
||||
@@ -418,6 +417,7 @@ struct dbr_ctrl_char{
|
||||
unsigned char lower_alarm_limit;
|
||||
unsigned char upper_ctrl_limit; /* upper control limit */
|
||||
unsigned char lower_ctrl_limit; /* lower control limit */
|
||||
char RISC_pad; /* RISC alignment */
|
||||
unsigned char value; /* current value */
|
||||
};
|
||||
|
||||
@@ -442,6 +442,7 @@ struct dbr_ctrl_double{
|
||||
short status; /* status of value */
|
||||
short severity; /* severity of alarm */
|
||||
short precision; /* number of decimal places */
|
||||
short RISC_pad0; /* RISC alignment */
|
||||
char units[8]; /* units of value */
|
||||
double upper_disp_limit; /* upper limit of graph */
|
||||
double lower_disp_limit; /* lower limit of graph */
|
||||
@@ -455,6 +456,8 @@ struct dbr_ctrl_double{
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* From $cs/dblib/src/dbiocsubs.c
|
||||
* subroutines
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
#include <db_access.h>
|
||||
#include <task_params.h>
|
||||
#include <server.h>
|
||||
#include <dblib.h>
|
||||
#include <caerr.h>
|
||||
|
||||
|
||||
@@ -58,6 +57,7 @@ void event_cancel_reply();
|
||||
void clear_channel_reply();
|
||||
void send_err();
|
||||
void log_header();
|
||||
void search_fail_reply();
|
||||
|
||||
|
||||
/*
|
||||
@@ -397,7 +397,7 @@ read_reply(pevext, paddr, hold, pfl)
|
||||
FAST struct event_ext *pevext;
|
||||
FAST struct db_addr *paddr;
|
||||
int hold; /* more on the way if true */
|
||||
db_field_log *pfl;
|
||||
void *pfl;
|
||||
{
|
||||
FAST struct extmsg *mp = pevext->mp;
|
||||
FAST struct client *client = pevext->client;
|
||||
@@ -508,7 +508,6 @@ build_reply(mp, client)
|
||||
struct db_addr tmp_addr;
|
||||
FAST struct channel_in_use *pchannel;
|
||||
|
||||
void search_fail_reply();
|
||||
|
||||
|
||||
/* Exit quickly if channel not on this node */
|
||||
|
||||
@@ -1,26 +1,46 @@
|
||||
/* The IOC connection request server */
|
||||
/*
|
||||
*******************************************************************************
|
||||
** GTA PROJECT
|
||||
** Copyright 1988, The Regents of the University of California.
|
||||
** Los Alamos National Laboratory
|
||||
** Los Alamos New Mexico 87845
|
||||
** cast_server.c - GTA request server main loop
|
||||
** Sun UNIX 4.2 Release 3.4
|
||||
** First Release- Jeff Hill May 88
|
||||
**
|
||||
**
|
||||
**
|
||||
** FIXES NEEDED:
|
||||
**
|
||||
** Dont send channel found message unless there is memory, a task slot,
|
||||
** and a TCP socket available. Send a diagnostic instead.
|
||||
** Or ... make the timeout shorter? This is only a problem if
|
||||
** they persist in trying to make a connection after getting no
|
||||
** response.
|
||||
**
|
||||
*******************************************************************************
|
||||
*/
|
||||
/* @(#)cast_server.c
|
||||
* $Id$
|
||||
* Author: Jeffrey O. Hill
|
||||
* hill@luke.lanl.gov
|
||||
* (505) 665 1831
|
||||
* Date: 5-88
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .00 joh 030191 Fixed cast server to not block on TCP
|
||||
* .01 joh 030891 now reuses old client structure
|
||||
* .02 joh 032091 allways flushes if the client changes and the old
|
||||
* client has a TCP connection.(bug introduced by .00)
|
||||
*
|
||||
* Improvements
|
||||
* ------------
|
||||
* Dont send channel found message unless there is memory, a task slot,
|
||||
* and a TCP socket available. Send a diagnostic instead.
|
||||
* Or ... make the timeout shorter? This is only a problem if
|
||||
* they persist in trying to make a connection after getting no
|
||||
* response.
|
||||
*/
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <lstLib.h>
|
||||
@@ -33,230 +53,288 @@
|
||||
#include <task_params.h>
|
||||
#include <server.h>
|
||||
|
||||
|
||||
|
||||
STATUS
|
||||
|
||||
/*
|
||||
* CAST_SERVER
|
||||
*
|
||||
* service UDP messages
|
||||
*
|
||||
*/
|
||||
void
|
||||
cast_server()
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
FAST int status;
|
||||
int i;
|
||||
FAST struct client *client;
|
||||
FAST struct client *tmpclient = NULL;
|
||||
struct sockaddr_in recv_addr;
|
||||
int recv_addr_size = sizeof(recv_addr);
|
||||
unsigned nchars;
|
||||
static struct message_buffer udp_msg;
|
||||
# define TIMEOUT 60 /* sec */
|
||||
unsigned long timeout = TIMEOUT * sysClkRateGet();
|
||||
struct sockaddr_in sin;
|
||||
FAST int status;
|
||||
int count;
|
||||
FAST struct client *client = NULL;
|
||||
FAST struct client *true_client = NULL;
|
||||
FAST struct client *temp_client;
|
||||
struct sockaddr_in recv_addr;
|
||||
int recv_addr_size = sizeof(recv_addr);
|
||||
unsigned nchars;
|
||||
# define TIMEOUT 60 /* sec */
|
||||
unsigned long timeout = TIMEOUT*sysClkRateGet();
|
||||
static struct message_buffer udp_msg;
|
||||
|
||||
struct client *existing_client();
|
||||
struct client *create_udp_client();
|
||||
void rsrv_online_notify_task();
|
||||
struct client *existing_client();
|
||||
struct client *create_udp_client();
|
||||
void rsrv_online_notify_task();
|
||||
|
||||
if( IOC_cast_sock!=0 && IOC_cast_sock!=ERROR )
|
||||
if( (status = close(IOC_cast_sock)) == ERROR )
|
||||
logMsg("Unable to close open master socket\n");
|
||||
if( IOC_cast_sock!=0 && IOC_cast_sock!=ERROR )
|
||||
if( (status = close(IOC_cast_sock)) == ERROR )
|
||||
logMsg("Unable to close open master socket\n");
|
||||
|
||||
/*
|
||||
* Open the socket.
|
||||
* Use ARPA Internet address format and datagram socket.
|
||||
* Format described in <sys/socket.h>.
|
||||
*/
|
||||
/*
|
||||
* Open the socket.
|
||||
* Use ARPA Internet address format and datagram socket.
|
||||
* Format described in <sys/socket.h>.
|
||||
*/
|
||||
|
||||
if((IOC_cast_sock = socket (AF_INET, SOCK_DGRAM, 0)) == ERROR){
|
||||
logMsg("Socket creation error\n");
|
||||
printErrno (errnoGet ());
|
||||
taskSuspend(0);
|
||||
}
|
||||
if((IOC_cast_sock = socket (AF_INET, SOCK_DGRAM, 0)) == ERROR){
|
||||
logMsg("Socket creation error\n");
|
||||
printErrno (errnoGet ());
|
||||
taskSuspend(0);
|
||||
}
|
||||
|
||||
|
||||
/* Zero the sock_addr structure */
|
||||
bfill(&sin, sizeof(sin), 0);
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_addr.s_addr = INADDR_ANY;
|
||||
sin.sin_port = CA_SERVER_PORT;
|
||||
/* Zero the sock_addr structure */
|
||||
bfill(&sin, sizeof(sin), 0);
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_addr.s_addr = INADDR_ANY;
|
||||
sin.sin_port = CA_SERVER_PORT;
|
||||
|
||||
|
||||
/* get server's Internet address */
|
||||
if (bind (IOC_cast_sock, &sin, sizeof (sin)) == ERROR){
|
||||
logMsg("Bind error\n");
|
||||
printErrno (errnoGet ());
|
||||
close (IOC_cast_sock);
|
||||
taskSuspend(0);
|
||||
}
|
||||
/* get server's Internet address */
|
||||
if( bind(IOC_cast_sock, &sin, sizeof (sin)) == ERROR){
|
||||
logMsg("Bind error\n");
|
||||
printErrno (errnoGet ());
|
||||
close (IOC_cast_sock);
|
||||
taskSuspend(0);
|
||||
}
|
||||
|
||||
|
||||
bfill(&udp_msg, sizeof(udp_msg), NULL);
|
||||
bfill(&udp_msg, sizeof(udp_msg), NULL);
|
||||
|
||||
/* tell clients we are on line again */
|
||||
status = taskSpawn(
|
||||
CA_ONLINE_NAME,
|
||||
CA_ONLINE_PRI,
|
||||
CA_ONLINE_OPT,
|
||||
CA_ONLINE_STACK,
|
||||
rsrv_online_notify_task);
|
||||
if(status<0){
|
||||
logMsg("Cast_server: couldnt start up online notify task\n");
|
||||
printErrno(errnoGet ());
|
||||
}
|
||||
/* tell clients we are on line again */
|
||||
status = taskSpawn(
|
||||
CA_ONLINE_NAME,
|
||||
CA_ONLINE_PRI,
|
||||
CA_ONLINE_OPT,
|
||||
CA_ONLINE_STACK,
|
||||
rsrv_online_notify_task);
|
||||
if(status<0){
|
||||
logMsg("Cast_server: couldnt start up online notify task\n");
|
||||
printErrno(errnoGet ());
|
||||
}
|
||||
|
||||
|
||||
while(TRUE){
|
||||
while(TRUE){
|
||||
|
||||
status = recvfrom( IOC_cast_sock,
|
||||
&udp_msg.cnt,
|
||||
sizeof(udp_msg.cnt)+sizeof(udp_msg.buf),
|
||||
/*
|
||||
* setup new client structure but reuse old structure if
|
||||
* possible
|
||||
*
|
||||
*/
|
||||
if(!client){
|
||||
client = create_udp_client(IOC_cast_sock);
|
||||
if(!client){
|
||||
taskDelay(sysClkRateGet()*60*5);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
status = recvfrom(
|
||||
IOC_cast_sock,
|
||||
udp_msg.buf,
|
||||
sizeof(udp_msg.buf),
|
||||
NULL,
|
||||
&recv_addr,
|
||||
&recv_addr_size);
|
||||
if(status<0){
|
||||
logMsg("Cast_server: UDP recv error\n");
|
||||
printErrno(errnoGet ());
|
||||
taskSuspend(0);
|
||||
}
|
||||
if(status<0){
|
||||
logMsg("Cast_server: UDP recv error\n");
|
||||
printErrno(errnoGet ());
|
||||
taskSuspend(0);
|
||||
}
|
||||
|
||||
if(status != udp_msg.cnt){
|
||||
logMsg("Cast_server: Recieved a corrupt broadcast\n");
|
||||
continue;
|
||||
}
|
||||
udp_msg.cnt = status;
|
||||
udp_msg.stk = 0;
|
||||
|
||||
/*
|
||||
* If we are talking to a new client flush the old one
|
||||
* in case it is holding UDP messages for a
|
||||
* TCP connected client - waiting to see if the
|
||||
* next message is for this same client.
|
||||
* (replies to broadcasts are not returned over
|
||||
* an existing TCP connection to avoid a TCP
|
||||
* pend which could lock up the cast server).
|
||||
*/
|
||||
if( client->valid_addr &&
|
||||
(client->addr.sin_addr.s_addr !=
|
||||
recv_addr.sin_addr.s_addr ||
|
||||
client->addr.sin_port != recv_addr.sin_port)){
|
||||
cas_send_msg(client, TRUE);
|
||||
}
|
||||
client->addr = recv_addr;
|
||||
client->valid_addr = TRUE;
|
||||
|
||||
if(MPDEBUG==2){
|
||||
logMsg( "cast_server(): msg of %d bytes\n",
|
||||
status);
|
||||
logMsg( "from addr %x, port %x \n",
|
||||
recv_addr.sin_addr,
|
||||
recv_addr.sin_port);
|
||||
}
|
||||
|
||||
if(MPDEBUG==2){
|
||||
logMsg( "cast_server(): recieved a broadcast of %d bytes\n", status);
|
||||
logMsg( "from addr %x, port %x \n",
|
||||
recv_addr.sin_addr,
|
||||
recv_addr.sin_port);
|
||||
}
|
||||
if(MPDEBUG==3)
|
||||
count = client->addrq.count;
|
||||
|
||||
/* subtract header size */
|
||||
udp_msg.cnt -= sizeof(udp_msg.cnt);
|
||||
/*
|
||||
* check for existing client occurs after
|
||||
* message process so that this thread never
|
||||
* blocks sending TCP
|
||||
*/
|
||||
status = camessage(client, &udp_msg);
|
||||
if(status == OK){
|
||||
if(udp_msg.cnt != udp_msg.stk){
|
||||
printf( "CA UDP Message OF %d\n",
|
||||
udp_msg.cnt-udp_msg.stk);
|
||||
}
|
||||
}
|
||||
|
||||
/* setup new client structure but, reuse old structure if possible */
|
||||
LOCK_CLIENTQ;
|
||||
client = existing_client(&recv_addr);
|
||||
if(!client){
|
||||
if(tmpclient){
|
||||
client = tmpclient;
|
||||
tmpclient = NULL;
|
||||
}
|
||||
else
|
||||
client = create_udp_client(IOC_cast_sock);
|
||||
if(!client){
|
||||
UNLOCK_CLIENTQ;
|
||||
continue;
|
||||
}
|
||||
if(client->addrq.count){
|
||||
LOCK_CLIENTQ;
|
||||
|
||||
client->addr = recv_addr;
|
||||
client->ticks_at_creation = tickGet();
|
||||
lstAdd(&clientQ, client);
|
||||
}
|
||||
true_client = existing_client(&client->addr);
|
||||
if(true_client == NULL){
|
||||
client->ticks_at_creation = tickGet();
|
||||
lstAdd(&clientQ, client);
|
||||
client = NULL;
|
||||
}else{
|
||||
lstConcat(
|
||||
&true_client->addrq,
|
||||
&client->addrq);
|
||||
}
|
||||
|
||||
if(MPDEBUG==2)
|
||||
i = client->addrq.count;
|
||||
UNLOCK_CLIENTQ;
|
||||
|
||||
message_process(client, &udp_msg);
|
||||
if(MPDEBUG==3){
|
||||
logMsg( "Fnd %d name matches (%d tot)\n",
|
||||
client->addrq.count-count,
|
||||
client->addrq.count);
|
||||
}
|
||||
}
|
||||
|
||||
/* remove client data structure from list if channel not found */
|
||||
if(client->addrq.count){
|
||||
if(MPDEBUG==2)
|
||||
logMsg( "Found %d new channel name matches (%d cumulative)\n",
|
||||
client->addrq.count-i,
|
||||
client->addrq.count);
|
||||
}
|
||||
else{
|
||||
lstDelete(&clientQ, client);
|
||||
if(!tmpclient)
|
||||
tmpclient = client;
|
||||
else
|
||||
free(client);
|
||||
}
|
||||
/*
|
||||
* allow message to batch up if more are comming
|
||||
*/
|
||||
status = ioctl(IOC_cast_sock, FIONREAD, &nchars);
|
||||
if(status == ERROR){
|
||||
printErrno(errnoGet(0));
|
||||
taskSuspend(0);
|
||||
}
|
||||
|
||||
/*
|
||||
allow message to batch up if more are comming
|
||||
*/
|
||||
status = ioctl(IOC_cast_sock, FIONREAD, &nchars);
|
||||
if(status == ERROR){
|
||||
printErrno(errnoGet(0));
|
||||
taskSuspend(0);
|
||||
}
|
||||
if(nchars == 0){
|
||||
client = (struct client *) &clientQ;
|
||||
while(client = (struct client *) client->node.next)
|
||||
send_msg(client);
|
||||
if(nchars == 0){
|
||||
if(client)
|
||||
cas_send_msg(client, TRUE);
|
||||
|
||||
clean_clientq(timeout);
|
||||
}
|
||||
UNLOCK_CLIENTQ;
|
||||
/*
|
||||
* catch any that have not been sent yet
|
||||
*/
|
||||
LOCK_CLIENTQ;
|
||||
temp_client = (struct client *) &clientQ;
|
||||
while(temp_client = (struct client *)
|
||||
temp_client->node.next){
|
||||
if(temp_client->proto == IPPROTO_UDP)
|
||||
cas_send_msg(temp_client, TRUE);
|
||||
}
|
||||
|
||||
}
|
||||
clean_clientq(timeout);
|
||||
UNLOCK_CLIENTQ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
struct client
|
||||
*create_udp_client(sock)
|
||||
|
||||
/*
|
||||
* CREATE_UDP_CLIENT
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct client *create_udp_client(sock)
|
||||
unsigned sock;
|
||||
{
|
||||
struct client *client;
|
||||
struct client *client;
|
||||
|
||||
client = (struct client *)malloc(sizeof(struct client));
|
||||
if(!client){
|
||||
printErrno(errnoGet ());
|
||||
return NULL;
|
||||
}
|
||||
LOCK_CLIENTQ;
|
||||
client = (struct client *)lstGet(&rsrv_free_clientQ);
|
||||
UNLOCK_CLIENTQ;
|
||||
|
||||
if(MPDEBUG==2)
|
||||
logMsg( "cast_server(): Creating data structures for new udp client\n");
|
||||
if(!client){
|
||||
client = (struct client *)malloc(sizeof(struct client));
|
||||
if(!client){
|
||||
logMsg("CA: no mem for another client\n");
|
||||
printErrno(errnoGet ());
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
The following inits to zero done instead of a bfill since
|
||||
the send and recv buffers are large and don't need initialization.
|
||||
if(MPDEBUG==3)
|
||||
logMsg( "cast_server(): Creating new udp client\n");
|
||||
|
||||
bfill(client, sizeof(*client), NULL);
|
||||
*/
|
||||
lstInit(&client->addrq);
|
||||
client->tid = 0;
|
||||
client->send.stk = 0;
|
||||
client->send.cnt = 0;
|
||||
client->recv.stk = 0;
|
||||
client->recv.cnt = 0;
|
||||
client->evuser = NULL;
|
||||
client->eventsoff = FALSE;
|
||||
/*
|
||||
The following inits to zero done instead of a bfill since
|
||||
the send and recv buffers are large and don't need initialization.
|
||||
|
||||
client->proto = IPPROTO_UDP;
|
||||
client->send.maxstk = MAX_UDP-sizeof(client->recv.cnt);
|
||||
FASTLOCKINIT(&client->send.lock);
|
||||
bfill(client, sizeof(*client), NULL);
|
||||
*/
|
||||
lstInit(&client->addrq);
|
||||
client->tid = 0;
|
||||
client->send.stk = 0;
|
||||
client->send.cnt = 0;
|
||||
client->recv.stk = 0;
|
||||
client->recv.cnt = 0;
|
||||
client->evuser = NULL;
|
||||
client->eventsoff = FALSE;
|
||||
client->valid_addr = FALSE;
|
||||
client->disconnect = FALSE; /* for TCP only */
|
||||
|
||||
client->recv.maxstk = MAX_UDP;
|
||||
FASTLOCKINIT(&client->recv.lock);
|
||||
client->proto = IPPROTO_UDP;
|
||||
client->send.maxstk = MAX_UDP-sizeof(client->recv.cnt);
|
||||
FASTLOCKINIT(&client->send.lock);
|
||||
|
||||
client->sock = sock;
|
||||
client->recv.maxstk = MAX_UDP;
|
||||
FASTLOCKINIT(&client->recv.lock);
|
||||
|
||||
return client;
|
||||
client->sock = sock;
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
send lock must be applied
|
||||
|
||||
*/
|
||||
udp_to_tcp(client,sock)
|
||||
* UDP_TO_TCP
|
||||
*
|
||||
* send lock must be applied
|
||||
*
|
||||
*/
|
||||
int udp_to_tcp(client,sock)
|
||||
struct client *client;
|
||||
unsigned sock;
|
||||
{
|
||||
|
||||
if(MPDEBUG==2)
|
||||
logMsg("cast_server(): converting udp client to tcp\n");
|
||||
if(MPDEBUG==3)
|
||||
logMsg("cast_server(): converting udp client to tcp\n");
|
||||
|
||||
client->proto = IPPROTO_TCP;
|
||||
client->send.maxstk = MAX_TCP;
|
||||
client->recv.maxstk = MAX_TCP;
|
||||
client->sock = sock;
|
||||
client->proto = IPPROTO_TCP;
|
||||
client->send.maxstk = MAX_TCP;
|
||||
client->recv.maxstk = MAX_TCP;
|
||||
client->sock = sock;
|
||||
|
||||
return OK;
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,17 +1,36 @@
|
||||
/*
|
||||
*******************************************************************************
|
||||
** GTA PROJECT
|
||||
** Copyright 1988, The Regents of the University of California.
|
||||
** Los Alamos National Laboratory
|
||||
** Los Alamos New Mexico 87845
|
||||
** inmsgtask0.c - GTA request server message reader task.
|
||||
** Sun UNIX 4.2 Release 3.4
|
||||
** Bob Dingler February 11, 1988
|
||||
*******************************************************************************
|
||||
*/
|
||||
/* @(#)globalsource.c
|
||||
* $Id$
|
||||
* Author: Jeffrey O. Hill
|
||||
* hill@luke.lanl.gov
|
||||
* (505) 665 1831
|
||||
* Date: 5-88
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
*/
|
||||
#define GLBLSOURCE
|
||||
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <lstLib.h>
|
||||
#include <types.h>
|
||||
|
||||
@@ -1,11 +1,37 @@
|
||||
/*
|
||||
* O N L I N E _ N O T I F Y . C
|
||||
*
|
||||
* tell CA clients this a server has joined the network
|
||||
*
|
||||
* Author: Jeffrey O. Hill
|
||||
* @(#)online_notify.c
|
||||
* $Id$
|
||||
* Author: Jeffrey O. Hill
|
||||
* hill@luke.lanl.gov
|
||||
* (505) 665 1831
|
||||
* Date: 103090
|
||||
*
|
||||
* Hisory
|
||||
* .00 103090 joh First release
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* History
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -17,17 +43,13 @@
|
||||
#include <in.h>
|
||||
|
||||
/*
|
||||
* LAACS includes
|
||||
* EPICS includes
|
||||
*/
|
||||
#include <task_params.h>
|
||||
#include <iocmsg.h>
|
||||
|
||||
#define abort taskSuspend
|
||||
|
||||
struct complete_msg{
|
||||
unsigned length;
|
||||
struct extmsg extmsg;
|
||||
};
|
||||
|
||||
/*
|
||||
* RSRV_ONLINE_NOTIFY_TASK
|
||||
@@ -45,7 +67,7 @@ void rsrv_online_notify_task()
|
||||
* CA_ONLINE_DELAY [sec] max delay
|
||||
*/
|
||||
unsigned long maxdelay = CA_ONLINE_DELAY * sysClkRateGet();
|
||||
struct complete_msg msg;
|
||||
struct extmsg msg;
|
||||
|
||||
struct sockaddr_in send_addr;
|
||||
struct sockaddr_in recv_addr;
|
||||
@@ -90,9 +112,8 @@ void rsrv_online_notify_task()
|
||||
abort(0);
|
||||
|
||||
bfill(&msg, sizeof msg, NULL);
|
||||
msg.length = htonl(sizeof msg);
|
||||
msg.extmsg.m_cmmd = htons(IOC_RSRV_IS_UP);
|
||||
msg.extmsg.m_available = lcl.sin_addr.s_addr;
|
||||
msg.m_cmmd = htons(IOC_RSRV_IS_UP);
|
||||
msg.m_available = lcl.sin_addr.s_addr;
|
||||
|
||||
/* Zero the sock_addr structure */
|
||||
bfill(&send_addr, sizeof send_addr, 0);
|
||||
@@ -101,8 +122,6 @@ void rsrv_online_notify_task()
|
||||
send_addr.sin_port = htons(CA_CLIENT_PORT);
|
||||
|
||||
while(TRUE){
|
||||
|
||||
|
||||
status = sendto(
|
||||
sock,
|
||||
&msg,
|
||||
@@ -120,38 +139,3 @@ void rsrv_online_notify_task()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef JUNKYARD
|
||||
client = create_udp_client(sock);
|
||||
client->addr = send_addr;
|
||||
client->ticks_at_creation = tickGet();
|
||||
|
||||
while(TRUE){
|
||||
reply = (struct extmsg *) ALLOC_MSG(client, 0);
|
||||
if(!reply)
|
||||
abort(0);
|
||||
|
||||
|
||||
bfill(reply, sizeof(*reply), NULL);
|
||||
reply->m_cmmd = IOC_RSRV_IS_UP;
|
||||
reply->m_available = lcl.sin_addr.s_addr;
|
||||
reply->m_postsize = 0;
|
||||
|
||||
END_MSG(client);
|
||||
send_msg(client);
|
||||
|
||||
taskDelay(delay);
|
||||
delay = delay << 1;
|
||||
}
|
||||
/*
|
||||
Should it need to quit....
|
||||
|
||||
free_one_client(client);
|
||||
*/
|
||||
#endif
|
||||
|
||||
@@ -1,3 +1,34 @@
|
||||
/* @(#)rsrv_init.c
|
||||
* $Id$
|
||||
* Author: Jeffrey O. Hill
|
||||
* hill@luke.lanl.gov
|
||||
* (505) 665 1831
|
||||
* Date: 5-88
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
*/
|
||||
#include <vxWorks.h>
|
||||
#include <lstLib.h>
|
||||
#include <taskLib.h>
|
||||
@@ -11,35 +42,40 @@
|
||||
#define DELETE_TASK(TID)\
|
||||
if(errnoOfTaskGet(TID)!=ERROR)td(TID);
|
||||
|
||||
|
||||
/*
|
||||
* rsrv_init()
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
rsrv_init()
|
||||
{
|
||||
FAST struct client *client;
|
||||
void req_server();
|
||||
void cast_server();
|
||||
FAST struct client *client;
|
||||
|
||||
FASTLOCKINIT(&rsrv_free_addrq_lck);
|
||||
FASTLOCKINIT(&rsrv_free_eventq_lck);
|
||||
FASTLOCKINIT(&clientQlock);
|
||||
FASTLOCKINIT(&rsrv_free_addrq_lck);
|
||||
FASTLOCKINIT(&rsrv_free_eventq_lck);
|
||||
FASTLOCKINIT(&clientQlock);
|
||||
|
||||
/*
|
||||
the following is based on the assumtion that external variables
|
||||
are not reloaded when debugging.
|
||||
NOTE: NULL below specifies all clients
|
||||
*/
|
||||
free_client(NULL);
|
||||
/*
|
||||
* the following is based on the assumtion that external variables
|
||||
* are not reloaded when debugging. NOTE: NULL below specifies all
|
||||
* clients
|
||||
*/
|
||||
free_client(NULL);
|
||||
|
||||
|
||||
DELETE_TASK(taskNameToId(CAST_SRVR_NAME));
|
||||
DELETE_TASK(taskNameToId(REQ_SRVR_NAME));
|
||||
taskSpawn( REQ_SRVR_NAME,
|
||||
REQ_SRVR_PRI,
|
||||
REQ_SRVR_OPT,
|
||||
REQ_SRVR_STACK,
|
||||
req_server);
|
||||
DELETE_TASK(taskNameToId(CAST_SRVR_NAME));
|
||||
DELETE_TASK(taskNameToId(REQ_SRVR_NAME));
|
||||
taskSpawn(REQ_SRVR_NAME,
|
||||
REQ_SRVR_PRI,
|
||||
REQ_SRVR_OPT,
|
||||
REQ_SRVR_STACK,
|
||||
req_server);
|
||||
|
||||
taskSpawn( CAST_SRVR_NAME,
|
||||
CAST_SRVR_PRI,
|
||||
CAST_SRVR_OPT,
|
||||
CAST_SRVR_STACK,
|
||||
cast_server);
|
||||
taskSpawn(CAST_SRVR_NAME,
|
||||
CAST_SRVR_PRI,
|
||||
CAST_SRVR_OPT,
|
||||
CAST_SRVR_STACK,
|
||||
cast_server);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,54 @@
|
||||
/* @(#)server.h
|
||||
* $Id$
|
||||
* Author: Jeffrey O. Hill
|
||||
* hill@luke.lanl.gov
|
||||
* (505) 665 1831
|
||||
* Date: 5-88
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .01 joh 060691 removed 4 byte count from the beginning of
|
||||
* of each message
|
||||
* .02 joh 060791 moved send_msg stuff into caserverio.c
|
||||
*
|
||||
*/
|
||||
#ifndef INCLfast_lockh
|
||||
#include <fast_lock.h>
|
||||
#endif
|
||||
|
||||
#include <iocmsg.h>
|
||||
#ifndef INCLdb_accessh
|
||||
#include <db_access.h>
|
||||
#endif
|
||||
|
||||
#ifndef INClstLibh
|
||||
#include <lstLib.h>
|
||||
#endif
|
||||
|
||||
#ifndef __IOCMSG__
|
||||
#include <iocmsg.h>
|
||||
#endif
|
||||
|
||||
/* buf & cnt must be contiguous */
|
||||
/* cnt must be first */
|
||||
/* buf must be second */
|
||||
|
||||
struct message_buffer{
|
||||
unsigned stk;
|
||||
@@ -25,9 +67,11 @@ struct client{
|
||||
struct message_buffer recv;
|
||||
struct sockaddr_in addr;
|
||||
void *evuser;
|
||||
char eventsoff;
|
||||
unsigned long ticks_at_creation; /* for UDP timeout */
|
||||
int tid;
|
||||
char eventsoff;
|
||||
char valid_addr;
|
||||
char disconnect; /* disconnect detected */
|
||||
};
|
||||
|
||||
|
||||
@@ -69,7 +113,8 @@ LOCAL keyed;
|
||||
|
||||
GLBLTYPE int IOC_sock;
|
||||
GLBLTYPE int IOC_cast_sock;
|
||||
GLBLTYPE LIST clientQ;
|
||||
GLBLTYPE LIST clientQ; /* locked by clientQlock */
|
||||
GLBLTYPE LIST rsrv_free_clientQ; /* locked by clientQlock */
|
||||
GLBLTYPE FAST_LOCK clientQlock;
|
||||
GLBLTYPE int MPDEBUG;
|
||||
GLBLTYPE LIST rsrv_free_addrq;
|
||||
@@ -86,43 +131,25 @@ FASTUNLOCK(&(CLIENT)->send.lock);
|
||||
#define EXTMSGPTR(CLIENT)\
|
||||
((struct extmsg *) &(CLIENT)->send.buf[(CLIENT)->send.stk])
|
||||
|
||||
#define ALLOC_MSG(CLIENT, EXTSIZE)\
|
||||
(struct extmsg *)\
|
||||
((CLIENT)->send.stk + (EXTSIZE) + sizeof(struct extmsg) > \
|
||||
(CLIENT)->send.maxstk ? send_msg_nolock(CLIENT): NULL,\
|
||||
(CLIENT)->send.stk + (EXTSIZE) + sizeof(struct extmsg) >\
|
||||
(CLIENT)->send.maxstk ? NULL : EXTMSGPTR(CLIENT))
|
||||
/*
|
||||
* ALLOC_MSG get a ptr to space in the buffer
|
||||
* END_MSG push a message onto the buffer stack
|
||||
*
|
||||
*/
|
||||
#define ALLOC_MSG(CLIENT, EXTSIZE) cas_alloc_msg(CLIENT, EXTSIZE)
|
||||
|
||||
#define END_MSG(CLIENT)\
|
||||
EXTMSGPTR(CLIENT)->m_postsize = CA_MESSAGE_ALIGN(EXTMSGPTR(CLIENT)->m_postsize),\
|
||||
(CLIENT)->send.stk += sizeof(struct extmsg) + EXTMSGPTR(CLIENT)->m_postsize
|
||||
|
||||
/* send with lock */
|
||||
#define send_msg(CLIENT)\
|
||||
{LOCK_SEND(CLIENT); send_msg_nolock(CLIENT); UNLOCK_SEND(CLIENT)};
|
||||
|
||||
/* send with empty test */
|
||||
#define send_msg_nolock(CLIENT)\
|
||||
!(CLIENT)->send.stk ? FALSE: send_msg_actual(CLIENT)
|
||||
#define LOCK_CLIENTQ FASTLOCK(&clientQlock)
|
||||
|
||||
/* vanilla send */
|
||||
#define send_msg_actual(CLIENT)\
|
||||
(\
|
||||
(CLIENT)->send.cnt = (CLIENT)->send.stk + sizeof((CLIENT)->send.cnt),\
|
||||
(CLIENT)->send.stk = 0,\
|
||||
MPDEBUG==2?logMsg("Sent a message of %d bytes\n",(CLIENT)->send.cnt):NULL,\
|
||||
sendto ( (CLIENT)->sock, \
|
||||
&(CLIENT)->send.cnt, \
|
||||
(CLIENT)->send.cnt, \
|
||||
0,\
|
||||
&(CLIENT)->addr,\
|
||||
sizeof((CLIENT)->addr))==ERROR?LOG_SEND_ERROR,FALSE:TRUE\
|
||||
)
|
||||
#define UNLOCK_CLIENTQ FASTUNLOCK(&clientQlock)
|
||||
|
||||
#define LOG_SEND_ERROR \
|
||||
(logMsg("Send_msg() unable to send, connection broken? %\n"))
|
||||
|
||||
#define LOCK_CLIENTQ \
|
||||
FASTLOCK(&clientQlock)
|
||||
|
||||
#define UNLOCK_CLIENTQ \
|
||||
FASTUNLOCK(&clientQlock)
|
||||
struct client *existing_client();
|
||||
void camsgtask();
|
||||
void req_server();
|
||||
void cast_server();
|
||||
void cas_send_msg();
|
||||
struct extmsg *cas_alloc_msg();
|
||||
|
||||
Reference in New Issue
Block a user