1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
|
/*
msnsocket.h - Base class for the sockets used in MSN
Copyright (c) 2002 by Martijn Klingens <[email protected]>
Copyright (c) 2002-2004 by Olivier Goffart <ogoffart @ kde.org>
Copyright (c) 2005 by Gregg Edghill <[email protected]>
Kopete (c) 2002 by the Kopete developers <[email protected]>
Portions of this code are taken from KMerlin,
(c) 2001 by Olaf Lueg <[email protected]>
*************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
*************************************************************************
*/
#ifndef MSNSOCKET_H
#define MSNSOCKET_H
#include <qobject.h>
#include <qdatastream.h>
#include <qstringlist.h>
#include <qtimer.h>
#include <qvaluelist.h>
#include "kopete_export.h"
namespace KNetwork {
class KBufferedSocket;
class KServerSocket;
}
class MimeMessage;
/**
* @author Martijn Klingens <[email protected]>
*
* MSNSocket encapsulates the common functionality shared by the Dispatch
* Server, the Notification Server and the Switchboard Server. It is
* inherited by the various specialized classes.
*/
class KOPETE_EXPORT MSNSocket : public QObject
{
Q_OBJECT
public:
MSNSocket(QObject* parent=0l);
~MSNSocket();
/**
* Asynchronously read a block of data of the specified size. When the
* data is available, the blockRead() signal will be emitted with the
* data as parameter.
*
* NOTE: As the block queue takes precedence over the line-based
* command-processing this method can effectively block all
* communications when passed a wrong length!
*/
void readBlock( uint len );
/**
* OnlineStatus encapsulates the 4 states a connection can be in,
* Connecting, Connected, Disconnecting, Disconnected. Connecting
* and Disconnecting are in the default implementation not used,
* because the socket connect is an atomic operation and not yet
* performed asynchronously.
* In derived classes, like the Notification Server, this state is
* actively used, because merely having a socket connection established
* by no means indicates we're actually online - the rest of the
* handshake likely has to follow first.
*/
enum OnlineStatus { Connecting, Connected, Disconnecting, Disconnected };
enum LookupStatus { Processing, Success, Failed };
enum Transport { TcpTransport, HttpTransport };
enum ErrorType { ErrorConnectionLost, ErrorConnectionError, ErrorCannotConnect, ErrorServerError, ErrorInformation};
OnlineStatus onlineStatus() { return m_onlineStatus; }
/*
* return the local ip.
* Used for filetransfer
*/
QString getLocalIP();
//BEGIN Http
virtual bool setUseHttpMethod( bool useHttp );
bool useHttpMethod() const;
//END
public slots:
void connect( const QString &server, uint port );
virtual void disconnect();
/**
* Send an MSN command to the socket
*
* For debugging it's convenient to have this method public, but using
* it outside this class is deprecated for any other use!
*
* The size of the body (if any) is automatically added to the argument
* list and shouldn't be explicitly specified! This size is in bytes
* instead of characters to reflect what actually goes over the wire.
*
* if the param binary is set to true, then, the body is send as a binary message
*
* return the id
*/
int sendCommand( const QString &cmd, const QString &args = QString::null,
bool addId = true, const QByteArray &body = QByteArray() , bool binary=false );
signals:
/**
* A block read is ready.
* After this the normal line-based reads go on again
*/
void blockRead( const QByteArray &block );
/**
* The online status has changed
*/
void onlineStatusChanged( MSNSocket::OnlineStatus status );
/**
* The connection failed
*/
void connectionFailed();
/**
* The connection was closed
*/
void socketClosed();
/**
* A error has occured. Handle the display of the message.
*/
void errorMessage( int type, const QString &msg );
protected:
/**
* Convenience method: escape spaces with '%20' for use in the protocol.
* Doesn't escape any other sequence.
*/
QString escape( const QString &str );
/**
* And the other way round...
*/
QString unescape( const QString &str );
/**
* Set the online status. Emits onlineStatusChanged.
*/
void setOnlineStatus( OnlineStatus status );
/**
* This method is called directly before the socket will actually connect.
* Override in derived classes to setup whatever is needed before connect.
*/
virtual void aboutToConnect();
/**
* Directly after the connect, this method is called. The default
* implementation sets the OnlineStatus to Connected, be sure to override
* this if a handshake is required.
*/
virtual void doneConnect();
/**
* Directly after the disconnect, this method is called before the actual
* cleanup takes place. The socket is close here. Cleanup internal
* variables here.
*/
virtual void doneDisconnect();
/**
* Handle an MSN error condition.
* The default implementation displays a generic error message and
* closes the connection. Override to allow more graceful handling and
* possibly recovery.
*/
virtual void handleError( uint code, uint id );
/**
* Handle an MSN command response line.
* This method is pure virtual and *must* be overridden in derived
* classes.
*/
virtual void parseCommand( const QString &cmd, uint id,
const QString &data ) = 0;
/**
* Used in MSNFileTransferSocket
*/
virtual void bytesReceived( const QByteArray & );
bool accept( KNetwork::KServerSocket * );
void sendBytes( const QByteArray &data );
const QString &server() { return m_server; }
uint port() { return m_port; }
/**
* The last confirmed ID by the server
*/
//uint m_lastId;
private slots:
void slotDataReceived();
/**
* If the socket emits a connectionFailed() then this slot is called
* to handle the error.
*/
void slotSocketError( int error );
/*
* Calls connectDone() when connection is successfully established.
*/
void slotConnectionSuccess();
/**
* Sets m_lookupProgress to 'Finished' if count > 0 or 'Failed' if count = 0.
*/
void slotHostFound( );
/**
* Check if new lines of data are available and process the first line
*/
void slotReadLine();
void slotSocketClosed();
//BEGIN Http
/**
* Sends a poll request to the msn gateway when using HttpTransport.
* equivalent to sending a PNG command over TcpTransport.
*/
void slotHttpPoll();
//END
protected slots:
virtual void slotReadyWrite();
private:
/**
* Check if we're waiting for a block of raw data. Emits blockRead()
* when the data is available.
* Returns true when still waiting and false when there is no pending
* read, or when the read is successfully handled.
*/
bool pollReadBlock();
/**
* The id of the message sent to the MSN server. This ID will increment
* for each subsequent message sent.
*/
uint m_id;
/**
* Queue of pending commands (should be mostly empty, but is needed to
* send more than one command to the server)
*/
QValueList<QByteArray> m_sendQueue;
/**
* Parse a single line of data.
* Will call either parseCommand or handleError depending on the type of
* data received.
*/
void parseLine( const QString &str );
KNetwork::KBufferedSocket *m_socket;
OnlineStatus m_onlineStatus;
QString m_server;
uint m_port;
/**
* The size of the requested block for block-based reads
*/
uint m_waitBlockSize;
class Buffer : public QByteArray
{
public:
Buffer( unsigned size = 0 );
~Buffer();
void add( char *str, unsigned size );
QByteArray take( unsigned size );
};
Buffer m_buffer;
//BEGIN Http
/**
* Makes a http request headers string using the specified, host, query, and content length.
* return: The string containing the http request headers.
*/
QString makeHttpRequestString(const QString& host, const QString& query, uint contentLength);
bool m_useHttp; // Indicates whether to use the msn http gateway to connect to the msn service.
bool m_bCanPoll; // Indicates whether polling of the http server is allowed.
bool m_bIsFirstInTransaction; // Indicates whether pending message to be sent is the first in the transaction.
// If so, the gateway is used.
// Use the gateway only for initial connected state; Otherwise, use the host.
QString m_gateway; // Msn http gateway domain name.
QString m_gwip; // The ip address of the msn gateway.
QString m_sessionId; // session id.
QTimer *m_timer; // Msn http poll timer.
QString m_type; // Indicates the type of socket being used. NS or SB
bool m_pending; // Indicates whether a http response is pending.
int m_remaining; // Indicates how many bytes of content data remain
// to be received if the content bytes are sent in
// a seperate packet(s).
/**
* Provides access to information returned from a URI request.
*/
class WebResponse
{
public:
WebResponse(const QByteArray& bytes);
~WebResponse();
/**
* Gets the headers associated with this response from the server.
*/
MimeMessage* getHeaders();
/**
* Gets the data stream used to read the body of the response from the server.
*/
QDataStream* getResponseStream();
/**
* Gets the status code of the response.
*/
int getStatusCode();
/**
* Gets the status description returned with the response.
*/
QString getStatusDescription();
private:
MimeMessage *m_headers;
QDataStream *m_stream;
int m_statusCode;
QString m_statusDescription;
};
//END
};
#endif
|