⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 protocol.c

📁 Open DMT Client C Source code
💻 C
📖 第 1 页 / 共 5 页
字号:
// ----------------------------------------------------------------------------// Copyright 2006-2007, Martin D. Flynn// All rights reserved// ----------------------------------------------------------------------------//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at// // http://www.apache.org/licenses/LICENSE-2.0// // Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.//// ----------------------------------------------------------------------------// Description://  DMTP communication protocol manager//  Manages the dialog between the client and server during connections.// Notes://  - Thread support would be a useful addition to this module.  This would allow//  an immediate return to the main GPS checking loop without blocking.  This//  reference implementation will block until data communication has been made//  and data has been transferred.// ---// Change History://  2006/01/04  Martin D. Flynn//     -Initial release//  2006/02/09  Martin D. Flynn//     -Send ERROR_GPS_EXPIRED/ERROR_GPS_FAILURE is GPS fix has expired//  2006/04/02  Martin D. Flynn//     -Clear 'sendIdentification' after sending UniqueID//  2006/05/07  Martin D. Flynn//     -Add support for uploading GeoZones//  2006/05/26  Martin D. Flynn//     -Allow UniqueID to be >= 4//  2007/01/28  Martin D. Flynn//     -WindowsCE port//     -Fix 'tight loop' issue when 'serial/bluetooth' transport goes down//      (propagate error up from 'protocolReadServerPacket').//     -Return ERROR_COMMAND_ERROR for PROP_ERROR_COMMAND_ERROR on 'set' property.//     -Switched to generic thread access methods in 'tools/threads.h'//     -Flush server input buffers on received EOB-done (serial transport only)//     -Separated all protocol variables into a separate structure to allow//      multiple simultaneous connecting protocols.//     -Changed PKT_SERVER_GET_PROPERTY to retrieve a single property value.//      The remaining bytes behind the property key can now be used as arguments//      on the property 'get' (via 'PROP_REFRESH_GET').//     -Made some significant changes to this module to allow multiple virtual//      protocol "instances".  (While this would have been easier in 'C++', this//      has been implemented in 'C' to allow compiling on any 'C' capable platform.)//  2007/02/05  Martin D. Flynn//     -Fixed Fletcher checksum packet generation that inappropriately used//      "sizeof(ChecksumFletcher_t)" to determine the length of the checksum value.//      This created a compiler dependency that could return a length of 4, instead//      of the corrent value '2'. (Thanks to Tomasz Rostanski for catching this!).//  2007/04/28  Martin D. Flynn//     -Moved the following functions from 'events.c' to this modules to support //      dual transport: evGetEventQueue, evGetHighestPriority,//      evEnableOverwrite, evAcknowledgeFirst, evAcknowledgeToSequence// ----------------------------------------------------------------------------#include "stdafx.h" // TARGET_WINCE#include "custom/defaults.h"#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <string.h>#include <ctype.h>#include <time.h>#include "custom/log.h"#include "custom/transport.h"#include "custom/gps.h"#include "tools/stdtypes.h"#include "tools/strtools.h"#include "tools/utctools.h"#include "tools/base64.h"#include "tools/checksum.h"#include "base/propman.h"#include "base/events.h"#include "base/cerrors.h"#include "base/serrors.h"#include "base/pqueue.h"#include "base/accting.h"#include "base/packet.h"#include "base/protocol.h"#if defined(ENABLE_UPLOAD)#  include "base/upload.h"#endif#include "modules/motion.h"// ----------------------------------------------------------------------------// thread control#ifdef PROTOCOL_THREAD//#warning Protocol thread support enabled#define PROTOCOL_LOCK(PV)       MUTEX_LOCK(&((PV)->protocolMutex));#define PROTOCOL_UNLOCK(PV)     MUTEX_UNLOCK(&((PV)->protocolMutex));#define PROTOCOL_WAIT(PV)       CONDITION_WAIT(&((PV)->protocolCond), &((PV)->protocolMutex));#define PROTOCOL_NOTIFY(PV)     CONDITION_NOTIFY(&((PV)->protocolCond));#else//#warning Protocol thread support disabled#define PROTOCOL_LOCK(PV)#define PROTOCOL_UNLOCK(PV)#define PROTOCOL_WAIT(PV)#define PROTOCOL_NOTIFY(PV)#endif// ----------------------------------------------------------------------------/* severe error counts */#define MAX_SEVERE_ERRORS               10#define EXCESSIVE_SEVERE_ERRORS         15// ----------------------------------------------------------------------------// ----------------------------------------------------------------------------// '_protoGetVars' allows separating the protocol handler into separate virtual// instances. Ideally, this should be a C++ class, but this has been implemented// in 'C' to allow this module to compile on any 'C' compatible platform.static ProtocolVars_t   protoVars[MAX_SIMULTANEOUS_PROTOCOLS];static ProtocolVars_t *_protoGetVars(const char *fn, int line, int protoNdx){    if (protoNdx <= 0) {        // primary protocol        return &protoVars[0];    } else    if (protoNdx < MAX_SIMULTANEOUS_PROTOCOLS) {        // secondary protocol, etc.        //logINFO(LOGSRC,"Secondary protocol #%d [%s:%d] ...", protoNdx, fn, line);        return &protoVars[protoNdx];    } else {        // invalid index, return last protocol        //logWARNING(LOGSRC,"Secondary protocol out-of-bounds #%d [%s:%d] ...", protoNdx, fn, line);        return &protoVars[MAX_SIMULTANEOUS_PROTOCOLS - 1];    }}// ----------------------------------------------------------------------------// ----------------------------------------------------------------------------#if defined(SECONDARY_SERIAL_TRANSPORT)PacketQueue_DEFINE(secondaryQueue,SECONDARY_EVENT_QUEUE_SIZE);#endif/* get event queue (evGetEventQueue) */static PacketQueue_t *_protocolGetEventQueue(ProtocolVars_t *pv){#if defined(SECONDARY_SERIAL_TRANSPORT)    return pv->isPrimary? evGetEventQueue() : &secondaryQueue;#else    return evGetEventQueue();#endif}PacketQueue_t *protocolGetEventQueue(int protoNdx){    ProtocolVars_t *pv = _protoGetVars(LOGSRC,protoNdx);    return _protocolGetEventQueue(pv);}/* return the highest priority event in the queue (evGetHighestPriority) */static PacketPriority_t _protocolGetHighestPriority(ProtocolVars_t *pv){    PacketQueue_t *evQue = _protocolGetEventQueue(pv);    if (evQue) {        return pqueGetHighestPriority(evQue);    } else {        return PRIORITY_NONE;    }}/* enable overwriting of the oldest event if the event queue fills up (evEnableOverwrite) */static void _protocolEnableOverwrite(ProtocolVars_t *pv, utBool overwrite){    PacketQueue_t *evQue = _protocolGetEventQueue(pv);    if (evQue) {        pqueEnableOverwrite(evQue, overwrite);    }}/* acknowledge events up to and including the specified sequence (evAcknowledgeToSequence) */static utBool _protocolAcknowledgeToSequence(ProtocolVars_t *pv, UInt32 sequence){    // 'primary' transport events only    utBool didAck = utFalse;    utBool ackAll = (sequence == SEQUENCE_ALL)? utTrue : utFalse;    PacketQueue_t *eventQueue = _protocolGetEventQueue(pv);    if (eventQueue && (ackAll || pqueHasSentPacketWithSequence(eventQueue,sequence))) {        PacketQueueIterator_t evi;        pqueGetIterator(eventQueue, &evi);        for (;;) {            // As we iterate through the event packets, we can assume the following:            // - If we get to a null packet, we are finished with the list            // - If we find a packet that hasn't been sent, then all following packets have             //   also not been sent.            // - Once we find the 'first' matching sequence, we delete it then stop. This is            //   safer that deleting the last matching sequence.  (Note: multiple possible            //   matching sequence numbers can occur if the byte length of the sequence             //   number is 1 (ie. 0 to 255), and more than 255 events are currently in the             //   event packet queue.  Granted, an unlikely situation, but it can occur.)            // - No packet->sequence will ever match SEQUENCE_ALL (see 'ackAll').            Packet_t *pkt = pqueGetNextPacket((Packet_t*)0, &evi);            if (!pkt || !pkt->sent) {                //logWARNING(LOGSRC,"Stop at first non-sent packet");                break;  // stop at first null or non-sent packet            }            pqueDeleteFirstEntry(eventQueue);            didAck = utTrue;            if (ackAll) {                // ackowledge all sent packets                continue;            } else            if (pkt->sequence == SEQUENCE_ALL) {                // This condition can not (should not) occur.                // We don't know what the real sequence of the packet is.                // it's safer to stop here.                break;            } else            if (pkt->sequence != (sequence & SEQUENCE_MASK(pkt->seqLen))) {                // no match yet                continue;            }            break; // stop when sequence matches        }    } else {        logERROR(LOGSRC,"No packet with sequence: 0x%04lX", (UInt32)sequence);    }    return didAck;}/* acknowledge first sent event (evAcknowledgeFirst) */static utBool _protocolAcknowledgeFirst(ProtocolVars_t *pv){    PacketQueue_t *evQue = _protocolGetEventQueue(pv);    if (evQue) {        UInt32 seq = pqueGetFirstSentSequence(evQue); // return 'SEQUENCE_ALL' if no first event        if (seq != SEQUENCE_ALL) {            return _protocolAcknowledgeToSequence(pv,seq);        } else {            return utFalse;        }    } else {        return utFalse;    }}// ----------------------------------------------------------------------------// ----------------------------------------------------------------------------/* set current session packet encoding */static void _protocolSetSessionEncoding(ProtocolVars_t *pv, TransportType_t xportType, PacketEncoding_t enc){    // Since this reference implementation does not support received CSV packet encoding    // from the server, we must make sure that our first packet to the server is NOT    // CSV encoded if we are transmitting via TRANSPORT_DUPLEX    pv->sessionEncoding         = enc;    pv->sessionEncodingChanged  = utFalse;    pv->sessionFirstEncoding    = pv->sessionEncoding;    if (xportType == TRANSPORT_DUPLEX) {        if (ENCODING_VALUE(pv->sessionEncoding) == ENCODING_CSV) {            PacketEncoding_t dft = ENCODING_BASE64;            pv->sessionFirstEncoding = ENCODING_IS_CHECKSUM(enc)? ENCODING_CHECKSUM(dft) : dft;        }    }}/* return true if specified encoding is supported */static PacketEncoding_t _protocolGetSupportedEncoding(ProtocolVars_t *pv, PacketEncoding_t dftEncoding){    UInt32 enc = ENCODING_VALUE(dftEncoding); // <-- max 15    if (enc == ENCODING_BINARY) {        return (PacketEncoding_t)enc;    } else {        UInt32 propEncodings = pv->isPrimary? propGetUInt32(PROP_COMM_ENCODINGS, 0L) : 0L; // protocol dependent        UInt32 encodingMask = propEncodings | ENCODING_REQUIRED_MASK; // <-- must include binary        while ((ENCODING_MASK(enc) & encodingMask) == 0L) {            // ENCODING_CSV     3             // ENCODING_HEX     2             // ENCODING_BASE64  1             // ENCODING_BINARY  0             enc--;        }        //if (enc != ENCODING_VALUE(dftEncoding)) { logDEBUG(LOGSRC,"Encoding down-graded to %ld\n", enc); }        return ENCODING_IS_CHECKSUM(dftEncoding)?             (PacketEncoding_t)ENCODING_CHECKSUM(enc) :             (PacketEncoding_t)enc;    }}// ----------------------------------------------------------------------------// The following are wrappers to the 'transport.c' module function calls/* return transport 'open' state */utBool protocolIsSpeakFreely(int protoNdx){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -