1
votes

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?

1
What is the Format of the MQMD?JoshMc
@JoshMc, MQFMT_RF_HEADER_2HighPredator
Have you tried setting CodedCharSetId also to 1208?JoshMc
@JoshMc, yes I did. Same error.HighPredator
I added contents of descriptorHighPredator

1 Answers

2
votes

The short answer to your question is you will need to set the length if you create the RFH2 header in the above fashion. The RFH2 header can vary in length. The default length will be MQRFH_STRUC_LENGTH_FIXED_2.

Regarding why it doesn't display properly I don't have a good understanding of why that might be.

I would recommend some RFH2 code samples for you to review. These samples can be found in your installation directory, for example: C:\Program Files\IBM\WebSphere MQ\Tools\c\Samples\pubsub\amqsgr2a.c. The samples in the pubsub directory have build RFH2 header functions. In these examples the length is explicitly set. They take a slightly different approach than you when it comes to obtaining and initializing storage.

There is also the MQSETMP api, that I believe can be used to modify the RFH2 header. This api may also maintain and set the length for you in the RFH2 header. I haven't been able to find examples of its usage.

Hope this helps.