Main server program for sinqhm_srv
This commit is contained in:
361
sinqhm/sinqhm_srv_main.c
Executable file
361
sinqhm/sinqhm_srv_main.c
Executable file
@ -0,0 +1,361 @@
|
||||
#define IDENT "1D02"
|
||||
/*
|
||||
** +--------------------------------------------------------------+
|
||||
** | 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_main.c
|
||||
**
|
||||
** Author . . . . . . . . . . : D. Maden
|
||||
** Date of creation . . . . . . : Oct 1996
|
||||
**
|
||||
** Updates:
|
||||
** 1A01 1-Oct-1996 DM Initial version.
|
||||
** 1B01 16-Jul-1997 DM Flush fibre-optic FIFO on SQHM_ZERO and SQHM_WRITE.
|
||||
** 1C01 24-Jun-1998 DM Add TOF support.
|
||||
** 1C06 10-Aug-1999 DM Add instrument dependent conditional code.
|
||||
**---------------------------------------------------------------------------
|
||||
** SinqHM_srv_main.c is the main program of a SINQ Histogram Memory process
|
||||
** which will run in a front-end processor and perform the necessary
|
||||
** operations for a SINQ multi-detector.
|
||||
**
|
||||
** Communication between SinqHM_srv and the client is via TCP/IP protocol.
|
||||
**
|
||||
** To compile and link this program for VxWorks on PSS123, use:
|
||||
**
|
||||
ccvx '-DINST="<instr>"' SinqHM_srv_main.c
|
||||
ccvx '-DINST="<instr>"' SinqHM_srv_routines.c
|
||||
ccvx '-DINST="<instr>"' SinqHM_srv_filler.c
|
||||
ccvx '-DINST="<instr>"' 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
|
||||
** and
|
||||
** <instr> = DMC, SANS, FOCUS, HRPT, TRICS or POLDI
|
||||
|
||||
ldppc -o SinqHM_srv.o -r SinqHM_srv_main.o \
|
||||
SinqHM_srv_routines.o \
|
||||
SinqHM_srv_filler.o \
|
||||
SinqHM_srv_server.o
|
||||
|
||||
** and, on the target,
|
||||
**
|
||||
** -> ld < /home/pss123/aco/maden/wind/SinqHM/SinqHM_srv.o
|
||||
** -> taskSpawn "SinqHM_srv", 100, 8, 20000, SinqHM_srv, <port>
|
||||
** ^
|
||||
** |
|
||||
** default = 2400 ------+
|
||||
**
|
||||
**====================================================================
|
||||
*/
|
||||
#include "vxWorks.h"
|
||||
#include "taskLib.h"
|
||||
#include "msgQLib.h"
|
||||
#include "sockLib.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <setjmp.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <signal.h> /* Get POSIX signal definitions. */
|
||||
#include <timers.h>
|
||||
#include <sys/mman.h> /* Get POSIX mem mgmnt definitions. */
|
||||
#include <sys/wait.h> /* Get POSIX wait definitions. */
|
||||
/*
|
||||
**==================== Global Definitions =====================================
|
||||
*/
|
||||
#include "SinqHM_def.h"
|
||||
#include "SinqHM_gbl.h"
|
||||
/*
|
||||
|
||||
**=============================================================================
|
||||
** Local routines.
|
||||
**
|
||||
** None
|
||||
*/
|
||||
/*==============================================================================
|
||||
|
||||
** Main line program
|
||||
** ------------------
|
||||
**============================================================================*/
|
||||
int SinqHM_srv (int port, int use_level_gen, char *base_addr,
|
||||
int arg4, int arg5, int arg6, int arg7, int arg8, int arg9,
|
||||
int suspend) {
|
||||
/*============================================================================*/
|
||||
struct req_buff_struct req_buff;
|
||||
struct rply_buff_struct rply_buff;
|
||||
|
||||
int i, j, is, status, cntr;
|
||||
int keep_going = OK;
|
||||
int bytes_to_come, n_bytes_got;
|
||||
char *p_addr;
|
||||
int cl_port;
|
||||
int do_send;
|
||||
int cnct_skt; /* Connection socket */
|
||||
int rw_skt; /* Read/write socket */
|
||||
struct sockaddr_in lcl_sockname;
|
||||
struct sockaddr_in rmt_sockname;
|
||||
int rmt_sockname_len;
|
||||
int pkt_size;
|
||||
time_t timer;
|
||||
|
||||
sigset_t proc_sigmask;
|
||||
struct sigaction sig_action;
|
||||
|
||||
/*============================================================================
|
||||
*/
|
||||
if (suspend != 0) {
|
||||
printf ("\nSinqHM_srv: Suspending ...\n");
|
||||
taskSuspend (0); /* We've been told to suspend ourself, ..
|
||||
** .. presumably for debug reasons.
|
||||
*/
|
||||
printf ("\nSinqHM_srv: Suspension ended!\n");
|
||||
}
|
||||
/*============================================================================
|
||||
** Perform the initialisation of global variables ...
|
||||
*/
|
||||
StrJoin (Instr_name, sizeof (Instr_name), INST, ""); /* Save the instr.
|
||||
** name in a global
|
||||
*/
|
||||
StrJoin (Def_ident, sizeof (Def_ident), SINQHM_DEF_ID, "");
|
||||
StrJoin (Sqhm_main_ident, sizeof (Sqhm_main_ident), IDENT, "");
|
||||
StrJoin (Sqhm_main_date, sizeof (Sqhm_main_date), __DATE__, ", ");
|
||||
StrJoin (Sqhm_main_date, sizeof (Sqhm_main_date), Sqhm_main_date, __TIME__);
|
||||
SinqHM_server_setup_id ();
|
||||
SinqHM_filler_setup_id ();
|
||||
SinqHM_routines_setup_id ();
|
||||
time (&Sqhm_start_time); /* Initialise the start time */
|
||||
|
||||
StrJoin (Tsk_name[0], sizeof (Tsk_name[0]), taskName (get_pid ()), "");
|
||||
|
||||
Dbg_mask = 0;
|
||||
Dbg_lev0 = 0;
|
||||
Dbg_lev1 = 0;
|
||||
Dbg_lev2 = 0;
|
||||
Dbg_lev3 = 0;
|
||||
Cfgn_done = 0; /* Force a configuration before we can do anything. */
|
||||
|
||||
free_HM_memory (NULL); /* Release memory (possibly) in case ..
|
||||
** .. of a restart of the program */
|
||||
Parent_pid = get_pid ();
|
||||
Filler_pid = 0;
|
||||
for (i = 0; i <= MAX_CLIENTS; i++) {
|
||||
Child_pid[i] = 0;
|
||||
Child_exit_status[i] = 0;
|
||||
}
|
||||
|
||||
if (Sem_Filler == NULL) {
|
||||
Sem_Filler = semBCreate (SEM_Q_FIFO, SEM_FULL);
|
||||
}
|
||||
|
||||
if (Sem_Server == NULL) {
|
||||
Sem_Server = semBCreate (SEM_Q_FIFO, SEM_FULL);
|
||||
}
|
||||
/*
|
||||
** Debug hint - set Use_sem_tmo to zero to disable semaphore time-outs
|
||||
** during debug sessions. This will stop FILLER falling off.
|
||||
*/
|
||||
Sem_tmo = 10; /* 10 second time-out by default */
|
||||
Use_sem_tmo = 0;
|
||||
|
||||
setupLevelGenerator (use_level_gen, base_addr);
|
||||
/*============================================================================
|
||||
** Clear the process signal mask to let in all signals (actually, on
|
||||
** PPC VxWorks this seems to cause all signals to get ignored!) and then
|
||||
** declare action routine for SIGUSR1. Our children signal with SIGUSR1
|
||||
** just before they exit in a more or less controlled manner. If the
|
||||
** child gets deleted from the shell, it will not signal.
|
||||
*/
|
||||
Cnt_SIGUSR1 = 0;
|
||||
|
||||
status = sigemptyset (&proc_sigmask);
|
||||
status = sigprocmask (SIG_SETMASK, &proc_sigmask, NULL);
|
||||
status = sigemptyset (&sig_action.sa_mask);
|
||||
sig_action.sa_handler = catch_signal;
|
||||
sig_action.sa_flags = 0;
|
||||
|
||||
if (sigaction (SIGUSR1, &sig_action, NULL) == -1) {
|
||||
getErrno (&My_errno);
|
||||
perror ("sigaction error:");
|
||||
exit (0);
|
||||
}
|
||||
/*============================================================================
|
||||
** Get a port number to use. If the argument "port" is not
|
||||
** a valid port number (not in range 128 to 32767), use PORT_BASE.
|
||||
*/
|
||||
Port_base = PORT_BASE;
|
||||
if ((port >= 128) && (port < 32768)) Port_base = port;
|
||||
/*============================================================================
|
||||
** Create a TCP/IP socket for receiving connection requests, bind it and
|
||||
** set it to listen.
|
||||
*/
|
||||
cnct_skt = socket (AF_INET, SOCK_STREAM, 0);
|
||||
if (cnct_skt == -1)
|
||||
failInet_port ("\nhmRoot%d -- Cnct-Socket socket error", Port_base);
|
||||
lcl_sockname.sin_family = AF_INET;
|
||||
lcl_sockname.sin_port = htons (Port_base);
|
||||
lcl_sockname.sin_addr.s_addr = 0;
|
||||
status = bind (cnct_skt, (struct sockaddr *) &lcl_sockname,
|
||||
sizeof (lcl_sockname));
|
||||
if (status != 0) failInet_port ("\nhmRoot%d -- Cnct-Socket bind error",
|
||||
Port_base);
|
||||
status = listen (cnct_skt, 5);
|
||||
if (status != 0) failInet_port ("\nhmRoot%d -- Cnct-Socket listen error",
|
||||
Port_base);
|
||||
/*
|
||||
** Clients must now connect to the Connect-port and send either a
|
||||
** connect, configure, deconfigure, status or exit request. A
|
||||
** successful configure request must precede any connection request.
|
||||
**
|
||||
** When a configure request arrives, the histogram data structures are
|
||||
** initialised, the histogram filler process (FILLER) is spawned and
|
||||
** connection requests are enabled. A status reply is sent to the
|
||||
** client and the connection closed.
|
||||
**
|
||||
** When a connection request arrives, a child will be spawned to
|
||||
** handle the connection. The child will be told which port to use
|
||||
** and he will release a semaphore when the port is ready. The parent
|
||||
** then sends the client a reply to tell him which port to use. The
|
||||
** connection is then closed to await further connections.
|
||||
*/
|
||||
setup_inet_info (Inet_host, sizeof (Inet_host), /* Find out who we are */
|
||||
Inet_addr, sizeof (Inet_addr));
|
||||
printf ("\n%s: Program Ident = \"%s\". Started on %s (%s).\n",
|
||||
Tsk_name[0], IDENT, Inet_host, Inet_addr);
|
||||
printf ("%s: Protocol Ident = \"%s\"\n", Tsk_name[0], SINQHM_DEF_ID);
|
||||
|
||||
#ifndef INST
|
||||
#error Define the target instrument via the symbol "INST"!
|
||||
#endif
|
||||
|
||||
if (strcmp (INST, "DMC") == 0) {
|
||||
printf ("%s: Instrument = \"%s\"\n", Tsk_name[0], "DMC");
|
||||
Lwl_hdr_daq_mask = LWL_HDR_NRL_MASK;
|
||||
Lwl_hdr_daq_soll = 0;
|
||||
}else if (strcmp (INST, "SANS") == 0) {
|
||||
printf ("%s: Instrument = \"%s\"\n", Tsk_name[0], "SANS");
|
||||
Lwl_hdr_daq_mask = LWL_HDR_NRL_MASK;
|
||||
Lwl_hdr_daq_soll = 0;
|
||||
}else if (strcmp (INST, "FOCUS") == 0) {
|
||||
Lwl_hdr_daq_mask = LWL_HDR_NRL_MASK | LWL_HDR_SYNC2_MASK;
|
||||
Lwl_hdr_daq_soll = 0;
|
||||
printf ("%s: Instrument = \"%s\"\n", Tsk_name[0], "FOCUS");
|
||||
}else if (strcmp (INST, "HRPT") == 0) {
|
||||
printf ("%s: Instrument = \"%s\"\n", Tsk_name[0], "HRPT");
|
||||
Lwl_hdr_daq_mask = LWL_HDR_SYNC0_MASK | LWL_HDR_SYNC2_MASK;
|
||||
Lwl_hdr_daq_soll = LWL_HDR_SYNC2_MASK;
|
||||
}else if (strcmp (INST, "TRICS") == 0) {
|
||||
printf ("%s: Instrument = \"%s\"\n", Tsk_name[0], "TriCS");
|
||||
Lwl_hdr_daq_mask = LWL_HDR_NRL_MASK;
|
||||
Lwl_hdr_daq_soll = 0;
|
||||
printf ("%s: Warning -- Lwl_hdr_daq_mask and Lwl_hdr_daq_soll are "
|
||||
"provisional!\n", Tsk_name[0]);
|
||||
}else if (strcmp (INST, "POLDI") == 0) {
|
||||
printf ("%s: Instrument = \"%s\"\n", Tsk_name[0], "POLDI");
|
||||
Lwl_hdr_daq_mask = LWL_HDR_NRL_MASK;
|
||||
Lwl_hdr_daq_soll = 0;
|
||||
printf ("%s: Warning -- Lwl_hdr_daq_mask and Lwl_hdr_daq_soll are "
|
||||
"provisional!\n", Tsk_name[0]);
|
||||
}else {
|
||||
printf ("%s: Instrument is not defined\n", Tsk_name[0]);
|
||||
Lwl_hdr_daq_mask = LWL_HDR_NRL_MASK;
|
||||
Lwl_hdr_daq_soll = 0;
|
||||
}
|
||||
printf ("%s: Lwl_hdr_daq_mask = 0x%08x", Tsk_name[0], Lwl_hdr_daq_mask);
|
||||
if ((Lwl_hdr_daq_mask & LWL_HDR_NRL_MASK) != 0) printf (" NRL");
|
||||
if ((Lwl_hdr_daq_mask & LWL_HDR_SYNC3_MASK) != 0) printf (" SYNC3");
|
||||
if ((Lwl_hdr_daq_mask & LWL_HDR_SYNC2_MASK) != 0) printf (" SYNC2");
|
||||
if ((Lwl_hdr_daq_mask & LWL_HDR_SYNC1_MASK) != 0) printf (" SYNC1");
|
||||
if ((Lwl_hdr_daq_mask & LWL_HDR_SYNC0_MASK) != 0) printf (" SYNC0");
|
||||
printf ("\n%s: Lwl_hdr_daq_soll = 0x%08x", Tsk_name[0], Lwl_hdr_daq_soll);
|
||||
if ((Lwl_hdr_daq_soll & LWL_HDR_NRL_MASK) != 0) printf (" NRL");
|
||||
if ((Lwl_hdr_daq_soll & LWL_HDR_SYNC3_MASK) != 0) printf (" SYNC3");
|
||||
if ((Lwl_hdr_daq_soll & LWL_HDR_SYNC2_MASK) != 0) printf (" SYNC2");
|
||||
if ((Lwl_hdr_daq_soll & LWL_HDR_SYNC1_MASK) != 0) printf (" SYNC1");
|
||||
if ((Lwl_hdr_daq_soll & LWL_HDR_SYNC0_MASK) != 0) printf (" SYNC0");
|
||||
printf ("\n");
|
||||
|
||||
while (keep_going == OK) {
|
||||
rmt_sockname_len = sizeof (rmt_sockname);
|
||||
rw_skt = accept (cnct_skt, (struct sockaddr *) &rmt_sockname,
|
||||
&rmt_sockname_len);
|
||||
if (rw_skt == -1) {
|
||||
getErrno (&My_errno);
|
||||
failInet_port ("\nhmRoot%d -- Cnct-Socket accept error", Port_base);
|
||||
/* No return */
|
||||
}
|
||||
Rw_bytes_got = 0; Rw_bytes_put = 0;
|
||||
|
||||
p_addr = inet_ntoa (rmt_sockname.sin_addr);
|
||||
cl_port = ntohs (rmt_sockname.sin_port);
|
||||
printf ("\n%s: Connected to Host %s, Port %d.\n",
|
||||
Tsk_name[0], p_addr, cl_port);
|
||||
|
||||
bytes_to_come = sizeof (req_buff); /* Read a command */
|
||||
p_addr = (char *) &req_buff;
|
||||
while (bytes_to_come > 0) {
|
||||
n_bytes_got = recv (rw_skt, p_addr, bytes_to_come, 0);
|
||||
if (n_bytes_got <= 0) break;
|
||||
Rw_bytes_got += n_bytes_got;
|
||||
bytes_to_come -= n_bytes_got;
|
||||
p_addr += n_bytes_got;
|
||||
}
|
||||
|
||||
if (Cnt_SIGUSR1 > 0) { /* Have any children exited? */
|
||||
if (Dbg_lev0) printf ("hmRoot%d: Cleaning up children ...", Port_base);
|
||||
cleanup_children (); /* Yes, update our database. */
|
||||
if (Dbg_lev0) printf ("\n ... cleanup of children done.\n");
|
||||
}
|
||||
|
||||
if (n_bytes_got < 0) {
|
||||
printf ("\007"
|
||||
"%s -- R/W-Socket recv error\n", Tsk_name[0]);
|
||||
printf ("%s -- Connection to %s will be closed.\n", Tsk_name[0],
|
||||
inet_ntoa (rmt_sockname.sin_addr));
|
||||
}else if (n_bytes_got == 0) {
|
||||
printf ("\007"
|
||||
"%s -- no command received!\n", Tsk_name[0]);
|
||||
printf ("%s -- Connection to %s will be closed.\n", Tsk_name[0],
|
||||
inet_ntoa (rmt_sockname.sin_addr));
|
||||
}else if (n_bytes_got != sizeof (req_buff)) {
|
||||
printf ("\007"
|
||||
"%s -- command packet has wrong number of bytes:"
|
||||
" %d instead of %d\n", Tsk_name[0],
|
||||
n_bytes_got, sizeof (req_buff));
|
||||
printf ("%s -- Connection to %s will be closed.\n", Tsk_name[0],
|
||||
inet_ntoa (rmt_sockname.sin_addr));
|
||||
}else if (ntohl (req_buff.bigend) != 0x12345678) {
|
||||
printf ("\007"
|
||||
"%s -- big-endian/little-endian problem!\n"
|
||||
" Buffer received in non-network byte order!\n", Tsk_name[0]);
|
||||
}else {
|
||||
do_command (0, rw_skt, 4096, &req_buff, &rply_buff);
|
||||
}
|
||||
close (rw_skt);
|
||||
if (ntohl (req_buff.cmnd) == SQHM_EXIT) keep_going = !OK;
|
||||
}
|
||||
close (cnct_skt);
|
||||
exit (KER__SUCCESS);
|
||||
}
|
||||
/*========================================= End of SinqHM_srv_main.c ========*/
|
Reference in New Issue
Block a user