📄 protocol.c
字号:
case TRANSPORT_SIMPLEX: if (pv->isPrimary) { // max simplex events maxEvents = (int)propGetUInt32(PROP_COMM_MAX_SIM_EVENTS, 4L); // primary only if (maxEvents > MAX_SIMPLEX_EVENTS) { maxEvents = MAX_SIMPLEX_EVENTS; } } else if (pv->isSerial) { maxEvents = 1; // will never occur, 'serial' doesn't send events via 'simplex' } else { maxEvents = MAX_SIMPLEX_EVENTS; } break; case TRANSPORT_DUPLEX: if (pv->isPrimary) { // max duplex events maxEvents = (int)propGetUInt32(PROP_COMM_MAX_DUP_EVENTS, 8L); // primary only if (maxEvents > MAX_DUPLEX_EVENTS) { maxEvents = MAX_DUPLEX_EVENTS; } } else if (pv->isSerial) { maxEvents = 1; } else { maxEvents = MAX_DUPLEX_EVENTS; } break; default: logCRITICAL(LOGSRC,"Invalid Transport-Type: %d", (int)xportType); break; } if ((dftMaxEvents > 0) && (maxEvents > dftMaxEvents)) { // limit number of event to the specified default maximum // (the value of 'dftMaxEvent' is disregarded if less than '0') maxEvents = dftMaxEvents; } /* max priority events to send */ // - This function is getting called because "_getTransportType()" returned a transport // type based on what it found in the event queue. If it chose a Simplex connection // based on 'Low' priority events found in the queue, then we should make sure that // only low priority events will get sent via Simplex. This prevents Normal and High // priority events from getting sent that may have entered the queue while we are // still trying to set up the connection (which could take a while). // - If it is desirable to go ahead and send all (including High priority) events found // in the queue, then this restriction should be relaxed, however it would then be // necessary to insure that these event don't get purged from the queue until they were // successfully later sent via Duplex. PacketPriority_t maxPri; maxPri = (pv->isSerial || (xportType == TRANSPORT_DUPLEX) || !acctSupportsDuplex())? PRIORITY_HIGH : // all priority events will be sent PRIORITY_LOW; // only low priority events will be sent /* transmit unacknowledged event packets */ if (eventQueue && !_protocolSendQueue(pv, eventQueue, maxPri, maxEvents, &hasMoreEvents)) { return utFalse; // write error: close socket } } else { /* We didn't send events yet. Check to see if we have any to send */ hasMoreEvents = _protocolHasDataToSend(pv); } } /* send end-of-block packet */ if ((xportType == TRANSPORT_DUPLEX) && !pv->speakFreely) { if (!_protocolSendEOB(pv,hasMoreEvents)) { return utFalse; } } return utTrue;}// ----------------------------------------------------------------------------/* handle server-originated error packet */static utBool _protocolHandleErrorCode(ProtocolVars_t *pv, UInt16 errCode, ClientPacketType_t pktHdrType, UInt8 *valData, int valDataLen){ //Buffer_t argBuf, *argSrc = binBuffer(&argBuf, valData, valDataLen, BUFFER_SOURCE); switch ((ServerError_t)errCode) { case NAK_OK : { // Everything ok (should never occur here return utTrue; } case NAK_ID_INVALID : { // Invalid unique id // The DMT server doesn't recognize our unique-id. // We should try to send our account and device id. pv->sendIdentification = SEND_ID_ACCOUNT; return utTrue; } case NAK_ACCOUNT_ERROR : // Internal server error case NAK_DEVICE_ERROR : { // Internal server error // The DMT server encountered an error retrieve our ID pv->severeErrorCount++; if (++(pv->invalidAcctErrorCount) >= 2) { // fail on 2nd error return utFalse; } else { // try one more time (if the server will let us) return utTrue; } } case NAK_ACCOUNT_INVALID : // Invalid/missing account id case NAK_DEVICE_INVALID : { // Invalid/missing device id // The DMT server doesn't know who we are pv->severeErrorCount++; if (++(pv->invalidAcctErrorCount) >= 2) { // fail on 2nd error return utFalse; } else { // try one more time (if the server will let us) return utTrue; } } case NAK_ACCOUNT_INACTIVE : // Account has expired, or has become inactive case NAK_DEVICE_INACTIVE : { // Device has expired, or has become inactive pv->severeErrorCount++; return utFalse; } case NAK_EXCESSIVE_CONNECTIONS : { // Excessive connections if (pv->isPrimary) { // excessive connections // The DMT server may mark (or has marked) us as an abuser. // No alternative, but to quit // Slow down minimum connection interval propAddUInt32(PROP_COMM_MIN_XMIT_RATE , 300L); propAddUInt32(PROP_COMM_MIN_XMIT_DELAY, 300L); } else { // should not occur for secondary protocol } return utFalse; } case NAK_PACKET_HEADER : // Invalid/Unsupported packet header case NAK_PACKET_TYPE : { // Invalid/Unsupported packet type // The DMT server does not support our custom extensions // Ignore the error and continue. return utTrue; } case NAK_PACKET_LENGTH : // Invalid packet length case NAK_PACKET_PAYLOAD : { // Invalid packet payload // This indicates a protocol compliance issue in the client pv->severeErrorCount++; return utFalse; } case NAK_PACKET_ENCODING : { // Encoding not supported // DMT servers are required to support Binary, ASCII-Base64, and ASCII-Hex encoding. // This should only occur if we are encoding packets in ASCII CSV format and the // server doesn't support this encoding. We shoud try again with HEX or Base64 // encoding for the remainder of the session. // We need to handle getting several of these errors during a transmission block. if (!pv->sessionEncodingChanged) { pv->sessionEncodingChanged = utTrue; // mark changed UInt32 encMask = ENCODING_MASK(pv->sessionEncoding); if (encMask & ENCODING_REQUIRED_MASK) { // We're already encoding in a server supported encoding // This is likely some protocol compliance issue with the client // (of course it can't be the server! :-) return utFalse; } if (pv->isPrimary) { // session encodings UInt32 propEncodings = propGetUInt32(PROP_COMM_ENCODINGS, 0L); // primary only UInt32 encodingMask = propEncodings & ~encMask; propSetUInt32(PROP_COMM_ENCODINGS, encodingMask | ENCODING_REQUIRED_MASK); // primary only pv->sessionEncoding = _protocolGetSupportedEncoding(pv, pv->sessionEncoding); } else { pv->sessionEncoding = _protocolGetSupportedEncoding(pv, ENCODING_HEX); } if ((pktHdrType == PKT_CLIENT_UNIQUE_ID) || (pktHdrType == PKT_CLIENT_ACCOUNT_ID) || (pktHdrType == PKT_CLIENT_DEVICE_ID) ) { // error occured on identification packets, resend id#if defined(TRANSPORT_MEDIA_SERIAL) // send account/device for serial transport pv->sendIdentification = SEND_ID_ACCOUNT;#else // try unique-id first for everything else pv->sendIdentification = SEND_ID_UNIQUE;#endif } } return utTrue; } case NAK_PACKET_CHECKSUM : // Invalid packet checksum (ASCII encoding only) case NAK_BLOCK_CHECKSUM : { // Invalid block checksum // increment checksum failure indicator, if it gets too large, quit if (++(pv->checkSumErrorCount) >= 3) { // fail on 3rd error (per session) pv->severeErrorCount++; return utFalse; } else { return utTrue; } } case NAK_PROTOCOL_ERROR : { // Protocol error // This indicates a protocol compliance issue in the client pv->severeErrorCount++; return utFalse; } case NAK_FORMAT_DEFINITION_INVALID: { // Custom format type is invalid if (pv->isPrimary) { // invalid format definition // The custom type we've specified isn't within the supported custom format packet types // This indicates a protocol compliance issue in the client propSetBoolean(PROP_COMM_CUSTOM_FORMATS, utFalse); pv->severeErrorCount++; } else { // should not occur for secondary protocol } return utFalse; } case NAK_FORMAT_NOT_SUPPORTED : { // Custom formats not supported // The DMT server does not support custom formats (at least not for our current level of service) _protocolAcknowledgeToSequence(pv,SEQUENCE_ALL); if (pv->isPrimary) { // custom formats not supported // We should acknowledge all sent events, and set a flag indicating that // we should not send custom formats to this server in the future. propSetBoolean(PROP_COMM_CUSTOM_FORMATS, utFalse); } else { // should not occur for secondary protocol } return utTrue; } case NAK_FORMAT_NOT_RECOGNIZED : { // Custom format not recognized // The DMT does support custom formats, but it doesn't recognize the // format we've used in an event packet. We should send the custom // format template(s), then resend the events. Packet_t custPkt; int rtn = evGetCustomFormatPacket(&custPkt, pktHdrType); if (rtn >= 0) { custPkt.priority = PRIORITY_HIGH; return _protocolQueuePacket(pv,&custPkt); } else { // One of the following has occured: // - The server just told us it doesn't support a custom format that we didn't // send it (unlikely). // - An internal buffer overflow has ocurred. // - We were unable to add the packet to the queue pv->severeErrorCount++; return utFalse; } } case NAK_EXCESSIVE_EVENTS : { // Excessive events // If present, the next (first) event will never be accepted, purge it from the queue. _protocolAcknowledgeFirst(pv); // first "sent" event if (pv->isPrimary) { // excessive events // The DMT server may mark (or has marked) us as an abuser. // Slow down periodic messages to prevent this from occurring in the future UInt32 inMotionInterval = propGetUInt32(PROP_MOTION_IN_MOTION, 0L); // primary only if (inMotionInterval > 0L) { propSetUInt32(PROP_MOTION_IN_MOTION, (inMotionInterval + MINUTE_SECONDS(2))); // primary only } UInt32 dormantInterval = propGetUInt32(PROP_MOTION_DORMANT_INTRVL, 0L); // primary only if (dormantInterval > 0L) { propSetUInt32(PROP_MOTION_DORMANT_INTRVL, (dormantInterval + MINUTE_SECONDS(10))); // primary only } } else { // should not occur for secondary protocol } // continue with session return utTrue; } case NAK_DUPLICATE_EVENT : { // Duplicate event found // ignore error return utTrue; } case NAK_EVENT_ERROR : { // Server had an error when processing this event // ignore error return utTrue; } } /* unhandled error - ignore */ return utTrue;}// ----------------------------------------------------------------------------/* handle server-originated packet */static utBool _protocolHandleServerPacket(ProtocolVars_t *pv, Packet_t *srvPkt){ // client should return 'utFalse' if an error has occured and communication should not continue /* check header */ if (CLIENT_PACKET_HEADER(srvPkt->hdrType) != PACKET_HEADER_BASIC) { // unsupported header _protocolQueueError(pv,"%2x%2x", (UInt32)ERROR_PACKET_HEADER, (UInt32)srvPkt->hdrType); // returned errors are ignored (possible internal buffer overflow) return utTrue; // continue communication } /* handle packet */ switch ((ServerPacketType_t)srvPkt->hdrType) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -