📄 cm_targt.c
字号:
case CI_LOGICAL_SEG_INSTANCE | CI_LOGICAL_SEG_8_BIT:
/*
** 8 bit instance segment.
*/
psConnRecord->sPublic.iInstance = *( (UINT8*)(pbPath + 1) );
iSegSize = 1;
break;
case CI_LOGICAL_SEG_INSTANCE | CI_LOGICAL_SEG_16_BIT:
/*
** 16 bit instance segment.
*/
psConnRecord->sPublic.iInstance = UC_iLeTOi( *( (UINT16*)(pbPath + 2) ) );
iSegSize = 2;
break;
default:
/*
** Unknown segment. Force a bail out with an error.
*/
psConnRecord->sPublic.bGRC = CI_GRC_FAILURE;
psConnRecord->sPublic.iERC = CM_ERC_BAD_SEGMENT;
iSegSize = iSize;
break;
}
break;
case CI_DATA_SEGMENT:
/*
** Data segment.
*/
psConnRecord->sPublic.bDataSegSize = *(pbPath + 1);
psConnRecord->sPublic.pLeDataSeg = (void*)(pbPath + 2);
iSegSize = *(pbPath + 1) + 1;
break;
case CI_NETWORK_SEGMENT:
if( ( CD_s[ psConnRecord->sPublic.iPort ].fUsesScheduleSegs ) && ( !fHaveNetSegment ) )
{
/*
** The port that this message arrived on can use network segments.
** (Must be ControlNet or a similar network.)
** So, grab a net-segment to use for producing data on this port.
*/
fHaveNetSegment = TRUE; /* Only one net-segment is needed, pass others on. */
switch( *pbPath )
{
case CI_NETWORK_SEGMENT | CI_NETWORK_SEG_SCHEDULE:
/*
** Schedule segment.
** Unpack the rate and start NUT.
*/
iSegSize = 1; /*!!NOTE!! Find out why this can't be after cm_UnpackSchedule */
if( *(pbPath + 1) == 0 )
{
/*
** Invalid Net Segment. Force a bail out with an error.
*/
psConnRecord->sPublic.bGRC = CI_GRC_FAILURE;
psConnRecord->sPublic.iERC = CM_ERC_BAD_NET_SEGMENT;
iSegSize = iSize;
}
else
{
cm_UnpackSchedule( psConnRecord, *(pbPath + 1) );
}
break;
#ifdef CD_EN_OBJECTS
case CI_NETWORK_SEGMENT | CI_NETWORK_SEG_PROD_INHIBIT:
/*
** Production inhibit segment.
*/
psConnRecord->sPublic.lProInhib = *(pbPath + 1);
/*
** The production inhibit segment is specified in milliseconds, all
** other timing is done in microseconds. Convert it here to
** be consistent throughout the EML
*/
psConnRecord->sPublic.lProInhib *= 1000;
/* Production inhibit time must be larger than RPI */
if ( psConnRecord->sPublic.lProApi < psConnRecord->sPublic.lProInhib)
{
psConnRecord->sPublic.bGRC = CI_GRC_FAILURE;
psConnRecord->sPublic.iERC = CM_ERC_BAD_RPI;
}
iSegSize = iSize;
break;
#endif
default:
/*
** Unknown segment. Force a bail out with an error.
*/
psConnRecord->sPublic.bGRC = CI_GRC_FAILURE;
psConnRecord->sPublic.iERC = CM_ERC_BAD_SEGMENT;
iSegSize = iSize;
break;
}
break;
}
else
{
/*
** A Network segment has been detected that
** could only be usefull for a bridged message.
**
** However, this device cannot do bridging.
** So force a bail out with an error.
*/
psConnRecord->sPublic.bGRC = CI_GRC_FAILURE;
psConnRecord->sPublic.iERC = CM_ERC_BAD_SEGMENT;
iSegSize = iSize;
break;
}
default:
/*
** Unknown segment. Force a bail out with an error.
*/
psConnRecord->sPublic.bGRC = CI_GRC_FAILURE;
psConnRecord->sPublic.iERC = CM_ERC_BAD_SEGMENT;
iSegSize = iSize;
break;
}
/*
** Bump the parsing pointer and remaining size counter.
*/
pbPath += iSegSize << 1;
iSize -= iSegSize;
}
/*
** Done parsing. The remaining size should be 0 (or greater than 0 if bridging).
** Complain if it isn't.
*/
if( iSize < 0 )
{
psConnRecord->sPublic.bGRC = CI_GRC_PARTIAL_DATA;
goto BailOut;
}
/*
** If port needed a schedule segment, make sure we found one
*/
if( ( CD_s[ psConnRecord->sPublic.iPort ].fUsesScheduleSegs )
&& ( !fHaveNetSegment )
&& ( ( psConnRecord->sPublic.bClassTrigger & CM_TCT_CLASS_MASK ) == CM_TCT_CLASS_1 )
&& ( !CM_IsConnectionTypeNull( &( psConnRecord->sPublic ) ) ) )
{
psConnRecord->sPublic.bGRC = CI_GRC_FAILURE;
psConnRecord->sPublic.iERC = CM_ERC_BAD_SEGMENT;
goto BailOut;
}
/*
** Validate the electronic key if we found one.
*/
cm_ValidateKey( psConnRecord );
/*
** Initialize the transport related information in the connection record.
*/
BailOut:
psConnRecord->sPublic.xQid = GS_NO_QUEUE;
psConnRecord->sPublic.iConTransportId =
psConnRecord->sPublic.iProTransportId = 0;
/*
** Shrink the Combuf by the ammount of data consumed.
**
** If not bridging the combuf will look empty.
** If bridging, it will contain the remaining path.
** In either case, we may still use the data in the comBuf
** during the remainder of establishing the connection.
*/
CB_ShrinkComBuf( pComBuf, ( (iStartingSize - iSize) << 1 ) );
} /* end of cm_ParseFwdOpen() */
/*---------------------------------------------------------------------------
** cm_ProcessAppClose()
**---------------------------------------------------------------------------
*/
void cm_ProcessAppClose( CM_AppOpenCloseTrrblType *pTrrbl )
{
CB_ComBufType *pComBuf;
cm_ConnectionRecordType *psConnRecord;
/*
** Get the connection record pointer & toss the tribble.
*/
psConnRecord = cm_GetPrivateRecord( pTrrbl->psConnRecord );
GS_DeleteTrrbl( pTrrbl );
/*
** If the app returned an empty combuf, build a word aligned zero length
** data segment in it before going any further.
*/
if( psConnRecord->pTrrblFC != NULL )
{
pComBuf = psConnRecord->pTrrblFC->pComBuf;
if( ( pComBuf != NULL ) && ( CB_GetDataSizeComBuf( pComBuf ) == 0 ) )
{
CB_ClearAndExpandComBuf( pComBuf, 2 );
*( (UINT16*)CB_GetDataPtrComBuf( pComBuf ) ) = 0;
}
}
/*
** Note that we've received the response and continue processing.
*/
psConnRecord->iSteps |= CM_PS_AC_RETURNED;
cm_ContinueProcessing( psConnRecord );
} /* end of cm_ProcessAppClose() */
/*---------------------------------------------------------------------------
** cm_ProcessAppOpen()
**---------------------------------------------------------------------------
*/
void cm_ProcessAppOpen( CM_AppOpenCloseTrrblType *pTrrbl )
{
CB_ComBufType *pComBuf;
cm_ConnectionRecordType *psConnRecord;
/*
** Get the connection record pointer and the remains of the forward open.
*/
psConnRecord = cm_GetPrivateRecord( pTrrbl->psConnRecord );
pComBuf = pTrrbl->pComBuf;
/*
** If the app returned an empty combuf, build a word aligned zero length
** data segment in it before going any further.
*/
if( ( pComBuf != NULL ) && ( CB_GetDataSizeComBuf( pComBuf ) == 0 ) )
{
CB_ClearAndExpandComBuf( pComBuf, 2 );
*( (UINT16*)CB_GetDataPtrComBuf( pComBuf ) ) = 0;
}
/*
** If the object doesn't exist or can't accept connections,
** put the appropriate status details into the connection record.
*/
if( pTrrbl->eStatus == MR_UNROUTABLE_PACKET )
{
psConnRecord->sPublic.bGRC = CI_GRC_FAILURE;
psConnRecord->sPublic.iERC = CM_ERC_BAD_SEGMENT;
}
if( pTrrbl->eStatus == CM_UNCONNECTABLE_OBJECT )
{
psConnRecord->sPublic.bGRC = CI_GRC_FAILURE;
psConnRecord->sPublic.iERC = CM_ERC_NO_APP_RESOURCES;
}
/*
** Calculate the connection operating timeout from the API and the
** multiplier from the forward open.
** Convert the result of that one from microseconds to milliseconds.
*/
psConnRecord->sPublic.lTimeout = psConnRecord->sPublic.lConApi * ( 4 << psConnRecord->sPublic.bTimeoutMult );
psConnRecord->sPublic.lTimeout /= 1000L;
/*
** Discard the app open response tribble.
** Note that we've received the response.
** If there was a problem, bump the processing state so we don't bother
** the app object anymore.
*/
GS_DeleteTrrbl( pTrrbl );
psConnRecord->iSteps |= CM_PS_AO_RETURNED;
if( psConnRecord->sPublic.bGRC != CI_GRC_SUCCESS )
{
psConnRecord->iSteps |= CM_PS_AOC_ISSUED | CM_PS_AOC_RETURNED | CM_PS_AC_ISSUED | CM_PS_AC_RETURNED;
}
/*
** Continue processing this connection.
*/
cm_ContinueProcessing( psConnRecord );
} /* end of cm_ProcessAppOpen() */
/*---------------------------------------------------------------------------
** cm_ProcessAppOpenComplete()
**---------------------------------------------------------------------------
*/
void cm_ProcessAppOpenComplete( CM_AppOpenCloseTrrblType *pTrrbl )
{
cm_ConnectionRecordType *psConnRecord;
/*
** Grab the stuff of interest from the response tribble & toss it.
*/
psConnRecord = cm_GetPrivateRecord( pTrrbl->psConnRecord );
GS_DeleteTrrbl( pTrrbl );
/*
** Note that we've received the response.
** Continue processing the connection.
*/
psConnRecord->iSteps |= CM_PS_AOC_RETURNED;
cm_ContinueProcessing( psConnRecord );
} /* end of cm_ProcessAppOpenComplete() */
/*---------------------------------------------------------------------------
** cm_ProcessFwdClose()
**---------------------------------------------------------------------------
*/
void cm_ProcessFwdClose( CD_PacketTrrblType *pTrrbl )
{
cm_ConnectionRecordType *psConnRecord;
CB_ComBufType *pComBuf;
CM_LeFwdCloseType *pLeFwdClose;
UINT8 *pIOI;
UINT8 bGRC;
UINT16 iERC;
/*
** Build pointers to the IOI and forward close portions of the packet.
*/
pComBuf = pTrrbl->pComBuf;
pIOI = CB_GetDataPtrComBuf( pComBuf );
pLeFwdClose = (CM_LeFwdCloseType*)( pIOI + CI_IoiPathSize( pComBuf, 0 ) );
bGRC = CI_GRC_SUCCESS;
/*
** Look for a matching connection.
*/
psConnRecord = cm_FindConnection( 0,
UC_iLeTOi( pLeFwdClose->iLeOrigVendorId ),
UC_lLeTOl( pLeFwdClose->lLeOrigDeviceSn ),
UC_iLeTOi( pLeFwdClose->iLeOrigConnectionSn ),
pTrrbl->iPort,
0, 0, 0, 0 );
if( ( psConnRecord == NULL ) || ( psConnRecord->iState & CM_PS_CLOSING ) )
{
bGRC = CI_GRC_FAILURE;
iERC = CM_ERC_BAD_CONNECTION;
}
/*
** Any errors detected?
*/
if( bGRC != CI_GRC_SUCCESS )
{
/*
** Connection not found or already being closed or path bad.
** Build the appropriate error reply packet.
*/
cm_BuildFwdErrorReply( pComBuf,
pLeFwdClose->iLeOrigConnectionSn,
pLeFwdClose->iLeOrigVendorId,
pLeFwdClose->lLeOrigDeviceSn,
pLeFwdClose->bClosePathSize,
CM_SC_FWD_CLOSE,
bGRC,
iERC );
GS_ReturnTrrbl( pTrrbl );
return;
}
/*
** Save the remaining path size before changing the Combuf.
*/
psConnRecord->bRemainingPathSize = pLeFwdClose->bClosePathSize;
/*
** Strip off all of the forward close but the data segment.
*/
CI_StripIoiPath( pComBuf, 0 );
CB_ShrinkComBuf( pComBuf, sizeof( CM_LeFwdCloseType ) );
/*
** Save the forward close tribble for future use.
** Adjust the connection state & continue processi
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -