#define _SESSION_C
#include <stdlib.h>
#include <sys/time.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <locale.h>
#include "open-axiom.h"
#include "sockio.h"
#include "com.h"
#include "bsdsignal.h"
#include "cfuns.h"
#include "sockio.h"
using namespace OpenAxiom;
static void usr1_handler(int);
static void usr2_handler(int);
static void term_handler(int);
static void close_client(int);
static void read_SpadServer_command(void);
static int test_sock_for_process(openaxiom_sio*);
static void read_menu_client_command(void);
static void read_from_spad_io(void);
static void kill_spad(void);
static int accept_session_connection(openaxiom_sio*);
static void read_from_session(openaxiom_sio*);
static void manage_sessions(void);
#define BufSize 4096
typedef struct sock_list {
openaxiom_sio Socket;
struct sock_list *next;
} Sock_List;
openaxiom_sio* spad_io = 0;
openaxiom_sio* spad_server = 0;
openaxiom_sio* menu_client = 0;
openaxiom_sio* active_session = 0;
Sock_List *plSock = (Sock_List *) 0;
char big_bad_buf[BufSize];
int num_active_clients = 0;
int reading_output = 0;
fd_set session_socket_mask;
static void
usr1_handler(int sig)
{
return;
}
static void
usr2_handler(int sig)
{
send_signal(spad_server, SIGINT);
return;
}
static void
term_handler(int sig)
{
exit(1);
}
static void
pr()
{
Sock_List *pSock;
fprintf(stderr,"The socket list:\n");
for(pSock=plSock;pSock!=(Sock_List *)0;pSock=pSock->next){
fprintf(stderr,"(%d,%d,%d)\t",pSock->Socket.pid,2<<(pSock->Socket.socket),pSock->Socket.frame);
}
fprintf(stderr,"\n");
}
static void
close_client(int frame)
{
Sock_List *pSock,*locSock;
int socket_fd;
#ifdef DEBUG
fprintf(stderr,"close_client(%d)\n",frame);
#endif
if ( (plSock) && (plSock->Socket.frame == frame) ){
socket_fd = plSock->Socket.socket;
send_signal((openaxiom_sio *)plSock, SIGTERM);
if ( menu_client != (openaxiom_sio *) 0){
send_int(menu_client,CloseClient);
send_int(menu_client,(*plSock).Socket.pid);
}
#ifdef DEBUG
fprintf(stderr,"trying to clear %u\n",socket_fd);
#endif
FD_CLR(socket_fd,&session_socket_mask);
locSock = plSock;
if ((*plSock).next == (Sock_List *) 0)
{plSock = (Sock_List *) 0;}
else
{plSock = plSock->next;}
active_session = (openaxiom_sio *) 0;
num_active_clients--;
free(locSock);
}
else {
for (pSock=plSock; pSock->next != (Sock_List *) 0 ; pSock=pSock->next)
if (pSock->next->Socket.frame == frame){
socket_fd = pSock->next->Socket.socket;
send_signal((openaxiom_sio *)pSock->next, SIGTERM);
if ( menu_client != (openaxiom_sio *) 0){
send_int(menu_client,CloseClient);
send_int(menu_client,(*plSock).Socket.pid);
}
#ifdef DEBUG
fprintf(stderr,"trying to clear %u\n",socket_fd);
#endif
FD_CLR(socket_fd,&session_socket_mask);
locSock = pSock->next;
if ( pSock->next->next == (Sock_List *) 0 )
{ pSock->next= (Sock_List *) 0;}
else
{ pSock->next = pSock->next->next;}
num_active_clients--;
active_session = (openaxiom_sio *) 0;
free(locSock);
break;
}
}
#ifdef DEBUG
pr();
#endif
}
static void
read_SpadServer_command(void)
{
int cmd, frame, num;
cmd = get_int(spad_server);
switch (cmd) {
case EndOfOutput:
if (menu_client != (openaxiom_sio *) 0) send_signal(menu_client, SIGUSR2);
if (reading_output != 0) reading_output = 0;
break;
case QueryClients:
num = num_active_clients ;
send_int(spad_server, num);
break;
case CloseClient:
frame = get_int(spad_server);
if (frame != -1) close_client(frame);
break;
case SendXEventToHyperTeX:
break;
default:
fprintf(stderr, "session : unknown command from SpadServer %d\n", cmd);
break;
}
}
static int
test_sock_for_process(openaxiom_sio *sock)
{
if (sock == (openaxiom_sio *)0 ) return -1;
return kill(sock->pid, 0);
}
static void
read_menu_client_command(void)
{
int cmd,frame, i,socket_fd;
Sock_List *pSock;
socket_fd = menu_client->socket;
if (test_sock_for_process(menu_client) == -1) {
FD_CLR(socket_fd,&session_socket_mask);
menu_client = (openaxiom_sio *) 0;
reading_output = 0;
return;
}
cmd = get_int(menu_client);
switch(cmd) {
case -1:
FD_CLR(socket_fd,&session_socket_mask);
menu_client = (openaxiom_sio *) 0;
reading_output = 0;
break;
case SwitchFrames:
#ifdef DEBUG
fprintf(stderr,"menu:SwitchFrames\n");
#endif
frame = get_int(menu_client);
send_int(spad_server, SwitchFrames);
send_int(spad_server, frame);
for(i=0,pSock=plSock; pSock != (Sock_List *) 0 ; i++,pSock=pSock->next)
if (pSock->Socket.frame == frame) {
active_session = (openaxiom_sio *)pSock;
reading_output = 1;
break;
}
if (i == num_active_clients) {
}
break;
case QuerySpad:
#ifdef DEBUG
fprintf(stderr,"menu:QuerySpad\n");
#endif
send_int(menu_client, reading_output);
break;
default:
fprintf(stderr, "session : unknown command from MenuServer: %d\n", cmd);
menu_client = (openaxiom_sio *) 0;
break;
}
}
static void
read_from_spad_io(void)
{
int ret_code;
ret_code = sread(spad_io, byte_address(big_bad_buf), BufSize,
"session: stdout socket");
if (ret_code == -1) return;
if(active_session != (openaxiom_sio *) 0) {
ret_code = swrite(active_session, byte_address(big_bad_buf),
ret_code, NULL);
}
}
static void
kill_spad(void)
{
int i;
Sock_List *pSock;
send_signal(spad_server, SIGTERM);
for (pSock=plSock,i=0;
(i<num_active_clients) && (pSock != (Sock_List *) 0);
i++,pSock=pSock->next) {
if ((pSock->Socket).socket != 0)
send_signal((openaxiom_sio *)pSock, SIGTERM);
}
if (menu_client != (openaxiom_sio *) 0) send_signal(menu_client, SIGTERM);
exit(0);
}
static int
accept_session_connection(openaxiom_sio *server_sock)
{
int sock_fd, ret_code;
Sock_List *pls;
pls = (Sock_List *) malloc(sizeof (Sock_List));
sock_fd = accept(server_sock->socket, 0, 0);
if (sock_fd == -1) {
perror("session : accepting connection");
return -1;
}
(pls->Socket).socket = sock_fd;
get_socket_type((openaxiom_sio *)pls);
switch((pls->Socket).purpose) {
case KillSpad:
kill_spad();
return KillSpad;
free(pls);
case MenuServer:
#ifdef DEBUG
fprintf(stderr,"session: accepted MenuServer , fd = %d\n",sock_fd);
#endif
menu_client = &(pls->Socket);
FD_SET(menu_client->socket, &session_socket_mask);
return MenuServer;
case InterpWindow:
#ifdef DEBUG
fprintf(stderr,"session: accepted InterpWindow , fd = %d\n",sock_fd);
#endif
if (plSock == (Sock_List *)0 ) {
plSock = pls;
plSock->next = (Sock_List *)0 ;
}
else{
pls->next = plSock;
plSock = pls;
}
FD_SET(plSock->Socket.socket, &session_socket_mask);
send_int(spad_server, CreateFrame);
plSock->Socket.frame = get_int(spad_server);
active_session = (openaxiom_sio *)plSock;
get_string_buf(spad_server, big_bad_buf, BufSize);
ret_code = swrite((openaxiom_sio *)plSock,
byte_address(big_bad_buf),
strlen(big_bad_buf)+1,
"session: writing to InterpWindow");
if (ret_code == -1)
return -1;
num_active_clients++;
#ifdef DEBUG
pr();
#endif
return plSock->Socket.purpose;
}
return (-1);
}
static void
read_from_session(openaxiom_sio *sock)
{
int ret_code;
if (sock != active_session) {
send_int(spad_server, SwitchFrames);
send_int(spad_server, sock->frame);
}
active_session = sock;
ret_code = sread(sock, byte_address(big_bad_buf), BufSize,
"session: reading InterpWindow");
if (ret_code == -1) {
active_session = (openaxiom_sio *) 0;
reading_output = 0;
return;
}
ret_code = swrite(spad_io, byte_address(big_bad_buf), ret_code,
"session: writing SessionIO");
if (ret_code == -1) {
active_session = (openaxiom_sio *)0 ;
reading_output = 0;
return;
}
reading_output = 1;
}
static void
manage_sessions(void)
{
int ret_code;
fd_set rd, wr, ex;
Sock_List *pSock;
reading_output = 0;
while (1) {
FD_ZERO(&rd);
FD_ZERO(&wr);
FD_ZERO(&ex);
#ifdef DEBUG
fprintf(stderr,"session_socket_mask=%u ",*((long *)session_socket_mask.fds_bits));
#endif
rd = session_socket_mask;
if (!reading_output) {
rd = session_socket_mask;
}
if (active_session) FD_SET(active_session->socket, &rd);
#ifdef DEBUG
fprintf(stderr,"[rd=%u ",*((long *)rd.fds_bits));
#endif
ret_code = sselect(FD_SETSIZE, &rd, &wr, &ex, NULL);
if (ret_code == -1) {
break;
}
#ifdef DEBUG
fprintf(stderr,"rd=%u]\n",*((long *)rd.fds_bits));
#endif
if ((menu_client != (openaxiom_sio *) 0)
&& FD_ISSET(menu_client->socket, &rd)) {
read_menu_client_command(); }
if (FD_ISSET(spad_io->socket, &rd)) {
read_from_spad_io(); }
if (FD_ISSET(server.socket, &rd)) {
accept_session_connection(&server); }
for(pSock=plSock; pSock != (Sock_List *) 0 ; pSock=pSock->next) {
if ((active_session == (openaxiom_sio *)pSock || !reading_output) &&
(pSock->Socket).socket>0 && FD_ISSET(pSock->Socket.socket, &rd)) {
read_from_session((openaxiom_sio *)pSock); }
}
if (FD_ISSET(spad_server->socket, &rd)) {
read_SpadServer_command(); }
}
}
int
main(void)
{
using namespace OpenAxiom;
#ifdef DEBUG2
openaxiom_sleep(30);
#endif
oa_setenv("LC_ALL", "C");
setlocale(LC_ALL, "");
spad_server = connect_to_local_server(SpadServer, SessionManager, Forever);
if (spad_server == (openaxiom_sio *) 0) {
fprintf(stderr, "session: Cannot connect to OpenAxiom server!\n");
exit(0);
}
else {
#ifdef DEBUG
fprintf(stderr, "session: connected SpadServer , fd = %d\n",
spad_server->socket);
#endif
FD_SET(spad_server->socket, &session_socket_mask);
}
spad_io = connect_to_local_server(SessionIOName, SessionIO, Forever);
if (spad_io == (openaxiom_sio *) 0) {
fprintf(stderr, "session: Cannot connect to OpenAxiom IO!\n");
exit(0);
}
else {
#ifdef DEBUG
fprintf(stderr,"session: connected SessionIOName , fd = %d\n",
spad_io->socket);
#endif
FD_SET(spad_io->socket, &session_socket_mask);
}
bsdSignal(SIGUSR2, usr2_handler,DontRestartSystemCalls);
bsdSignal(SIGUSR1, usr1_handler,RestartSystemCalls);
bsdSignal(SIGINT, SIG_IGN,RestartSystemCalls);
bsdSignal(SIGTERM, term_handler,RestartSystemCalls);
if (open_server(SessionServer) == -2) {
fprintf(stderr, "session: Cannot make server socket!\n");
exit(-1);
}
else {
#ifdef DEBUG
fprintf(stderr, "session: opened SessionServer , fd = %d\n",
server.socket);
#endif
FD_SET(server.socket,&session_socket_mask);
}
manage_sessions();
return(0);
}