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

📄 packet.c

📁 Open DMT Client C Source code
💻 C
字号:
// ----------------------------------------------------------------------------// 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://  Server DMTP packet handler// ---// Change History://  2006/01/04  Martin D. Flynn//     -Initial release// ----------------------------------------------------------------------------#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <string.h>#include <ctype.h>#include <time.h>#include <sys/time.h>#include "tools/stdtypes.h"#include "tools/strtools.h"#include "tools/utctools.h"#include "tools/bintools.h"#include "tools/base64.h"#include "tools/checksum.h"#include "server/packet.h"#include "server/log.h"// ----------------------------------------------------------------------------/* initialize a format buffer with the packet payload */FmtBuffer_t *pktFmtBuffer(FmtBuffer_t *bf, Packet_t *pkt){    binFmtBuffer(bf, pkt->data, sizeof(pkt->data), pkt->dataFmt, sizeof(pkt->dataFmt));    return bf;}// ----------------------------------------------------------------------------/* create/initialize a packet with the specified values */int pktInit(Packet_t *pkt, ServerPacketType_t pktType, const char *fmt, ...){    if (pkt) {        va_list ap;        va_start(ap, fmt);        int rtn = pktVInit(pkt, pktType, fmt, ap);        va_end(ap);        return rtn;    } else {        logERROR(LOGSRC,"Null packet");        return PKTERR_NULL_PACKET;    }}/* create/initialize a packet with the specified argument list */// All packet initialization should occur hereint pktVInit(Packet_t *pkt, ServerPacketType_t pktType, const char *fmt, va_list ap){    if (pkt) {        memset(pkt, 0, sizeof(Packet_t));        pkt->hdrType  = pktType;        if (fmt && *fmt) {            FmtBuffer_t bb, *bf = pktFmtBuffer(&bb, pkt);            int len = binFmtVPrintf(bf, fmt, ap);            if (len < 0) {                pkt->dataLen = 0;                return PKTERR_BIN_PRINTF; // internal error: invalid format, or buffer overflow            } else {                pkt->dataLen = BUFFER_DATA_LENGTH(bf); // same as 'len'                return pkt->dataLen;            }        }        return 0;    } else {        return PKTERR_NULL_PACKET;    }}// ----------------------------------------------------------------------------/* encode the specified packet into a CSV string */static int _pktEncodeCSVPacket(Buffer_t *dest, Packet_t *pkt){    UInt16 oldLen = BUFFER_DATA_LENGTH(dest);    Buffer_t bsrc, *src = binBuffer(&bsrc, pkt->data, pkt->dataLen, BUFFER_SOURCE);    /* header */    snprintf(BUFFER_DATA(dest), BUFFER_DATA_SIZE(dest), "%c", PACKET_ASCII_ENCODING_CHAR);    binAdvanceBuffer(dest, strlen(BUFFER_DATA(dest)));    snprintf(BUFFER_DATA(dest), BUFFER_DATA_SIZE(dest), "%04X", (UInt16)pkt->hdrType);    binAdvanceBuffer(dest, strlen(BUFFER_DATA(dest)));    /* CSV (default) */    const char *v = pkt->dataFmt;    int err = 0;    for (;;) {                /* find start of next format */        while (*v && (*v != '%')) { v++; }        if (!*v) {            break;         }        v++;                /* 1+ digits must follow */        int len = 0;        if (isdigit(*v)) {            const char *d = v;            while (*d && isdigit(*d)) { d++; }            len = atoi(v);            v = d;        } else {            // invalid format (not a digit)            err = PKTERR_BIN_FORMAT_DIGIT;            break;        }        /* check remaining data length */        if (len > BUFFER_DATA_LENGTH(src)) {            // overflow            logERROR(LOGSRC,"Length [%d] greater that available data [%d] ...\n", len, BUFFER_DATA_LENGTH(src));            err = PKTERR_OVERFLOW;            break;        }                /* next char must be one of 'iuxsbgz' */        UInt32 i;        UInt8 tmp[PACKET_MAX_ENCODED_LENGTH];        GPSPoint_t gp;        int actualLen = 0;        switch (*v) {            case 'x': case 'X': // unsigned            case 'u': case 'U': // unsigned            case 'i': case 'I': // signed                i = binDecodeInt32(BUFFER_DATA(src), len, ((*v == 'i')||(*v == 'I')));                if ((*v == 'i')||(*v == 'I')) {                    snprintf(BUFFER_DATA(dest), BUFFER_DATA_SIZE(dest), "%c%ld", ENCODING_CSV_CHAR, i);                } else                if ((*v == 'x')||(*v == 'X')) {                    snprintf(BUFFER_DATA(dest), BUFFER_DATA_SIZE(dest), "%c0x%0*lX", ENCODING_CSV_CHAR, len*2, i);                } else {                    snprintf(BUFFER_DATA(dest), BUFFER_DATA_SIZE(dest), "%c%lu", ENCODING_CSV_CHAR, i);                }                binAdvanceBuffer(dest, strlen(BUFFER_DATA(dest)));                binAdvanceBuffer(src, len);                break;            case 's': case 'S':                actualLen = strLength(BUFFER_DATA(src), len); // lessor of field, or string length                snprintf(BUFFER_DATA(dest), BUFFER_DATA_SIZE(dest), "%c%.*s", ENCODING_CSV_CHAR, actualLen, BUFFER_DATA(src));                binAdvanceBuffer(dest, strlen(BUFFER_DATA(dest))); // advance by string length                binAdvanceBuffer(src, ((actualLen<len)?(actualLen+1):len)); // string length + terminator                break;            case 'b': case 'B':                strEncodeHex(tmp, sizeof(tmp), BUFFER_DATA(src), len);                snprintf(BUFFER_DATA(dest), BUFFER_DATA_SIZE(dest), "%c0x%s", ENCODING_CSV_CHAR, tmp);                binAdvanceBuffer(dest, strlen(BUFFER_DATA(dest)));                binAdvanceBuffer(src, len); // advance length of binary field                break;            case 'g': case 'G':                if ((len >= 6) && (len < 8)) {                    gpsPointDecode6(&gp, BUFFER_DATA(src));                    snprintf(BUFFER_DATA(dest), BUFFER_DATA_SIZE(dest), "%c%.4lf%c%.4lf", ENCODING_CSV_CHAR, gp.latitude, ENCODING_CSV_CHAR, gp.longitude);                } else                if (len >= 8) {                    gpsPointDecode8(&gp, BUFFER_DATA(src));                    snprintf(BUFFER_DATA(dest), BUFFER_DATA_SIZE(dest), "%c%.6lf%c%.6lf", ENCODING_CSV_CHAR, gp.latitude, ENCODING_CSV_CHAR, gp.longitude);                } else {                    // invalid format                    snprintf(BUFFER_DATA(dest), BUFFER_DATA_SIZE(dest), "%c%c", ENCODING_CSV_CHAR, ENCODING_CSV_CHAR);                }                binAdvanceBuffer(dest, strlen(BUFFER_DATA(dest)));                binAdvanceBuffer(src, len); // advance length of GPS field                break;            case 'z': case 'Z': // zero filled                binAdvanceBuffer(src, len); // advance length of ZERO field                break;            default:                // invalid format (unrecognized type)                err = PKTERR_BIN_FORMAT_CHAR;                break;        }    }        /* error? */    if (err < 0) {        return err;    }    return BUFFER_DATA_LENGTH(dest) - oldLen;}/* encode the specified packet into a hex string */static int _pktEncodeHEXPacket(Buffer_t *dest, Packet_t *pkt){    UInt16 oldLen = BUFFER_DATA_LENGTH(dest);    snprintf(BUFFER_DATA(dest), BUFFER_DATA_SIZE(dest), "%c", PACKET_ASCII_ENCODING_CHAR);    binAdvanceBuffer(dest, strlen(BUFFER_DATA(dest)));    snprintf(BUFFER_DATA(dest), BUFFER_DATA_SIZE(dest), "%04X", (UInt16)pkt->hdrType);    binAdvanceBuffer(dest, strlen(BUFFER_DATA(dest)));    if (pkt->dataLen > 0) {        char hex[PACKET_MAX_ENCODED_LENGTH]; // 256 * 2 == 512        snprintf(BUFFER_DATA(dest), BUFFER_DATA_SIZE(dest), "%c", ENCODING_HEX_CHAR);        binAdvanceBuffer(dest, strlen(BUFFER_DATA(dest)));        strEncodeHex(hex, sizeof(hex), pkt->data, pkt->dataLen);        snprintf(BUFFER_DATA(dest), BUFFER_DATA_SIZE(dest), "%s", hex);        binAdvanceBuffer(dest, strlen(BUFFER_DATA(dest)));    }    return BUFFER_DATA_LENGTH(dest) - oldLen;}/* encode the specified packet into a Base64 string */static int _pktEncodeB64Packet(Buffer_t *dest, Packet_t *pkt){    UInt16 oldLen = BUFFER_DATA_LENGTH(dest);    snprintf(BUFFER_DATA(dest), BUFFER_DATA_SIZE(dest), "%c", PACKET_ASCII_ENCODING_CHAR);    binAdvanceBuffer(dest, strlen(BUFFER_DATA(dest)));    snprintf(BUFFER_DATA(dest), BUFFER_DATA_SIZE(dest), "%04X", (UInt16)pkt->hdrType);    binAdvanceBuffer(dest, strlen(BUFFER_DATA(dest)));    if (pkt->dataLen > 0) {        char b64[PACKET_MAX_ENCODED_LENGTH]; // ((256 + 2) / 3) * 4 == 344        snprintf(BUFFER_DATA(dest), BUFFER_DATA_SIZE(dest), "%c", ENCODING_BASE64_CHAR);        binAdvanceBuffer(dest, strlen(BUFFER_DATA(dest)));        base64Encode(b64, sizeof(b64), pkt->data, pkt->dataLen);        snprintf(BUFFER_DATA(dest), BUFFER_DATA_SIZE(dest), "%s", b64);        binAdvanceBuffer(dest, strlen(BUFFER_DATA(dest)));    }    return BUFFER_DATA_LENGTH(dest) - oldLen;}/* encode the specified packet into the provided buffer */int pktEncodePacket(Buffer_t *dest, Packet_t *pkt, PacketEncoding_t encoding){    // Approximate "Safe" minimum 'strLen' values     // (assuming all 255 bytes of the data payload are utilized, and the checksum is included):    // Base64: (6 + (((255 + 2) / 3) * 4) + 3 + 1)         = 350    // Hex   : (6 + (2 * 255) + 3 + 1)                     = 520    // CSV   : (6 + ((2 * 255) + (3 * (#Fields))) + 3 + 1) = ~580 (20 fields)        /* encoding */    // Packet encoding override can occur here if needed    PacketEncoding_t enc = encoding;    /* binary encoding special case */    if (ENCODING_VALUE(enc) == ENCODING_BINARY) {        if ((3 + pkt->dataLen) <= BUFFER_DATA_SIZE(dest)) {            int len = binPrintf(BUFFER_DATA(dest), BUFFER_DATA_SIZE(dest), "%2x%1x%*b",                 (UInt32)pkt->hdrType, (UInt32)pkt->dataLen, (int)pkt->dataLen, pkt->data);            if (len >= 0) {                binAdvanceBuffer(dest, len);                return BUFFER_DATA_LENGTH(dest);            } else {                return PKTERR_OVERFLOW;            }        } else {            return PKTERR_OVERFLOW;        }    }        /* ascii encode */    UInt8 *str = BUFFER_DATA(dest);        // point to start of ASCII encoded record    int len = 0; // return length of this encoded packet (or an error)    switch (ENCODING_VALUE(enc)) {                    case ENCODING_CSV:            if (pkt->dataFmt && *(pkt->dataFmt)) {                len = _pktEncodeCSVPacket(dest, pkt); // format present, encode as CSV            } else {                len = _pktEncodeHEXPacket(dest, pkt); // format missing, encode as HEX            }            break;                case ENCODING_BASE64:            len = _pktEncodeB64Packet(dest, pkt);            break;                    default: // default to hex        case ENCODING_HEX:            len = _pktEncodeHEXPacket(dest, pkt);            break;    }        /* error? */    if (len < 0) {        return len;    }    // we assume that the packet has been properly encoded at this point    /* include checksum? */    if (ENCODING_IS_CHECKSUM(enc)) {        if (3 > BUFFER_DATA_SIZE(dest)) {            // internal error: not likely            logERROR(LOGSRC,"'3' greater that available data ...\n");            return PKTERR_OVERFLOW;        } else {            ChecksumXOR_t cksum = 0x00;            cksumCalcCharXOR(str + 1, &cksum);            sprintf(&str[len], "*%02X", (UInt16)cksum);            binAdvanceBuffer(dest, 3);        }    }        /* ascii line terminator */    snprintf(BUFFER_DATA(dest), BUFFER_DATA_SIZE(dest), "\r"); // \r\n    binAdvanceBuffer(dest, strlen(BUFFER_DATA(dest)));    /* return total length */    return BUFFER_DATA_LENGTH(dest);    }// ----------------------------------------------------------------------------/* print/log a packet */void pktPrintPacket(Packet_t *pkt, const char *msg, PacketEncoding_t encoding){    UInt8 buf[PACKET_MAX_ENCODED_LENGTH];    Buffer_t bb, *dest = binBuffer(&bb, buf, sizeof(buf), BUFFER_DESTINATION);    if (!msg) { msg = ""; }    int len = pktEncodePacket(dest, pkt, encoding);    if (len >= 0) {        if (*buf == PACKET_ASCII_ENCODING_CHAR) {            logDEBUG(LOGSRC,"%s %.*s [%d]", msg, len - 1, buf, len);         } else {            UInt8 hex[PACKET_MAX_ENCODED_LENGTH];            logDEBUG(LOGSRC,"%s 0x%s [%d]", msg, strEncodeHex(hex, sizeof(hex), buf, len), len);         }    } else {        logWARNING(LOGSRC,"%s <InvalidPacket> [%d]", msg, len);    }}// ----------------------------------------------------------------------------

⌨️ 快捷键说明

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