
- Refactored site specific stuff into a site module - PSI specific stuff is now in the PSI directory. - The old version has been tagged with pre-ansto
285 lines
10 KiB
C
Executable File
285 lines
10 KiB
C
Executable File
#define IDENT "1A08"
|
||
/*
|
||
** +--------------------------------------------------------------+
|
||
** | Paul Scherrer Institute |
|
||
** | SINQ Division |
|
||
** | |
|
||
** | This software may be used freely by non-profit organizations.|
|
||
** | It may be copied provided that the name of P.S.I. and of the |
|
||
** | author is included. Neither P.S.I. nor the author assume any |
|
||
** | responsibility for the use of this software outside of P.S.I.|
|
||
** +--------------------------------------------------------------+
|
||
**
|
||
** Module Name . . . . . . . . : [...SinqHM]SinqHM_srv_server.c
|
||
**
|
||
** Author . . . . . . . . . . : D. Maden
|
||
** Date of creation . . . . . . : Oct 1996
|
||
**
|
||
** Updates:
|
||
** 1A01 2-Oct-1996 DM Initial version.
|
||
**
|
||
** SinqHM_srv_server.c forms a child process of the SINQ Histogram Memory
|
||
** process. It does the communication with the client.
|
||
**
|
||
** To compile this program for VxWorks on PSS123, use:
|
||
**
|
||
ccvx SinqHM_srv_server.c
|
||
** where
|
||
ccvx = ccppc -O0 \
|
||
-mcpu=603 \
|
||
-I${WIND_BASE}/target/h \
|
||
-fno-builtin \
|
||
-fno-for-scope \
|
||
-nostdinc \
|
||
-DCPU=PPC603 \
|
||
-D_GNU_TOOL \
|
||
-gdwarf -c -Wimplicit
|
||
**
|
||
**====================================================================
|
||
*/
|
||
#include <vxWorks.h>
|
||
#include <taskLib.h>
|
||
#include <msgQLib.h>
|
||
#include <sockLib.h>
|
||
|
||
#include <stdlib.h>
|
||
#include <stdio.h>
|
||
#include <setjmp.h>
|
||
|
||
#include <unistd.h> /* Get the POSIX environment defined ..
|
||
** .. see DEC OSF/1 Guide to Realtime Programming */
|
||
#include <errno.h>
|
||
#include <netinet/in.h>
|
||
#include <sys/types.h>
|
||
#include <sys/socket.h>
|
||
|
||
#include <sys/mman.h> /* Get POSIX mem mgmnt definitions. */
|
||
#include <signal.h> /* Get POSIX signal definitions. */
|
||
#include <timers.h>
|
||
#include <sys/wait.h> /* Get POSIX wait definitions. */
|
||
/*
|
||
**==================== Global Definitions =====================================
|
||
*/
|
||
#include "SinqHM_def.h"
|
||
#include "SinqHM_gbl.h"
|
||
/*==============================================================================
|
||
Local Routines for SRV
|
||
** None
|
||
*/
|
||
/*==============================================================================
|
||
Global Routines for SRV
|
||
**
|
||
*/
|
||
void SinqHM_server_setup_id () {
|
||
/* ======================
|
||
** Simply copy some ident information to global variables
|
||
** for use by the SQHM_IDENT request.
|
||
*/
|
||
StrJoin (Sqhm_serv_ident, sizeof (Sqhm_serv_ident), IDENT, "");
|
||
StrJoin (Sqhm_serv_date, sizeof (Sqhm_serv_date), __DATE__, ", ");
|
||
StrJoin (Sqhm_serv_date, sizeof (Sqhm_serv_date), Sqhm_serv_date, __TIME__);
|
||
}
|
||
/*==============================================================================
|
||
Here beginneth the main code for SinqHM_server ...
|
||
**
|
||
** Note: There must be NO return from this function.
|
||
*/
|
||
int SinqHM_server (int suspend_flag, int index, int pkt_size) {
|
||
/* =============
|
||
**
|
||
** Set up TCP/IP port for operations with client, accept his
|
||
** connection and perform services for him.
|
||
*/
|
||
int status, status0, status1;
|
||
int i, is, nbytes, bytes_to_come;
|
||
char recd[80];
|
||
char *p_nxt_byte;
|
||
int cnct_skt, rw_skt;
|
||
struct sockaddr_in my_lcl_sockname;
|
||
struct sockaddr_in my_rmt_sockname;
|
||
int my_rmt_sockname_len;
|
||
char *buff_pntr;
|
||
int port;
|
||
|
||
sigset_t proc_sigmask;
|
||
struct sigaction sig_action;
|
||
|
||
struct req_buff_struct my_req_bf;
|
||
struct rply_buff_struct my_rply_bf;
|
||
|
||
port = Port_base + index;
|
||
/*============================================================================
|
||
*/
|
||
StrJoin (Tsk_name[index], sizeof (Tsk_name[0]), taskName (get_pid ()), "");
|
||
|
||
if (suspend_flag != 0) {
|
||
printf ("\n%s: Suspending ..\n", Tsk_name[index]);
|
||
taskSuspend (0); /* We've been told to suspend ourself, ..
|
||
** .. presumably for debug reasons.
|
||
*/
|
||
printf ("\n%s: Suspension ended!\n", Tsk_name[index]);
|
||
}
|
||
/*============================================================================
|
||
** Define our signal mask first and define an action routine to catch
|
||
** the SIGINT signal our parent will send us when he wants us to exit.
|
||
*/
|
||
status = sigemptyset (&proc_sigmask);
|
||
status = sigprocmask (SIG_SETMASK, &proc_sigmask, NULL);
|
||
|
||
status = sigemptyset (&sig_action.sa_mask);
|
||
sig_action.sa_handler = catch_int_signal;
|
||
sig_action.sa_flags = 0;
|
||
if (sigaction (SIGINT, &sig_action, NULL) == -1) {
|
||
getErrno (&My_errno);
|
||
perror ("sigaction error:");
|
||
Child_exit_status[index] = -1; /* Tell our parent we've given up */
|
||
is = semGive (Sem_Server); /* Let our parent continue */
|
||
exit (KER__BAD_VALUE);
|
||
}
|
||
/*============================================================================
|
||
** Create a TCP/IP socket for communication, bind it and listen.
|
||
*/
|
||
Child_cnct_skt[index] = 0;
|
||
cnct_skt = socket (AF_INET, SOCK_STREAM, 0);
|
||
if (cnct_skt == -1) {
|
||
perror (StrJoin (recd, sizeof (recd),
|
||
Tsk_name[index], " -- cnct_skt socket error"));
|
||
Child_exit_status[index] = -2; /* Tell our parent we've given up */
|
||
is = semGive (Sem_Server); /* Let our parent continue */
|
||
exit (KER__BAD_VALUE);
|
||
}
|
||
status = 1;
|
||
setsockopt(cnct_skt, SOL_SOCKET, SO_REUSEADDR, &status, sizeof(int));
|
||
|
||
my_lcl_sockname.sin_family = AF_INET;
|
||
my_lcl_sockname.sin_port = htons (port);
|
||
my_lcl_sockname.sin_addr.s_addr = 0;
|
||
status = bind (cnct_skt, (struct sockaddr *) &my_lcl_sockname,
|
||
sizeof (my_lcl_sockname));
|
||
if (status != 0) {
|
||
close (cnct_skt);
|
||
perror (StrJoin (recd, sizeof (recd),
|
||
Tsk_name[index], " -- cnct_skt bind error"));
|
||
Child_exit_status[index] = -2; /* Tell our parent we've given up */
|
||
is = semGive (Sem_Server); /* Let our parent continue */
|
||
exit (KER__BAD_VALUE);
|
||
}
|
||
|
||
status = listen (cnct_skt, 1);
|
||
if (status != 0) {
|
||
close (cnct_skt);
|
||
perror (StrJoin (recd, sizeof (recd),
|
||
Tsk_name[index], " -- cnct_skt listen error"));
|
||
Child_exit_status[index] = -3; /* Tell our parent we've given up */
|
||
is = semGive (Sem_Server); /* Let our parent continue */
|
||
exit (KER__BAD_VALUE);
|
||
}
|
||
/*============================================================================
|
||
** Tell parent our cnct port is set up and waiting by releasing
|
||
** semaphore so that our parent can continue. The parent will then
|
||
** send a message to the client telling him which port he is to use.
|
||
*/
|
||
is = semGive (Sem_Server);
|
||
if (is != OK) {
|
||
kill (Parent_pid, SIGUSR1); /* Inform parent that we are in trouble */
|
||
printf ("%s -- sem release error\n", Tsk_name[index]);
|
||
close (cnct_skt);
|
||
exit (KER__BAD_VALUE);
|
||
}
|
||
Child_cnct_skt[index] = cnct_skt;
|
||
/*============================================================================
|
||
** Ensure that our bit in SinqHM_Dsbl_Mask is clear.
|
||
*/
|
||
do_daq (&my_rply_bf, index, DAQ__CLR);
|
||
/*============================================================================
|
||
** Wait for the client to connect to our port
|
||
*/
|
||
my_rmt_sockname_len = sizeof (my_rmt_sockname);
|
||
rw_skt = accept (cnct_skt, (struct sockaddr *) &my_rmt_sockname,
|
||
&my_rmt_sockname_len);
|
||
if (rw_skt == -1) {
|
||
perror (StrJoin (recd, sizeof (recd),
|
||
Tsk_name[index], " -- cnct_skt accept error"));
|
||
close (cnct_skt);
|
||
Child_cnct_skt[index] = 0;
|
||
kill (Parent_pid, SIGUSR1); /* Inform parent that we are in trouble */
|
||
exit (KER__BAD_VALUE);
|
||
}
|
||
Child_rw_skt[index] = rw_skt;
|
||
/*
|
||
**-------------------------------------------------------------------------
|
||
** Here is the main recv loop
|
||
*/
|
||
main_loop:
|
||
/*=========
|
||
*/ bytes_to_come = sizeof (my_req_bf); /* Read a command */
|
||
p_nxt_byte = (char *) &my_req_bf;
|
||
while (bytes_to_come > 0) {
|
||
nbytes = recv (rw_skt, p_nxt_byte, bytes_to_come, 0);
|
||
if (nbytes <= 0) break;
|
||
Rw_bytes_got += nbytes;
|
||
bytes_to_come -= nbytes;
|
||
p_nxt_byte += nbytes;
|
||
}
|
||
if ((bytes_to_come == 0) &&
|
||
(ntohl (my_req_bf.bigend) == 0x12345678) &&
|
||
(ntohl (my_req_bf.cmnd) != SQHM_CLOSE)) {
|
||
is = do_command (index, rw_skt, pkt_size, &my_req_bf, &my_rply_bf);
|
||
if (is == OK) goto main_loop; /* Break out of loop on error */
|
||
}
|
||
/*
|
||
** End of the main recv loop
|
||
**-------------------------------------------------------------------------
|
||
** Get here if we drop out of the "recv" loop.
|
||
** This should only happen on getting a SQHM_CLOSE message.
|
||
** Anything else is a fatal error.
|
||
*/
|
||
do_daq (&my_rply_bf, index, DAQ__CLR); /* Ensure our inhibit bit is clear */
|
||
|
||
close (rw_skt); Child_rw_skt[index] = 0;
|
||
close (cnct_skt); Child_cnct_skt[index] = 0;
|
||
/*
|
||
** Check the various error conditions
|
||
*/
|
||
if (bytes_to_come != 0) { /* Was a complete request read? */
|
||
/* No, it may be a network error, in which case
|
||
** nbytes is -1, or nothing was read, which
|
||
** indicates that our client simply closed
|
||
** his connection (forgetting to send a
|
||
** SQHM_CLOSE message), or the client has
|
||
** screwed up the protocol! */
|
||
if (nbytes == -1) {
|
||
/* It's a network error */
|
||
perror (StrJoin (recd, sizeof (recd),
|
||
Tsk_name[index], " -- rw_skt recv error"));
|
||
status = KER__EXIT_SIGNAL;
|
||
}else if (bytes_to_come == sizeof (my_req_bf)) {
|
||
/* Our client simply closed his connection.
|
||
** Treat this as normal. */
|
||
printf ("\n%s exiting.\n", Tsk_name[index]);
|
||
status = KER__SUCCESS;
|
||
}else {
|
||
printf ("\n%s -- rw_skt recv wrong number of bytes: %d\n",
|
||
Tsk_name[index], nbytes);
|
||
status = KER__EXIT_SIGNAL;
|
||
}
|
||
}else if (ntohl (my_req_bf.bigend) != 0x12345678) {
|
||
/* Network byte-order wrong! */
|
||
printf ("\n%s -- big-endian/little-endian problem!\n"
|
||
" Buffer received in non-network byte order!\n", Tsk_name[index]);
|
||
status = KER__EXIT_SIGNAL;
|
||
}else if (ntohl (my_req_bf.cmnd) == SQHM_CLOSE) {
|
||
/* SQHM_CLOSE request received. This is normal */
|
||
printf ("\n%s exiting.\n", Tsk_name[index]);
|
||
status = KER__SUCCESS;
|
||
}else {
|
||
/* Unrecognised request received! */
|
||
printf ("\n%s -- unrecognised command received: 0x%x\n",
|
||
Tsk_name[index], ntohl (my_req_bf.cmnd));
|
||
status = KER__EXIT_SIGNAL;
|
||
}
|
||
kill (Parent_pid, SIGUSR1); /* Inform parent that we are exiting */
|
||
exit (status);
|
||
}
|
||
/*======================================= End of SinqHM_srv_server.c ========*/
|