Código
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Program : MSG_EXIT.C, Message Exit.
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Setup :
//
// Place MY_DLL.DLL in e:\mq\exits\ and configure channel
// to use MSGEXIT('MY_DLL(My_Exit)')
//
// On MQ 5.3 GUI, you have to code "MY_DLL(My_Exit)" in the channel
// "Rutinas de Salida" tab, campo "Nombre Rutina Salida Mensaje".
//
// Send Channel .-
//
// The name of the DLL must have been coded in DEFINE CHANNEL,
// keyword MSGEXIT, with parameter My_Exit.
//
// Example :
// DEFINE CHANNEL ... +
// CHLTYPE(SDR) +
// MSGEXIT('MY_DLL(My_Exit)') +
//
// Receive channel .-
//
// The name of the DLL must have been coded in DEFINE CHANNEL,
// keyword MSGEXIT, with parameter My_Exit.
// Example :
// DEFINE CHANNEL ... +
// CHLTYPE(RCVR) +
// MSGEXIT('MY_DLL(My_Exit)') +
//
// Input :
//
// Message channel exit gets control from MQ Agent.
// Parameters :
// MQCXP - channel exit parameter structure.
// MQCD - channel data structure.
// MQXQH - transmission queue header structure.
// Contains MQMD, message descriptor.
//
// Exits are passed an agent buffer with contents depending upon
// type of exit. For Message Exit, the transmission queue header MQXQH
// and the application message text are retrieved from the queue.
//
// Output :
//
// MQCXP.ExitResponse and MQCXP.Feedback, in MQCXP structure.
// If a channel exit sets the "ExitResponse" field to MQCXX_SUPPRESS_FUNCTION,
// the "Feedback" field specifies the code that identifies why the
// message was put on the dead-letter queue.
//
// "e:\mq\exits\MSG_EXIT.TRC" file is generated if DO_DEBUG is defined not-null.
// 2004 : write "c:\temp\MSG_EXIT.TRC", as maybe disc "E" does not exist.
//
// How to modify the message :
//
// a) inplace : modify the message and "DataLength".
//
// b) into ExitBuffer : ExitResponse2 := MQXR2_USE_EXIT_BUFFER ;
// 1) modify message into ExitBuffer, then
// 2) set ExitResponse2 := MQXR2_USE_EXIT_BUFFER ;
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Logic :
//
// Display parameters ;
//
// Send Exit :
//
// Dump_Msg ;
// Modify message ;
// Dump_Msg ;
//
// Receive Exit :
//
// Dump_Msg ;
//
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// How to compile it :
//
// CL -I"e:\MQ\tools\c\include" MSG_EXIT.C
// -o MY_DLL.dll -LD
// -DEFAULTLIB e:\MQ\tools\lib\mqm.lib e:\MQ\tools\lib\mqmvx.lib msg_exi.def
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Some documentation extracts :
//
// MQ Series Distributed Queuing Guide, SC33-1139-06.
//
// Page 274 :
// All exits are called with :
// a channel exit parameter structure (MQCXP)
// a channel definition structure (MQCD)
// a prepared data buffer
// a data length parameter
// a buffer length parameter.
// The buffer length must not be exceeded.
//
// Page 293 :
// The data structures are :
// MQCD - channel data structure, page 312.
// MQCXP - channel exit parameter structure, page 329.
//
// ----------------------------------------------------------------------------
//
// MQ Series Command Reference, SC33-1369-05.
// Page 69 :
// MSGEXIT(string) ... on OS/2 is of the form :
// dllname(funcionname)
//
// ----------------------------------------------------------------------------
//
// MQ Series Application Programming Reference, S33-1673-01.
//
// Applications that put messages should normally specify MQENC_NATIVE.
// Applications that retrieve messages should compare this field against
// the value MQENC_NATIVE; if the values differ, the application
// may need to convert numeric data in the message.
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Releases :
// 1.01, 29-Jun-04 : First release, BBVA.
// 1.02, 30-Jun-04 : Modify message inplace.
// FIX02 1.03, 15-Oct-04 : verify "AA0" in "Cabecera General".
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
#define DO_DEBUG 1 // debug : 0 = dont write trace, other = do.
#if DO_DEBUG > 0
// Some external libraries :
#include // required for FILE.
#include // required for TIME and CTIME.
#endif // debug : dont include the libraries needed to trace into a file.
#include
#include
// in T30, C headers are located at "E:\MQ\Tools\c\include" ...
#include "cmqc.h" // For MQI datatypes. And MQXQH !
#include "cmqxc.h" // For MQI exit-related definitions.
#if DO_DEBUG > 0
void Traza ( FILE * traceArchivo, char * Texto ) ;
void DumpMsg ( MQBYTE * pDato, int Max_Lng, FILE * Ostr ) ;
#define mTraza(MyArg1,MyArg2) \
Traza ( MyArg1, MyArg2 )
#else
#define mTraza(MyArg1,MyArg2)
#endif // debug : dont define the vars needed to trace into a file.
/********************************************************************/
/* Insert the function prototypes for the functions produced by */
/* the data conversion utility program. */
/********************************************************************/
void MQStart ( ) { ; } ;
void MQENTRY My_Exit (
PMQVOID mqcxpptr, /* Channel exit parameter block MQCXP in/out */
PMQVOID mqcdptr, /* Channel definition MQCD in/out */
PMQLONG inmsglngptr, /* Length of data in/out */
PMQLONG inbuflngptr, /* Length of agent buffer in */
PMQVOID inbufptr, /* Agent buffer MQXQH+data in/out */
PMQLONG outmsglngptr, /* Length of exit buffer in/out */
PMQPTR outbufptr ) /* Address of exit buffer in/out */
{
PMQCXP pMQCXPptr ; // channel exit parameter block pointer.
PMQCD pMQCDptr ; // channel definition structure pointer.
PMQXQH pMQXQHptr ; // transmission queue header pointer.
PMQBYTE pMsgData ; // message data pointer.
MQLONG MsgDataLength ; // message data length.
PMQBYTE pMsgDataEnd ; // message data end pointer.
PMQBYTE pMsgDataTmp ; // message data temporal pointer.
MQLONG LngDataTmp ; // message data intermediate length.
// MQCXP :
MQLONG MyMQCXP_StrucVersion = 0 ;
MQLONG MyMQCXP_ExitId = 0 ;
MQLONG MyMQCXP_ExitReason = 0 ;
// MQCD :
MQCHAR MyMQCD_ChannelName [ 20 ] = "\0" ; // Channel definition name.
MQLONG MyMQCD_StrucVersion = 0; // Structure version number.
MQLONG MyMQCD_ChannelType = 0 ; // Channel type.
// MQXQH :
MQLONG MyMQXQH_Version = 0 ; // Structure version number.
MQCHAR48 MyMQXQH_RemoteQName = "\0" ; // Name of destination queue.
MQCHAR48 MyMQXQH_RemoteQMgrName = "\0" ; // Name of destination queue manager.
MQCHAR8 MyMQMD_Format = "\0" ; // Message format (MQFMT_NONE, MQFMT_STRING).
MQBYTE24 MyMQMD_MsgId = "\0" ; // Message Identifier.
MQBYTE24 MyMQMD_CorrelId = "\0" ; // Correlation Identifier.
MQLONG MyMQMD_Report = 0 ; // Report options.
MQLONG MyMQMD_Encoding = 0 ; // Numbers encoding .
MQLONG MyMQMD_CodedCharSetId = 0 ; // Coded character set identifier.
#define CCSID_MVS500 500 // MVS Coded Character Set Id.
#define CCSID_850 850 // ASCII 850 Coded Character Set Id.
#define CCSID_819 819 // ASCII 819 Coded Character Set Id.
MQLONG MyMQMD_MsgType = 0 ; // Mesage type (Datagram, Request, Reply, Report).
MQLONG MyMQMD_Feedback = 0 ; // Feedback or reason code (MQMT_REPORT MsgType only).
MQCHAR48 MyMQMD_ReplyToQ = "\0" ; // "Reply To" Queue.
MQCHAR48 MyMQMD_ReplyToQMgr = "\0" ; // "Reply To" Queue Manager.
MQCHAR12 MyMQMD_UserIdentifier ; // User identifier in MQMD.
// Return codes from MVQTRXIT :
// MQMT_APPL_FIRST is 65535 ...
#define MyRC_1 65540 // MQCXP Struc Version < 2.
#define MyRC_2 65541 // MQCD Struc Version < 3.
#define MyRC_3 65542 // Not a Channel exit.
#define MyRC_4 65543 // Unknown Channel type (not SND, RCV, REQ, or SRV).
#if DO_DEBUG > 0
// Some aux vars :
char * Filename_Trace = "c:\\TEMP\\MSG_EXIT.TRC" ; // event trace file name.
FILE * Trace_log_stream ; // stream to write a log.
char * Separador = "=================================" ;
char * MyVersion = "MY_DLL.DLL trace, version 1.03 a, 15-Oct-04. PTFnone." ;
char MiDbg_Buffer [ 256 ] = "\0" ; // string concatenation buffer.
int cnt = 0 ; // sprintf return value.
struct timeb t;
#endif // debug : dont define the vars needed to trace into a file.
int mirc = 0 ; // my functions return code.
int i ;
PMQBYTE pMsgDataSource ; // to Modify the message ...
PMQBYTE pMsgDataDestination ;
int iMsgNuestro ; // el mensaje es nuestro ? ("AA0" in Codigo Formato Cabecera ?)
// char MiHeader_Format_Code [ 4 ] = "\0" ; // string concatenation buffer.
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++main++++++++++
pMQCXPptr = (MQCXP *) mqcxpptr ; // set MQCXP pointer.
#if DO_DEBUG > 0
Trace_log_stream = fopen ( Filename_Trace, "a" ) ; // open to APPEND !
mTraza ( Trace_log_stream, MyVersion ) ;
ftime ( & t ) ;
cnt = sprintf ( MiDbg_Buffer, "Time : (%ld.%d)", t.time, t.millitm ) ;
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
#endif // debug : dont open the file needed to trace into a file.
#if DO_DEBUG > 0
cnt = sprintf ( MiDbg_Buffer, "Param : MQCXP ptr (%li).", mqcxpptr ) ;
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
cnt = sprintf ( MiDbg_Buffer, "Param : MQCD ptr (%li).", mqcdptr ) ;
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
cnt = sprintf ( MiDbg_Buffer, "Param : Data Lng ptr (%li).", inmsglngptr ) ;
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
cnt = sprintf ( MiDbg_Buffer, "Param : Agent Buf Lng ptr (%li).", inbuflngptr ) ;
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
cnt = sprintf ( MiDbg_Buffer, "Param : Agent Buf ptr (%li).", inbufptr ) ;
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
cnt = sprintf ( MiDbg_Buffer, "Param : Exit Buf Lng ptr (%li).", outmsglngptr ) ;
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
cnt = sprintf ( MiDbg_Buffer, "Param : Exit Buf ptr (%li).", outbufptr ) ;
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
#endif // debug : dont write input parameters.
// Set pointers from calling parameters, and do type cast :
pMQCXPptr = (MQCXP *) mqcxpptr ; // set MQCXP pointer.
pMQCDptr = (MQCD *) mqcdptr ; // set MQCD pointer.
pMQXQHptr = (MQXQH *) inbufptr ; // set MQXQH pointer.
pMsgData = ((MQBYTE *)inbufptr) + sizeof(MQXQH) ;
MsgDataLength = (*inmsglngptr) - sizeof(MQXQH) ;
pMsgDataEnd = pMsgData + MsgDataLength ;
#if DO_DEBUG > 0
cnt = sprintf ( MiDbg_Buffer, "MQCXPptr is (%li), size is (%li).", pMQCXPptr, sizeof(MQCXP) ) ;
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
cnt = sprintf ( MiDbg_Buffer, "MQCDptr is (%li), size is (%li).", pMQCDptr, sizeof(MQCD) ) ;
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
cnt = sprintf ( MiDbg_Buffer, "MQXQHptr is (%li), size is (%li).", pMQXQHptr, sizeof(MQXQH) ) ;
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
cnt = sprintf ( MiDbg_Buffer, "MsgDataptr is (%li).", pMsgData ) ;
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
cnt = sprintf ( MiDbg_Buffer, "DataLng is (%i).", MsgDataLength ) ;
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
cnt = sprintf ( MiDbg_Buffer, "MsgDataEndptr is (%li).", pMsgDataEnd ) ;
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
#endif // debug : dont write deduced parameters.
// Get some MQCXP values :
if ( pMQCXPptr == 0 ) {
mTraza ( Trace_log_stream, "Error : null MQCXP pointer." ) ;
goto My_Common_End ;
} ;
MyMQCXP_StrucVersion = pMQCXPptr -> Version ;
MyMQCXP_ExitId = pMQCXPptr -> ExitId ;
MyMQCXP_ExitReason = pMQCXPptr -> ExitReason ;
// Get some MQCD values :
if ( pMQCDptr == 0 ) {
mTraza ( Trace_log_stream, "Error : null MQCD pointer." ) ;
goto My_Common_End ;
} ;
strncpy ( MyMQCD_ChannelName, pMQCDptr -> ChannelName, sizeof(pMQCDptr -> ChannelName) ) ;
MyMQCD_StrucVersion = pMQCDptr -> Version ;
MyMQCD_ChannelType = pMQCDptr -> ChannelType ;
#if DO_DEBUG > 0
cnt = sprintf ( MiDbg_Buffer, "Channel Name = (%.20s).", MyMQCD_ChannelName ) ;
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
#endif // debug : dont trace.
// Get some MQXQH values :
if ( pMQXQHptr != 0 ) {
mTraza ( Trace_log_stream, "Part get MQMD data." ) ;
MyMQXQH_Version = pMQXQHptr -> Version ;
strncpy ( MyMQXQH_RemoteQName, pMQXQHptr -> RemoteQName, sizeof(pMQXQHptr -> RemoteQName) ) ;
strncpy ( MyMQXQH_RemoteQMgrName, pMQXQHptr -> RemoteQMgrName, sizeof(pMQXQHptr -> RemoteQMgrName) ) ;
strncpy ( MyMQMD_Format, pMQXQHptr -> MsgDesc.Format, sizeof(pMQXQHptr -> MsgDesc.Format) ) ;
strncpy ( MyMQMD_MsgId, pMQXQHptr -> MsgDesc.MsgId, sizeof(pMQXQHptr -> MsgDesc.MsgId) ) ;
strncpy ( MyMQMD_CorrelId, pMQXQHptr -> MsgDesc.CorrelId, sizeof(pMQXQHptr -> MsgDesc.CorrelId) ) ;
MyMQMD_Report = pMQXQHptr -> MsgDesc.Report ;
MyMQMD_Encoding = pMQXQHptr -> MsgDesc.Encoding ;
MyMQMD_CodedCharSetId = pMQXQHptr -> MsgDesc.CodedCharSetId ;
MyMQMD_MsgType = pMQXQHptr -> MsgDesc.MsgType ;
MyMQMD_Feedback = pMQXQHptr -> MsgDesc.Feedback ;
strncpy ( MyMQMD_ReplyToQ,
pMQXQHptr -> MsgDesc.ReplyToQ,
sizeof(pMQXQHptr -> MsgDesc.ReplyToQ) ) ;
strncpy ( MyMQMD_ReplyToQMgr,
pMQXQHptr -> MsgDesc.ReplyToQMgr,
sizeof(pMQXQHptr -> MsgDesc.ReplyToQMgr) ) ;
strncpy ( MyMQMD_UserIdentifier,
pMQXQHptr -> MsgDesc.UserIdentifier,
sizeof(pMQXQHptr -> MsgDesc.UserIdentifier) ) ;
#if DO_DEBUG > 0
cnt = sprintf ( MiDbg_Buffer, "Destination Q = (%.48s).", MyMQXQH_RemoteQName ) ;
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
cnt = sprintf ( MiDbg_Buffer, "Destination Q Mgr = (%.48s).", MyMQXQH_RemoteQMgrName ) ;
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
cnt = sprintf ( MiDbg_Buffer, "Reply To Q = (%.48s).", MyMQMD_ReplyToQ ) ;
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
cnt = sprintf ( MiDbg_Buffer, "Reply To Q Mgr = (%.48s).", MyMQMD_ReplyToQMgr ) ;
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
cnt = sprintf ( MiDbg_Buffer, "User Identifier = (%.12s).", MyMQMD_UserIdentifier ) ;
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
cnt = sprintf ( MiDbg_Buffer, "MQXQH Format (%.8s).", MyMQMD_Format ) ;
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
cnt = sprintf ( MiDbg_Buffer, "MQXQH MsgId (%.24s).", MyMQMD_MsgId ) ;
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
cnt = sprintf ( MiDbg_Buffer, "MQXQH CorrelId (%.24s).", MyMQMD_CorrelId ) ;
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
cnt = sprintf ( MiDbg_Buffer, "MQXQH Report (%x).", MyMQMD_Report ) ;
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
if ( MyMQMD_Report & MQRO_PASS_MSG_ID ) {
mTraza ( Trace_log_stream, " PASS MSG ID." ) ;
} else {
mTraza ( Trace_log_stream, " NEW MSG ID." ) ;
} ;
if ( MyMQMD_Report & MQRO_PASS_CORREL_ID ) {
mTraza ( Trace_log_stream, " PASS CORREL ID." ) ;
} else {
mTraza ( Trace_log_stream, " COPY MSG ID TO CORREL ID." ) ;
} ;
if ( MyMQMD_Report & MQRO_COA ) {
mTraza ( Trace_log_stream, " COA requested." ) ;
} else {
mTraza ( Trace_log_stream, " COA not requested." ) ;
} ;
if ( MyMQMD_Report & MQRO_COD ) {
mTraza ( Trace_log_stream, " COD requested." ) ;
} else {
mTraza ( Trace_log_stream, " COD not requested." ) ;
} ;
if ( MyMQMD_Report & MQRO_EXCEPTION ) {
mTraza ( Trace_log_stream, " EXCEPTION requested." ) ;
} else {
mTraza ( Trace_log_stream, " EXCEPTION not requested." ) ;
} ;
if ( MyMQMD_Report & MQRO_EXPIRATION ) {
mTraza ( Trace_log_stream, " EXPIRATION requested." ) ;
} else {
mTraza ( Trace_log_stream, " EXPIRATION not requested." ) ;
} ;
cnt = sprintf ( MiDbg_Buffer, "MQXQH Encoding (%i).", MyMQMD_Encoding ) ;
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
if ( ( MyMQMD_Encoding & MQENC_INTEGER_MASK ) == MQENC_INTEGER_REVERSED ) {
mTraza ( Trace_log_stream, " Numbers encoding = Intel (reversed)." ) ;
} else {
if ( ( MyMQMD_Encoding & MQENC_INTEGER_MASK ) == MQENC_INTEGER_NORMAL ) {
mTraza ( Trace_log_stream, " Numbers encoding = Host-AIX (normal)." ) ;
} else {
mTraza ( Trace_log_stream, " Numbers encoding = Unknown." ) ;
} ;
} ;
cnt = sprintf ( MiDbg_Buffer, "MQXQH CCSID (%i).", MyMQMD_CodedCharSetId ) ;
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
cnt = sprintf ( MiDbg_Buffer, "MQXQH Msg Type (%i).", MyMQMD_MsgType ) ;
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
if ( MyMQMD_MsgType == MQMT_DATAGRAM ) {
mTraza ( Trace_log_stream, " Msg Type = Datagram." ) ;
} else {
if ( MyMQMD_MsgType == MQMT_REQUEST ) {
mTraza ( Trace_log_stream, " Msg Type = Request." ) ;
} else {
if ( MyMQMD_MsgType == MQMT_REPLY ) {
mTraza ( Trace_log_stream, " Msg Type = Reply." ) ;
} else {
if ( MyMQMD_MsgType == MQMT_REPORT ) {
mTraza ( Trace_log_stream, " Msg Type = Report." ) ;
} else {
mTraza ( Trace_log_stream, " Msg Type = Unknown." ) ;
} ;
} ;
} ;
} ;
cnt = sprintf ( MiDbg_Buffer, "MQXQH Feedback (%i).", MyMQMD_Feedback ) ;
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
if ( MyMQMD_Feedback == MQFB_NONE ) {
mTraza ( Trace_log_stream, " Feedback = None." ) ;
} else {
if ( MyMQMD_Feedback == MQFB_COA ) {
mTraza ( Trace_log_stream, " Feedback = COA." ) ;
} else {
if ( MyMQMD_Feedback == MQFB_COD ) {
mTraza ( Trace_log_stream, " Feedback = COD." ) ;
} else {
mTraza ( Trace_log_stream, " Feedback = Other. MQFB_APPL_FIRST = 65536." ) ;
} ;
} ;
} ;
#endif // debug : dont trace.
} ;
// Verify some values :
mTraza ( Trace_log_stream, "Part Verify Versions." ) ;
if ( MyMQCXP_StrucVersion < MQCXP_VERSION_2 ) {
pMQCXPptr -> ExitResponse = MQXCC_SUPPRESS_FUNCTION ; // indicate ERROR end.
pMQCXPptr -> Feedback = MyRC_1 ; // indicate some detail.
mTraza ( Trace_log_stream, "Error : MQCXP version." ) ;
goto My_Common_End ;
} ; /* endif */
if ( MyMQCD_StrucVersion < MQCD_VERSION_3 ) {
pMQCXPptr -> ExitResponse = MQXCC_SUPPRESS_FUNCTION ; // indicate ERROR end.
pMQCXPptr -> Feedback = MyRC_2 ; // indicate some detail.
mTraza ( Trace_log_stream, "Error : MQCD version." ) ;
goto My_Common_End ;
} ; /* endif */
if ( MyMQCXP_ExitId != MQXT_CHANNEL_MSG_EXIT ) {
pMQCXPptr -> ExitResponse = MQXCC_SUPPRESS_FUNCTION ; // indicate ERROR end.
pMQCXPptr -> Feedback = MyRC_3 ; // indicate some detail.
mTraza ( Trace_log_stream, "Error : not a channel msg exit." ) ;
goto My_Common_End ;
} ; /* endif */
if ( MyMQCXP_ExitReason == MQXR_INIT ) {
mTraza ( Trace_log_stream, "End : INIT entry." ) ;
goto My_Good_End ;
} ; /* endif */
if ( MyMQCXP_ExitReason == MQXR_TERM ) {
mTraza ( Trace_log_stream, "End : TERM entry." ) ;
goto My_Good_End ;
} ; /* endif */
// See MQXQH.MsgDesc.Format :
mTraza ( Trace_log_stream, "Part Ver MsgDesc-Format." ) ;
if ( strncmp ( MyMQMD_Format, MQFMT_NONE, sizeof(MyMQMD_Format) ) == 0 ) {
mTraza ( Trace_log_stream, "Work : NONE format." ) ;
} else {
if ( strncmp ( MyMQMD_Format, MQFMT_STRING, sizeof(MyMQMD_Format) ) == 0 ) {
mTraza ( Trace_log_stream, "Work : STRING format." ) ;
} else {
if ( strncmp ( MyMQMD_Format, "MQ", sizeof("MQ") ) == 0 ) {
mTraza ( Trace_log_stream, "End : MQ format." ) ;
goto My_Good_End ;
} else {
#if DO_DEBUG > 0
cnt = sprintf ( MiDbg_Buffer,
"Work : Other -> NONE format (%.8s).",
MyMQMD_Format ) ; // 131097.
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
#endif // debug : dont trace.
strncpy ( MyMQMD_Format, MQFMT_NONE, sizeof(pMQXQHptr -> MsgDesc.Format) ) ;
} ; /* endif */
} ; /* endif */
} ; /* endif */
mTraza ( Trace_log_stream, "Part see Channel Type." ) ;
switch ( MyMQCD_ChannelType ) {
case MQCHT_SENDER :
// *******************
mTraza ( Trace_log_stream, "Work : SND channel type." ) ;
// Display OLD message.
#if DO_DEBUG > 0
DumpMsg ( pMsgData, MsgDataLength, Trace_log_stream ) ;
#endif // debug : dont display msg.
// UserID comes right after MD and is 8 chars long (Host User Id size).
#define LngMsg2Delete 8
#define Shift2Delete 0
// Copy UserID from message into own area, then to MD.
memset ( MyMQMD_UserIdentifier, '\0', sizeof(MyMQMD_UserIdentifier) ) ;
strncpy ( MyMQMD_UserIdentifier, pMsgData, LngMsg2Delete ) ;
strncpy ( pMQXQHptr -> MsgDesc.UserIdentifier,
MyMQMD_UserIdentifier,
sizeof(pMQXQHptr -> MsgDesc.UserIdentifier) ) ;
// +++ FIX02
// assign "iMsgNuestro" := 1 if "AA0" in Header Format Code :
iMsgNuestro = 0 ; // not ours unless verified
// memset ( MiHeader_Format_Code, '\0', sizeof(MiHeader_Format_Code) ) ;
// Header Format Code comes after MsgStart plus :
// 8(user), 2(lng), 2(reserved), 8(IMS code), 1(separator) ... total 21.
#define Shift2HFC 21
// #define LngMsgHFC2Copy 3
#define LngMsgHFC2Cmp 3
pMsgDataSource = pMsgData + Shift2HFC ;
// strncpy ( pMsgDataSource,
// MiHeader_Format_Code,
// LngMsgHFC2Copy ) ;
if ( strncmp ( pMsgDataSource,
"AA0",
LngMsgHFC2Cmp ) == 0 ) {
iMsgNuestro = 1 ; // our code is present in Header.
} ;
// --- FIX02
// Modify the message inplace (if it is a Request or a Datagram) + ours
// Reflect changes in DataLength !
if (
(
( MyMQMD_MsgType == MQMT_REQUEST )
||
( MyMQMD_MsgType == MQMT_DATAGRAM )
)
&&
( MsgDataLength > LngMsg2Delete )
&&
( MsgDataLength >= Shift2Delete + LngMsg2Delete )
&&
( iMsgNuestro == 1 )
) {
pMsgDataSource = pMsgData + Shift2Delete + LngMsg2Delete ;
pMsgDataDestination = pMsgData + Shift2Delete ;
i = MsgDataLength - ( LngMsg2Delete + Shift2Delete ) ;
while ( i > 0 ) {
( * pMsgDataDestination ) = ( * pMsgDataSource ) ;
pMsgDataSource ++ ;
pMsgDataDestination ++ ;
i -- ;
} ; /* endwhile */
( * pMsgDataDestination ) = '\0' ;
MsgDataLength = MsgDataLength - LngMsg2Delete ;
(*inmsglngptr) = MsgDataLength + sizeof(MQXQH) ;
} ; /* endif */
// Display NEW message.
#if DO_DEBUG > 0
DumpMsg ( pMsgData, MsgDataLength, Trace_log_stream ) ;
#endif // debug : dont display msg.
goto My_Good_End ;
break ;
case MQCHT_RECEIVER :
// *********************
mTraza ( Trace_log_stream, "Work : RCV channel type." ) ;
// Debug only : see input msg, Rcv.
#if DO_DEBUG > 0
DumpMsg ( pMsgData, MsgDataLength, Trace_log_stream ) ;
#endif // debug : dont display msg.
goto My_Good_End ;
break ;
case MQCHT_SERVER :
mTraza ( Trace_log_stream, "No work : SRV channel type." ) ;
goto My_Good_End ;
break ;
case MQCHT_REQUESTER :
mTraza ( Trace_log_stream, "No work : REQ channel type." ) ;
goto My_Good_End ;
break ;
default :
pMQCXPptr -> ExitResponse = MQXCC_SUPPRESS_FUNCTION ; // indicate ERROR end.
pMQCXPptr -> Feedback = MyRC_4 ; // indicate some detail.
#if DO_DEBUG > 0
cnt = sprintf ( MiDbg_Buffer, "MQCD channel type (%i) unknown.", MyMQCD_ChannelType ) ;
mTraza ( Trace_log_stream, MiDbg_Buffer ) ;
#endif // debug : dont trace.
goto My_Common_End ;
break ;
} ; /* endswitch */
My_Good_End:
#if DO_DEBUG > 0
mTraza ( Trace_log_stream, "Part Good End." ) ;
#endif // debug : dont close the file needed to trace into a file.
pMQCXPptr -> ExitResponse = MQXCC_OK ; // indicate OK end.
pMQCXPptr -> ExitResponse2 = MQXR2_USE_AGENT_BUFFER ; // indicate OK end.
My_Common_End:
#if DO_DEBUG > 0
mTraza ( Trace_log_stream, "End of the trace." ) ;
mTraza ( Trace_log_stream, Separador ) ;
fclose ( Trace_log_stream ) ;
#endif // debug : dont close the file needed to trace into a file.
return ;
} ; // end of MsgExit.
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#if DO_DEBUG > 0
void DumpMsg ( MQBYTE * pDato, int Max_Lng, FILE * Ostr )
{
char aux [ 3 ] ;
int cnt = 0 ; // sprintf return value.
int i ;
char DmpTxt_Buffer [ 256 ] ; // string concatenation buffer
cnt = fprintf ( Ostr, "Dump (%i) chars from (%li).\n", Max_Lng, pDato ) ;
DmpTxt_Buffer [ 0 ] = '\0';
for ( i = 0 ; i < Max_Lng ; i++ ) {
sprintf ( aux, "%2.2x", pDato [ i ] ) ;
strcat ( DmpTxt_Buffer, aux ) ;
if ( i < Max_Lng -1 ) {
strcat ( DmpTxt_Buffer, "-" ) ;
} ; /* endif */
if ( strlen ( DmpTxt_Buffer ) >= 60 ) {
strcat ( DmpTxt_Buffer, "\n" ) ;
cnt = fprintf ( Ostr, DmpTxt_Buffer ) ; /* output to file */
DmpTxt_Buffer [ 0 ] = '\0';
} /* endif */
} ; /* endfor */
if ( strlen ( DmpTxt_Buffer ) > 0 ) {
strcat ( DmpTxt_Buffer, "\n" ) ;
cnt = fprintf ( Ostr, DmpTxt_Buffer ) ; /* output (remaining) to file */
} ;
} ;
#endif // debug : dont display msg.
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#if DO_DEBUG > 0
void Traza ( FILE * traceArchivo, char * Texto )
{
char MiTime [ 64 ] ; // used by _strtime
char MiTxt_Buffer [ 256 ] ; // string concatenation buffer
int cnt ; // sprintf return value
time_t mvqtime_t ;
struct tm * tmptr ;
int len ;
time ( & mvqtime_t ) ;
tmptr = localtime ( & mvqtime_t ) ;
strcpy ( MiTime, asctime ( tmptr ) ) ;
len = strlen ( MiTime ) ;
MiTime [ len -1 ] = '\0' ; // remove CR
cnt = sprintf ( MiTxt_Buffer, "(%s) %s\n", MiTime, Texto ) ;
cnt = fprintf ( traceArchivo, MiTxt_Buffer ) ; /* output to file */
fflush ( traceArchivo ) ;
} ; // end of TRAZA.
#endif // debug : dont generate the code needed to trace into a file.
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++