~ubuntu-branches/ubuntu/trusty/kvirc/trusty

« back to all changes in this revision

Viewing changes to src/modules/objects/KvsObject_socket.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Kai Wasserbäch, Kai Wasserbäch, Raúl Sánchez Siles
  • Date: 2011-02-12 10:40:21 UTC
  • mfrom: (14.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20110212104021-5mh4f75jlku20mnt
The combined "Twisted Experiment" and "Nocturnal Raid" release.

[ Kai Wasserbäch ]
* Synced to upstream's SVN revision 5467.
* debian/rules:
  - Added .PHONY line.
  - Resurrect -DMANUAL_REVISION, got lost somewhere and we build SVN
    revisions again.
  - Replace "-DWITH_NO_EMBEDDED_CODE=YES" with "-DWANT_CRYPTOPP=YES".
  - Change the remaining -DWITH/-DWITHOUT to the new -DWANT syntax.
* debian/control:
  - Removed DMUA, I'm a DD now.
  - Changed my e-mail address.
  - Removed unneeded relationships (no upgrades over two releases are
    supported).
  - Fix Suggests for kvirc-dbg.
  - kvirc-data: Make the "Suggests: kvirc" a Recommends, doesn't make much
    sense to install the -data package without the program.
* debian/source/local-options: Added with "unapply-patches".
* debian/kvirc.lintian-overrides: Updated to work for 4.1.1.
* debian/patches/21_make_shared-mime-info_B-D_superfluous.patch: Updated.
* debian/kvirc-data.install: Added .notifyrc.

[ Raúl Sánchez Siles ]
* Stating the right version where kvirc-data break and replace should happen.
* Fixing link to license file.
* Added French and Portuguese man pages.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//=============================================================================
 
2
//
 
3
//   File : KvsObject_socket.cpp
 
4
//   Creation date : Sun Nov 11 03:13:45 2001 GMT by Szymon Stefanek
 
5
//
 
6
//   This file is part of the KVIrc irc client distribution
 
7
//   Copyright (C) 2001-2010 Szymon Stefanek (pragma at kvirc dot net)
 
8
//
 
9
//   This program is FREE software. You can redistribute it and/or
 
10
//   modify it under the terms of the GNU General Public License
 
11
//   as published by the Free Software Foundation; either version 2
 
12
//   of the License, or (at your opinion) any later version.
 
13
//
 
14
//   This program is distributed in the HOPE that it will be USEFUL,
 
15
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
17
//   See the GNU General Public License for more details.
 
18
//
 
19
//   You should have received a copy of the GNU General Public License
 
20
//   along with this program. If not, write to the Free Software Foundation,
 
21
//   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
22
//
 
23
//=============================================================================
 
24
 
 
25
#include "KvsObject_socket.h"
 
26
#include "KvsObject_memoryBuffer.h"
 
27
#include "KvsObject_file.h"
 
28
 
 
29
 
 
30
 
 
31
#include "kvi_settings.h"
 
32
#include "KviQString.h"
 
33
 
 
34
#include "kvi_debug.h"
 
35
 
 
36
#include "KviFile.h"
 
37
#include "KviFileUtils.h"
 
38
#include "KviLocale.h"
 
39
#include "KviError.h"
 
40
#include "KviNetUtils.h"
 
41
#include "KviDnsResolver.h"
 
42
#include "KviError.h"
 
43
#include "kvi_socket.h"
 
44
#include "KviMemory.h"
 
45
#include "KviDataBuffer.h"
 
46
 
 
47
#include <QByteArray>
 
48
#include <QTcpSocket>
 
49
#include <QUdpSocket>
 
50
#include <QAbstractSocket>
 
51
#include <QHostAddress>
 
52
#include <QTcpServer>
 
53
 
 
54
const char * const sockstate_tbl[] = {
 
55
        "Unconnected",
 
56
        "HostLookUp",
 
57
        "Connecting",
 
58
        "Connected",
 
59
        "Bound",
 
60
        "Listening",
 
61
        "Closing"
 
62
};
 
63
 
 
64
const char * const sockerrors_tbl[] = {
 
65
        "ConnectionRefused",
 
66
        "RemoteHostClosed",
 
67
        "HostNotFound",
 
68
        "SocketAccess",
 
69
        "SocketResource",
 
70
        "SocketTimeout",
 
71
        "DatagramTooLarge",
 
72
        "Network",
 
73
        "AddressInUse",
 
74
        "SocketAddressNotAvailable",
 
75
        "UnsupportedSocketOperation",
 
76
        "ProxyAuthenticationRequired",
 
77
        "SslHandshakeFailed",
 
78
        "UnfinishedSocketOperation",
 
79
        "ProxyConnectionRefused",
 
80
        "ProxyConnectionClosed",
 
81
        "ProxyConnectionTimeout",
 
82
        "ProxyNotFound",
 
83
        "ProxyProtocol",
 
84
        "UnknownSocket"
 
85
};
 
86
/*
 
87
        @doc: socket
 
88
        @keyterms:
 
89
                socket object class
 
90
        @title:
 
91
                socket class
 
92
        @type:
 
93
                class
 
94
        @short:
 
95
                A Ipv4/Ipv6 TCP socket
 
96
        @inherits:
 
97
                [class]object[/class]
 
98
        @description:
 
99
                This class provides a standard TCP/IP socket functionality.[br]
 
100
                It can be used either for connecting to a remote host or to listening for incoming connections.[br]
 
101
                If the KVIrc executable has been compiled with the IPV6 protocol support, this socket also supports it.[br]
 
102
        @functions:
 
103
                !fn: <integer or string> $status(<asString:boolean>)
 
104
                Returns the status of the socket :[br]
 
105
                0=Unconnected
 
106
                1=HostLookUp
 
107
                2=Connecting[br]
 
108
                3=Connected[br]
 
109
                4=Bound[br]
 
110
                5=Closing[br]
 
111
                6=Listening
 
112
                
 
113
                !fn: $connect(<host>,<port>)
 
114
                Attempts a connection to <host> on port <port>.[br]
 
115
                <host> can be a numeric internet address (either Ipv4 or Ipv6 (if supported)) or a hostname.[br]
 
116
                If a hostname is used, a DNS lookup is performed (the socket enters the "dns call" state).[br]
 
117
                This function returns 1 if the connect attempt can be successfully initiated,
 
118
                0 otherwise.[br] In fact, this function returns 0 only if the supplied <port> parameter
 
119
                is invalid or the socket is in an incoherent state (already connected or listening):
 
120
                for a newly created socket and with a valid <port> number you can safely ignore
 
121
                the return value.[br]
 
122
                Please note that the connection is asynchronous: when this function returns
 
123
                the socket is NOT connected: it has just initiated the connect attempt
 
124
                and you will be notified of the attempt result by an asynchronous event call:
 
125
                in case of failure, $connectFailedEvent() will be called, in case of
 
126
                succes, $connectEvent() will be called.
 
127
                
 
128
                !fn: $listen([<port>[,<interface>[,<force_ipv6>]]])
 
129
                Attempts to listen on the specified <port> and <interface>.[br]
 
130
                If <port> is not passed it is assumed to be 0, if <interface> is not passed, it is assumed to be
 
131
                "any interface" (INADDR_ANY).[br] Port 0 means that the kernel should choose a "random" port to listen on.[br]
 
132
                If the <interface> is recognized as IPV6 address, and IPV6 is supported, the socket listens
 
133
                in IPV6 mode. If <interface> is an empty string and <force_ipv6> is 1 the socket listens
 
134
                on "any ipv6 interface".[br]
 
135
                This function returns '1' in case of success and '0' in case of failure.[br]
 
136
                On some systems listening in the IPV6 namespace allows to accept also IPV4 connections (this includes
 
137
                linux but not windows afaik).[br]
 
138
                When an incoming connection will arrive, $incomingConnectionEvent() will be called.
 
139
                
 
140
                !fn: $connectedEvent()
 
141
                This function is called when a connection attempt has been successfully completed.
 
142
                The socket is actually connected to [classfnc:socket]$remoteIp[/classfnc]() on
 
143
                [classfnc:socket]$remotePort[/classfnc](). You can start
 
144
                writing data and you may expect [classfnc:socket]$dataAvailableEvent[/classfnc]() to be
 
145
                triggered.
 
146
                
 
147
                !fn: $incomingConnectionEvent(<socket:h_object>)
 
148
                This function is called when an incoming connection arrives over a socket in listening state.[br]
 
149
                You must return 1 if you to terminad this incoming connectioncall [classfnc:socket]$accept[/classfnc]() passing a newly created socket object
 
150
                to accept and handle the connection.[br] If you don't call [classfnc:socket]$accept[/classfnc]()
 
151
                the incoming connection will be automatically terminated.
 
152
 
 
153
                !fn: $connectFailedEvent(<reason>)
 
154
                This function is called when a connection attempt fails for some reason. <reason> contains
 
155
                the error string.[br]
 
156
                This function may be called only between a call to [classfnc:socket]$connect[/classfnc]() and
 
157
                the [classfnc:socket]$connectEvent[/classfnc]().
 
158
 
 
159
                !fn: $disconnectEvent([error])
 
160
                This function is called when a connection is terminated either cleanly or because of an error.[br]
 
161
                [error] is an empty string in case of a "clean" termination (connection closed by the remote host)
 
162
                or is a message describing the socket error that caused the connection to be interrupted.
 
163
 
 
164
                !fn: $dataAvailableEvent(<data_length>)
 
165
                This function is called when some data is available to be read: the <data_length> parameter specifies
 
166
                the length of the available data in bytes.[br]
 
167
                You can use one of the $read* functions to obtain the data
 
168
                
 
169
                !fn: $read(<length>[,<hobject>])
 
170
                Reads at most <length> bytes of data from the socket. If <length> is anything "outside" the
 
171
                available data range (<length> < 0 or <length> > available_data_length), this function
 
172
                returns all the available data.[br]
 
173
                By default this function can deal ascii data only: NULL characters are transformed to
 
174
                ASCII characters 255. You can pass a [class]memorybuffer[/class] object to read binary data.
 
175
                
 
176
                !fn: $write(<data, array,files or hobject>[,length])
 
177
                Writes <data> to the socket.[br]
 
178
                This function can deal with binary data passing  a [class]memorybuffer[/class] object[br]
 
179
                Please note that when this function finishes it does not mean that the data has reached the remote end.[br]
 
180
                Basically it does not even mean that the data has been sent to the remote host.[br]
 
181
                The data is enqueued for sending and will be sent as soon as possible.[br]
 
182
                Using an array you can pass bytes or data string like this: @$write($array($(0xff),$(0xff),$(0xff),$(0xff),"This is an example"));
 
183
                If you're going to [cmd]delete[/cmd] this object just after the $write call, you should
 
184
                call [classfnc:socket]$close[/classfnc]() just before [cmd]delete[/cmd] to ensure the data delivery.
 
185
                
 
186
                !fn: $close()
 
187
                Resets this socket state: kills any pending or active connection. After a close() call
 
188
                the socket may be used for a new connection.[br]
 
189
                If there is an active connection, there is a last attempt to flush the pending outgoing data.[br]
 
190
                You don't need to call $close() if you [cmd]delete[/cmd] the socket: KVIrc will
 
191
                reset the socket state automatically and free the memory. But if you want to ensure data delivery
 
192
                after a $write call sequece and just before a [cmd]delete[/cmd], $close() is the only chance to do it.
 
193
                
 
194
                !fn: $remoteIp()
 
195
                Returns the IP address of the remote end of this socket.[br]
 
196
                The return value is meaningful only if the socket is in connected or connecting state.
 
197
                
 
198
                !fn: $setProtocol(<protocol>)
 
199
                Let KVIrc use TCP or UDP protocol
 
200
                
 
201
                !fn: $remotePort()
 
202
                Returns the port of the remote end of this socket.[br]
 
203
                The return value is meaningful only if the socket is in connected or connecting state.
 
204
                
 
205
                !fn: $localIp()
 
206
                Returns the IP address of the local end of this socket.[br]
 
207
                The return value is meaningful only if the socket is in connected, listening or connecting state.
 
208
                
 
209
                !fn: $localPort()
 
210
                Returns the port of the local end of this socket.[br]
 
211
                The return value is meaningful only if the socket is in connected, listening or connecting state.
 
212
 
 
213
@examples:
 
214
                [example]
 
215
                // Server socket: listen 8080 port and answer to requests (multi-threaded)
 
216
                class("webserver","socket")
 
217
                {
 
218
                        function incomingConnectionEvent()
 
219
                        {
 
220
                            // incoming connection socket passed by the framework
 
221
                            %socket = $0
 
222
                            debug "Webserver incoming Conection from: %socket->$remoteIp : %socket->$remotePort"
 
223
                            %socket->$write("HTTP/1.0 200 OK\n\n<html><head></head><body><h1>KVIrc Webserver</h1></body></html>\n")
 
224
                            // tells KVIrc no need this socket anymore
 
225
                            return $true()
 
226
                        }
 
227
                        function constructor()
 
228
                        {
 
229
                            debug listen @$listen(8080, "127.0.0.1")
 
230
                        }
 
231
                }
 
232
                // finally start webserver
 
233
                %WebS = $new(webserver)
 
234
                [/example]
 
235
                [example]
 
236
                // Client socket - go to google and grab request header[br]
 
237
                class("httprequest","socket")
 
238
                {
 
239
                        function errorEvent()
 
240
                        {
 
241
                                // the connection to the server failed
 
242
                                debug  "Connection failed: "$0
 
243
                                delete $$
 
244
                        }
 
245
                        function disconnectedEvent()
 
246
                        {
 
247
                                // connection has been closed
 
248
                                debug  "Connection is closed"
 
249
                                delete $$
 
250
                        }
 
251
                        function destructor()
 
252
                        {
 
253
                                // if the socket is still open close it
 
254
                                if(@$status() == "Connected") @$close()
 
255
                        }
 
256
                        function stateChangedEvent()
 
257
                        {
 
258
                                debug socket state $0
 
259
                        }
 
260
                        function dataAvailableEvent()
 
261
                        {
 
262
                                // reading the received data
 
263
                                debug reading $0 bytes
 
264
                                %newdata  = @$read($0)
 
265
                                debug data:  %newdata
 
266
                                // close and delete the socket
 
267
                                @$close()
 
268
                                delete $$
 
269
                        }
 
270
                        function constructor()
 
271
                        {
 
272
                                // connect to the server
 
273
                                @$connect("www.google.com",80)
 
274
                        }
 
275
                        function connectedEvent()
 
276
                        {
 
277
                                // connection is complete
 
278
                                // send a request to receive the headers only from http://www.google.com/
 
279
                                debug connected
 
280
                                debug written bytes @$write("HEAD / HTTP/1.1\r\nHost: www.google.de\r\nConnection: Close\r\nUser-Agent: KVIrc socket\r\n\r\n") on socket;
 
281
                        }
 
282
                }
 
283
                %Temp = $new(httprequest)
 
284
                [/example]
 
285
*/
 
286
 
 
287
KVSO_BEGIN_REGISTERCLASS(KvsObject_socket,"socket","object")
 
288
 
 
289
        KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,status)
 
290
        KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,remotePort)
 
291
        KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,remoteIp)
 
292
        KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,localIp)
 
293
        KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,localPort)
 
294
        KVSO_REGISTER_HANDLER(KvsObject_socket,"connect",functionConnect)
 
295
        KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,close)
 
296
        KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,read)
 
297
        KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,write)
 
298
        KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,bytesAvailable)
 
299
 
 
300
        KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,setProtocol)
 
301
        KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,listen)
 
302
        KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,dataAvailableEvent)
 
303
        KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,incomingConnectionEvent)
 
304
        KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,connectedEvent)
 
305
        KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,disconnectedEvent)
 
306
        KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,errorEvent)
 
307
        KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,hostFoundEvent)
 
308
        KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,stateChangedEvent)
 
309
 
 
310
KVSO_END_REGISTERCLASS(KvsObject_socket)
 
311
 
 
312
bool KvsObject_socket::init(KviKvsRunTimeContext *c,KviKvsVariantList *)
 
313
{
 
314
        m_pSocket = new QTcpSocket();
 
315
        m_pServer = 0;
 
316
        m_pContext = c ;
 
317
        makeConnections();
 
318
        return true;
 
319
}
 
320
 
 
321
 
 
322
KVSO_BEGIN_CONSTRUCTOR(KvsObject_socket,KviKvsObject)
 
323
KVSO_END_CONSTRUCTOR(KvsObject_socket)
 
324
 
 
325
KVSO_BEGIN_DESTRUCTOR(KvsObject_socket)
 
326
        if (m_pSocket)delete m_pSocket;
 
327
        m_pSocket = 0;
 
328
        if (m_pServer) delete m_pServer;
 
329
        m_pServer = 0;
 
330
KVSO_END_DESTRUCTOR(KvsObject_socket)
 
331
//----------------------
 
332
 
 
333
 
 
334
KVSO_CLASS_FUNCTION(socket,status)
 
335
{
 
336
 
 
337
        c->returnValue()->setString(getStateString(m_pSocket->state()));
 
338
        return true;
 
339
}
 
340
 
 
341
KVSO_CLASS_FUNCTION(socket,close)
 
342
{
 
343
        Q_UNUSED(c);
 
344
        m_pSocket->disconnectFromHost();
 
345
        return true;
 
346
}
 
347
 
 
348
KVSO_CLASS_FUNCTION(socket,remotePort)
 
349
{
 
350
        c->returnValue()->setInteger(m_pSocket->peerPort());
 
351
        return true;
 
352
}
 
353
 
 
354
KVSO_CLASS_FUNCTION(socket,remoteIp)
 
355
{
 
356
        c->returnValue()->setString(m_pSocket->peerAddress().toString());
 
357
        return true;
 
358
}
 
359
 
 
360
KVSO_CLASS_FUNCTION(socket,localPort)
 
361
{
 
362
        c->returnValue()->setInteger(m_pSocket->localPort());
 
363
        return true;
 
364
}
 
365
KVSO_CLASS_FUNCTION(socket,bytesAvailable)
 
366
{
 
367
        c->returnValue()->setInteger(m_pSocket->bytesAvailable());
 
368
        return true;
 
369
}
 
370
KVSO_CLASS_FUNCTION(socket,localIp)
 
371
{
 
372
        c->returnValue()->setString(m_pSocket->localAddress().toString());
 
373
        return true;
 
374
}
 
375
 
 
376
 
 
377
KVSO_CLASS_FUNCTION(socket,read)
 
378
{
 
379
        kvs_int_t iLen;
 
380
        KviKvsObject * pObject;
 
381
        kvs_hobject_t hObject;
 
382
        KVSO_PARAMETERS_BEGIN(c)
 
383
                KVSO_PARAMETER("length",KVS_PT_INTEGER,KVS_PF_OPTIONAL,iLen)
 
384
                KVSO_PARAMETER("hobject",KVS_PT_HOBJECT,KVS_PF_OPTIONAL,hObject)
 
385
        KVSO_PARAMETERS_END(c)
 
386
        if (iLen>m_pSocket->bytesAvailable() || !iLen) iLen=m_pSocket->bytesAvailable();
 
387
        if (hObject)
 
388
        {
 
389
                pObject=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
 
390
                if(!pObject)
 
391
                {
 
392
                        c->warning(__tr2qs_ctx("Buffer parameter is not an object","objects"));
 
393
                        return true;
 
394
                }
 
395
                if(pObject->inheritsClass("memorybuffer"))
 
396
                {
 
397
                        QByteArray *pBuffer=((KvsObject_memoryBuffer *)pObject)->pBuffer();
 
398
                        int oldsize=pBuffer->size();
 
399
                        pBuffer->resize(oldsize+iLen);
 
400
                        m_pSocket->read(pBuffer->data()+oldsize,iLen);
 
401
                } 
 
402
                else if(pObject->inheritsClass("file"))
 
403
                {
 
404
                        KviFile *pFile=((KvsObject_file *)pObject)->file();
 
405
                        if (!pFile->isOpen())
 
406
                        {
 
407
                                c->warning(__tr2qs_ctx("File is not open!","objects"));
 
408
                                return true;
 
409
                        }
 
410
                        pFile->write(m_pSocket->read(iLen));
 
411
                } 
 
412
                else
 
413
                {
 
414
                        c->warning(__tr2qs_ctx("Buffer parameter is not a memorybuffer object","objects"));
 
415
                        return true;
 
416
                }
 
417
                return true;
 
418
        }
 
419
        if(iLen > 0)
 
420
        {
 
421
                // convert NULLS to char 255
 
422
                char * buffer = (char*) KviMemory::allocate(iLen);
 
423
                m_pSocket->read(buffer,iLen);
 
424
                for(unsigned int i = 0;i < iLen;i++)
 
425
                {
 
426
                        if(!buffer[i]) buffer[i] = (char)(255);
 
427
                }
 
428
                QString tmpBuffer = QString::fromUtf8(buffer,iLen);
 
429
                c->returnValue()->setString(tmpBuffer);
 
430
                KviMemory::free(buffer);
 
431
        }
 
432
        return true;
 
433
}
 
434
 
 
435
 
 
436
 
 
437
KVSO_CLASS_FUNCTION(socket,write)
 
438
{
 
439
        kvs_uint_t uLen;
 
440
        KviKvsObject * pObject;
 
441
        KviKvsVariant * pVariantData;
 
442
        kvs_hobject_t hObject;
 
443
        KVSO_PARAMETERS_BEGIN(c)
 
444
                KVSO_PARAMETER("data_or_file_or_memorybuffer",KVS_PT_VARIANT,0,pVariantData)
 
445
                KVSO_PARAMETER("length",KVS_PT_UNSIGNEDINTEGER,KVS_PF_OPTIONAL,uLen)
 
446
        KVSO_PARAMETERS_END(c)
 
447
        if (pVariantData->isHObject())
 
448
        {
 
449
                pVariantData->asHObject(hObject);
 
450
                pObject = KviKvsKernel::instance()->objectController()->lookupObject(hObject);
 
451
                if(!pObject)
 
452
                {
 
453
                        c->warning(__tr2qs_ctx("Buffer parameter is not an object","objects"));
 
454
                        return true;
 
455
                }
 
456
                if(pObject->inheritsClass("memorybuffer"))
 
457
                {
 
458
                        QByteArray *p=((KvsObject_memoryBuffer *)pObject)->pBuffer();
 
459
                        m_pSocket->write(*p);
 
460
                } 
 
461
                else if(pObject->inheritsClass("file"))
 
462
                {
 
463
                        KviFile * pFile = ((KvsObject_file *)pObject)->file();
 
464
                        if(!pFile->isOpen())
 
465
                        {
 
466
                                c->warning(__tr2qs_ctx("File is not open!","objects"));
 
467
                                return true;
 
468
                        }
 
469
                        if(!uLen) uLen = pFile->size();
 
470
                        kvs_int_t size = pFile->size();
 
471
                        pFile->flush();
 
472
                        m_pSocket->write((const char*)pFile->read(uLen).data(),uLen);
 
473
                        c->returnValue()->setBoolean((size-pFile->pos()==0));
 
474
                } else {
 
475
                        c->warning(__tr2qs_ctx("Buffer parameter is not a memorybuffer or file object","objects"));
 
476
                        return true;
 
477
                }
 
478
        } else {
 
479
                if(pVariantData->isArray())
 
480
                {
 
481
                        KviKvsArray * pArray = pVariantData->array();
 
482
                        for(unsigned int i=0; i < pArray->size(); i++)
 
483
                        {
 
484
                                KviKvsVariant * pVar = pArray->at(i);
 
485
                                kvs_int_t iValue;
 
486
                                if(pVar->asInteger(iValue))
 
487
                                {
 
488
                                        if(iValue < 256 && iValue >= 0)
 
489
                                        {
 
490
                                                m_pSocket->putChar(iValue);
 
491
                                                continue;
 
492
                                        } else {
 
493
                                                c->warning(__tr2qs_ctx("Only values in the range of 0-255 are allowed: integer %d is out of range","objects"),iValue);
 
494
                                                return true;
 
495
                                        }
 
496
                                } else {
 
497
                                        if(pVar->isString())
 
498
                                        {
 
499
                                                QString szData;
 
500
                                                pVar->asString(szData);
 
501
                                                QByteArray szData8 = szData.toUtf8();
 
502
                                                m_pSocket->write((const char*)szData8.data(),szData8.length());
 
503
                                        } else {
 
504
                                                c->warning(__tr2qs_ctx("Datatype not supported","objects"));
 
505
                                                return true;
 
506
                                        }
 
507
                                }
 
508
                        }
 
509
                        return true;
 
510
                }
 
511
                QString szData;
 
512
                pVariantData->asString(szData);
 
513
                if(!KviFileUtils::fileExists(szData))
 
514
                {
 
515
                        QByteArray szData8 = szData.toUtf8();
 
516
                        if(szData8.length() > 0)
 
517
                        {
 
518
                                qDebug("write on socket %s",szData8.data());
 
519
                                kvs_int_t bytes=m_pSocket->write((const char*)szData8.data(),szData8.length());
 
520
                                c->returnValue()->setInteger(bytes);
 
521
                        }
 
522
                } else {
 
523
                        KviFile f(szData);
 
524
                        f.open(QIODevice::ReadOnly);
 
525
                        QByteArray ar = f.readAll();
 
526
                        m_pSocket->write((const char*)ar.data(),ar.size());
 
527
                        f.close();
 
528
                }
 
529
        }
 
530
        return true;
 
531
}
 
532
KVSO_CLASS_FUNCTION(socket,setProtocol)
 
533
{
 
534
        QString szProto;
 
535
        KVSO_PARAMETERS_BEGIN(c)
 
536
                KVSO_PARAMETER("protocol",KVS_PT_STRING,0,szProto)
 
537
        KVSO_PARAMETERS_END(c)
 
538
        if (m_pSocket) delete m_pSocket;
 
539
        if(KviQString::equalCI(szProto,"udp")) m_pSocket = new QUdpSocket();
 
540
        else m_pSocket = new QTcpSocket();
 
541
        makeConnections();
 
542
        return true;
 
543
}
 
544
KVSO_CLASS_FUNCTION(socket,functionConnect)
 
545
{
 
546
        kvs_uint_t uRemotePort;
 
547
        QString szRemoteIp;
 
548
        KVSO_PARAMETERS_BEGIN(c)
 
549
                KVSO_PARAMETER("remote_ip",KVS_PT_STRING,0,szRemoteIp)
 
550
                KVSO_PARAMETER("remote_port",KVS_PT_UNSIGNEDINTEGER,0,uRemotePort)
 
551
        KVSO_PARAMETERS_END(c)
 
552
        if (uRemotePort>65535)
 
553
        {
 
554
                c->warning(__tr2qs_ctx("Value %d for port is out of range (values allowed are from 0 to 65535)","objects"),uRemotePort);
 
555
                return true;
 
556
        }
 
557
        m_pSocket->connectToHost(szRemoteIp,uRemotePort);
 
558
        c->returnValue()->setBoolean(true);
 
559
        return true;
 
560
}
 
561
 
 
562
KVSO_CLASS_FUNCTION(socket,listen)
 
563
{
 
564
        kvs_uint_t uLocalPort;
 
565
        QString m_szLocalIp;
 
566
        KVSO_PARAMETERS_BEGIN(c)
 
567
                KVSO_PARAMETER("local_port",KVS_PT_UNSIGNEDINTEGER,0,uLocalPort)
 
568
                KVSO_PARAMETER("interface",KVS_PT_STRING,KVS_PF_OPTIONAL,m_szLocalIp)
 
569
        KVSO_PARAMETERS_END(c)
 
570
        if (uLocalPort>65535)
 
571
        {
 
572
                c->warning(__tr2qs_ctx("Value %d for port is out of range (values allowed are from 0 to 65535): switch to random value","objects"),uLocalPort);
 
573
                uLocalPort=0;
 
574
        }
 
575
        if(m_pServer) delete m_pServer;
 
576
        m_pServer = new QTcpServer();
 
577
        QHostAddress address(m_szLocalIp);
 
578
        bool bOk=m_pServer->listen(address,uLocalPort);
 
579
        connect(m_pServer,SIGNAL(newConnection()),this,SLOT(slotNewConnection()));
 
580
        c->returnValue()->setBoolean(bOk);
 
581
        return true;
 
582
}
 
583
void KvsObject_socket::makeConnections()
 
584
{
 
585
        connect(m_pSocket,SIGNAL(connected()),this,SLOT(slotConnected()));
 
586
        connect(m_pSocket,SIGNAL(readyRead()),this,SLOT(slotReadyRead()));
 
587
        connect(m_pSocket,SIGNAL(disconnected()),this,SLOT(slotDisconnected()));
 
588
        connect(m_pSocket,SIGNAL(error( QAbstractSocket::SocketError)),this,SLOT(slotError(QAbstractSocket::SocketError)));
 
589
        connect(m_pSocket,SIGNAL(hostFound()),this,SLOT(slotHostFound()));
 
590
        connect(m_pSocket,SIGNAL(stateChanged(QAbstractSocket::SocketState)),this,SLOT(slotStateChanged(QAbstractSocket::SocketState)));
 
591
        //proxyAuthenticationRequired ( const QNetworkProxy & proxy, QAuthenticator * authenticator )
 
592
}
 
593
const char * KvsObject_socket::getStateString(QAbstractSocket::SocketState state)
 
594
{
 
595
        int idx=0;
 
596
        switch(state)
 
597
        {
 
598
                case QAbstractSocket::UnconnectedState:
 
599
                {
 
600
                        idx=0;
 
601
                        break;
 
602
                }
 
603
                case QAbstractSocket::HostLookupState:
 
604
                {
 
605
                        idx=1;
 
606
                        break;
 
607
                }
 
608
                case QAbstractSocket::ConnectingState:
 
609
                {
 
610
                        idx=2;
 
611
                        break;
 
612
                }
 
613
                case QAbstractSocket::ConnectedState:
 
614
                {
 
615
                        idx=3;
 
616
                        break;
 
617
                }
 
618
                case QAbstractSocket::BoundState:
 
619
                {
 
620
                        idx=4;
 
621
                        break;
 
622
                }
 
623
                case QAbstractSocket::ListeningState:
 
624
                {
 
625
                        idx=5;
 
626
                        break;
 
627
                }
 
628
                case QAbstractSocket::ClosingState:
 
629
                {
 
630
                        idx=6;
 
631
                        break;
 
632
                }
 
633
                default:
 
634
                {
 
635
                        // internal state?
 
636
                }
 
637
            }
 
638
            return sockstate_tbl[idx];
 
639
}
 
640
 
 
641
// slots
 
642
void KvsObject_socket::slotReadyRead()
 
643
{
 
644
        KviKvsVariantList lParams;
 
645
        lParams.append(new KviKvsVariant((kvs_int_t)m_pSocket->bytesAvailable()));
 
646
        callFunction(this,"dataAvailableEvent",&lParams);
 
647
}
 
648
void KvsObject_socket::slotConnected()
 
649
{
 
650
        KviKvsVariantList *lParams=0;
 
651
        callFunction(this,"connectedEvent",lParams);
 
652
}
 
653
 
 
654
void KvsObject_socket::slotDisconnected()
 
655
{
 
656
        KviKvsVariantList *lParams=0;
 
657
        callFunction(this,"disconnectedEvent",lParams);
 
658
}
 
659
 
 
660
void KvsObject_socket::slotError( QAbstractSocket::SocketError socketError )
 
661
{
 
662
        KviKvsVariantList lParams;
 
663
        QString szError = sockerrors_tbl[socketError];
 
664
        lParams.append(new KviKvsVariant(szError));
 
665
         callFunction(this,"errorEvent",&lParams);
 
666
}
 
667
 
 
668
void KvsObject_socket::slotHostFound()
 
669
{
 
670
        KviKvsVariantList *lParams=0;
 
671
        callFunction(this,"hostFoundEvent",lParams);
 
672
}
 
673
 
 
674
void KvsObject_socket::slotStateChanged( QAbstractSocket::SocketState socketState )
 
675
{
 
676
        KviKvsVariantList lParams;
 
677
        QString szState = getStateString(socketState);
 
678
        lParams.append(new KviKvsVariant(szState));
 
679
        callFunction(this,"stateChangedEvent",&lParams);
 
680
}
 
681
 
 
682
void KvsObject_socket::slotNewConnection()
 
683
{
 
684
        qDebug ("New connection");
 
685
        QTcpSocket *pSocket =  m_pServer->nextPendingConnection();
 
686
        KviKvsObjectClass * pClass = KviKvsKernel::instance()->objectController()->lookupClass("socket");
 
687
        KviKvsVariantList lParams;
 
688
        KviKvsObject * pObject = pClass->allocateInstance(0,"internalsocket",m_pContext,&lParams);
 
689
        ((KvsObject_socket *)pObject)->setInternalSocket(pSocket);
 
690
        kvs_hobject_t hobj=pObject->handle();
 
691
        KviKvsVariantList params(new KviKvsVariant(hobj));
 
692
        bool ret=false;
 
693
        KviKvsVariant *retv=new KviKvsVariant(ret);
 
694
        callFunction(this,"incomingConnectionEvent",retv,&params);
 
695
        if (retv){
 
696
                pObject=KviKvsKernel::instance()->objectController()->lookupObject(hobj);
 
697
                if (pObject) pObject->dieNow();
 
698
        }
 
699
}
 
700
KVSO_CLASS_FUNCTION(socket,incomingConnectionEvent)
 
701
{
 
702
        emitSignal("incomingConnection",c,c->params());
 
703
        return true;
 
704
}
 
705
KVSO_CLASS_FUNCTION(socket,dataAvailableEvent)
 
706
{
 
707
        emitSignal("dataAvailable",c,c->params());
 
708
        return true;
 
709
}
 
710
 
 
711
KVSO_CLASS_FUNCTION(socket,connectedEvent)
 
712
{
 
713
        emitSignal("connected",c,c->params());
 
714
        return true;
 
715
}
 
716
 
 
717
KVSO_CLASS_FUNCTION(socket,disconnectedEvent)
 
718
{
 
719
        emitSignal("disconnected",c,c->params());
 
720
        return true;
 
721
}
 
722
 
 
723
KVSO_CLASS_FUNCTION(socket,errorEvent)
 
724
{
 
725
        emitSignal("error",c,c->params());
 
726
        return true;
 
727
}
 
728
 
 
729
KVSO_CLASS_FUNCTION(socket,hostFoundEvent)
 
730
{
 
731
        emitSignal("hostFound",c,c->params());
 
732
        return true;
 
733
}
 
734
 
 
735
KVSO_CLASS_FUNCTION(socket,stateChangedEvent)
 
736
{
 
737
        emitSignal("stateChanged",c,c->params());
 
738
        return true;
 
739
}
 
740
 
 
741
#ifndef COMPILE_USE_STANDALONE_MOC_SOURCES
 
742
#include "m_KvsObject_socket.moc"
 
743
#endif //!COMPILE_USE_STANDALONE_MOC_SOURCES
 
744
 
 
745
 
 
746
 
 
747