📄 protocol.c
字号:
// End of transmission, query response // Payload: maxEvents[optional], serverKey[optional] case PKT_SERVER_EOB_DONE : { // flush server input buffer (useful for 'serial' transport only) _protocolFlushInput(pv); // The server is expecting the client to respond as soon as possible pv->speakFreely = utFalse; // relinquish speak-freely permission pv->speakFreelyMaxEvents = -1; // Get max number of events to send (if specified) Int32 eobMaxEvents = -1L; if (srvPkt->dataLen > 0) { int fldCnt = binScanf(srvPkt->data, (int)srvPkt->dataLen, "%1i", &eobMaxEvents); if (fldCnt < 1) { eobMaxEvents = -1L; } } // Send our packets if (!_protocolSendAllPackets(pv, TRANSPORT_DUPLEX, pv->speakBrief, (int)eobMaxEvents)) { return utFalse; // write error } // Clear 'speakBrief' (we've already had our opportunity to speak). pv->speakBrief = utFalse; return utTrue; } // End of transmission, speak freely // Payload: maxEvents[optional], serverKey[optional] case PKT_SERVER_EOB_SPEAK_FREELY: { // The server is NOT expecting the client to respond anytime soon pv->speakFreely = utTrue; // 'speak-freely' permission granted pv->speakFreelyMaxEvents = -1; // Get max number of events to send (if specified) Int32 eobMaxEvents = -1L; if (srvPkt->dataLen > 0) { int fldCnt = binScanf(srvPkt->data, (int)srvPkt->dataLen, "%1i", &eobMaxEvents); if (fldCnt < 1) { eobMaxEvents = -1L; } // SpeakFreely 'eobMaxEvents' is interpreted as follows: // 0 - speak-freely, but don't send data from the 'event' queue // # - normal speak-freely, but send at most '#' events per ack block. pv->speakFreelyMaxEvents = (int)eobMaxEvents; } // We will be sending data shortly (in the outer loop) return utTrue; } // Acknowledge [optional sequence] // Payload: sequence[optional] case PKT_SERVER_ACK : { UInt32 sequence = SEQUENCE_ALL; int fldCnt = binScanf(srvPkt->data, (int)srvPkt->dataLen, "%4x", &sequence); if (fldCnt > 0) { // remove sent/acknowledged events from queue up to specified sequence # if (!_protocolAcknowledgeToSequence(pv,sequence)) { // ACK error int seqLen = (srvPkt->dataLen <= 4)? srvPkt->dataLen : 4; _protocolQueueError(pv,"%2x%2x%*x", (UInt32)ERROR_PACKET_ACK, (UInt32)srvPkt->hdrType, seqLen, sequence); } } else { // remove all sent events from queue _protocolAcknowledgeToSequence(pv,SEQUENCE_ALL); } return utTrue; } // Get property // Payload: propertyKey(s) case PKT_SERVER_GET_PROPERTY : { Buffer_t srcBuf, *src = binBuffer(&srcBuf, srvPkt->data, srvPkt->dataLen, BUFFER_SOURCE); if (BUFFER_DATA_LENGTH(src) >= 2) { // while? UInt32 propKey = 0L; int fldCnt = binScanf(BUFFER_DATA(src), (int)BUFFER_DATA_LENGTH(src), "%2u", &propKey); binAdvanceBuffer(src, 2); if (fldCnt > 0) { UInt8 *args = BUFFER_DATA(src); UInt16 argLen = BUFFER_DATA_LENGTH(src); // queue property value packet Packet_t propPkt; PropertyError_t propErr = propGetPropertyPacket(pv->protoNdx, &propPkt, (Key_t)propKey, args, argLen); if (PROP_ERROR_CODE(propErr) == PROP_ERROR_OK) { // property packet initialized successfully _protocolQueuePacket(pv,&propPkt); // packet queueing errors are ignored (possible internal buffer overflow) } else if (PROP_ERROR_CODE(propErr) == PROP_ERROR_INVALID_KEY) { // unsupported property _protocolQueueError(pv,"%2x%2x", (UInt32)ERROR_PROPERTY_INVALID_ID, (UInt32)propKey); // packet queueing errors are ignored (possible internal buffer overflow) } else if (PROP_ERROR_CODE(propErr) == PROP_ERROR_WRITE_ONLY) { // write-only property _protocolQueueError(pv,"%2x%2x", (UInt32)ERROR_PROPERTY_WRITE_ONLY, (UInt32)propKey); // packet queueing errors are ignored (possible internal buffer overflow) } else if (PROP_ERROR_CODE(propErr) == PROP_ERROR_INVALID_LENGTH) { // invalid payload length _protocolQueueError(pv,"%2x%2x", (UInt32)ERROR_PROPERTY_INVALID_VALUE, (UInt32)propKey); // returned 'queue' errors are ignored (possible internal buffer overflow) } else if (PROP_ERROR_CODE(propErr) == PROP_ERROR_COMMAND_INVALID) { // command not supported/initialized // this will not occur, since commands are write-only _protocolQueueError(pv,"%2x%2x", (UInt32)ERROR_COMMAND_INVALID, (UInt32)propKey); // packet queueing errors are ignored (possible internal buffer overflow) } else if (PROP_ERROR_CODE(propErr) == PROP_ERROR_COMMAND_ERROR) { // command error // this will not occur, since commands are write-only UInt16 errCode = (UInt16)PROP_ERROR_ARG(propErr); _protocolQueueError(pv,"%2x%2x%2x", (UInt32)ERROR_COMMAND_ERROR, (UInt32)propKey, (UInt32)errCode); // packet queueing errors are ignored (possible internal buffer overflow) } else { // internal error // send error back to server: ERROR_PROPERTY_UNKNOWN_ERROR _protocolQueueError(pv,"%2x%2x", (UInt32)ERROR_PROPERTY_UNKNOWN_ERROR, (UInt32)propKey); // packet queueing errors are ignored (possible internal buffer overflow) } } else { // no property specified _protocolQueueError(pv,"%2x%2x", (UInt32)ERROR_PACKET_PAYLOAD, (UInt32)srvPkt->hdrType); // packet queueing errors are ignored (possible internal buffer overflow) } } return utTrue; } // Set property // Payload: propertyKey, propertyValue[optional] case PKT_SERVER_SET_PROPERTY : { UInt32 propKey = 0L; int valDataLen = (srvPkt->dataLen > 2)? (int)(srvPkt->dataLen - 2) : 0; UInt8 valData[PACKET_MAX_ENCODED_LENGTH]; int fldCnt = binScanf(srvPkt->data, (int)srvPkt->dataLen, "%2x%*b", &propKey, valDataLen, valData); if (fldCnt >= 1) { // set property value // TODO: If property is a 'Command', it would be very handy to be able to // let the property manager where to queue the returned data (specifically // the primary/secondary protocol) PropertyError_t propErr = propSetValueCmd(pv->protoNdx, (Key_t)propKey, valData, valDataLen); // ok as-is if (PROP_ERROR_CODE(propErr) == PROP_ERROR_OK) { // property set successfully // no packet response } else if (PROP_ERROR_CODE(propErr) == PROP_ERROR_INVALID_KEY) { // unsupported property key _protocolQueueError(pv,"%2x%2x", (UInt32)ERROR_PROPERTY_INVALID_ID, (UInt32)propKey); // returned errors are ignored (possible internal buffer overflow) } else if (PROP_ERROR_CODE(propErr) == PROP_ERROR_INVALID_TYPE) { // internal error, invalid type _protocolQueueError(pv,"%2x%2x", (UInt32)ERROR_PROPERTY_UNKNOWN_ERROR, (UInt32)propKey); // returned errors are ignored (possible internal buffer overflow) } else if (PROP_ERROR_CODE(propErr) == PROP_ERROR_INVALID_LENGTH) { // invalid payload length _protocolQueueError(pv,"%2x%2x", (UInt32)ERROR_PROPERTY_INVALID_VALUE, (UInt32)propKey); // returned errors are ignored (possible internal buffer overflow) } else if (PROP_ERROR_CODE(propErr) == PROP_ERROR_READ_ONLY) { // read-only property _protocolQueueError(pv,"%2x%2x", (UInt32)ERROR_PROPERTY_READ_ONLY, (UInt32)propKey); // returned errors are ignored (possible internal buffer overflow) } else if (PROP_ERROR_CODE(propErr) == PROP_ERROR_COMMAND_INVALID) { // command not supported/initialized _protocolQueueError(pv,"%2x%2x", (UInt32)ERROR_COMMAND_INVALID, (UInt32)propKey); // returned errors are ignored (possible internal buffer overflow) } else if (PROP_ERROR_CODE(propErr) == PROP_ERROR_COMMAND_ERROR) { // command not supported/initialized, or possibly COMMAND_OK_ACK UInt16 errCode = (UInt16)PROP_ERROR_ARG(propErr); _protocolQueueError(pv,"%2x%2x%2x", (UInt32)ERROR_COMMAND_ERROR, (UInt32)propKey, (UInt32)errCode); // returned errors are ignored (possible internal buffer overflow) } else { // likely internal error _protocolQueueError(pv,"%2x%2x", (UInt32)ERROR_PROPERTY_UNKNOWN_ERROR, (UInt32)propKey); // returned errors are ignored (possible internal buffer overflow) } } else { // no property specified _protocolQueueError(pv,"%2x%2x", (UInt32)ERROR_PACKET_PAYLOAD, (UInt32)srvPkt->hdrType); // returned errors are ignored (possible internal buffer overflow) } return utTrue; } // File upload case PKT_SERVER_FILE_UPLOAD : { #if defined(ENABLE_UPLOAD) uploadProcessRecord(pv->protoNdx, srvPkt->data, (int)srvPkt->dataLen); // this already sends error/ack packets#else _protocolQueueError(pv,"%2x%2x", (UInt32)ERROR_PACKET_TYPE, (UInt32)srvPkt->hdrType); // returned errors are ignored (possible internal buffer overflow)#endif return utTrue; } // NAK/Error codes // Payload: errorCode, packetHeader, packetType, extraData case PKT_SERVER_ERROR : { UInt32 errCode = 0L, pktHdrType = 0L; int valDataLen = (srvPkt->dataLen > 2)? (int)(srvPkt->dataLen - 2) : 0; UInt8 valData[PACKET_MAX_ENCODED_LENGTH]; int fldCnt = binScanf(srvPkt->data, (int)srvPkt->dataLen, "%2x%2x%*b", &errCode, &pktHdrType, valDataLen, valData); if (fldCnt >= 1) { // 'errCode' contains the Error Code // 'pktHdr' contains the error packet header // 'pktTyp' containt the error packet type // 'valData' contains any additional data utBool ok = _protocolHandleErrorCode(pv, (UInt16)errCode, (ClientPacketType_t)pktHdrType, valData, valDataLen); if (!ok) { return utFalse; // critical error determined by error code } } else { // no error specified _protocolQueueError(pv,"%2x%2x", (UInt32)ERROR_PACKET_PAYLOAD, (UInt32)srvPkt->hdrType); // returned errors are ignored (possible internal buffer overflow) } return utTrue; } // End transmission (socket will be closed) // Payload: none case PKT_SERVER_EOT : { // return false to close communications return utFalse; // server is closing the connection } // Invalid packet type default: { _protocolQueueError(pv,"%2x%2x", (UInt32)ERROR_PACKET_TYPE, (UInt32)srvPkt->hdrType); // returned errors are ignored (possible internal buffer overflow) return utTrue; } } }// ----------------------------------------------------------------------------// This function checks to see if it is time to make a connection to the DMT service// provider, and what type of connection to make. The time of the last connection// and the number of connections made in the last hour are considered.static TransportType_t _getTransportType(ProtocolVars_t *pv){ /* secondary protocol */ if (!pv->isPrimary) { // duplex transport for non-primary transport // Assume the secondary protocol supports duplex // - Highest event priority is PRIORITY_NONE (no events are sent to the secondary protocol) // - Never over duplex quota return TRANSPORT_DUPLEX; } /* first check absolute minimum delay between connections */ if (!acctAbsoluteDelayExpired()) { // absolute minimum delay interval has not expired //logINFO(LOGSRC,"Absolute minimum delay interval has not expired"); return TRANSPORT_NONE; } /* check specific event priority */ TransportType_t xportType = TRANSPORT_NONE; PacketPriority_t evPri = _protocolGetHighestPriority(pv); switch (evPri) { // no events, time for 'checkup'? case PRIORITY_NONE: if (!acctUnderTotalQuota()) { // over Total quota xportType = TRANSPORT_NONE; } else if (!acctMaxIntervalExpired()) { // MAX interval has not expired xportType = TRANSPORT_NONE; } else if (acctUnderDuplexQuota()) { // under Total/Duplex quota and MAX interval expired, time for Duplex checkup //logDEBUG(LOGSRC,"_getTransportType: NONE/DUPLEX ..."); xportType = TRANSPORT_DUPLEX; } else { // over Duplex quota xportType = TRANSPORT_NONE; } break; // low priority events case PRIORITY_LOW: if (!acctUnderTotalQuota()) { // over Total quota, no sending xportType = TRANSPORT_NONE; } else if (!acctMinIntervalExpired()) { // min interval has not expired, no sending xportType = TRANSPORT_NONE; } else if (acctSupportsSimplex()) { // under Total quota, min interval expired, send Simplex //logDEBUG(LOGSRC,"_getTransportType: 1 LOW/SIMPLEX ..."); xportType = TRANSPORT_SIMPLEX; } else if (acctUnderDuplexQuota()) { // under Total/Duplex quota and min interval expired, Simplex not supported, send Duplex
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -