From aaee6867ddd1a5dc7d7cd12d096ad9adc265760d Mon Sep 17 00:00:00 2001 From: cvs Date: Mon, 6 Nov 2000 13:05:34 +0000 Subject: [PATCH] Child server task for sinqhm_srv --- sinqhm/sinqhm_srv_server.c | 282 +++++++++++++++++++++++++++++++++++++ 1 file changed, 282 insertions(+) create mode 100755 sinqhm/sinqhm_srv_server.c diff --git a/sinqhm/sinqhm_srv_server.c b/sinqhm/sinqhm_srv_server.c new file mode 100755 index 00000000..8c056418 --- /dev/null +++ b/sinqhm/sinqhm_srv_server.c @@ -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 +#include +#include +#include + +#include +#include +#include + +#include /* Get the POSIX environment defined .. + ** .. see DEC OSF/1 Guide to Realtime Programming */ +#include +#include +#include +#include + +#include /* Get POSIX mem mgmnt definitions. */ +#include /* Get POSIX signal definitions. */ +#include +#include /* 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 ========*/