How to replay a ACK to the Host?
Windows Server Forum Index Windows Server
Server discussion on Windows platform.
 
 FAQFAQ   MemberlistMemberlist     RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 
 
Google
 
Web winserverhelp.com
How to replay a ACK to the Host?

 
Post new topic   Reply to topic    Windows Server Forum Index -> Host Integration Server
Author Message
SAM



Joined: 07 Nov 2005
Posts: 1

Posted: Mon Nov 07, 2005 7:15 am    Post subject: How to replay a ACK to the Host? Reply with quote

We are making a connection between HIS 2003 and OS390(with IMS).
The follow is the LUA sample program we modified as a communication control over the application server and IMS.
Now we have a problem.
Between receving the end of data and issuing SHTUD command, the process step 'Send a Clear(6D)' causes the HOST to reply the error message as 'DFS064 DESTINATION CAN NOT BE FOUND OR CREATED.' .
But the sense data seems not usually affact the later processes(i.e. SHUTD, UNBIND).
Although we know that 'Send a Clear' does not fit in this knid of circumstance, but if we take away the 'Send a Clear' step, there will be a queue leave in the Host's IMS node(IMS node's status:RESP, RESYNC).
We all know that we should reply a 'ACK' to the Host to inform it the data receiving completeness and then purge the queue data.
But we have no idea how to do that(that is, what command sould we issue? Or what parameters should be set in SLI_REVEIVE? )
THANKS A LOT!!

/*****************************************************************************/
/* SLI Sample Program */
/* */
/* (C) Copyright 1990 - 1993 Data Connection Ltd. */
/* */
/* This program is a crude 3270 emulator. It uses the SLI API to access the */
/* LU-LU session. Outbound data from the host is displayed on the screen */
/* unformatted. */
/* */
/* If the outbound data is an RQD request an automatic positive response */
/* is sent. Inbound data can be entered at the keyboard and is sent on */
/* the current session. */
/* */
/* The program is invoked with two parameters - the name of the LUA LU */
/* to use and a logon string. This is converted to upper case and must */
/* match an LUA LU in the configuration file. This LU should be configured */
/* for a 327? on the host. */
/* */
/* The program can only access hosts that use simple unformatted logon */
/* requests */
/* */
/* To exit the program type ] (right square bracket) */
/* */
/* The CSV CONVERT function is used to convert data between ASCII and */
/* EBCDIC. This uses the type G conversion table, so the environment */
/* variable COMTBLG must be set to point to a suitable file. */
/* */
/* Keys that work are: */
/* */
/* Alt-1 to Alt-9 are PF1 to PF9 */
/* F2 sends a CLEAR to the host */
/* backspace */
/* Letters, numbers and symbols */
/* ] terminates the program */
/* */
/*****************************************************************************/


#ifdef WIN32
#include <windows.h>
#else
#define INCL_DOS
#define INCL_DOSERRORS
#include <os2.h>
#endif

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
#include <lua_c.h>
#include <acssvcc.h>


/*****************************************************************************/
/* Program constants */
/*****************************************************************************/
#define DATASIZE 4096 /* Max size of RU */
#define EXITKEY 0x5D /* ']' to exit program */

#define BETB 1 /* Between brackets */
#define SEND 2 /* In bracket and can send */
#define RECV 3 /* In bracket, but cannot send */


/*****************************************************************************/
/* State variables */
/* */
/* We can only have one read or write verb outstanding per flow. These */
/* state variables keep track of these verbs and what we need to do with */
/* them. */
/*****************************************************************************/

UINT write_state;
#define NO_WRITE 1
#define WRITE_OUTSTANDING 2 /* waiting for write to complete */
#define WRITE_QUEUED 3 /* have data to write */

UINT read_state;
#define NO_READ 1
#define READ_OUTSTANDING 2 /* read verb outstanding */
#define RSP_QUEUED 3 /* have a response to write */
#define RSP_OUTSTANDING 4 /* waiting for a response to complete */

UINT rpq_state;
#define NO_RPQ 1
#define RPQ_OUTSTANDING 2 /* waiting for an RPQ to complete */
#define RPQ_QUEUED 3 /* have RPQ to send */

/***************************************************************************/
/* Global variables */
/* */
/* Inbound data is prefixed with the <enter> key AID plus a two byte */
/* cursor address. */
/***************************************************************************/
LUA_VERB_RECORD recv_verb; /* SLI read verb */
LUA_VERB_RECORD other_verb; /* SLI init, write or term verb */
LUA_VERB_RECORD rpq_verb; /* SLI_WRITE for RPQs */

UCHAR rpq_data[] = {

0x88,
0x00, 0x0C, 0x81, 0x80, 0x80, 0x81, 0x85, 0x86, 0x87, 0x88, 0x95, 0xA6,

0x00, 0x17, 0x81, 0x81, 0x21, 0x00, 0x00, 0x50, 0x00, 0x18, 0x00, 0x00,
0x0A, 0x02, 0xE5, 0x00, 0x02, 0x00, 0x6F, 0x09, 0x10, 0x07, 0x80,

0x00, 0x14, 0x81, 0x85, 0x02, 0x00, 0x09, 0x0E, 0x00, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x02, 0xB9, 0x01, 0x1D,

0x00, 0x16, 0x81, 0x86, 0x00, 0x08, 0x00, 0xF4, 0xF1, 0x00, 0xF2, 0x00,
0xF3, 0x00, 0xF4, 0x00, 0xF5, 0x00, 0xF6, 0x00, 0xF7, 0x00,

0x00, 0x0D, 0x81, 0x87, 0x04, 0x00, 0xF0, 0xF1, 0x00, 0xF2, 0x00, 0xF4,
0x00,

0x00, 0x07, 0x81, 0x88, 0x00, 0x01, 0x02,

0x00, 0x0C, 0x81, 0x95, 0x00, 0x00, 0x7F, 0xFF, 0x7F, 0xFF, 0x01, 0x01,

0x00, 0x11, 0x81, 0xA6, 0x00, 0x00, 0x0B, 0x01, 0x00, 0x00, 0x50, 0x00,
0x18, 0x00, 0x50, 0x00, 0x18};

#define RPQ_LENGTH (sizeof(rpq_data))




unsigned char read_data[DATASIZE]; /* Outbound RU */
#define WRITE_EXTRA 6
unsigned char write_array[DATASIZE + WRITE_EXTRA] =
{0x7d, 0x40, 0x40, 0x11, 0x40, 0x40};
/* Inbound RU */
unsigned char *write_data = write_array + WRITE_EXTRA;
/* Pointer to inbound RU */
UINT data_offset = 0; /* offset into read_data */
UINT write_len = 0; /* length of write data */

struct convert convert_to_asc; /* Outbound convert verb */
struct convert convert_to_ebc; /* Inbound convert verb */

#ifdef WIN32
HANDLE write_event = 0l; /* write arm verb semaphore */
HANDLE read_event = 0l; /* read arm verb semaphore */
HANDLE init_event = 0l; /* SLI_OPEN semaphore */
HANDLE term_event = 0l; /* SLI_CLOSE semaphore */
HANDLE rpq_event = 0l;
HANDLE std_input; /* standard input handle */
HANDLE std_output; /* standard output handle */
#else
ULONG write_sema4 = 0l; /* write arm verb semaphore */
ULONG read_sema4 = 0l; /* read arm verb semaphore */
ULONG init_sema4 = 0l; /* SLI_OPEN semaphore */
ULONG term_sema4 = 0l; /* SLI_CLOSE semaphore */
ULONG rpq_sema4 = 0l;
#endif

BOOL terminating = FALSE; /* are we already in closedown() ? */

unsigned long sense = 0l; /* sense code */

unsigned char lu_name[9] = " "; /* LU name */
unsigned long sid; /* SLI session ID */
int send_state = BETB; /* LU session send state */

#define LOGON_MAX 25 /* maximum logon string length */

UCHAR logon_data[LOGON_MAX+1] = {0};
UCHAR logon_length = 0;

#ifdef WIN32
#define OPENPOST (ULONG) init_event
#define CLOSEPOST (ULONG) term_event
#define RECVPOST (ULONG) read_event
#define SENDPOST (ULONG) write_event
#define RPQPOST (ULONG) rpq_event
#else
#define OPENPOST (unsigned long) ((UCHAR FAR *) &init_sema4)
#define CLOSEPOST (unsigned long) ((UCHAR FAR *) &term_sema4)
#define RECVPOST (unsigned long) ((UCHAR FAR *) &read_sema4)
#define SENDPOST (unsigned long) ((UCHAR FAR *) &write_sema4)
#define RPQPOST (unsigned long) ((UCHAR FAR *) &rpq_sema4)
#endif


/*****************************************************************************/
/* Function declarations. */
/*****************************************************************************/

#ifdef WIN32
#define LOADDS
#else
#define LOADDS _loadds
#endif

void pascal far LOADDS SLI (LUA_VERB_RECORD FAR *);

#ifdef WIN32
void _CRTAPI1 main(int argc, char *argv[]);
#else
int main (int argc,char * *argv);
#endif
void csv_init (void);
int issue_verb (unsigned int type);
void issue_receive (void);
void other_done (LUA_VERB_RECORD *verb);
void recv_done (LUA_VERB_RECORD *verb);
void issue_rsp (unsigned long sense);
void rsp_done (LUA_VERB_RECORD *verb);
void closedown (void);
BOOL do_send (void);
void wait_verb_complete (LUA_VERB_RECORD *verb);
void set_semaphore (LUA_VERB_RECORD *verb);
BOOL do_keyboard_stuff (void);
BOOL check_verb_complete (LUA_VERB_RECORD *verb);
void parse_data (UCHAR FAR *, USHORT);
BOOL issue_rpq (void);

/**PROC+**********************************************************************/
/* Name: main */
/* */
/* Purpose: set up CSV convert verbs */
/* */
/* Returns: none */
/* */
/* Params: argv, argc */
/* */
/* Operation: Get LU name and logon string from command line */
/* do some initialisation */
/* Issue SLI_OPEN to get LU-LU session */
/* Loop reading data from keyboard and host, and send keyboard */
/* data to host */
/**PROC-**********************************************************************/
#ifdef WIN32
void _CRTAPI1 main(int argc, char *argv[])
#else
int main(argc, argv)
int argc;
char *argv[];
#endif
{
BOOL whole_data; /* we have a whole data string to write */
BOOL verb_complete; /* Has a verb completed */
BOOL write_ok; /* Has write worked? */
BOOL rpq_ok; /* Has rpq worked */
int ii;
#ifdef WIN32
HANDLE handle_list [6];
#endif
#ifdef DOS5
DEFINEMUXSEMLIST(sem_list,5)
USHORT sem_index;
#endif

printf("SLI simple 3270 application\n");

/***************************************************************************/
/* Validate parameter usage and get LU name. */
/***************************************************************************/
if (argc != 3)
{
printf("Usage: SLI3270 luname \"logon string\"\n");
exit(1);
}
if (strlen(argv[1]) > Cool
{
printf("LU name too long\n");
exit(1);
}
if (strlen(argv[2]) > LOGON_MAX)
{
printf("Logon string too long");
}

/***************************************************************************/
/* Convert to upper case */
/***************************************************************************/
ii=0;
while (argv[1][ii])
{
if (argv[1][ii] >= 'a' && argv[1][ii] <= 'z')
{
argv[1][ii] = argv[1][ii] - 'a' + 'A';
}
ii++;
}
memcpy(lu_name, argv[1], strlen(argv[1]));
printf("lu_name %s\n", lu_name);

/***************************************************************************/
/* Set up logon message */
/***************************************************************************/
strcpy (logon_data, argv[2]);
logon_length = strlen(logon_data);
convert_to_ebc.opcode = SV_CONVERT;
convert_to_ebc.direction = SV_ASCII_TO_EBCDIC;
convert_to_ebc.char_set = SV_G;
convert_to_ebc.source = logon_data;
convert_to_ebc.target = logon_data;
convert_to_ebc.len = (unsigned short) logon_length;
ACSSVC_C((LONG)((UCHAR FAR *)&convert_to_ebc));

/***************************************************************************/
/* Set up CSV convert verbs */
/***************************************************************************/
csv_init();

#ifdef WIN32
/***************************************************************************/
/* Create the necessary events */
/***************************************************************************/
write_event = CreateEvent (NULL, TRUE, FALSE, NULL);
read_event = CreateEvent (NULL, TRUE, FALSE, NULL);
init_event = CreateEvent (NULL, TRUE, FALSE, NULL);
term_event = CreateEvent (NULL, TRUE, FALSE, NULL);
rpq_event = CreateEvent (NULL, TRUE, FALSE, NULL);


/***************************************************************************/
/* Get standard input and output handles. */
/***************************************************************************/
std_input = GetStdHandle (STD_INPUT_HANDLE );
std_output = GetStdHandle (STD_OUTPUT_HANDLE);
if ((std_input == INVALID_HANDLE_VALUE) ||
(std_output == INVALID_HANDLE_VALUE))
{
printf("GetStdHandle Failed, %d", GetLastError());
exit (1);
}

/***************************************************************************/
/* Set up list of handles to wait for */
/***************************************************************************/
handle_list[0] = write_event;
handle_list[1] = read_event;
handle_list[2] = init_event;
handle_list[3] = term_event;
handle_list[4] = rpq_event;
handle_list[5] = std_input;
#endif

#ifdef DOS5
/***************************************************************************/
/* Set semaphores to begin with */
/***************************************************************************/
DosSemSet (&init_sema4);
DosSemSet (&term_sema4);
DosSemSet (&read_sema4);
DosSemSet (&write_sema4);
DosSemSet (&rpq_sema4);

sem_list.amxs[0].hsem = &init_sema4;
sem_list.amxs[1].hsem = &term_sema4;
sem_list.amxs[2].hsem = &read_sema4;
sem_list.amxs[3].hsem = &write_sema4;
sem_list.amxs[4].hsem = &rpq_sema4;
#endif


/***************************************************************************/
/* Initialize SLI (get LU-LU session) */
/***************************************************************************/
if (issue_verb((unsigned int) LUA_OPCODE_SLI_OPEN))
{
printf("OPEN failed\n");
exit(1);
}

/***************************************************************************/
/* Set initial states */
/***************************************************************************/
write_state = NO_WRITE;
read_state = NO_READ;
rpq_state = NO_RPQ;

/***************************************************************************/
/* Loop reading inbound data from the keyboard */
/***************************************************************************/
while (!terminating)
{
/*************************************************************************/
/* Determine if we can pause */
/*************************************************************************/
if ( (read_state != NO_READ) &&

((write_state != WRITE_QUEUED) ||
(rpq_state != NO_RPQ) ||
(read_state == RSP_OUTSTANDING) ||
(read_state == RSP_QUEUED)) &&

((rpq_state != RPQ_QUEUED) ||
(write_state == WRITE_OUTSTANDING) ||
(read_state == RSP_OUTSTANDING) ||
(read_state == RSP_QUEUED)) &&

((read_state != RSP_QUEUED) ||
(write_state == WRITE_OUTSTANDING)))
{
#ifdef WIN32
WaitForMultipleObjects (6, handle_list, FALSE, INFINITE);
#else
if (!kbhit())
{
DosMuxSemWait (&sem_index, &sem_list, 200l);
}
#endif
}

/*************************************************************************/
/* First check on the state of write verbs */
/*************************************************************************/
if ((write_state == NO_WRITE) &&
(rpq_state == NO_RPQ) &&
(read_state != RSP_QUEUED) &&
(read_state != RSP_OUTSTANDING))
{
/***********************************************************************/
/* Don't write here if we need to respond, since we can only have one */
/* write outstanding on each flow. */
/* Here we want to check if we have a whole string of data (i.e. that */
/* the user has hit enter). If so write the data to the HOST */
/***********************************************************************/
whole_data = do_keyboard_stuff ();
if (whole_data)
{
/*********************************************************************/
/* Attempt to write the data. May not work because of bracket state */
/*********************************************************************/

write_ok = do_send ();
if (write_ok)
{
/*******************************************************************/
/* If verb completes async change state to indicate this o.w. */
/* call the verb done processor */
/*******************************************************************/
if (other_verb.common.lua_flag2.async)
{
write_state = WRITE_OUTSTANDING;
}
else
{
other_done (&other_verb);
write_state = NO_WRITE;
}
}
else
{
/*******************************************************************/
/* Failed to do a write. Queue up data */
/*******************************************************************/
write_state = WRITE_QUEUED;
}
}
}
else if ((write_state == WRITE_QUEUED) &&
(rpq_state == NO_RPQ) &&
(read_state != RSP_OUTSTANDING) &&
(read_state != RSP_QUEUED))
{
/***********************************************************************/
/* Attempt to write the data. May not work because of bracket state */
/***********************************************************************/
write_ok = do_send ();
if (write_ok)
{
/*********************************************************************/
/* If verb completes async change state to indicate this o.w. call */
/* the verb done processor */
/*********************************************************************/
if (other_verb.common.lua_flag2.async)
{
write_state = WRITE_OUTSTANDING;
}
else
{
other_done (&other_verb);
write_state = NO_WRITE;
}
}

}
else if (write_state == WRITE_OUTSTANDING)
{
/***********************************************************************/
/* We have a SLI_WRITE outstanding so check if it is complete */
/***********************************************************************/
verb_complete = check_verb_complete (&other_verb);
if (verb_complete)
{
other_done (&other_verb);
write_state = NO_WRITE;
}
}



/*************************************************************************/
/* Now check the RPQ state */
/*************************************************************************/
if ((rpq_state == RPQ_QUEUED) &&
(write_state != WRITE_OUTSTANDING) &&
(read_state != RSP_OUTSTANDING) &&
(read_state != RSP_QUEUED))
{
/***********************************************************************/
/* We have an RPQ queued up. Try to send it */
/***********************************************************************/
rpq_ok = issue_rpq ();
if (rpq_ok)
{
/*********************************************************************/
/* If verb completes async change state to indicate this o.w. call */
/* the verb done processor */
/*********************************************************************/
if (rpq_verb.common.lua_flag2.async)
{
rpq_state = WRITE_OUTSTANDING;
}
else
{
other_done (&rpq_verb);
write_state = NO_RPQ;
}
}
}
else if (rpq_state == RPQ_OUTSTANDING)
{
/***********************************************************************/
/* Check for verb completion */
/***********************************************************************/
verb_complete = check_verb_complete (&rpq_verb);
if (verb_complete)
{
other_done (&rpq_verb);
rpq_state = NO_RPQ;
}

}



/*************************************************************************/
/* Now check on read verbs */
/*************************************************************************/
if (read_state == NO_READ)
{
issue_receive ();
if (recv_verb.common.lua_flag2.async)
{
read_state = READ_OUTSTANDING;
}
else
{
/*********************************************************************/
/* recv_done will change read_state to RESPONSE_QUEUED or NO_READ */
/*********************************************************************/
recv_done (&recv_verb);
}
}
else if (read_state == READ_OUTSTANDING)
{
verb_complete = check_verb_complete (&recv_verb);
if (verb_complete)
{
/*********************************************************************/
/* recv_done will change read_state to RESPONSE_QUEUED or NO_READ */
/*********************************************************************/
recv_done (&recv_verb);
}
}
else if (read_state == RSP_QUEUED)
{
/***********************************************************************/
/* We need to respond to a message read. Do a write if one is */
/* availible. */
/***********************************************************************/
if (write_state != WRITE_OUTSTANDING)
{
/*********************************************************************/
/* The response is issued using the recv_verb */
/*********************************************************************/
issue_rsp (sense);
if (recv_verb.common.lua_flag2.async)
{
read_state = RSP_OUTSTANDING;
}
else
{
rsp_done (&recv_verb);
read_state = NO_READ;
}
}
}
else if (read_state == RSP_OUTSTANDING)
{
/***********************************************************************/
/* Check to see if the response is complete */
/***********************************************************************/
verb_complete = check_verb_complete (&recv_verb);
if (verb_complete)
{
rsp_done (&recv_verb);
read_state = NO_READ;
}
}
else
{
/***********************************************************************/
/* Invalid state */
/***********************************************************************/
printf("invalid state");
}

} /* while not terminating */


} /* main () */


/**PROC+**********************************************************************/
/* Name: csv_init */
/* */
/* Purpose: set up CSV convert verbs */
/* */
/* Returns: void */
/* */
/* Params: none */
/* */
/* Operation: sets uup two CSV convert verbs, one in each direction. Only */
/* the length needs to be set when the verb is called */
/**PROC-**********************************************************************/
void csv_init (void)
{
convert_to_asc.opcode = SV_CONVERT;
convert_to_asc.direction = SV_EBCDIC_TO_ASCII;
convert_to_asc.char_set = SV_G;
convert_to_asc.source = read_data;
convert_to_asc.target = read_data;

convert_to_ebc.opcode = SV_CONVERT;
convert_to_ebc.direction = SV_ASCII_TO_EBCDIC;
convert_to_ebc.char_set = SV_G;
convert_to_ebc.source = write_data;
convert_to_ebc.target = write_data;
} /* csv_init */


/**PROC+**********************************************************************/
/* Name: issue_verb */
/* */
/* Purpose: build a verb and send it */
/* */
/* Returns: int - non-zero => verb failed */
/* */
/* Params: IN type - type of verb to issue */
/* */
/* Operation: Build an OPEN or CLOSE verb and issue it. Wait for the verb */
/* to complete */
/**PROC-**********************************************************************/
int issue_verb(type)
unsigned int type;
{
memset(&other_verb, 0, sizeof(other_verb));
other_verb.common.lua_verb = LUA_VERB_SLI;
other_verb.common.lua_opcode = type;
if (type == LUA_OPCODE_SLI_OPEN)
{
other_verb.common.lua_verb_length = sizeof(struct LUA_COMMON)+
sizeof(other_verb.specific.open.lua_init_type) +
sizeof(other_verb.specific.open.lua_resv65) +
sizeof(other_verb.specific.open.lua_wait) +
sizeof(other_verb.specific.open.lua_ending_delim);
memcpy(other_verb.common.lua_luname, lu_name, Cool;
other_verb.common.lua_post_handle = OPENPOST;
other_verb.specific.open.lua_init_type = LUA_INIT_TYPE_SEC_LOG;
other_verb.common.lua_data_length = logon_length;
other_verb.common.lua_data_ptr = logon_data;
other_verb.specific.open.lua_open_extension[0].lua_routine_type =
LUA_ROUTINE_TYPE_END;
}
else
{
other_verb.common.lua_verb_length = sizeof(struct LUA_COMMON);
other_verb.common.lua_sid = sid;
other_verb.common.lua_post_handle = CLOSEPOST;
}
SLI((LUA_VERB_RECORD FAR *) &other_verb);
if (other_verb.common.lua_flag2.async)
{
wait_verb_complete (&other_verb);
}
other_done(&other_verb);

return(other_verb.common.lua_prim_rc != LUA_OK);
} /* issue_verb */


/**PROC+**********************************************************************/
/* Name: issue_receive */
/* */
/* Purpose: build a recv verb and send it */
/* */
/* Returns: void */
/* */
/* Params: none */
/* */
/* Operation: Build a read verb for all flows and issue it */
/**PROC-**********************************************************************/
void issue_receive (void)
{
memset(&recv_verb, 0, sizeof(recv_verb));
memset(read_data, 0, DATASIZE);
recv_verb.common.lua_verb = LUA_VERB_SLI;
recv_verb.common.lua_verb_length = sizeof(struct LUA_COMMON);
recv_verb.common.lua_opcode = LUA_OPCODE_SLI_RECEIVE;
recv_verb.common.lua_sid = sid;
recv_verb.common.lua_max_length = DATASIZE;
recv_verb.common.lua_data_ptr = (char *) read_data;
recv_verb.common.lua_post_handle = RECVPOST;
recv_verb.common.lua_flag1.lu_norm = 1;
recv_verb.common.lua_flag1.lu_exp = 1;
recv_verb.common.lua_flag1.sscp_norm = 1;
recv_verb.common.lua_flag1.sscp_exp = 1;
SLI((LUA_VERB_RECORD FAR *)&recv_verb);

} /* issue_receive */


/**PROC+**********************************************************************/
/* Name: other_done */
/* */
/* Purpose: handle completed open, send or close verb */
/* */
/* Returns: void */
/* */
/* Params: IN verb - completed verb */
/* */
/* Operation: write status to he screen */
/**PROC-**********************************************************************/
void other_done(verb)
LUA_VERB_RECORD *verb;
{
switch (verb->common.lua_opcode)
{
case LUA_OPCODE_SLI_OPEN:
if (verb->common.lua_prim_rc == LUA_OK)
{
printf("session active\n");
sid = verb->common.lua_sid;
}
else
{
printf("OPEN failed, (%4.4x, %8.8lx)\n",
verb->common.lua_prim_rc, verb->common.lua_sec_rc);
}
break;

case LUA_OPCODE_SLI_SEND:
if (verb->common.lua_prim_rc != LUA_OK)
{
printf("SEND failed, (%4.4x, %8.8lx)\n",
verb->common.lua_prim_rc, verb->common.lua_sec_rc);
}
break;

case LUA_OPCODE_SLI_CLOSE:
printf("Terminated\n");
break;

}
} /* other_done */


/**PROC+**********************************************************************/
/* Name: recv_done */
/* */
/* Purpose: handle completed receive verb */
/* */
/* Returns: void */
/* */
/* Params: IN verb - completed read verb */
/* */
/* Operation: If the completed verb contains data, first parse it and then */
/* display it. */
/* If message is a BIND or an UNBIND, set the LU-LU session state */
/* accordingly */
/* Also check for EB, CD and change session state flags */
/**PROC-**********************************************************************/
void recv_done(verb)
LUA_VERB_RECORD *verb;
{
int count; /* number of bytes of data left to display */
unsigned char *data; /* pointer to next data to display */
BOOL rsp_required = FALSE; /* is a resonse required */

sense = 0l;

if (verb->common.lua_prim_rc == LUA_OK)
{
if (verb->common.lua_message_type == LUA_MESSAGE_TYPE_LU_DATA)
{
if (verb->common.lua_data_length > 0)
{
/*********************************************************************/
/* We now have to parse the data. For the moment we only look for */
/* RPQ requests. */
/*********************************************************************/
parse_data (read_data, (USHORT) (verb->common.lua_data_length));

/*********************************************************************/
/* Display outbound data. */
/*********************************************************************/
convert_to_asc.len = (unsigned short) verb->common.lua_data_length;
ACSSVC_C((LONG)((UCHAR FAR *)&convert_to_asc));
data = read_data;
count = strlen(data);
while (count > 0)
{
if (count <= 80)
{
printf("%s\n",data);
count = 0;
}
else
{
printf("%80.80s\n",data);
count -= 80;
data += 80;
}
}
}

/***********************************************************************/
/* Set session state. */
/***********************************************************************/
if (verb->common.lua_rh.ebi)
{
printf("EB\n");
send_state = BETB;
}
else if (verb->common.lua_rh.cdi)
{
printf("CD\n");
send_state = SEND;
}
else
{
send_state = RECV;
}
}

/*************************************************************************/
/* Respond to any RQD request. */
/*************************************************************************/
if ((verb->common.lua_message_type != LUA_MESSAGE_TYPE_RSP) &&
(verb->common.lua_rh.ri == 0)) /* definite response */
{
rsp_required = TRUE;
}
}
else /* primary rc not OK - read failed - stop now */
{
printf("RECEIVE ERROR, primary rc = %4.4x, secondary rc = %8.8lx\n",
verb->common.lua_prim_rc, verb->common.lua_sec_rc);
closedown();
}

/***************************************************************************/
/* Continue processing with either another recv or a send positive rsp. */
/* (The callback from issuing response will then issue another recv) If */
/* we've already gone into closedown, stop here */
/***************************************************************************/
if (!terminating)
{
if (rsp_required)
{
read_state = RSP_QUEUED;
}
else
{
read_state = NO_READ;
}
}
} /* recv_done */


/**PROC+**********************************************************************/
/* Name: issue_rsp */
/* */
/* Purpose: issue a response for a request from the host */
/* */
/* Returns: void */
/* */
/* Params: IN sense - sense code for the response */
/* */
/* Operation: Build a response and write it out. Uses the recv verb control */
/* block because it has the necessary information. */
/* */
/**PROC-**********************************************************************/
void issue_rsp(sense)
unsigned long sense;
{
recv_verb.common.lua_opcode = LUA_OPCODE_SLI_SEND;
recv_verb.common.lua_max_length = 0;
recv_verb.common.lua_post_handle = (ULONG) RECVPOST;
recv_verb.common.lua_message_type = LUA_MESSAGE_TYPE_RSP;
recv_verb.common.lua_verb_length = sizeof(struct LUA_COMMON) +
sizeof(recv_verb.specific.lua_sequence_number);

recv_verb.common.lua_rh.rri = 1; /* response */
recv_verb.common.lua_flag1.lu_norm = 0;
recv_verb.common.lua_flag1.lu_exp = 0;
recv_verb.common.lua_flag1.sscp_norm = 0;
recv_verb.common.lua_flag1.sscp_exp = 0;

/***************************************************************************/
/* If we have been given a sense code this must be a negative response */
/***************************************************************************/
if (sense)
{
recv_verb.common.lua_data_length = 4;
memcpy(read_data, &sense, 4);
recv_verb.common.lua_rh.ri = 1; /* negative rsp */
}
else
{
recv_verb.common.lua_data_length = 0;
recv_verb.common.lua_rh.ri = 0; /* positive rsp */
}
/***************************************************************************/
/* Send the response back on the flow from which the request came */
/***************************************************************************/
if (recv_verb.common.lua_flag2.lu_norm)
{
recv_verb.common.lua_flag1.lu_norm = 1;
}
else if (recv_verb.common.lua_flag2.lu_exp)
{
recv_verb.common.lua_flag1.lu_exp = 1;
}
else if (recv_verb.common.lua_flag2.sscp_norm)
{
recv_verb.common.lua_flag1.sscp_norm = 1;
}
else if (recv_verb.common.lua_flag2.sscp_exp)
{
recv_verb.common.lua_flag1.sscp_exp = 1;
}
/***************************************************************************/
/* Send out the verb */
/***************************************************************************/
SLI((LUA_VERB_RECORD FAR *)&recv_verb); /* write the response */
} /* issue_rsp */


/**PROC+**********************************************************************/
/* Name: rsp_done */
/* */
/* Purpose: handle completion of SLI_SEND, when SLI_SEND has written a */
/* response */
/* */
/* Returns: void */
/* */
/* Params: IN verb - completed verb */
/* */
/* Operation: If verb did not complete OK print a message and terminate */
/* */
/**PROC-**********************************************************************/
void rsp_done (verb)
LUA_VERB_RECORD *verb;
{
if (verb->common.lua_prim_rc != LUA_OK) /* failed to write the response */
{ /* so stop here */
printf("SEND for response failed, (%4.4x, %8.8lx)\n",
verb->common.lua_prim_rc, verb->common.lua_sec_rc);
closedown();
}
} /* rsp_done */


/**PROC+**********************************************************************/
/* Name: closedown */
/* */
/* Purpose: terminate the application cleanly */
/* */
/* Returns: void */
/* */
/* Params: none */
/* */
/* Operation: Issue an SLI_CLOSE and wait for it to complete. Then exit */
/* */
/**PROC-**********************************************************************/
void closedown (void)
{
if (!terminating) /* check we haven't already got here from */
{ /* another section of the code */
terminating = TRUE; /* then make sure we can't get here again */
printf("Closedown\n");
if (issue_verb((unsigned int) LUA_OPCODE_SLI_CLOSE))
{
exit(1);
}
exit(0);
}
} /* closedown */


/**PROC+**********************************************************************/
/* Name: check_verb_complete */
/* */
/* Purpose: check for asynchronous verb completion */
/* */
/* Returns: BOOL - TRUE => verb has completed */
/* */
/* Params: IN - verb - pointer to verb control block */
/* */
/* Operation: OS specific */
/* */
/**PROC-**********************************************************************/
BOOL check_verb_complete (verb)

LUA_VERB_RECORD * verb;
{
#ifdef DOS5
/***************************************************************************/
/* OS/2 case. The verb is complete when the semaphore is cleared */
/***************************************************************************/
USHORT RetCode; /* Holds return code from OS calls */
BOOL verb_complete; /* Has the verb completed */

verb_complete = FALSE;

RetCode = DosSemRequest ((HSEM)verb->common.lua_post_handle, 0l);

if (RetCode != NO_ERROR)
{
if (RetCode != ERROR_SEM_TIMEOUT)
{
/***********************************************************************/
/* If we get here we've got problems */
/***********************************************************************/
printf("Bad DosSemRequest return code, %d", RetCode);
}
}
else
{
verb_complete = TRUE;
set_semaphore (verb);
}

return(verb_complete);
#endif

#ifdef PDOS
/***************************************************************************/
/* DOS case. The verb is complete when the lua_post_handle is cleared */
/***************************************************************************/
BOOL verb_complete; /* Has the verb completed */

verb_complete = FALSE;

if (!verb->common.lua_post_handle)
{
verb_complete = TRUE;
set_semaphore (verb);
}

return(verb_complete);
#endif

#ifdef WIN32
/***************************************************************************/
/* Win32 case. The verb is complete when the semaphore is cleared */
/***************************************************************************/
DWORD RetCode;

RetCode = WaitForSingleObject((HANDLE) verb->common.lua_post_handle, 0l);

if (RetCode == 0)
{
set_semaphore (verb);
}
return((RetCode == 0));
#endif
} /* check_verb_complete */


/**PROC+**********************************************************************/
/* Name: wait_verb_complete */
/* */
/* Purpose: waits for async verb completion */
/* */
/* Returns: void */
/* */
/* Params: IN - verb - pointer to verb control block */
/* */
/* Operation: Wait for the lua_post_handle to become clear */
/* */
/**PROC-**********************************************************************/
void wait_verb_complete (verb)

LUA_VERB_RECORD * verb ;
{
#ifdef DOS5
USHORT RetCode; /* Holds return code from OS calls */

RetCode = DosSemRequest ((HSEM)verb->common.lua_post_handle, -1l);
#endif

#ifdef WIN32
DWORD RetCode;

RetCode = WaitForSingleObject((HANDLE)verb->common.lua_post_handle,
(DWORD)-1l);
#endif
set_semaphore (verb);

} /* wait_verb_complete */


/**PROC+**********************************************************************/
/* Name: set_semaphore */
/* */
/* Purpose: sets verb completion flags */
/* */
/* Returns: void */
/* */
/* Params: IN - verb - pointer to vcb */
/* */
/* Operation: set the lua_post_handle to the non-signaled state */
/* */
/**PROC-**********************************************************************/
void set_semaphore (verb)

LUA_VERB_RECORD * verb;
{
#ifdef DOS5
USHORT RetCode;
RetCode = DosSemSet ((HSEM)verb->common.lua_post_handle);
#endif

#ifdef WIN32
/*W32***********************************************************************/
/*W32* Win 32 case. Clear the event */
/*W32***********************************************************************/
ResetEvent ((HANDLE) verb->common.lua_post_handle);
#endif
} /* set_semaphore */


/**PROC+**********************************************************************/
/* Name: do_keyboard_stuff */
/* */
/* Purpose: poll keyboard for data */
/* */
/* Returns: BOOL - TRUE => we have data to send */
/* */
/* Params: none */
/* */
/* Operation: poll keyboard */
/* if some data */
/* read it in */
/* add it to data buffer */
/* if data is <enter> */
/* return TRUE */
/* endif */
/* endif */
/* return false */
/* */
/* Also keep track of which session is being used, and if user wishes to */
/* exit. */
/* */
/**PROC-**********************************************************************/
BOOL do_keyboard_stuff (void)

{
BOOL data_to_send; /* do we have data to send? */
INT input_char; /* an input character */
#ifdef WIN32
INPUT_RECORD input_record; /* input record */
DWORD no_read; /* number of input records read */
#endif

data_to_send = FALSE;

/***************************************************************************/
/* Check if keyboard has been hit */
/***************************************************************************/
#ifdef WIN32
while ((!data_to_send) &&
(!terminating) &&
(PeekConsoleInput (std_input, &input_record, 1, &no_read)) &&
(no_read > 0))
#else
while ((!data_to_send) && (!terminating) && (kbhit()))
#endif
{
#ifndef WIN32
input_char = getche ();
if ((input_char == 0) || (input_char == 0xE0))
#else
ReadConsoleInput (std_input, &input_record, 1, &no_read);


if ((input_record.EventType == KEY_EVENT) &&
(input_record.Event.KeyEvent.bKeyDown) &&
((input_record.Event.KeyEvent.dwControlKeyState == LEFT_ALT_PRESSED) ||
((input_record.Event.KeyEvent.wVirtualKeyCode >= VK_F1 ) &&
(input_record.Event.KeyEvent.wVirtualKeyCode <= VK_F24))))
#endif
{
/***********************************************************************/
/* Not an ascii char */
/***********************************************************************/
#ifndef WIN32
input_char = getch ();
#endif


/***********************************************************************/
/* Check for function keys and ALT-?? */
/***********************************************************************/
#ifndef WIN32
if (input_char == 60) /* F2 */
#else
if (input_record.Event.KeyEvent.wVirtualKeyCode == VK_F2)
#endif
{
/*********************************************************************/
/* Send a Clear. */
/*********************************************************************/
printf("sending clear\n");
*write_data = 0x6d;
write_len = 1;
data_to_send = TRUE;
}
#ifndef WIN32
else if ((input_char >= 120) && (input_char <= 129))
#else
else if ((input_record.Event.KeyEvent.wVirtualKeyCode >= '0') &&
(input_record.Event.KeyEvent.wVirtualKeyCode <= '9'))
#endif
{
/*********************************************************************/
/* ALT-1 to ALT-0 */
/* 0xF1 is the AID code for PF1 */
/* Follow this with the cursor address */
/*********************************************************************/
#ifndef WIN32
*write_data = 0xF1 + input_char - 120;
#else
*write_data = 0xF0 + input_record.Event.KeyEvent.wVirtualKeyCode - '0';
#endif
*(write_data + 1) = 0x40;
*(write_data + 2) = 0x40;
write_len = 3;
data_to_send = TRUE;

}
}
else
#ifdef WIN32
if ((input_record.EventType == KEY_EVENT ) &&
(input_record.Event.KeyEvent.bKeyDown))
#endif
{
/***********************************************************************/
/* An ASCII char */
/***********************************************************************/
#ifdef WIN32
input_char = input_record.Event.KeyEvent.uChar.AsciiChar;
#endif
if (input_char == EXITKEY)
{
closedown();
}
else
{
/*********************************************************************/
/* Key should be real data. Add it to the string */
/* For Windows NT echo the character to the screen */
/*********************************************************************/

if (input_char == 13)
{
#ifdef WIN32
WriteConsole (std_output, &input_char, 1, &no_read, NULL);
#endif
/*******************************************************************/
/* If user pressed return key then send the data. Reset */
/* data_offset for next data. */
/*******************************************************************/
write_data[data_offset++] = '\0';
data_to_send = TRUE;
data_offset = 0;

/*******************************************************************/
/* Convert data to EBCDIC */
/*******************************************************************/
convert_to_ebc.len = (unsigned short) (strlen(write_data) );
if (convert_to_ebc.len > 0)
{
ACSSVC_C((LONG)((UCHAR FAR *)&convert_to_ebc));
}
write_len = convert_to_ebc.len;

/*******************************************************************/
/* Allow for ENTER AID if necessary */
/*******************************************************************/
write_data -= WRITE_EXTRA;
write_len += WRITE_EXTRA;
}
else if (input_char == Cool
{
#ifdef WIN32
WriteConsole (std_output, &input_char, 1, &no_read, NULL);
#endif
/*******************************************************************/
/* Backspace. Delete last char */
/*******************************************************************/
if (data_offset > 0)
{
data_offset--;
}
}
else if (input_char != 0)
{
#ifdef WIN32
WriteConsole (std_output, &input_char, 1, &no_read, NULL);
#endif
write_data[data_offset++] = (UCHAR) input_char;
}
}
}
} /* if (kbhit()) */

return(data_to_send);
} /* do_keyboard_stuff */



/**PROC+**********************************************************************/
/* Name: do_send */
/* */
/* Purpose: issue a write verb */
/* */
/* Returns: BOOL - TRUE => data sent OK */
/* */
/* Params: none */
/* */
/* Operation: convert data to EBCDIC and send it on the right session */
/* */
/**PROC-**********************************************************************/
BOOL do_send (void)

{
BOOL ok;

ok = TRUE;


/***************************************************************************/
/* Set up the vcb */
/***************************************************************************/
memset(&other_verb, 0, sizeof(other_verb));
other_verb.common.lua_verb = LUA_VERB_SLI;
other_verb.common.lua_verb_length = sizeof(struct LUA_COMMON) +
sizeof(other_verb.specific.lua_sequence_number);
other_verb.common.lua_opcode = LUA_OPCODE_SLI_SEND;
other_verb.common.lua_sid = sid;
other_verb.common.lua_message_type = LUA_MESSAGE_TYPE_LU_DATA;
other_verb.common.lua_data_length = write_len;
other_verb.common.lua_data_ptr = (char far *) write_data;
other_verb.common.lua_post_handle = SENDPOST;
other_verb.common.lua_rh.dr1i = 1;

/***************************************************************************/
/* On the LU session we must add the <enter> key prefix. All inbound */
/* requests flow RQE with the BBI and CDI flags set depending on the */
/* current session state. */
/***************************************************************************/
other_verb.common.lua_rh.ri = 1;
if (send_state == BETB)
{
/*************************************************************************/
/* Between bracket, so open bracket and give direction. Note that we */
/* can do this since we will always be contention winner. */
/*************************************************************************/
other_verb.common.lua_rh.bbi = 1;
other_verb.common.lua_rh.cdi = 1;
send_state = RECV;
}
else if (send_state = SEND)
{
/*************************************************************************/
/* In bracket and we have direction, so simply give direction. */
/*************************************************************************/
other_verb.common.lua_rh.cdi = 1;
send_state = RECV;
}
else
{
/*************************************************************************/
/* In bracket and we do not have direction, so do not send.
Back to top
View user's profile Send private message
 
Post new topic   Reply to topic    Windows Server Forum Index -> Host Integration Server All times are GMT
Page 1 of 1

 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum




New Topics Powered by phpBB