?? udprotcl.c
字號:
/* $Header: "%n Ver=%v %f LastEdit=%w Locker=%l" */
/* "UDPROTCL.C Ver=5 26-Nov-97,9:43:02 LastEdit=JIMV Locker=***_NOBODY_***" */
/***********************************************************************\
* *
* Copyright Wonderware Software Development Corp. 1992-1997 *
* *
* ThisFileName="L:\ww\dde_serv\src\udsample\udprotcl.c" *
* LastEditDate="1997 Nov 26 09:43:00" *
* *
\***********************************************************************/
#define LINT_ARGS
#include <windows.h>
#include <windowsx.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "ntconv.h"
#include "hmemcpy.h"
#include "chainmgr.h"
#include "udprot.h"
#include "uddefs.h"
#include "protocol.h"
#include "debug.h"
#include "wwassert.h"
#include "strval.h"
#include "udgetstr.h"
#include "ntsrvr.h"
USES_ASSERT
#define ENSURE_BCD /* force operands, results to valid BCD */
extern CHAIN PortList;
extern BOOL ShowingSend, ShowingReceive, ShowingEvents, ShowingErrors;
extern WORD tickChange;
extern BOOL bBldSendMsgInBinary, bBldRecvMsgInBinary;
extern int nBldRecvMsgMinLen;
extern BOOL bFlushOnError;
/***********************************************************************/
/** Data conversion tables **/
/** This table provides a simple way of getting a mask for bit n.
Note that for this table, bit 0 is the msbit of the word.
For bit 0 as the lsbit of the word, use bit 15-n to access the table. **/
static WORD bitMask[] = {
0x8000, 0x4000, 0x2000, 0x1000,
0x0800, 0x0400, 0x0200, 0x0100,
0x0080, 0x0040, 0x0020, 0x0010,
0x0008, 0x0004, 0x0002, 0x0001
};
/***********************************************************************/
/** local prototypes **/
static void WINAPI UdprotSendQuery(LPPORT lpPort, LPUDMSG lpMsg);
static void WINAPI UdprotDeleteCurWriteMsg(LPPORT lpPort);
static void WINAPI UdprotDeleteWriteMsg(LPUDMSG lpMsg, LPSTAT lpTopic);
static BOOL WINAPI UdprotValidMessage(LPPORT lpPort);
static void WINAPI UdprotCheckAndUpdateStatus (LPSTAT lpTopic);
static void WINAPI UdprotFailStationTopics (LPPORT lpPort);
static BOOL WINAPI UdprotSetTopicStatus (LPPORT lpPort, LPSTAT lpTopic, unsigned bFailed);
static void WINAPI UdprotSetMsgQuality (LPSTAT lpTopic, LPUDMSG lpMsg, PTQUALITY ptQuality);
static void WINAPI UdprotSetTopicQuality (LPSTAT lpTopic, PTQUALITY ptQuality);
static void WINAPI UdprotSetSlowPollMode (LPPORT lpPort, LPSTAT lpTopic);
static LPSTR WINAPI UdprotGetDateTimeString (LPPTTIME lpPtTime, LPSTR szDateTime);
#ifndef WIN32
#define DbNewVTQFromDevice(hLogDev, hProt, ptValue, lpPtTime, ptQuality) \
DbNewValueFromDevice(hLogDev, hProt, ptValue)
#endif
/***********************************************************************/
/** have the logger show the contents of the message being sent **/
void
WINAPI
showSendData(LPUDMSG lpMsg)
{
BYTE FAR *rd;
int i, n, L;
int max_str, max_msg;
/* get and check message length */
n = lpMsg->mmSize;
if (n == 0) {
/* no message being sent, nothing to display */
return;
}
/* get pointer to message */
rd = (BYTE FAR *) lpMsg->mmData;
/* get number of characters that can be stored in display string */
max_str = DBG_BUF_SIZE - 1;
/* format message for display */
strcpy(dbgBuf, GetString(STRUSER + 80) /* "S: " */ );
/****************************************************************\
Format the rest of the message and append it to dbgBuf.
Depending on the protocol, it may be appropriate to
convert bytes to hex ASCII, or simply copy an ASCII string.
\****************************************************************/
L = strlen (dbgBuf);
if (lpMsg->mmMsgInBinary) {
/* convert characters to hex ASCII */
if (!bBldSendMsgInBinary) {
/* indicate message converted from ASCII to binary */
strcpy (&dbgBuf[L], "[in binary] ");
L += strlen (&dbgBuf[L]);
}
max_msg = (max_str - L) / 2;
if (n > max_msg)
/* make sure message doesn't overflow buffer */
n = max_msg;
for (i = 1; i <= n; i++) {
sprintf (&dbgBuf[L], "%02X", *(rd++));
L += strlen (&dbgBuf[L]);
}
} else {
/* take characters just as they are */
max_msg = max_str - L;
if (n > max_msg)
/* make sure message doesn't overflow buffer */
n = max_msg;
_fstrncpy (&dbgBuf[L], (LPSTR) rd, n);
dbgBuf[L+n] = '\0';
}
/* output display string to logger */
debug(dbgBuf);
} /* showSendData */
/***********************************************************************/
/** have the logger show the contents of the message received **/
void
WINAPI
showReceivedData(LPPORT lpPort)
{
BYTE FAR *rd;
int i, n, L;
int max_str, max_msg;
/* get and check message length */
n = lpPort->mbRspIndex;
if (n == 0) {
/* message length is zero, indicate nothing received */
debug(GetString(STRUSER + 84) /* "R: <nothing>" */ );
return;
}
/* get pointer to message */
rd = lpPort->mbRspBuffer;
/* get number of characters that can be stored in display string */
max_str = DBG_BUF_SIZE - 1;
/* format message for display */
strcpy(dbgBuf, GetString(STRUSER + 85) /* "R: " */ );
/****************************************************************\
Format the rest of the message and append it to dbgBuf.
Depending on the protocol, it may be appropriate to
convert bytes to hex ASCII, or simply copy an ASCII string.
\****************************************************************/
L = strlen (dbgBuf);
if (lpPort->mbMsgInBinary) {
/* convert characters to hex ASCII */
if (!bBldRecvMsgInBinary) {
/* indicate message converted from ASCII to binary */
strcpy (&dbgBuf[L], "[in binary] ");
L += strlen (&dbgBuf[L]);
}
max_msg = (max_str - L) / 2;
if (n > max_msg)
/* make sure message doesn't overflow buffer */
n = max_msg;
for (i = 1; i <= n; i++) {
sprintf (&dbgBuf[L], "%02X", *(rd++));
L += strlen (&dbgBuf[L]);
}
} else {
/* take characters just as they are */
max_msg = max_str - L;
if (n > max_msg)
/* make sure message doesn't overflow buffer */
n = max_msg;
_fstrncpy (&dbgBuf[L], (LPSTR) rd, n);
dbgBuf[L+n] = '\0';
}
/* output display string to logger */
debug(dbgBuf);
} /* showReceivedData */
/***********************************************************************/
/** Initiate the transmission of a message out of the communication port.
The message may be a poll for new data or a write of data from the client.
The status from the last sent message will have to be checked
during the next time slice. **/
static
void
WINAPI
UdprotSendQuery(LPPORT lpPort,
LPUDMSG lpMsg)
{
int iWCRet;
/* indicate error if pointers are null or there is no current message */
assert(lpPort);
assert(lpMsg);
assert(lpPort->mbCurMsg);
if (lpMsg == (LPUDMSG) NULL) {
/* no message, just return */
return;
}
if (lpMsg->mmActiveCt == 0) {
/* active count is zero, indicate port is idle */
lpPort->mbState = PROT_IDLE;
return;
}
/* flush port buffers, indicate if residual received data is present */
FlushPort (lpPort, (LPSTR) "Port has data at command send time:");
/* attempt to write message to port */
iWCRet = WritePortMsg (lpPort, lpMsg);
if (iWCRet <= 0) {
/* error occurred on write, identify and display if appropriate */
/* set up port for error delay */
lpPort->mbTimer = (WORD) GetDeltaTime () + lpPort->mbReplyTime;
lpPort->mbState = PROT_PROTERRORDELAY;
} else {
/* message output successfully, set up to handle response */
if (ShowingSend)
/* output send message to logger */
showSendData(lpMsg);
/*
* Set the appropriate state, timeout, and initialize the
* response buffer
*/
lpPort->mbState = PROT_WAITHDR; /* wait state */
lpPort->mbTimer = (WORD) GetDeltaTime () +
lpPort->mbReplyTime; /* timeout */
lpPort->mbRspIndex = 0; /* bytes received */
/***************************************************************\
Setup the number of bytes to wait for in the PROT_WAITHDR
state. It can be any length up to the total length of the
expected response. If the length of the response is not
known at this time, then wait for enough bytes to arrive
so that the length of the response can be determined.
See the function GetResponse for further details.
lpPort->mbRspExpLen = length of the message header;
The example code below assumes the receive message will
contain a header or be one of a fixed set of error messages,
so that by the time a certain number of characters
nBldRecvMsgMinLen
have been received, we know how many are coming.
This value should be at least 1 so that even if the entire
message will be coming at once, we'll be able to recognize
that more than zero characters have arrived.
The BOOL variable bBldRecvMsgInBinary indicates whether
the incoming message is expected in binary or ASCII.
\***************************************************************/
//lpPort->mbRspExpLen = nBldRecvMsgMinLen;
lpPort->mbRspExpLen = INQSIZE;
lpPort->mbMsgInBinary = bBldRecvMsgInBinary;
}
} /* UdprotSendQuery */
/***********************************************************************/
/** Set up protocol poll:
If the communication port is clear,
see if an unacknowledged write message needs to be retransmitted.
If nothing was sent,
see if messages are now in the queue and send one of them. **/
void
WINAPI
UdprotPoll(LPPORT lpPort)
{
LPSTAT lpTopic, startTopic;
LPUDMSG lpMsg, startMsg, wMsg, rMsg;
BOOL found, done;
CHAINSCANNER station_scanner;
CHAINSCANNER message_scanner;
/* indicate error if pointer is null */
assert(lpPort);
/* get pointer to current station, if any */
startTopic = lpPort->mbCurTopic;
/* Set up scanner, find the current station on this port, if any
If no current station, find the first station on this port, if any */
lpTopic = (LPSTAT) FindItemStartingAt ((LPCHAINLINK) startTopic,
&lpPort->mbTopicList, SCAN_FROM_HEAD,
NULL, NULL, &station_scanner);
if (lpTopic == (LPSTAT) NULL)
/* no stations, just return */
return;
if (startTopic == (LPSTAT) NULL) {
/* no current station, set current station to first station */
lpPort->mbCurTopic = startTopic = lpTopic;
}
/** search through the stations on this port,
starting with the one AFTER the current station **/
found = FALSE;
do {
/*******************************/
/* get pointer to next station */
/*******************************/
/* check for end of list */
if (GetScannerNextItem (&station_scanner) != NULL) {
/* get next item from station list */
lpTopic = (LPSTAT) FindNextItem (&station_scanner);
} else {
/* end of list reached, wrap around to beginning of list */
lpTopic = (LPSTAT) FindFirstItem (&lpPort->mbTopicList,
SCAN_FROM_HEAD,
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -