Child server task for SinqHM_srv

This commit is contained in:
cvs
2000-11-07 11:57:51 +00:00
parent 14f9ac99f3
commit 675f210150

282
sinqhm/SinqHM_srv_server.c Executable file
View File

@ -0,0 +1,282 @@
#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);
}
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 ========*/