430 lines
12 KiB
C++
430 lines
12 KiB
C++
/***********************************************************************
|
|
*
|
|
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; version 2.1
|
|
* of the License.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, Novell, Inc.
|
|
*
|
|
* To contact Novell about this file by physical or electronic mail,
|
|
* you may find current contact information at www.novell.com.
|
|
*
|
|
* Author: Juan Carlos Luciani <jluciani@novell.com>
|
|
*
|
|
***********************************************************************/
|
|
|
|
|
|
//===[ Include files ]=====================================================
|
|
|
|
#define __STDC_LIMIT_MACROS
|
|
#include "ipcint.h"
|
|
|
|
//===[ External data ]=====================================================
|
|
|
|
//===[ External prototypes ]===============================================
|
|
|
|
//===[ Manifest constants ]================================================
|
|
|
|
//===[ Type definitions ]==================================================
|
|
|
|
//===[ Function prototypes ]===============================================
|
|
|
|
//===[ Global variables ]==================================================
|
|
|
|
// Channel Packet Types
|
|
string DataCarrierTypeTemplate = "TypeXX";
|
|
string ReqDataCarrierType = "Type01";
|
|
string ReqErrorCarrierType = "Type02";
|
|
|
|
// Channel Packet Headers
|
|
string ReqIdHdr = "ReqIdHdr =";
|
|
string PayloadLengthHdr = "PayloadLength =";
|
|
|
|
// Req Data Pkt Hdr Template
|
|
string ReqDataPktHdrTemplate = "Type01\r\nReqIdHdr =XXXXXXXX\r\nPayloadLength =XXXXXXXX\r\n\r\n";
|
|
|
|
// Req Error Pkt Hdr Template
|
|
string ReqErrorPktHdrTemplate = "Type02\r\nReqIdHdr =XXXXXXXX\r\nPayloadLength =XXXXXXXX\r\n\r\n";
|
|
|
|
|
|
//++=======================================================================
|
|
int
|
|
ChannelProto::buildReqDataPktHdr(
|
|
uint32_t reqId,
|
|
uint32_t payloadLength,
|
|
char *pPktHdr)
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Abstract:
|
|
//
|
|
// Notes: pPktHdr must point to a buffer of size ReqDataPktHdrTemple.length().
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
int retStatus = -1;
|
|
|
|
DbgTrace(1, "ChannelProto::buildReqDataPktHdr- Start\n", 0);
|
|
|
|
try {
|
|
// - Req Data Packet Header Format -
|
|
//
|
|
// ReqDataCarrierType
|
|
// ReqIdHdr value (value format=%08X)
|
|
// PayloadLengthHdr value (value format=%08X)
|
|
//
|
|
|
|
// Setup the necessary value strings
|
|
char wrkBuffer[10];
|
|
|
|
sprintf(wrkBuffer, "%08X", reqId);
|
|
string reqIdValue = wrkBuffer;
|
|
sprintf(wrkBuffer, "%08X", payloadLength);
|
|
string payloadLengthValue = wrkBuffer;
|
|
|
|
// Format the header.
|
|
char* pCurr = pPktHdr;
|
|
|
|
memcpy(pCurr, ReqDataCarrierType.c_str(), ReqDataCarrierType.length());
|
|
pCurr += ReqDataCarrierType.length();
|
|
memcpy(pCurr, "\r\n", 2);
|
|
pCurr += 2;
|
|
|
|
memcpy(pCurr, ReqIdHdr.c_str(), ReqIdHdr.length());
|
|
pCurr += ReqIdHdr.length();
|
|
memcpy(pCurr, reqIdValue.c_str(), reqIdValue.length());
|
|
pCurr += reqIdValue.length();
|
|
memcpy(pCurr, "\r\n", 2);
|
|
pCurr += 2;
|
|
|
|
memcpy(pCurr, PayloadLengthHdr.c_str(), PayloadLengthHdr.length());
|
|
pCurr += PayloadLengthHdr.length();
|
|
memcpy(pCurr, payloadLengthValue.c_str(), payloadLengthValue.length());
|
|
pCurr += payloadLengthValue.length();
|
|
memcpy(pCurr, "\r\n\r\n", 4);
|
|
|
|
// Success
|
|
retStatus = 0;
|
|
}
|
|
catch (...) {
|
|
DbgTrace(0, "ChannelProto::buildReqDataPktHdr- Exception caught while creating header\n", 0);
|
|
}
|
|
|
|
DbgTrace(1, "ChannelProto::buildReqDataPktHdr- End, retStatus = %0X\n", retStatus);
|
|
|
|
return retStatus;
|
|
|
|
} /*-- ChannelProto::buildReqDataPktHdr() --*/
|
|
|
|
|
|
//++=======================================================================
|
|
int
|
|
ChannelProto::buildReqErrorPktHdr(
|
|
uint32_t reqId,
|
|
uint32_t payloadLength,
|
|
char *pPktHdr)
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Abstract:
|
|
//
|
|
// Notes: pPktHdr must point to a buffer of size ReqErrorPktHdrTemple.length().
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
int retStatus = -1;
|
|
|
|
DbgTrace(1, "ChannelProto::buildReqErrorPktHdr- Start\n", 0);
|
|
|
|
try {
|
|
// - Req Error Packet Header Format -
|
|
//
|
|
// ReqErrorCarrierType
|
|
// ReqIdHdr value (value format=%08X)
|
|
// PayloadLengthHdr value (value format=%08X)
|
|
//
|
|
|
|
// Setup the necessary value strings
|
|
char wrkBuffer[10];
|
|
|
|
sprintf(wrkBuffer, "%08X", reqId);
|
|
string reqIdValue = wrkBuffer;
|
|
sprintf(wrkBuffer, "%08X", payloadLength);
|
|
string payloadLengthValue = wrkBuffer;
|
|
|
|
// Format the header.
|
|
char* pCurr = pPktHdr;
|
|
|
|
memcpy(pCurr, ReqErrorCarrierType.c_str(), ReqErrorCarrierType.length());
|
|
pCurr += ReqErrorCarrierType.length();
|
|
memcpy(pCurr, "\r\n", 2);
|
|
pCurr += 2;
|
|
|
|
memcpy(pCurr, ReqIdHdr.c_str(), ReqIdHdr.length());
|
|
pCurr += ReqIdHdr.length();
|
|
memcpy(pCurr, reqIdValue.c_str(), reqIdValue.length());
|
|
pCurr += reqIdValue.length();
|
|
memcpy(pCurr, "\r\n", 2);
|
|
pCurr += 2;
|
|
|
|
memcpy(pCurr, PayloadLengthHdr.c_str(), PayloadLengthHdr.length());
|
|
pCurr += PayloadLengthHdr.length();
|
|
memcpy(pCurr, payloadLengthValue.c_str(), payloadLengthValue.length());
|
|
pCurr += payloadLengthValue.length();
|
|
memcpy(pCurr, "\r\n\r\n", 4);
|
|
|
|
// Success
|
|
retStatus = 0;
|
|
}
|
|
catch (...) {
|
|
DbgTrace(0, "ChannelProto::buildReqErrorPktHdr- Exception caught while creating header\n", 0);
|
|
}
|
|
|
|
DbgTrace(1, "ChannelProto::buildReqErrorPktHdr- End, retStatus = %0X\n", retStatus);
|
|
|
|
return retStatus;
|
|
|
|
} /*-- ChannelProto::buildReqErrorPktHdr() --*/
|
|
|
|
|
|
//++=======================================================================
|
|
ChannelProto::PacketTypes
|
|
ChannelProto::getPktType(
|
|
char &buff,
|
|
int hdrLength)
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Abstract:
|
|
//
|
|
// Notes:
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
PacketTypes packetType = UnknownPacketType;
|
|
|
|
DbgTrace(1, "ChannelProto::getPktType- Start\n", 0);
|
|
|
|
// Find the end of the Channel Packet Type
|
|
char *pCurr = &buff;
|
|
int bytesLeft = hdrLength;
|
|
bool endFound = false;
|
|
while (bytesLeft)
|
|
{
|
|
if (*pCurr == '\r')
|
|
{
|
|
endFound = true;
|
|
break;
|
|
}
|
|
|
|
pCurr ++;
|
|
bytesLeft --;
|
|
}
|
|
|
|
if (endFound)
|
|
{
|
|
// Found the end of the Channel Packet Type, now
|
|
// calculate its length.
|
|
int channelPktTypeLength = pCurr - &buff;
|
|
|
|
// Now start comparing
|
|
if (channelPktTypeLength == ReqDataCarrierType.length()
|
|
&& !memcmp(&buff, ReqDataCarrierType.c_str(), channelPktTypeLength))
|
|
{
|
|
// The type is Channel Req Data Carrier
|
|
packetType = ReqDataCarrierPacketType;
|
|
}
|
|
else if (channelPktTypeLength == ReqErrorCarrierType.length()
|
|
&& !memcmp(&buff, ReqErrorCarrierType.c_str(), channelPktTypeLength))
|
|
{
|
|
// The type is Channel Req Error Carrier
|
|
packetType = ReqErrorCarrierPacketType;
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "ChannelProto::getPktType- No match found\n", 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "ChannelProto::getPktType- Invalid header\n", 0);
|
|
}
|
|
|
|
DbgTrace(1, "ChannelProto::getPktType- End, type = %d\n", packetType);
|
|
|
|
return packetType;
|
|
|
|
} /*-- ChannelProto::getPktType() --*/
|
|
|
|
|
|
//++=======================================================================
|
|
bool
|
|
ChannelProto::getReqIdAndPayloadLength(
|
|
char *pBuff,
|
|
int hdrLength,
|
|
uint32_t *pReqId,
|
|
uint32_t *pPayloadLength)
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Abstract:
|
|
//
|
|
// Notes:
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
bool reqIdObtained = false;
|
|
bool payloadLengthObtained = false;
|
|
|
|
DbgTrace(1, "ChannelProto::getReqIdAndPayloadLength- Start\n", 0);
|
|
|
|
char *pCurr = pBuff;
|
|
char *pChannelHdr = NULL;
|
|
int bytesLeft = hdrLength;
|
|
|
|
// Skip the Channel Packet Type which should always
|
|
// be the first header.
|
|
while (bytesLeft >= 2)
|
|
{
|
|
if (*pCurr == '\r'
|
|
&& *(pCurr+1) == '\n')
|
|
{
|
|
// Found the end of the channel packet type
|
|
pCurr += 2;
|
|
bytesLeft -= 2;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
pCurr ++;
|
|
bytesLeft --;
|
|
}
|
|
}
|
|
|
|
// Start processing Channel Packet Headers
|
|
pChannelHdr = pCurr;
|
|
while (bytesLeft >= 2
|
|
&& (!reqIdObtained || !payloadLengthObtained))
|
|
{
|
|
if (*pCurr == '\r'
|
|
&& *(pCurr+1) == '\n')
|
|
{
|
|
// Found the end of the current channel header
|
|
pCurr += 2;
|
|
bytesLeft -= 2;
|
|
|
|
// Check if the line is empty or if it contained a
|
|
// channel header.
|
|
if ((pCurr - pChannelHdr) == 2)
|
|
{
|
|
// This was an empty line, which means that
|
|
// we reached the end of the channel packet header.
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
// Check if the header is the Req Id Hdr
|
|
if (!reqIdObtained && (pCurr - pChannelHdr) > ReqIdHdr.length()
|
|
&& !memcmp(pChannelHdr, ReqIdHdr.c_str(), ReqIdHdr.length()))
|
|
{
|
|
// We found the Req Id Hdr, get the value.
|
|
char *pValue = pChannelHdr + ReqIdHdr.length();
|
|
|
|
// Temporarily NULL terminate the value
|
|
*(pCurr-2) = '\0';
|
|
|
|
// Convert the value to hex
|
|
errno = 0;
|
|
unsigned long int value = strtoul(pValue, NULL, 16);
|
|
if (errno != 0
|
|
|| value > UINT32_MAX)
|
|
{
|
|
DbgTrace(0, "ChannelProto::getReqIdAndPayloadLength- Invalid reqId value, %s\n", pValue);
|
|
break;
|
|
}
|
|
|
|
// Use the value
|
|
*pReqId = (uint32_t) value;
|
|
|
|
// Undo the damage that we did
|
|
*(pCurr-2) = '\r';
|
|
|
|
// Remember that the Req Id was obtained
|
|
reqIdObtained = true;
|
|
}
|
|
// Check if the header is the Payload Length Hdr
|
|
else if ((pCurr - pChannelHdr) > PayloadLengthHdr.length()
|
|
&& !memcmp(pChannelHdr, PayloadLengthHdr.c_str(), PayloadLengthHdr.length()))
|
|
{
|
|
// We found the Payload Length Hdr, get the value.
|
|
char *pValue = pChannelHdr + PayloadLengthHdr.length();
|
|
|
|
// Temporarily NULL terminate the value
|
|
*(pCurr-2) = '\0';
|
|
|
|
// Convert the value to hex
|
|
errno = 0;
|
|
unsigned long int value = strtoul(pValue, NULL, 16);
|
|
if (errno != 0
|
|
|| value > UINT32_MAX)
|
|
{
|
|
DbgTrace(0, "ChannelProto::getReqIdAndPayloadLength- Invalid payloadLength value, %s\n", pValue);
|
|
break;
|
|
}
|
|
|
|
// Use the value
|
|
*pPayloadLength = (uint32_t) value;
|
|
|
|
// Undo the damage that we did
|
|
*(pCurr-2) = '\r';
|
|
|
|
// Remember that the Payload Lenght was obtained
|
|
payloadLengthObtained = true;
|
|
}
|
|
|
|
// Get set to process the next header
|
|
pChannelHdr = pCurr;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pCurr ++;
|
|
bytesLeft --;
|
|
}
|
|
}
|
|
|
|
DbgTrace(1,
|
|
"ChannelProto::getReqIdAndPayloadLength- End, retStatus = %0X\n",
|
|
reqIdObtained && payloadLengthObtained);
|
|
|
|
return reqIdObtained && payloadLengthObtained;
|
|
|
|
} /*-- ChannelProto::getReqIdAndPayloadLength() --*/
|
|
|
|
|
|
//=========================================================================
|
|
//=========================================================================
|
|
|
|
|