📄 dmtpclientpackethandler.java
字号:
// ----------------------------------------------------------------------------// Copyright 2006-2008, 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.//// ----------------------------------------------------------------------------// Change History:// 2006/03/26 Martin D. Flynn// -Initial release// 2006/05/26 Martin D. Flynn// -Now accepts a PKT_CLIENT_UNIQUE_ID payload of up to 20 bytes.// 2007/02/25 Martin D. Flynn// -Changed to respond with server EOB (rather than EOT) if any pending packets// were sent to the client. Also, pending packets will continue to be// sent until there are no more packets to send. This allows the Device DB// implementation to optimize the storage and retrieval of pending packets.// 2007/12/04 Martin D. Flynn// -Hold on to PendingPackets if an error occurred during the session// 2008/01/10 Martin D. Flynn// -Added ability to record connection information/statistics// 2008/04/04 Martin D. Flynn// -Changed error messages for unrecognized custom event packet types.// -Allow client to respond with an event template during the same session // where the server has responded with a NAK_FORMAT_NOT_RECOGNIZED error.// ----------------------------------------------------------------------------package org.opendmtp.server.base;import java.lang.*;import java.util.*;import java.io.*;import java.net.*;import java.sql.*;import org.opengts.util.*;import org.opendmtp.codes.*;import org.opendmtp.server.db.*;public class DMTPClientPacketHandler extends AbstractClientPacketHandler{ // ------------------------------------------------------------------------ // Set this to 'true' for production. // When 'false' this prevents the device table from being updated with marked connection // information, allowing unlimited connections to occur in a short period of time. // This mode is useful for debugging purposes, but should not be used in production. private static boolean SAVE_MARKED_CONNECTION_INFO = true; // ------------------------------------------------------------------------ //private int dataNdx = 0; private boolean terminate = false; /* duplex/simplex */ private boolean isDuplex = true; /* session start time */ private long sessionStartTime = 0L; /* session IP address */ private InetAddress inetAddress = null; private String ipAddress = null; /* packet */ private int encoding = Encoding.ENCODING_UNKNOWN; /* Fletcher checksum */ private FletcherChecksum fletcher = null; /* identification */ private AccountID accountId = null; private DeviceID deviceId = null; /* event accounting */ private int eventTotalCount = 0; private int eventBlockCount = 0; private Event lastValidEvent = null; private Packet eventErrorPacket = null; private int formatErrorCount = 0; private int formatErrorType = 0; private int formatRecvTemplate = 0; // number of event template packets received private boolean expectEventTemplate = false; /* pending packets */ private boolean sendPending = true; private PacketList pendingPackets = null; public DMTPClientPacketHandler() { super(); this.fletcher = new FletcherChecksum(); } // ------------------------------------------------------------------------ public void sessionStarted(InetAddress inetAddr, boolean isTCP, boolean isText) { super.sessionStarted(inetAddr, isTCP, isText); /* init */ this.sessionStartTime = DateTime.getCurrentTimeSec(); this.inetAddress = inetAddr; this.ipAddress = (inetAddr != null)? inetAddr.getHostAddress() : null; this.isDuplex = isTCP; this.eventTotalCount = 0; this.formatErrorCount = 0; this.formatErrorType = 0; /* debug message */ if (this.isDuplex) { Print.logInfo("Begin Duplex communication: " + this.ipAddress); } else { Print.logInfo("Begin Simplex communication: " + this.ipAddress); } } public void sessionTerminated(Throwable err, long readCount, long writeCount) { // called before the socket is closed boolean hasError = (err != null); /* clear any pending packets if no errors have occurred */ if (hasError) { if (this.pendingPackets != null) { Print.logWarn("**** Session terminating with errors (PendingPackets remain intact)"); } else { Print.logWarn("Session terminating with errors"); } } else { try { this._clearPendingPackets(); } catch (PacketParseException ppe) { // ignore any error at this point } } /* save session statistics */ if (this.deviceId != null) { this.deviceId.saveSessionStatistics(this.sessionStartTime,this.ipAddress,this.isDuplex,readCount,writeCount,this.eventTotalCount); } /* log session termination */ if (this.isDuplex()) { Print.logInfo("End Duplex communication: " + this.ipAddress); // short pause to 'help' make sure the pending outbound data is transmitted try { Thread.sleep(75L); } catch (Throwable t) {} } else { Print.logInfo("End Simplex communication: " + this.ipAddress); } } // ------------------------------------------------------------------------ public boolean isDuplex() { return this.isDuplex; } // ------------------------------------------------------------------------ public int getActualPacketLength(byte packet[], int packetLen) { if ((packetLen >= 1) && (packet[0] == Encoding.AsciiEncodingChar)) { // look for line terminator return -1; } else if (packetLen >= Packet.MIN_HEADER_LENGTH) { int payloadLen = (int)packet[2] & 0xFF; return Packet.MIN_HEADER_LENGTH + payloadLen; } else { // this should not occur, since minimum length has been set above return 0; } } // ------------------------------------------------------------------------ public byte[] getHandlePacket(byte pktBytes[]) { String ipAddr = this.getHostAddress(); //Print.logInfo("handlePacket: IP = " + ipAddr); Packet resp[] = this._parsePacket(ipAddr, pktBytes); if ((resp == null) || (resp.length == 0)) { //Print.logWarn("<-- null (no response)"); return null; } else if (this.isDuplex()) { if (resp.length == 1) { Print.logDebug("==> " + resp[0].toString(this.encoding)); return resp[0].encode(this.encoding); } else { ByteArrayOutputStream baos = new ByteArrayOutputStream(); for (int i = 0; i < resp.length; i++) { Print.logDebug("==> " + resp[i].toString(this.encoding)); byte b[] = resp[i].encode(this.encoding); baos.write(b, 0, b.length); } return baos.toByteArray(); } } else { Print.logError("Response discarded due to Simplex communication"); return null; } } // ------------------------------------------------------------------------ /* indicate that the session should terminate */ public boolean terminateSession() { return this.terminate; } /* set terminate session */ private void _setTerminateSession() { this.terminate = true; } // ------------------------------------------------------------------------ /* load account/device from unique id */ private void loadUniqueID(String ipAddr, byte id[]) throws PacketParseException { /* device already defined? */ if (this.deviceId != null) { Print.logError("Device ID already defined"); throw new PacketParseException(ServerErrors.NAK_PROTOCOL_ERROR, null); // errData ok } /* invalid id specified? */ UniqueID uniqId = new UniqueID(id); if (!uniqId.isValid()) { throw new PacketParseException(ServerErrors.NAK_ID_INVALID, null); // errData ok } /* load device */ DeviceID devId = DeviceID.loadDeviceID(uniqId); // will throw PacketParseException if named DeviceID does not exist /* set account/device */ this._setAccountId(ipAddr, devId.getAccountID()); this._setDeviceId(ipAddr, devId); } // ------------------------------------------------------------------------ private void loadAccountId(String ipAddr, String acctName) throws PacketParseException { /* account already defined? */ if (this.accountId != null) { Print.logError("Account ID already defined"); throw new PacketParseException(ServerErrors.NAK_PROTOCOL_ERROR, null); // errData ok } else if ((acctName == null) || acctName.equals("")) { Print.logError("Account name is null/empty"); throw new PacketParseException(ServerErrors.NAK_ACCOUNT_INVALID, null); // errData ok } /* load account */ AccountID acctId = AccountID.loadAccountID(acctName.toLowerCase()); // will throw PacketParseException if named AccountID does not exist /* set account */ this._setAccountId(ipAddr, acctId); } private void _setAccountId(String ipAddr, AccountID acctId) throws PacketParseException { /* null? */ if (acctId == null) { throw new PacketParseException(ServerErrors.NAK_ACCOUNT_INVALID, null); // errData ok } /* validate account */ if (!acctId.isActive()) { throw new PacketParseException(ServerErrors.NAK_ACCOUNT_INACTIVE, null); // errData ok } this.accountId = acctId; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -