~ubuntu-branches/ubuntu/hoary/kvirc/hoary

« back to all changes in this revision

Viewing changes to src/kvirc/kvi_scriptsocket.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Robin Verduijn
  • Date: 2004-12-14 15:32:19 UTC
  • mfrom: (0.2.1 upstream) (1.1.1 warty)
  • Revision ID: james.westby@ubuntu.com-20041214153219-fdink3gyp2s20b6g
Tags: 2:2.1.3.1-2
* Change Recommends on xmms to a Suggests.
* Rebuild against KDE 3.3.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//
2
 
//   This file is part of the KVirc irc client distribution
3
 
//   Copyright (C) 1999-2000 Szymon Stefanek (stefanek@tin.it)
4
 
//
5
 
//   This program is FREE software. You can redistribute it and/or
6
 
//   modify it under the terms of the GNU General Public License
7
 
//   as published by the Free Software Foundation; either version 2
8
 
//   of the License, or (at your opinion) any later version.
9
 
//
10
 
//   This program is distributed in the HOPE that it will be USEFUL,
11
 
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
 
//   See the GNU General Public License for more details.
14
 
//
15
 
//   You should have received a copy of the GNU General Public License
16
 
//   along with this program. If not, write to the Free Software Foundation,
17
 
//   Inc. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
 
//
19
 
 
20
 
#define _KVI_DEBUG_CHECK_RANGE_
21
 
 
22
 
#include "kvi_scriptsocket.h"
23
 
#include "kvi_error.h"
24
 
#include "kvi_netutils.h"
25
 
#include "kvi_malloc.h"
26
 
#include "kvi_debug.h"
27
 
#include "kvi_memmove.h"
28
 
 
29
 
#include <sys/socket.h>
30
 
#include <netdb.h>
31
 
#include <fcntl.h>
32
 
#include <errno.h>
33
 
#include <unistd.h>
34
 
 
35
 
/*
36
 
        @class: socket
37
 
        @short:
38
 
                A socket device.
39
 
        @inherits:
40
 
                <a href="class_object.kvihelp">object</a>
41
 
        @functions:
42
 
                !fn: $setDomain(&lt;domain&gt;)
43
 
                Set the domain of the socket: valid values for &lt;domain&gt; are:<br>
44
 
                inet and unix. (inet is the default for new socket objects)<br>
45
 
 
46
 
                !fn: $domain()
47
 
                Returns the name of the domain of the socket.
48
 
 
49
 
                !fn: $setType(&lt;type&gt;)
50
 
                Set the type of the socket: valid values for &lt;type&gt; are:<br>
51
 
                stream and raw. (stream is the default for new socket objects)<br>
52
 
 
53
 
                !fn: $type()
54
 
                Returns the type of the socket
55
 
 
56
 
                !fn: $setProtocol(&lt;protocol&gt;)
57
 
                Sets the protocol of the socket .<br>
58
 
                The &lt;protocol&gt; argument is the protocol name to be matched
59
 
                in the /etc/protocols file (see man getprotobyname :).<br>
60
 
                (The default protocol is "ip" : that should work in most cases).<br>
61
 
 
62
 
                !fn: $protocol()
63
 
                Returns the protocol of the socket
64
 
 
65
 
                !fn: $lastError()
66
 
                Returns the last error string
67
 
 
68
 
                !fn: $setMode(&lt;data_mode&gt;)
69
 
                Sets the data mode of the socket.<br>
70
 
                The valid modes are:<br>
71
 
                - Ascii : for text based protocols (pop3 , irc...) , messages separated by combinations of CR and LF characters<br>
72
 
                - Hex : hexadecimal endoded , for binary protocols. (see <a href="s_hextostr.kvihelp">$HexToStr()</a> and <a href="s_strtohex.kvihelp">$StrToHex()</a>)
73
 
 
74
 
                !fn: $mode()
75
 
                Returns the data mode of the socket.
76
 
 
77
 
                !fn: $write(&lt;string&gt;)
78
 
                Writes data to the socket and returns the length of the written buffer (that may also be zero!).<br>
79
 
                If a serious error occures , -1 is returned and the OnDisconnect event is triggered.<br>
80
 
                Please note that this function does NOT implicitly write a trailing CR or LF:
81
 
                you must add it by yourself (All text based protocols require a messages terminator).<br>
82
 
                Please note that this function can be called either in Ascii or Hex mode.<br>
83
 
 
84
 
                !fn: $writeHex(&lt;hexstring&gt;)
85
 
                Writes data (transformed to binary form) to the socket and returns the length of the written buffer (that may also be zero!).<br>
86
 
                If an error occures , the OnDisconnect event is fired and -1 is returned.<br>
87
 
                The hexstring is a string of pairs of hexadecimal digits that encode the bytes to be sent.<br>
88
 
                This is useful when you want send null or unprintable characters.<br>
89
 
                For example $writeHex(68656C6C6F00) writes a null terminated "hello" string to the socket.<br>
90
 
                There is no other way to write the null character.<br>
91
 
                (see also <a href="s_hextostr.kvihelp">$HexToStr()</a> and <a href="s_strtohex.kvihelp">$StrToHex()</a>)<br>
92
 
                Please note that this function can be called either in Ascii or Hex mode.<br>
93
 
 
94
 
                !fn: $close()
95
 
                Closes the connection. The OnDisconnect event is NOT fired.<br>
96
 
 
97
 
                !fn: $state()
98
 
                Returns the state of the socket : ready , connecting , listening or connected.<br>
99
 
 
100
 
                !fn: $connect(&lt;ipaddress&gt;,&lt;port&gt;)
101
 
                Attempts a connection to the specified host on a specified port.<br>
102
 
                This function returns 1 if the creation of the socket and the "connect" system call
103
 
                have been succesfull. Please note that this does NOT mean that you're connected:
104
 
                the connection attempt has been only started.<br>
105
 
                From that moment you can receive two events:<br>
106
 
                OnConnectFailed , if the connection fails for some reason (for example the specified
107
 
                host is unreachable) or OnConnect when the connection has been estabilished.<br>
108
 
                If this function returns 0 you can obtain the error string by calling $lastError().<br>
109
 
 
110
 
                !fn: $listen(&lt;local_interface_address&gt;,&lt;port&gt;)
111
 
                Starts listening for incoming connectons on the specified port.<br>
112
 
                &lt;local_interface_address&gt; can be a valid ip address of a local
113
 
                network interface or the string "any" (or "default") that will cause to listen
114
 
                on all available interfaces.<br>
115
 
                This function returns 1 if the socket creation and the system "listen" call
116
 
                have been succesfull. Please nothe that this does NOT mean that you're connected
117
 
                to some host: the listening has just been started.<br>
118
 
                When a connection arrives the "OnIncomingConnection" event will be triggered.<br>
119
 
                If this function returns 0 you can obtain the error string by calling $lastError().<br>
120
 
                Please note that not all ports are available to be "listened":
121
 
                especially , if you're not the root user , you may have no access to ports below 1024.<br>
122
 
                This function may fail also if some other "entity" is listening on the specified port.<br>
123
 
                Passing 0 as the &lt;port&gt; argument causes the kernel to select the first available port for you,
124
 
                (....at least on Linux).<br>
125
 
 
126
 
                !fn: $host()
127
 
                Returns the ip address of the currently connected remote host
128
 
 
129
 
                !fn: $port()
130
 
                Returns the remote end port of the current connection
131
 
 
132
 
                !fn: $accept(&lt;listening_socket_id&gt;)
133
 
                This function accepts an incoming connection that is pending on the specified listening socket.<br>
134
 
                Returns 1 on success , 0 otherwise.<br>
135
 
                Please note that usually the &lt;listening_socket_id&gt; is NOT *this* socket.<br>
136
 
                Commonly , you will create a listening socket and override its OnIncomingConnection event.<br>
137
 
                There you will create a new socket object to serve the incoming connection and call its
138
 
                $accept member function passing the listening socket id.<br>
139
 
                See the OnIncomingConnection example.<br>
140
 
                The most common failure causes are:<br>
141
 
                - The &lt;listening_socket_id&gt; is not an object id at all (the object can't be found)<br>
142
 
                - The &lt;listening_socket_id&gt; object id does not refer to a class that inherits socket<br>
143
 
                - The &lt;listening_socket_id&gt; socket has no pending incoming connections.<br>
144
 
                You can retrieve the failure reason by calling $lastError().<br>
145
 
                After a succesfull call of this function , the caller socket is ready to communicate:<br>
146
 
                You can retrieve the remote host and port data with the $host and $port functions.<br>
147
 
                The OnConnect event is not triggered (not useful).<br>
148
 
 
149
 
                !fn: $localhost()
150
 
                Returns the IP address of the local host.<br>
151
 
                This identifier returns valid values only when the socket object is in connected state.<br>
152
 
 
153
 
        @events:
154
 
                !ev: OnConnect($1 = HostIp,$2 = Port)
155
 
                Triggered just after a succesfull connection has been estabilished
156
 
                The default implementation of this event echoes "Connected to $1 on port $2" to the active window
157
 
 
158
 
                !ev: OnIncomingConnection()
159
 
                Triggered by a listening socket when a connection request arrives.<br>
160
 
                To accept the incoming connection you should create a new socket (or derived class)
161
 
                object and call accept(<a href="s_this.kvihelp">$this</a>)<br>
162
 
                <example>
163
 
                        event(OnIncomingConnection)
164
 
                        {
165
 
                        &nbsp;&nbsp;%sock = <a href="s_new.kvihelp">$new</a>(socket,<a href="s_this.kvihelp">$this</a>,incoming)
166
 
                        &nbsp;&nbsp;if(!%sock->$accept(<a href="s_this.kvihelp">$this</a>))
167
 
                        &nbsp;&nbsp;{
168
 
                        &nbsp;&nbsp;&nbsp;&nbsp;# Ops...something went really wrong
169
 
                        &nbsp;&nbsp;&nbsp;&nbsp;<a href="echo.kvihelp">echo</a> Accept failed : %sock->$lastError()
170
 
                        &nbsp;&nbsp;&nbsp;&nbsp;<a href="destroy.kvihelp">destroy</a> %sock;
171
 
                        &nbsp;&nbsp;}
172
 
                        }
173
 
                </example>
174
 
                If you do not accept in this way the incoming connection in this event,
175
 
                it will be automatically discarded (the socket will be closed and the remote end will
176
 
                see some error such as "Connection reset by peer").<br>
177
 
                You can also accept the incoming connection with <a href="s_this.kvihelp">$this</a> socket
178
 
                (the listening one) , but then you will obviously stop listening.<br>
179
 
                <example>
180
 
                        event(OnIncomingConnection)
181
 
                        {
182
 
                        &nbsp;&nbsp;if(!<a href="s_this.kvihelp">$this</a>->$accept(<a href="s_this.kvihelp">$this</a>))
183
 
                        &nbsp;&nbsp;{
184
 
                        &nbsp;&nbsp;&nbsp;&nbsp;# Ops...something went really wrong
185
 
                        &nbsp;&nbsp;&nbsp;&nbsp;<a href="echo.kvihelp">echo</a> Accept failed : <a href="s_this.kvihelp">$this</a>->$lastError()
186
 
                        &nbsp;&nbsp;&nbsp;&nbsp;# Still listening
187
 
                        &nbsp;&nbsp;}
188
 
                        }
189
 
                </example>
190
 
                If $accept succeeds in this case , <a href="s_this.kvihelp">$this</a> socket stops listening
191
 
                and starts the communication on the accepted connection.<br>
192
 
                If $accept fails , <a href="s_this.kvihelp">$this</a> socket will be still listening.
193
 
                The default implementation of this event does nothing
194
 
 
195
 
                !ev: OnConnectFailed($1- = Error String)
196
 
                Triggered when a connection attempt fails
197
 
                The default implementation of this event echoes "Connect failed : $this->$lastError()" to the active window
198
 
 
199
 
                !ev: OnDisconnect($1- = Error String)
200
 
                Triggered when the socket gets disconnected for some user-independent reason.<br>
201
 
                It may be caused by a transmission error or the remote host may simply close the connection
202
 
                after a timeout...<br>
203
 
                The default implementation of this event echoes "Disconnected from $this->$host() : $this->$lastError()" to the active window
204
 
 
205
 
                !ev: OnDataReceived($1 = Data length,$2- = Data String)
206
 
                The data string is a "normal" text line if the socket is in the Ascii mode ,
207
 
                otherwise it is a sequence of hexadecimal-encoded bytes.<br>
208
 
                In Ascii mode you will be loosing the leading and trailing whitespace,
209
 
                and the unprintable characters. Also , in Ascii mode this event will NOT fire until
210
 
                a CR or LF has been readed from the socket (to signal the end of a line).<br>
211
 
                The $1 argument is the length of the Data string argument (in characters).<br>
212
 
                In Hex mode the $1 argument is the length of the Data string argument (in characters);
213
 
                since each character is encoded by two hexadecimal digits , so <a href="s_calc.kvihelp">$calc</a>($1 / 2) 
214
 
                will be the effective length in bytes of the received buffer.<br>
215
 
                In hex mode this event will be triggered whenever any data arrives.<br>
216
 
                If you need to receive such data , use the socket in Hex mode.<br>
217
 
                (see <a href="s_hextostr.kvihelp">$HexToStr()</a> and <a href="s_strtohex.kvihelp">$StrToHex()</a>)<br>
218
 
                This event has a default event handler (in case that you don't want to bother yourself with
219
 
                the <a href="class.kvihelp">CLASS</a> command) that "echoes" the received data to the active window.<br>
220
 
                The body of the event is: "echo -w=$activewindow SOCKET $this : Received data :$2-".<br>
221
 
                Obviously you can override it, as usual, with <a href="obj_setevent.kvihelp">obj_setevent</a>
222
 
                or in a subclass definition.<br>
223
 
 
224
 
        @description:
225
 
                A socket device object.<br>
226
 
                Theoretically it can work in the Unix and Inet domain
227
 
                but actually only the Inet (default) domain has been tested.<br>
228
 
                Theoretically it can work as Stream or Raw socket but
229
 
                actually only the Stream (default) socket implementation has been tested.<br>
230
 
                Theoretically it can work over any valid protocol but by now
231
 
                only "ip" (0 - default) has been tested.
232
 
 
233
 
        @examples:
234
 
                Simple code to check for new messages in a FIXED mailbox.<br>
235
 
                The connection is made in Ascii mode since unless messages are transmitted
236
 
                the pop3 protocol is text based: we will loose no data.<br>
237
 
                You can easily optimize this code and convert it to an alias
238
 
                that may accept the username, password and the mailserver as parameters.<br>
239
 
                This version also wants the real IP address of the mailserver , not the hostname.<br>
240
 
                Adding the DNS extension is left to you as exercise :).<br>
241
 
                <example>
242
 
                # Create a socket object
243
 
                %o=<a href="s_new.kvihelp">$new</a>(socket,<a href="s_root.kvihelp">$root</a>,mysock);
244
 
                # OnConnect event : Once connected , send USER , PASS and LIST
245
 
                # You will probably want to set a different username and password :)
246
 
                <a href="obj_setevent.kvihelp">obj_setevent</a>(%o,OnConnect)
247
 
                {
248
 
                &nbsp;&nbsp;<a href="echo.kvihelp">echo</a> CHECKMAIL : Connected to the mailserver...
249
 
                &nbsp;&nbsp;<a href="s_this.kvihelp">$this</a>->$write("USER place_here_your_username<a href="s_cr.kvihelp">$cr</a><a href="s_lf.kvihelp">$lf</a>")
250
 
                &nbsp;&nbsp;<a href="s_this.kvihelp">$this</a>->$write("PASS place_here_your_password<a href="s_cr.kvihelp">$cr</a><a href="s_lf.kvihelp">$lf</a>")
251
 
                &nbsp;&nbsp;<a href="s_this.kvihelp">$this</a>->$write("LIST<a href="s_cr.kvihelp">$cr</a><a href="s_lf.kvihelp">$lf</a>")
252
 
                }
253
 
                # When we get disconnected for some reason kill the object
254
 
                <a href="obj_setevent.kvihelp">obj_setevent</a>(%o,OnDisconnect)
255
 
                {
256
 
                &nbsp;&nbsp;<a href="echo.kvihelp">echo</a> CHECKMAIL : Disconnected ($1-)
257
 
                &nbsp;&nbsp;<a href="destroy.kvihelp">destroy</a> <a href="s_this.kvihelp">$this</a>
258
 
                }
259
 
                # Data received ...here's the clue
260
 
                <a href="obj_setevent.kvihelp">obj_setevent</a>(%o,OnDataReceived)
261
 
                {
262
 
                &nbsp;&nbsp;<a href="switch.kvihelp">switch</a>($2-)
263
 
                &nbsp;&nbsp;{
264
 
                &nbsp;&nbsp;&nbsp;&nbsp;<a href="switch.kvihelp">match</a>("+OK * messages*")
265
 
                &nbsp;&nbsp;&nbsp;&nbsp;{
266
 
                &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="echo.kvihelp">echo</a> CHECKMAIL : The mailbox contains <a href="s_strrightfromfirst.kvihelp">$strRightFromFirst</a>("+OK ",$1-)
267
 
                &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="destroy.kvihelp">destroy</a> <a href="s_this.kvihelp">$this</a>
268
 
                &nbsp;&nbsp;&nbsp;&nbsp;}
269
 
                &nbsp;&nbsp;&nbsp;&nbsp;<a href="switch.kvihelp">match</a>("-ERR *")
270
 
                &nbsp;&nbsp;&nbsp;&nbsp;{
271
 
                &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="echo.kvihelp">echo</a> CHECKMAIL : Received error : $2-
272
 
                &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="echo.kvihelp">echo</a> CHECKMAIL : Aborting
273
 
                &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="destroye.kvihelp">destroy</a> <a href="s_this.kvihelp">$this</a>
274
 
                &nbsp;&nbsp;&nbsp;&nbsp;}
275
 
                &nbsp;&nbsp;}
276
 
                }
277
 
                # If the connection fails for some reason , kill the object
278
 
                <a href="obj_setevent.kvihelp">obj_setevent</a>(%o,OnConnectFailed)
279
 
                {
280
 
                &nbsp;&nbsp;<a href="echo.kvihelp">echo</a> CHECKMAIL : Connect failed : ($1-)
281
 
                &nbsp;&nbsp;<a href="destroy.kvihelp">destroy</a> <a href="s_this.kvihelp">$this</a>
282
 
                }
283
 
                # Ok...ready to go... connect to our mailserver
284
 
                # You will probably want to change the ip address :)
285
 
                <a href="if.kvihelp">if</a>(!%o->$connect(127.0.0.1,110)){ <a href="echo.kvihelp">echo</a> Mail : Connection failed : %o->$lastError(); <a href="destroy.kvihelp">destroy</a> %o; }
286
 
                <a href="if.kvihelp">else</a> <a href="echo.kvihelp">echo</a> Checking mail on 127.0.0.1....
287
 
                # And now just wait and watch...
288
 
                </example>
289
 
        @seealso:
290
 
                <a href="syntax_objects.kvihelp">Objects documentation</a>
291
 
*/
292
 
 
293
 
KviScriptSocket::KviScriptSocket(KviScriptObjectController * cntrl,KviScriptObject * p,const char *name,KviScriptObjectClassDefinition * pDef)
294
 
: KviScriptObject(cntrl,p,name,pDef)
295
 
{
296
 
        m_sock = -1;
297
 
        m_domain = PF_INET;
298
 
        m_type = SOCK_STREAM;
299
 
        m_protocol = 0;
300
 
        m_error = KVI_ERROR_Success;
301
 
        m_mode = Ascii;
302
 
        m_iReadBufLen = 0;
303
 
        m_pReadBuffer = 0;
304
 
        m_pRsn = 0;
305
 
        m_pTmpSn = 0;
306
 
        m_state = Ready;
307
 
        m_incomingConnectionSock = -1;
308
 
        m_szLocalHostIp = "127.0.0.1";
309
 
}
310
 
 
311
 
KviScriptSocket::~KviScriptSocket()
312
 
{
313
 
        reset();
314
 
}
315
 
 
316
 
void KviScriptSocket::initializeClassDefinition(KviScriptObjectClassDefinition *d)
317
 
{
318
 
        d->addBuiltinFunction("mode",(scriptObjectFunction)&KviScriptSocket::builtinFunction_MODE);
319
 
        d->addBuiltinFunction("type",(scriptObjectFunction)&KviScriptSocket::builtinFunction_TYPE);
320
 
        d->addBuiltinFunction("setDomain",(scriptObjectFunction)&KviScriptSocket::builtinFunction_SETDOMAIN);
321
 
        d->addBuiltinFunction("setType",(scriptObjectFunction)&KviScriptSocket::builtinFunction_SETTYPE);
322
 
        d->addBuiltinFunction("setMode",(scriptObjectFunction)&KviScriptSocket::builtinFunction_SETMODE);
323
 
        d->addBuiltinFunction("setProtocol",(scriptObjectFunction)&KviScriptSocket::builtinFunction_SETPROTOCOL);
324
 
        d->addBuiltinFunction("write",(scriptObjectFunction)&KviScriptSocket::builtinFunction_WRITE);
325
 
        d->addBuiltinFunction("writeHex",(scriptObjectFunction)&KviScriptSocket::builtinFunction_WRITEHEX);
326
 
        d->addBuiltinFunction("close",(scriptObjectFunction)&KviScriptSocket::builtinFunction_CLOSE);
327
 
        d->addBuiltinFunction("protocol",(scriptObjectFunction)&KviScriptSocket::builtinFunction_PROTOCOL);
328
 
        d->addBuiltinFunction("host",(scriptObjectFunction)&KviScriptSocket::builtinFunction_HOST);
329
 
        d->addBuiltinFunction("port",(scriptObjectFunction)&KviScriptSocket::builtinFunction_PORT);
330
 
        d->addBuiltinFunction("state",(scriptObjectFunction)&KviScriptSocket::builtinFunction_STATE);
331
 
        d->addBuiltinFunction("domain",(scriptObjectFunction)&KviScriptSocket::builtinFunction_DOMAIN);
332
 
        d->addBuiltinFunction("connect",(scriptObjectFunction)&KviScriptSocket::builtinFunction_CONNECT);
333
 
        d->addBuiltinFunction("listen",(scriptObjectFunction)&KviScriptSocket::builtinFunction_LISTEN);
334
 
        d->addBuiltinFunction("lastError",(scriptObjectFunction)&KviScriptSocket::builtinFunction_LASTERROR);
335
 
        d->addBuiltinFunction("accept",(scriptObjectFunction)&KviScriptSocket::builtinFunction_ACCEPT);
336
 
        d->addBuiltinFunction("localhost",(scriptObjectFunction)&KviScriptSocket::builtinFunction_LOCALHOST);
337
 
 
338
 
        KviScriptEventStruct * s = new KviScriptEventStruct;
339
 
        s->szName = "OnDataReceived";
340
 
        s->szBuffer = "echo -w=$activewindow SOCKET $this : Received data :$2-";
341
 
        d->addDefaultEvent(s);
342
 
        s = new KviScriptEventStruct;
343
 
        s->szName = "OnDisconnect";
344
 
        s->szBuffer = "echo -w=$activewindow SOCKET $this : Disconnected from $this->$host() : $this->$lastError()";
345
 
        d->addDefaultEvent(s);
346
 
        s = new KviScriptEventStruct;
347
 
        s->szName = "OnConnect";
348
 
        s->szBuffer = "echo -w=$activewindow SOCKET $this : Connected to $1 on port $2";
349
 
        d->addDefaultEvent(s);
350
 
        s = new KviScriptEventStruct;
351
 
        s->szName = "OnConnectFailed";
352
 
        s->szBuffer = "echo -w=$activewindow SOCKET $this : Connect failed : $this->$lastError()";
353
 
        d->addDefaultEvent(s);
354
 
}
355
 
 
356
 
int KviScriptSocket::builtinFunction_MODE(QList<KviStr> * params,KviStr &buffer)
357
 
{
358
 
        if(m_mode == Ascii)buffer.append("ascii");
359
 
        else buffer.append("hex");
360
 
        return KVI_ERROR_Success;
361
 
}
362
 
 
363
 
int KviScriptSocket::builtinFunction_LOCALHOST(QList<KviStr> * params,KviStr &buffer)
364
 
{
365
 
        buffer.append(m_szLocalHostIp);
366
 
        return KVI_ERROR_Success;
367
 
}
368
 
 
369
 
int KviScriptSocket::builtinFunction_SETDOMAIN(QList<KviStr> * params,KviStr &buffer)
370
 
{
371
 
        if(params)
372
 
        {
373
 
                KviStr *pDomain = params->first();
374
 
                if(pDomain)
375
 
                {
376
 
                        if(kvi_strEqualCI(pDomain->ptr(),"inet"))m_domain = PF_INET;
377
 
                        else if(kvi_strEqualCI(pDomain->ptr(),"unix"))m_domain = PF_UNIX;
378
 
                        else return KVI_ERROR_InvalidParameter;
379
 
                        return KVI_ERROR_Success;
380
 
                }
381
 
        }
382
 
        return KVI_ERROR_MissingParameter;
383
 
}
384
 
 
385
 
int KviScriptSocket::builtinFunction_SETTYPE(QList<KviStr> * params,KviStr &buffer)
386
 
{
387
 
        if(params)
388
 
        {
389
 
                KviStr *pType = params->first();
390
 
                if(pType)
391
 
                {
392
 
                        if(kvi_strEqualCI(pType->ptr(),"stream"))m_type = SOCK_STREAM;
393
 
                        else if(kvi_strEqualCI(pType->ptr(),"raw"))m_type = SOCK_RAW;
394
 
                        else return KVI_ERROR_InvalidParameter;
395
 
                        return KVI_ERROR_Success;
396
 
                }
397
 
        }
398
 
        return KVI_ERROR_MissingParameter;
399
 
}
400
 
 
401
 
int KviScriptSocket::builtinFunction_SETMODE(QList<KviStr> * params,KviStr &buffer)
402
 
{
403
 
        if(params)
404
 
        {
405
 
                KviStr *pType = params->first();
406
 
                if(pType)
407
 
                {
408
 
                        if(kvi_strEqualCI(pType->ptr(),"ascii"))
409
 
                        {
410
 
                                if(m_mode != Ascii)
411
 
                                {
412
 
                                        m_mode = Ascii;
413
 
                                        m_iReadBufLen = 0;
414
 
                                        if(m_pReadBuffer)kvi_free(m_pReadBuffer);
415
 
                                        m_pReadBuffer = 0;
416
 
                                }
417
 
                        } else if(kvi_strEqualCI(pType->ptr(),"hex"))
418
 
                        {
419
 
                                if(m_mode != Hex)
420
 
                                {
421
 
                                        m_mode = Hex;
422
 
                                        m_iReadBufLen = 0;
423
 
                                        if(m_pReadBuffer)kvi_free(m_pReadBuffer);
424
 
                                        m_pReadBuffer = 0;
425
 
                                }
426
 
                        }
427
 
                        else return KVI_ERROR_InvalidParameter;
428
 
                        return KVI_ERROR_Success;
429
 
                }
430
 
        }
431
 
        return KVI_ERROR_MissingParameter;
432
 
}
433
 
 
434
 
int KviScriptSocket::builtinFunction_SETPROTOCOL(QList<KviStr> * params,KviStr &buffer)
435
 
{
436
 
        if(params)
437
 
        {
438
 
                KviStr *pProto = params->first();
439
 
                if(pProto)
440
 
                {
441
 
                        struct protoent * p = getprotobyname(pProto->ptr());
442
 
                        if(p)m_protocol = p->p_proto;
443
 
                        else return KVI_ERROR_InvalidParameter;
444
 
                        return KVI_ERROR_Success;
445
 
                }
446
 
        }
447
 
        return KVI_ERROR_MissingParameter;
448
 
}
449
 
 
450
 
int KviScriptSocket::builtinFunction_WRITE(QList<KviStr> * params,KviStr &buffer)
451
 
{
452
 
        if(params)
453
 
        {
454
 
                KviStr *pData = params->first();
455
 
                if(pData)
456
 
                {
457
 
                        KviStr tmp(KviStr::Format,"%d",writeData(pData->ptr(),pData->len()));
458
 
                        buffer.append(tmp.ptr());
459
 
                        return KVI_ERROR_Success;
460
 
                }
461
 
        }
462
 
        return KVI_ERROR_MissingParameter;
463
 
}
464
 
 
465
 
 
466
 
int KviScriptSocket::builtinFunction_WRITEHEX(QList<KviStr> * params,KviStr &buffer)
467
 
{
468
 
        if(params)
469
 
        {
470
 
                KviStr *pData = params->first();
471
 
                if(pData)
472
 
                {
473
 
                        char * buf = 0;
474
 
                        int len = pData->hexToBuffer(&buf);
475
 
                        KviStr tmp(KviStr::Format,"%d",writeData(buf,len));
476
 
                        if(buf)kvi_free(buf);
477
 
                        buffer.append(tmp.ptr());
478
 
                        return KVI_ERROR_Success;
479
 
                }
480
 
        }
481
 
        return KVI_ERROR_MissingParameter;
482
 
}
483
 
 
484
 
int KviScriptSocket::builtinFunction_CLOSE(QList<KviStr> * params,KviStr &buffer)
485
 
{
486
 
        if(m_sock == -1)buffer.append('0');
487
 
        else {
488
 
                reset();
489
 
                buffer.append('1');
490
 
        }
491
 
        return KVI_ERROR_Success;
492
 
}
493
 
 
494
 
int KviScriptSocket::builtinFunction_PROTOCOL(QList<KviStr> * params,KviStr &buffer)
495
 
{
496
 
        struct protoent * p = getprotobynumber(m_protocol);
497
 
        if(p)buffer.append(p->p_name);
498
 
        else {
499
 
                KviStr num;
500
 
                num.setNum(m_protocol);
501
 
                buffer.append(num.ptr());
502
 
        }
503
 
        return KVI_ERROR_Success;
504
 
}
505
 
 
506
 
int KviScriptSocket::builtinFunction_TYPE(QList<KviStr> * params,KviStr &buffer)
507
 
{
508
 
        if(m_type == SOCK_STREAM)buffer.append("stream");
509
 
        else buffer.append("raw");
510
 
        return KVI_ERROR_Success;
511
 
}
512
 
 
513
 
int KviScriptSocket::builtinFunction_HOST(QList<KviStr> * params,KviStr &buffer)
514
 
{
515
 
        if(m_state == Connected)buffer.append(m_szHostIp);
516
 
        return KVI_ERROR_Success;
517
 
}
518
 
 
519
 
int KviScriptSocket::builtinFunction_PORT(QList<KviStr> * params,KviStr &buffer)
520
 
{
521
 
        if(m_state == Connected)buffer.append(m_szPort);
522
 
        return KVI_ERROR_Success;
523
 
}
524
 
 
525
 
int KviScriptSocket::builtinFunction_STATE(QList<KviStr> * params,KviStr &buffer)
526
 
{
527
 
        if(m_state == Connected)buffer.append("connected");
528
 
        else if(m_state == Connecting)buffer.append("connecting");
529
 
        else if(m_state == Listening)buffer.append("listening");
530
 
        else buffer.append("ready");
531
 
        return KVI_ERROR_Success;
532
 
}
533
 
 
534
 
int KviScriptSocket::builtinFunction_DOMAIN(QList<KviStr> * params,KviStr &buffer)
535
 
{
536
 
        if(m_domain == PF_INET)buffer.append("inet");
537
 
        else buffer.append("unix");
538
 
        return KVI_ERROR_Success;
539
 
}
540
 
 
541
 
 
542
 
int KviScriptSocket::builtinFunction_CONNECT(QList<KviStr> * params,KviStr &buffer)
543
 
{
544
 
        if(params)
545
 
        {
546
 
                KviStr *pHost = params->first();
547
 
                if(pHost)
548
 
                {
549
 
                        KviStr *pPort = params->next();
550
 
                        if(pPort)
551
 
                        {
552
 
                                buffer.append(doConnect(pHost,pPort) ? '1' : '0');
553
 
                                return KVI_ERROR_Success;
554
 
                        }
555
 
                }
556
 
        }
557
 
        return KVI_ERROR_MissingParameter;
558
 
}
559
 
 
560
 
int KviScriptSocket::builtinFunction_LISTEN(QList<KviStr> * params,KviStr &buffer)
561
 
{
562
 
        if(params)
563
 
        {
564
 
                KviStr *pHost = params->first();
565
 
                if(pHost)
566
 
                {
567
 
                        KviStr *pPort = params->next();
568
 
                        if(pPort)
569
 
                        {
570
 
                                buffer.append(doListen(pHost,pPort) ? '1' : '0');
571
 
                                return KVI_ERROR_Success;
572
 
                        }
573
 
                }
574
 
        }
575
 
        return KVI_ERROR_MissingParameter;
576
 
}
577
 
 
578
 
int KviScriptSocket::builtinFunction_LASTERROR(QList<KviStr> * params,KviStr &buffer)
579
 
{
580
 
        buffer.append(kvi_getErrorString(m_error));
581
 
        return KVI_ERROR_Success;
582
 
}
583
 
 
584
 
int KviScriptSocket::builtinFunction_ACCEPT(QList<KviStr> * params,KviStr &buffer)
585
 
{
586
 
        if(params)
587
 
        {
588
 
                KviStr *pObId = params->first();
589
 
                if(pObId)
590
 
                {
591
 
                        buffer.append(doAccept(pObId->ptr()) ? '1' : '0');
592
 
                        return KVI_ERROR_Success;
593
 
                }
594
 
        }
595
 
        return KVI_ERROR_MissingParameter;
596
 
}
597
 
 
598
 
 
599
 
bool KviScriptSocket::doListen(KviStr *szLocalAddr,KviStr *szPort)
600
 
{
601
 
        struct in_addr     inAddress;
602
 
        struct sockaddr_in hostSockAddr;
603
 
 
604
 
        if(m_sock != -1){ m_error = KVI_ERROR_AnotherConnectionInProgress; return false; }
605
 
 
606
 
        if(!kvi_stringIpToBinaryIp(szLocalAddr->ptr(),&inAddress))
607
 
        {
608
 
                if(kvi_strEqualCI("default",szLocalAddr->ptr()) || kvi_strEqualCI("any",szLocalAddr->ptr()))hostSockAddr.sin_addr.s_addr = INADDR_ANY;
609
 
                else { m_error = KVI_ERROR_InvalidIpAddress; return false; }
610
 
        } else hostSockAddr.sin_addr = inAddress;
611
 
 
612
 
        bool bOk = false;
613
 
        unsigned short int port = szPort->toUInt(&bOk);
614
 
        if(!bOk){ m_error = KVI_ERROR_InvalidPort; return false; }
615
 
 
616
 
        hostSockAddr.sin_family = m_domain; //AF_INET == PF_INET && AF_UNIX == PF_UNIX
617
 
        hostSockAddr.sin_port   = htons(port);
618
 
 
619
 
        m_sock = ::socket(m_domain,m_type,m_protocol);
620
 
 
621
 
        if(m_sock < 0){ m_error = KVI_ERROR_SocketCreationFailed; return false; }
622
 
 
623
 
        if(fcntl(m_sock, F_SETFL, O_NONBLOCK) < 0){ m_error = KVI_ERROR_AsyncSocketFailed; return false; }
624
 
 
625
 
        int theError;
626
 
        if((theError = bind(m_sock,(struct sockaddr *)&hostSockAddr,sizeof(hostSockAddr))) < 0)
627
 
        { setErrorFromSystemError(theError); reset(); return false; }
628
 
        if((theError = listen(m_sock,1)) < 0)
629
 
        { setErrorFromSystemError(theError); reset(); return false; }
630
 
 
631
 
        // and setup the READ notifier...
632
 
        m_pTmpSn = new QSocketNotifier(m_sock,QSocketNotifier::Read);
633
 
 
634
 
        QObject::connect(m_pTmpSn,SIGNAL(activated(int)),this,SLOT(listenNotifierFired(int)));
635
 
 
636
 
        m_pTmpSn->setEnabled(true);
637
 
 
638
 
        m_szHostIp = "";
639
 
        m_szPort = "";
640
 
        m_error = KVI_ERROR_Success;
641
 
        m_state = Listening;
642
 
 
643
 
        return true;
644
 
}
645
 
 
646
 
void KviScriptSocket::listenNotifierFired(int)
647
 
{
648
 
        struct sockaddr_in connectedAddr;
649
 
 
650
 
        _this_should_be_socklen_t iSize = sizeof(connectedAddr);
651
 
        m_incomingConnectionSock = accept(m_sock,(struct sockaddr*)&connectedAddr,&iSize);
652
 
        if(m_incomingConnectionSock == -1)debug("warning : accept returns -1...waiting for the next accept call");
653
 
        else {
654
 
                // Connected
655
 
                m_szIncomingConnectionPort.setNum(ntohs(connectedAddr.sin_port));
656
 
                kvi_binaryIpToString(connectedAddr.sin_addr,m_szIncomingConnectionHostIp);
657
 
 
658
 
                KviStr parms;
659
 
                triggerEvent("OnIncomingConnection",parms);
660
 
 
661
 
                if(m_incomingConnectionSock != -1)
662
 
                {
663
 
                        // Not accepted
664
 
                        close(m_incomingConnectionSock);
665
 
                        m_incomingConnectionSock = -1;
666
 
                        m_szIncomingConnectionPort = "";
667
 
                        m_szIncomingConnectionHostIp = "";
668
 
                }
669
 
        }
670
 
}
671
 
 
672
 
bool KviScriptSocket::doAccept(const char *sockObjectId)
673
 
{
674
 
        KviScriptObject * o = (KviScriptObject *)controller()->findObjectById(sockObjectId);
675
 
 
676
 
        if(!o){ m_error = KVI_ERROR_ObjectNotFound; return false; }
677
 
        if(!o->inherits("KviScriptSocket")){ m_error = KVI_ERROR_ObjectIsNotASocket; return false; }
678
 
 
679
 
        KviScriptSocket * s = (KviScriptSocket *)o;
680
 
 
681
 
        if(!s>hasPendingConnection()){ m_error = KVI_ERROR_NoConnectionToAccept; return false; }
682
 
 
683
 
        if(m_state != Ready)
684
 
        {
685
 
                reset(); // if o == this it will work!...reset() will not clear the incomingConnectionSock
686
 
        }
687
 
 
688
 
        m_sock = s->m_incomingConnectionSock;
689
 
        s->m_incomingConnectionSock = -1;
690
 
        m_szHostIp = s->m_szIncomingConnectionHostIp;
691
 
        s->m_szIncomingConnectionHostIp = "";
692
 
        m_szPort = s->m_szIncomingConnectionPort;
693
 
        s->m_szIncomingConnectionPort = "";
694
 
        m_state = Connected;
695
 
        m_error = KVI_ERROR_Success;
696
 
 
697
 
        m_pRsn = new QSocketNotifier(m_sock,QSocketNotifier::Read);
698
 
        QObject::connect(m_pRsn,SIGNAL(activated(int)),this,SLOT(receivedData(int)));
699
 
        m_pRsn->setEnabled(true);
700
 
 
701
 
        setLocalHostIp();
702
 
 
703
 
        return true;
704
 
}
705
 
 
706
 
void KviScriptSocket::setLocalHostIp()
707
 
{
708
 
        if(m_state == Connected)
709
 
        {
710
 
                struct sockaddr_in name;
711
 
                _this_should_be_socklen_t len = sizeof(name);
712
 
                if(getsockname(m_sock, (struct sockaddr *)&name,&len) >= 0)
713
 
                {
714
 
                        if(kvi_binaryIpToString(name.sin_addr,m_szLocalHostIp))return;
715
 
                }
716
 
        }
717
 
        m_szLocalHostIp = "127.0.0.1";
718
 
}
719
 
 
720
 
bool KviScriptSocket::doConnect(KviStr * szHost,KviStr *szPort)
721
 
{
722
 
        struct in_addr     inAddress;
723
 
        struct sockaddr_in hostSockAddr;
724
 
 
725
 
        if(m_sock != -1){ m_error = KVI_ERROR_AnotherConnectionInProgress; return false; }
726
 
 
727
 
        if(!kvi_stringIpToBinaryIp(szHost->ptr(),&inAddress)){ m_error = KVI_ERROR_InvalidIpAddress; return false; }
728
 
 
729
 
        bool bOk = false;
730
 
        unsigned short int port = szPort->toUInt(&bOk);
731
 
        if(!bOk){ m_error = KVI_ERROR_InvalidPort; return false; }
732
 
 
733
 
        hostSockAddr.sin_family = m_domain; //AF_INET == PF_INET && AF_UNIX == PF_UNIX
734
 
        hostSockAddr.sin_port   = htons(port);
735
 
        hostSockAddr.sin_addr   = inAddress;
736
 
 
737
 
        // Let's go...
738
 
        m_sock = ::socket(m_domain,m_type,m_protocol);
739
 
 
740
 
        if(m_sock < 0){ m_error = KVI_ERROR_SocketCreationFailed; return false; }
741
 
 
742
 
        if(fcntl(m_sock, F_SETFL, O_NONBLOCK) < 0){ m_error = KVI_ERROR_AsyncSocketFailed; return false; }
743
 
 
744
 
        if(::connect(m_sock,(struct sockaddr*)(&hostSockAddr),sizeof(hostSockAddr))<0){
745
 
                if(errno != EINPROGRESS){
746
 
                        int sockError=errno;
747
 
                        if(sockError==0){
748
 
                                _this_should_be_socklen_t iSize=sizeof(int);
749
 
                                if(getsockopt(m_sock,SOL_SOCKET,SO_ERROR,(void *)&sockError,&iSize)<0)sockError=0;
750
 
                        }
751
 
                        if(sockError > 0)setErrorFromSystemError(sockError);
752
 
                        else m_error = KVI_ERROR_UnknownError; //Error 0 ?
753
 
                        return false;
754
 
                }
755
 
        }
756
 
 
757
 
        // and setup the WRITE notifier...
758
 
        m_pTmpSn = new QSocketNotifier(m_sock,QSocketNotifier::Write);
759
 
 
760
 
        QObject::connect(m_pTmpSn,SIGNAL(activated(int)),this,SLOT(writeNotifierFired(int)));
761
 
 
762
 
        m_pTmpSn->setEnabled(true);
763
 
        // set the timer
764
 
        m_szHostIp = szHost->ptr();
765
 
        m_szPort = szPort->ptr();
766
 
        m_error = KVI_ERROR_Success;
767
 
        m_state = Connecting;
768
 
        return true;
769
 
}
770
 
 
771
 
void KviScriptSocket::writeNotifierFired(int)
772
 
{
773
 
        int sockError;
774
 
        _this_should_be_socklen_t iSize=sizeof(int);
775
 
        if(getsockopt(m_sock,SOL_SOCKET,SO_ERROR,(void *)&sockError,&iSize)<0)sockError = -1;
776
 
        if(sockError != 0){
777
 
                //failed
778
 
                if(sockError > 0)setErrorFromSystemError(sockError);
779
 
                else m_error = KVI_ERROR_UnknownError; //Error 0 ?
780
 
                KviStr parms = kvi_getErrorString(m_error);
781
 
                triggerEvent("OnConnectFailed",parms);
782
 
                reset();
783
 
        } else {
784
 
                //Succesfully connected...
785
 
                m_pRsn = new QSocketNotifier(m_sock,QSocketNotifier::Read);
786
 
                // normal irc connection
787
 
                KviStr parms(KviStr::Format,"%s %s",m_szHostIp.ptr(),m_szPort.ptr());
788
 
                triggerEvent("OnConnect",parms);
789
 
                if(m_state != Connecting)return; //Killed ?
790
 
 
791
 
                QObject::connect(m_pRsn,SIGNAL(activated(int)),this,SLOT(receivedData(int)));
792
 
                m_pRsn->setEnabled(true);
793
 
                delete m_pTmpSn;
794
 
                m_pTmpSn = 0;
795
 
                m_state = Connected;
796
 
                setLocalHostIp();
797
 
        }
798
 
 
799
 
}
800
 
 
801
 
void KviScriptSocket::reset()
802
 
{
803
 
        if(m_sock != -1)
804
 
        {
805
 
                ::close(m_sock);
806
 
                m_sock = -1;
807
 
        }
808
 
        m_szHostIp = "";
809
 
        m_szPort = "";
810
 
        if(m_pReadBuffer)
811
 
        {
812
 
                kvi_free(m_pReadBuffer);
813
 
                m_pReadBuffer = 0;
814
 
        }
815
 
        m_iReadBufLen = 0;
816
 
        if(m_pRsn)
817
 
        {
818
 
                delete m_pRsn;
819
 
                m_pRsn = 0;
820
 
        }
821
 
        if(m_pTmpSn)
822
 
        {
823
 
                delete m_pTmpSn;
824
 
                m_pTmpSn = 0;
825
 
        }
826
 
        m_state = Ready;
827
 
}
828
 
 
829
 
void KviScriptSocket::setErrorFromSystemError(int errorNum)
830
 
{
831
 
        switch(errorNum){
832
 
                case EBADF:        m_error = KVI_ERROR_BadFileDescriptor;     break;
833
 
                case EFAULT:       m_error = KVI_ERROR_OutOfAddressSpace;     break;
834
 
                case ECONNREFUSED: m_error = KVI_ERROR_ConnectionRefused;     break;
835
 
                case ENOTSOCK:     m_error = KVI_ERROR_KernelNetworkingPanic; break;
836
 
                case ETIMEDOUT:    m_error = KVI_ERROR_ConnectionTimedOut;    break;
837
 
                case ENETUNREACH:  m_error = KVI_ERROR_NetworkUnreachable;    break;
838
 
                case EPIPE:        m_error = KVI_ERROR_BrokenPipe;            break;
839
 
                // Unhandled error...pass errno to the strerror function
840
 
                default:           m_error = -errorNum;                       break;
841
 
        }
842
 
}
843
 
 
844
 
void KviScriptSocket::handleInvalidSocketRead(int readedLength)
845
 
{
846
 
        if(readedLength==0){
847
 
                m_error = KVI_ERROR_RemoteEndClosedConnection;
848
 
                KviStr parms = kvi_getErrorString(m_error);
849
 
                triggerEvent("OnDisconnect",parms);
850
 
                reset();
851
 
        } else {
852
 
                //check for transmission errors
853
 
                if((errno != EAGAIN) && (errno != EINTR)){
854
 
                        if(errno > 0)setErrorFromSystemError(errno);
855
 
                        else m_error = KVI_ERROR_RemoteEndClosedConnection;
856
 
                        KviStr parms = kvi_getErrorString(m_error);
857
 
                        triggerEvent("OnDisconnect",parms);
858
 
                        reset();
859
 
                } //else transient error...wait again...
860
 
        }
861
 
}
862
 
 
863
 
void KviScriptSocket::receivedData(int fd)
864
 
{
865
 
        //read data
866
 
 
867
 
        char buffer[1025];
868
 
        int readLength = read(m_sock,buffer,1024);
869
 
 
870
 
        if(readLength <= 0){
871
 
                handleInvalidSocketRead(readLength);
872
 
                return;
873
 
        }
874
 
 
875
 
        if(m_mode == Hex)
876
 
        {
877
 
                KviStr parms;
878
 
                KviStr tmp(KviStr::Format,"%d ",readLength * 2);
879
 
                parms.bufferToHex(buffer,readLength);
880
 
                parms.prepend(tmp.ptr());
881
 
                m_pRsn->setEnabled(false);
882
 
                triggerEvent("OnDataReceived",parms);
883
 
                // check if we were closed() by the meantins
884
 
                if(m_state != Connected)return; //closed
885
 
                m_pRsn->setEnabled(true);
886
 
        } else {
887
 
                //terminate our buffer
888
 
                (*(buffer+readLength))='\0';
889
 
 
890
 
                register char *p=buffer;
891
 
                char *beginOfCurData = buffer;
892
 
                int   bufLen = 0;
893
 
                char *messageBuffer = (char *)kvi_malloc(1);
894
 
                //Shut up the socket notifier
895
 
                //in case that we enter in a local loop somewhere
896
 
                //while processing data...
897
 
 
898
 
                m_pRsn->setEnabled(false);
899
 
 
900
 
                while(*p){
901
 
                        if((*p == '\r' )||(*p == '\n')){
902
 
                                //found a CR or LF...
903
 
                                //prepare a message buffer
904
 
                                bufLen = p - beginOfCurData;
905
 
                                //check for previous unterminated data
906
 
                                KviStr parms;
907
 
 
908
 
                                if(m_iReadBufLen > 0){
909
 
 
910
 
                                        __range_valid(m_pReadBuffer);
911
 
                                        messageBuffer = (char *)kvi_realloc(messageBuffer,bufLen + m_iReadBufLen + 1);
912
 
                                        kvi_memmove(messageBuffer,m_pReadBuffer,m_iReadBufLen);
913
 
                                        kvi_memmove((void *)(messageBuffer + m_iReadBufLen),beginOfCurData,bufLen);
914
 
                                        *(messageBuffer + bufLen + m_iReadBufLen) = '\0';
915
 
                                        kvi_free(m_pReadBuffer);
916
 
                                        m_pReadBuffer = 0;
917
 
 
918
 
                                        parms.sprintf("%d %s",bufLen + m_iReadBufLen,messageBuffer);
919
 
                                        m_iReadBufLen = 0;
920
 
                                } else {
921
 
 
922
 
                                        __range_invalid(m_pReadBuffer);
923
 
                                        messageBuffer = (char *)kvi_realloc(messageBuffer,bufLen + 1);
924
 
                                        kvi_memmove(messageBuffer,beginOfCurData,bufLen);
925
 
                                        *(messageBuffer + bufLen) = '\0';
926
 
                                        parms.sprintf("%d %s",bufLen,messageBuffer);
927
 
                                }
928
 
 
929
 
                                triggerEvent("OnDataReceived",parms);
930
 
                                // check if we were closed() by the meantins
931
 
                                if(m_state != Connected)
932
 
                                {
933
 
                                        kvi_free(messageBuffer);
934
 
                                        return;
935
 
                                }
936
 
 
937
 
                                while(*p && ((*p=='\r')||(*p=='\n')) )p++;
938
 
                                beginOfCurData = p;
939
 
                        } else p++;
940
 
 
941
 
                        if(inDelayedDestroy())
942
 
                        {
943
 
                                // already a zombie! (destroyed while processing data!)
944
 
                                kvi_free(messageBuffer);
945
 
                                return;
946
 
                        }
947
 
                }
948
 
                //now *p == '\0'
949
 
                //beginOfCurData points to '\0' if we have
950
 
                //no more stuff to parse , or points to something
951
 
                //different than '\r' or '\n'...
952
 
                if(*beginOfCurData){
953
 
                        //Have remaining data...in the local buffer
954
 
                        bufLen = p - beginOfCurData;
955
 
                        if(m_iReadBufLen > 0){
956
 
                                //and there was more stuff saved... (really slow connection)
957
 
                                __range_valid(m_pReadBuffer);
958
 
                                m_pReadBuffer =(char *)kvi_realloc(m_pReadBuffer,m_iReadBufLen + bufLen);
959
 
                                kvi_memmove((void *)(m_pReadBuffer+m_iReadBufLen),beginOfCurData,bufLen);
960
 
                                m_iReadBufLen += bufLen;
961
 
                        } else {
962
 
                                //
963
 
                                __range_invalid(m_pReadBuffer);
964
 
                                m_iReadBufLen = bufLen;
965
 
                                m_pReadBuffer =(char *)kvi_malloc(m_iReadBufLen);
966
 
                                kvi_memmove(m_pReadBuffer,beginOfCurData,m_iReadBufLen);
967
 
                        }
968
 
                }
969
 
 
970
 
                kvi_free(messageBuffer);
971
 
                //ready to receive
972
 
                m_pRsn->setEnabled(true);
973
 
        }
974
 
}
975
 
 
976
 
 
977
 
int KviScriptSocket::writeData(char * buffer,int len)
978
 
{
979
 
        if(m_sock == -1)
980
 
        {
981
 
                m_error = KVI_ERROR_NotConnected;
982
 
                return -1;
983
 
        }
984
 
 
985
 
        int result = write(m_sock,buffer,len);
986
 
        if(result >= len)return len;
987
 
        else {
988
 
                // Oops...error ?
989
 
                if((errno == EAGAIN)||(errno == EINTR))return 0;
990
 
                {
991
 
                        // Disconnected... :(
992
 
                        setErrorFromSystemError(errno);
993
 
                        KviStr parms = kvi_getErrorString(m_error);
994
 
                        triggerEvent("OnDisconnect",parms);
995
 
                        reset();
996
 
                        return -1;
997
 
                }
998
 
        }
999
 
}
1000
 
#include "m_kvi_scriptsocket.moc"