I am trying to put a message with an RFH2 header in a queue using MQPUT function. Said function returns completion code 2 and reason 2142 which according to IBM docs means that header structure is not valid. Docs on this link specify the fields that need to be checked. Header and message descriptor have following contents:
MQMD:
StrucId = 'MD '
Version = 2
Report = 0
MsgType = 8
Expiry = -1
Feedback = 0
Encoding = 273
CodedCharSetId = 1208
Format = 'MQHRF2 '
Priority = -1
Persistence = 2
MsgId = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
CorrelId = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
BackoutCount = 0
ReplyToQ = ''
ReplyToQMgr = ''
UserIdentifier = ''
AccountingToken = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ApplIdentityData = ''
PutApplType = 0
PutApplName = ''
PutDate = ''
PutTime = ''
ApplOriginData = ''
GroupId = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
MsgSeqNumber = 1
Offset = 0
MsgFlags = 0
OriginalLength = -1
MQRFH2:
StrucId = 'RFH '
Version = 2
StrucLength = 128
Encoding = 273
CodedCharSetId = 0
Format = 'MQSTR '
Flags = 0
NameValueCCSID = 1208
I fail to understand how come the header is invalid and how do I fix this. Thanks in advance.
int SendMessage(PMQHCONN connectionDescriptorPtr, PMQHOBJ queueDescriptorPtr, const char* payload, const char* message)
{
MQLONG completionResult;
MQLONG reason;
unsigned char* buffer = NULL;
PMQRFH2 pHeader;
PMQINT32 pNameValueLength;
PMQCHAR pNameValueData;
PMQCHAR pMessage;
PMQCHAR p;
MQLONG bufferLength;
MQLONG structLength;
MQLONG nameValueLength;
size_t payloadLength = strlen(payload);
size_t messageLength = strlen(message);
size_t sizeOfLength = sizeof(MQINT32);
size_t headerStructLength = MQRFH_STRUC_LENGTH_FIXED_2;
size_t padding = CalcPadding(payload);
size_t i;
/* mqmd */
MQMD md = {MQMD_DEFAULT};
MQPMO pmo = {MQPMO_DEFAULT};
structLength = (MQLONG) (headerStructLength + sizeOfLength + payloadLength + padding);
/* calc total buffer length */
bufferLength = (MQLONG) (headerStructLength + sizeOfLength + payloadLength + padding + messageLength);
printf("Lengths:\n"
" Header:\n"
" structure : %zu\n"
" length field : %zu\n"
" payload : length = %zu, padding = %zu (total: %zu)\n"
" Total : %d\n"
" Message : %zu\n"
"Total : %d\n",
headerStructLength,
sizeOfLength,
payloadLength, padding, payloadLength + padding,
structLength,
messageLength,
bufferLength
);
buffer = malloc((size_t) bufferLength);
/* setting up payload */
nameValueLength = (MQLONG) payloadLength;
pNameValueData = (PMQCHAR) (buffer + MQRFH_STRUC_LENGTH_FIXED_2 + sizeOfLength);
memcpy(pNameValueData, payload, (size_t) nameValueLength);
p = pNameValueData + nameValueLength;
for (i = 0; i < padding; i++)
{
*p = ' ';
p++;
nameValueLength++;
}
/* setting up valueLength */
pNameValueLength = (PMQINT32) (buffer + MQRFH_STRUC_LENGTH_FIXED_2);
*pNameValueLength = nameValueLength;
/* setting up message */
pMessage = pNameValueData + nameValueLength;
memcpy(pMessage, message, messageLength);
/* setting up header */
pHeader = (PMQRFH2) buffer;
memcpy(pHeader, &DefaultHeader, MQRFH_STRUC_LENGTH_FIXED_2);
memcpy(pHeader->Format, MQFMT_STRING, MQ_FORMAT_LENGTH);
pHeader->CodedCharSetId = MQCCSI_INHERIT;
pHeader->NameValueCCSID = 1208;
pHeader->StrucLength = (MQLONG) (headerStructLength + sizeOfLength + nameValueLength); /* !!! */
/* seeting up for put */
memcpy(md.Format, MQFMT_RF_HEADER_2, MQ_FORMAT_LENGTH);
md.MsgType = MQMT_DATAGRAM;
md.Persistence = MQPER_PERSISTENT;
pmo.Options = pmo.Options | MQPMO_NEW_MSG_ID | MQPMO_NO_SYNCPOINT;
MQPUT(*connectionDescriptorPtr, *queueDescriptorPtr, &md, &pmo, bufferLength, buffer, &completionResult, &reason);
free(buffer);
printf("Message put in queue with code %d and reason %d\n", completionResult, reason);
return 0;
}
I use the code above to setup the buffer to be sent. The problem was narrowed down to the following cases:
1) if I DO NOT set the StrucLength field in header (line with !!!), message is being successfully put in queue and carries the correct format and data that can be read in message browser
2) if I DO set the field calculated correctly like in the code, the message is put in queue, but is displayed as MQSTR message type with no MQRFH2 header data
3) if I DO set the field calculated INCORRECTLY, then I get the 2142 reason code, which apparently was the source of the problem in the first place.
Now all of this has led me to a question: Am I not supposed to populate the StrucLength field manually if I put messages?