summaryrefslogtreecommitdiffstats
path: root/kopete/protocols/groupwise/libgroupwise/coreprotocol.h
diff options
context:
space:
mode:
Diffstat (limited to 'kopete/protocols/groupwise/libgroupwise/coreprotocol.h')
-rw-r--r--kopete/protocols/groupwise/libgroupwise/coreprotocol.h202
1 files changed, 202 insertions, 0 deletions
diff --git a/kopete/protocols/groupwise/libgroupwise/coreprotocol.h b/kopete/protocols/groupwise/libgroupwise/coreprotocol.h
new file mode 100644
index 00000000..4cd30b88
--- /dev/null
+++ b/kopete/protocols/groupwise/libgroupwise/coreprotocol.h
@@ -0,0 +1,202 @@
+/*
+ Kopete Groupwise Protocol
+ coreprotocol.h- the core GroupWise protocol
+
+ Copyright (c) 2004 SUSE Linux AG http://www.suse.com
+
+ Based on Iris, Copyright (C) 2003 Justin Karneges
+
+ Kopete (c) 2002-2004 by the Kopete developers <kopete-devel@kde.org>
+
+ *************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Lesser General Public *
+ * License as published by the Free Software Foundation; either *
+ * version 2 of the License, or (at your option) any later version. *
+ * *
+ *************************************************************************
+*/
+
+#ifndef GW_CORE_PROTOCOL_H
+#define GW_CORE_PROTOCOL_H
+
+#include <qcstring.h>
+#include <qobject.h>
+#include <qptrlist.h>
+
+#include "gwfield.h"
+
+class EventProtocol;
+class ResponseProtocol;
+class Request;
+class Transfer;
+
+/**
+ * This class handles transforming data between structured high level messages and encoded bytes that are sent
+ * and received over the network.
+ *
+ * 0) FIELD ARRAYS
+ * ---------------
+ * This is relevant to both input and output handling.
+ * Requests (out) and Responses (in) are messages containing, after a HTTP header, a series of 'Fields'.
+ * A message may contain a flat series of Fields, or each Field may mark the start of a nested array of more Fields.
+ * In this case the Field's value is the length of the following nested array.
+ * The length of the top level Field series is not given. The message ends when there are no more Fields expected as part of a nested array,
+ * and is marked by a terminator.
+ * The encoding used for Fields differs for Requests and Responses, and is described below.
+ *
+ * 1) INPUT
+ * --------
+ * The input functionality is a finite state machine that processes the stream of data from the GroupWise server.
+ * Since the server may arbitrarily truncate or run together protocol level messages, we buffer the incoming data stream,
+ * parsing it into individual messages that are removed from the buffer and passed back to the ClientStream, which propagates
+ * them to higher layers.
+ *
+ * Incoming data may be in either of two formats; a Response or an Event.
+ * All binary data is Little Endian on the network.
+ *
+ * 1.1) INPUT MESSAGE 'SPECIES'
+ *
+ * 1.1.1) Events
+ *
+ * Events are independently occuring notifications generated by the server or by the activity of other users.
+ * Events are represented on the wire in binary format:
+ *
+ * BYTE 1
+ * 0 8 6....
+ * AAAABBBBCCCCCCCCC....DDDDDDDD.....
+ * AAAA is a UINT32 giving the type of event
+ * BBBB is a UINT32 giving the length of the event source,
+ * CCCC... is the event source, a UTF8 encoded string, which is observed to be zero terminated
+ * DDDD... is event dependent binary data, which frequently consists of the conference the event relates to,
+ * conference flags describing the logging, chat security and closed status, and message data.
+ *
+ * As the DDDD portion is irregularly structured, it must be processed knowing the semantics of the event type.
+ * See the @ref EventProtocol documentation.
+ *
+ * Event message data is always a UINT32 giving the message length, then a message in RTF format.
+ * The message length may be zero.
+ *
+ * 1.1.2) Responses
+ * Responses are the server's response to client Requests. Each Request generates one Response. Requests and Responses are regularly structured
+ * and can be parsed/generated without any knowledge of their content.
+ * Responses consist of text/line oriented standard HTTP headers, followed by a binary payload. The payload is a series of Fields as described above,
+ * and the terminator following the last field is a null (0x0) byte.
+ *
+ * TODO: Add Field structure format: type, tag, method, flags, and value. see ResponseProtocol::readFields() for reference if this is incomplete.
+ *
+ * 1.3) INPUT PROCESSING IMPLEMENTATION
+ * CoreProtocol input handling operates on an event driven basis. It starts processing when it receives data via @ref addIncomingData(),
+ * and emits @ref incomingData() as each complete message is parsed in off the wire.
+ * Each call to addIncomingData() may result in zero or more incomingData() signals
+ *
+ * 2) REQUESTS
+ * -----------
+ * The output functionality is an encoding function that transforms outgoing Requests into the wire request format
+ * - a HTTP POST made up of the request operation type as the path, followed by a series of (repeated) variables that form the arguments.
+ * Order of the arguments is significant!
+ * Argument values are URL-encoded with spaces encoded as + rather than %20.
+ * The terminator used is a CRLF pair ("\r\n").
+ * HTTP headers are only used in a login operation, where they contain a Host: hostname:port line.
+ * Headers are separated from the arguments by a blank line (only CRLF) as usual.
+ *
+ * 3) USER MESSAGE BODY TEXT REPRESENTATION
+ * -----------------------------------
+ * Message text sent by users (found in both Requests and Events) is generally formatted as Rich Text Format.
+ * Text portions of the RTF may be be encoded in
+ * any of three ways -
+ * ascii text,
+ * latin1 as hexadecimal,
+ * escaped unicode code points (encoded/escaped as \uUNICODEVALUE?, with or without a space between the end of the unicode value and the ? )
+ * Outgoing messages may contain rich text, and additionally the plain text encoded as UTF8, but this plain payload is apparently ignored by the server
+ *
+ */
+class CoreProtocol : public QObject
+{
+Q_OBJECT
+public:
+ enum State { NeedMore, Available, NoData };
+
+ CoreProtocol();
+
+ virtual ~CoreProtocol();
+ /**
+ * Debug output
+ */
+ static void debug(const QString &str);
+
+ /**
+ * Reset the protocol, clear buffers
+ */
+ void reset();
+
+ /**
+ * Accept data from the network, and buffer it into a useful message
+ * @param incomingBytes Raw data in wire format.
+ */
+ void addIncomingData( const QByteArray& incomingBytes );
+
+ /**
+ * @return the incoming transfer or 0 if none is available.
+ */
+ Transfer* incomingTransfer();
+
+ /**
+ * Convert a request into an outgoing transfer
+ * emits @ref outgoingData() with each part of the transfer
+ */
+ void outgoingTransfer( Request* outgoing );
+
+ /**
+ * Get the state of the protocol
+ */
+ int state();
+
+signals:
+ /**
+ * Emitted as the core protocol converts fields to wire ready data
+ */
+ void outgoingData( const QByteArray& );
+ /**
+ * Emitted when there is incoming data, parsed into a Transfer
+ */
+ void incomingData();
+protected slots:
+ /**
+ * Just a debug method to test emitting to the socket, atm - should go to the ClientStream
+ */
+ void slotOutgoingData( const QCString & );
+
+protected:
+ /**
+ * Check that there is data to read, and set the protocol's state if there isn't any.
+ */
+ bool okToProceed();
+ /**
+ * Convert incoming wire data into a Transfer object and queue it
+ * @return number of bytes from the input that were parsed into a Transfer
+ */
+ int wireToTransfer( const QByteArray& wire );
+ /**
+ * Convert fields to a wire representation. Emits outgoingData as each field is written.
+ * Calls itself recursively to process nested fields, hence
+ * @param depth Current depth of recursion. Don't use this parameter yourself!
+ */
+ void fieldsToWire( Field::FieldList fields, int depth = 0 );
+ /**
+ * encodes a method number (usually supplied as a #defined symbol) to a char
+ */
+ QChar encode_method( Q_UINT8 method );
+private:
+ QByteArray m_in; // buffer containing unprocessed bytes we received
+ QDataStream* m_din; // contains the packet currently being parsed
+ int m_error;
+ Transfer* m_inTransfer; // the transfer that is being received
+ int m_state; // represents the protocol's overall state
+ EventProtocol* m_eventProtocol;
+ ResponseProtocol * m_responseProtocol;
+};
+
+#endif
+