Bonjour nick name is in Latin1 encoding
[kdenetwork.git] / kopete / protocols / bonjour / bonjourcontactconnection.h
blobc0d347ab2d0787bd18f2fdfa94a3418909a18885
1 /*
2 bonjourcontactconnection.h - Kopete Bonjour Protocol
4 Copyright (c) 2007 by Tejas Dinkar <tejas@gja.in>
5 Kopete (c) 2002-2003 by the Kopete developers <kopete-devel@kde.org>
7 *************************************************************************
8 * *
9 * This library is free software; you can redistribute it and/or *
10 * modify it under the terms of the GNU General Public *
11 * License as published by the Free Software Foundation; either *
12 * version 2 of the License, or (at your option) any later version. *
13 * *
14 *************************************************************************
17 #ifndef BONJOURCONTACTCONNECTION_H
18 #define BONJOURCONTACTCONNECTION_H
20 #include <QTcpSocket>
21 #include <QString>
22 #include <QHostAddress>
23 #include <QByteArray>
24 #include <QXmlStreamReader>
26 #include <kopetemessage.h>
28 /**
29 * @brief This Represents a connection to a contact
31 * The BonjourContactConnection contains a @ref socket which has a connection to some contact.
32 * Data from the @ref socket is parsed by the QXmlStreamReader @ref parser.
33 * We Get @ref BonjourXmlToken tokens one at a time using the @ref getNextToken() functions
34 * All Jabber specific code must be here ONLY
36 * There is a protocol document that nobody follows. This can be found here:
37 * http://www.xmpp.org/extensions/attic/jep-0174-0.5.html
38 * The standard is totally sucky, and I'm not surprised that there isn't a single client who
39 * follows it faithfully (that I know of). The standard `we` follow was derived from wireshark
40 * logs with a machine running Pidgen.
42 * Pass Two Strings for an outgoing connection (second constructor)
44 * @author Tejas Dinkar <tejas\@gja.in>
46 class BonjourContactConnection : public QObject {
48 Q_OBJECT
50 /**
51 * @brief The State of the Connection
53 * @ref connectionState holds this state
55 enum BonjourConnectionState {
56 BonjourConnectionNewOutgoing, // New Outgoing Stream
57 BonjourConnectionNewIncoming, // New Incoming Stream
59 BonjourConnectionOutgoingStream, // Expect a <stream>
60 BonjourConnectionToWho, // We are Unsure who we connect to
62 BonjourConnectionConnected = 50, // Connected
63 BonjourConnectionDisconnected, // Disconnected
65 BonjourConnectionError = 99 // Reserved for Future Use
66 } connectionState;
68 // The Actual Connection
69 QTcpSocket *socket;
71 // The XML Parser
72 QXmlStreamReader parser;
74 // The local and remote names
75 QString local;
77 // The local and remote names
78 QString remote;
80 // Set the Socket
81 void setSocket(QTcpSocket *socket);
83 /**
84 * @brief Description of A Token
86 * Internally used structures to describe a token as obtained by the parser
87 * Not all of these names represent valid token names. Some are just provided as a convenient
88 * way to call @ref getNextToken()
90 enum BonjourXmlTokenName {
91 BonjourXmlTokenOther,
92 BonjourXmlTokenNone,
93 BonjourXmlTokenStream,
94 BonjourXmlTokenMessage,
95 BonjourXmlTokenBody,
96 BonjourXmlTokenHtml,
97 BonjourXmlTokenX,
98 BonjourXmlTokenIq,
99 BonjourXmlTokenQuery,
101 BonjourXmlStartElement = 50, // Simply A Convenient Parameter to getNextToken
102 BonjourXmlEndElement, // No Token is ever of this type
103 BonjourXmlStartOrEndElement, // Instead see the value of 'type' (QXmlStreamReader::TokenType)
105 BonjourXmlTokenError = 99
109 * @brief table to translate between xml tokens and corresponding @BonjourXmlTokenName
111 * This is a Hash Object to Translate a qualified name into a BonjourXmlTokenName quickly
112 * Only one instance is needed. We derive from QHash and fill it in the constructor
114 static class TokenTable : public QHash <QString, BonjourXmlTokenName>{
115 public:
116 TokenTable();
117 } tokenTable;
120 * @brief This Describes a Token
122 * This Describes a Token. It contains a number of useful attributes like type, name, etc..
124 struct BonjourXmlToken {
125 QXmlStreamReader::TokenType type;
126 BonjourXmlTokenName name;
127 QStringRef qualifiedName;
128 QXmlStreamAttributes attributes;
129 QStringRef text;
133 * @brief Get the Next Token Read in Stream
135 * This Next Function Gets the Next Token in the stream
136 * This may be of any time. We recommend you pass it a parameter of what type(s)
137 * of tokens that you expect
139 * @return the token. If error, token.name will be BonjourXmlTokenError
141 const BonjourXmlToken getNextToken();
144 * @brief Get Next Token Of a Certain Type
146 * This Function returns the next token whose name matches. All tokens before this
147 * is found are simply thrown away.
148 * You May Also Search for Next Start Element or End Element (see @ref BonjourXmlTokenName)
150 * @param name The Name of the Next Token We want
151 * @return the token. If error, token.name will be BonjourXmlTokenError
153 const BonjourXmlToken getNextToken(BonjourXmlTokenName name);
156 * @brief This is called if we receive an iq packet
158 * iq is only sent by clients like miranda... Who don't care about the reply anyway.
159 * Later, we may implement support for iq packets. For now we ignore them.
161 * @todo FIXME: Currently we ignore everything between <iq> and </iq>
162 * @param token The Token Containing the iq. Will be erased
164 void ignoreAllIq(BonjourXmlToken &token);
167 public:
170 * @brief Constructor For Incoming Connections
172 * @param aSocket The Socket To Wrap Up
174 explicit BonjourContactConnection(QTcpSocket *aSocket, QObject *parent = NULL);
177 * @brief Constructor For Outgoing Connection
179 * This is For OutGoing Connections
180 * We Create a Socket Here, so this may take upto 3 seconds
182 * @param address The Address of the Remote Contact
183 * @param port The Port the contact is listening on
184 * @param remote The remoteuser@hostname
185 * @param local myself@hostname
187 BonjourContactConnection(const QHostAddress &address, short int port, const QString &alocal, const QString &aremote, QObject *parent = NULL);
189 // Destructor
190 ~BonjourContactConnection();
193 * @brief Write <stream:stream> in socket
195 * If the values of remote and local are set, we encode it in the stream as well
197 void sayStream();
200 * @brief Examine the Next Token, and perform action
202 * This Examines the Data From The Socket and emits a messageReceived (maybe)
203 * The Parameter is the most recent token.
205 * @param token The Most Recent Token. The value of this token is probably destroyed
207 void readData(BonjourXmlToken &token);
210 * @brief Called when we expect a stream token
212 * This is Called When a <stream> is expected
213 * The token should contain <stream>. If it doesn't, then we keep getting new tokens until
214 * we either get a <stream> or we get an EOF
216 * This emits either a @ref discoveredUserName() or @ref usernameNotInStream()
218 * @param token The token which probably contains the <stream>
220 void getStreamTag(BonjourXmlToken &token);
223 * @brief Called When we are connected, but don't know to who
225 * This is called when we are waiting for the remote and local values (incoming connections only).
226 * Honestly, this function is never used, as either signal emitted by @ref getSteam() may be used
227 * to uniquely identify a contact
229 * @todo FIXME: Currently unimplemented as (at least gaim) says who it is in the <stream>
231 void getWho(BonjourXmlToken &token);
234 * @brief Gets the Address of the Current Connection
236 * @return The HostAddress of the Remote Contact
238 QHostAddress getHostAddress();
241 * @brief Create a new Message
243 * This Creates a Message
245 * @param direction The Direction of the Message
246 * @return The Message
248 Kopete::Message newMessage(Kopete::Message::MessageDirection direction);
251 * @brief Get a message from stream of tokens
253 * This reads all tokens upto (and including) a </message>, and attempts to assemble
254 * a message out of the tokens. This emits a @ref messageReceived() signal if a message
255 * can be read.
257 * @todo FIXME: HTML messages are ignored
259 * @param token A Token which contains a <message>. It's value will be destroyed
261 void readMessage(BonjourXmlToken &token);
264 * @brief Check if a Connection is ready for general data transfer
265 * @return @c true if it is connected, @c false otherwise
267 inline bool isConnected()
269 return connectionState == BonjourConnectionConnected;
273 * @brief Send a </stream>
275 void sayGoodBye();
278 * @brief Set @ref remote and @ref local strings externally
280 * This function is usually called if the contact is identified via an
281 * IP lookup, and not via the stream element.
283 * @param remote The Remote User
284 * @param local The Local User
286 void setRemoteAndLocal(const QString &remote, const QString &local);
288 signals:
291 * @brief This Signal is Emitted when there is new data
293 * @todo FIXME: This is unused. Remove it
295 void newData(BonjourContactConnection *);
298 * @brief Signal Emitted when we discover who the remote user is
300 * This signal is emitted when we discover who we are connected to (unverified)
301 * Used in Incoming Connections Only
303 * The Username is sent back
305 void discoveredUserName(BonjourContactConnection *, const QString &);
308 * @brief Send if the stream tag didn't contain a from and to
310 * This signal is sent if we can't figure out who it is
312 void usernameNotInStream(BonjourContactConnection *);
315 * @brief This signal is sent if the @ref socket is disconnected
317 * This Signal is basically forwarding disconnect signal from socket
319 void disconnected(BonjourContactConnection *);
322 * @brief Signal Emitted when a new message has been received (already formatted)
324 void messageReceived(Kopete::Message);
327 * @brief Signal Emitted if we could not connect to an external socket
329 void errorCouldNotConnect();
331 public slots:
334 * @brief This slot is called by the socket, to signify new data
336 void dataInSocket();
339 * @brief This is Called when the socket disconnects
341 * This basically emits @ref disconnected()
343 void socketDisconnected();
346 * @brief Send a message
348 void sendMessage(const Kopete::Message &message);
351 #endif