Child server task for SinqHM_srv
This commit is contained in:
282
sinqhm/SinqHM_srv_server.c
Executable file
282
sinqhm/SinqHM_srv_server.c
Executable 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 ========*/
|
Reference in New Issue
Block a user