diff options
Diffstat (limited to 'src/modules/objects/KvsObject_socket.cpp')
| -rw-r--r-- | src/modules/objects/KvsObject_socket.cpp | 1041 |
1 files changed, 217 insertions, 824 deletions
diff --git a/src/modules/objects/KvsObject_socket.cpp b/src/modules/objects/KvsObject_socket.cpp index 6c40f8ea2..ce1f60e46 100644 --- a/src/modules/objects/KvsObject_socket.cpp +++ b/src/modules/objects/KvsObject_socket.cpp @@ -26,10 +26,11 @@ #include "KvsObject_memoryBuffer.h" #include "KvsObject_file.h" + + #include "kvi_settings.h" #include "KviQString.h" -#define _KVI_DEBUG_CHECK_RANGE_ #include "kvi_debug.h" #include "KviFile.h" @@ -45,12 +46,44 @@ #include "KviDataBuffer.h" #include <QByteArray> +#include <QTcpSocket> +#include <QUdpSocket> +#include <QAbstractSocket> +#include <QHostAddress> +#include <QTcpServer> -//#include <stdlib.h> - -#define KVI_IN_BUFFER_ALLOC_CHUNK 4096 -#define KVI_READ_CHUNK 1024 +const char * const sockstate_tbl[] = { + "Unconnected", + "HostLookUp", + "Connecting", + "Connected", + "Bound", + "Closing", + "Listening" +}; +const char * const sockerrors_tbl[] = { + "ConnectionRefused", + "RemoteHostClosed", + "HostNotFound", + "SocketAccess", + "SocketResource", + "SocketTimeout", + "DatagramTooLarge", + "Network", + "AddressInUse", + "SocketAddressNotAvailable", + "UnsupportedSocketOperation", + "ProxyAuthenticationRequired", + "SslHandshakeFailed", + "UnfinishedSocketOperation", + "ProxyConnectionRefused", + "ProxyConnectionClosed", + "ProxyConnectionTimeout", + "ProxyNotFound", + "ProxyProtocol", + "UnknownSocket" +}; /* @doc: socket @keyterms: @@ -68,23 +101,16 @@ It can be used either for connecting to a remote host or to listening for incoming connections.[br] If the KVIrc executable has been compiled with the IPV6 protocol support, this socket also supports it.[br] @functions: - !fn: $status() + !fn: <integer or string> $status(<asString:boolean>) Returns the status of the socket :[br] - 4=connected[br] - 3=listening[br] - 2=connecting[br] - 1=in dns call[br] - 0=disconnected - - !fn: $connectTimeout() - Returns the value of the connect attempt timeout in milliseconds.[br] - This is the timeout after that a connection attempt will be considered as failed if the remote - host is not responding. You can set it with [classfnc:socket]$setConnectTimeout[/classfnc](). - - !fn: $setConnectTimeout(<timeout>) - Sets the connect timeout for this socket. <timeout> must be a positive value in milliseconds.[br] - The default timeout is 60000. - + 0=Unconnected + 1=HostLookUp + 2=Connecting[br] + 3=Connected[br] + 4=Bound[br] + 5=Closing[br] + 6=Listening + !fn: $connect(<host>,<port>) Attempts a connection to <host> on port <port>.[br] <host> can be a numeric internet address (either Ipv4 or Ipv6 (if supported)) or a hostname.[br] @@ -99,7 +125,7 @@ and you will be notified of the attempt result by an asynchronous event call: in case of failure, $connectFailedEvent() will be called, in case of succes, $connectEvent() will be called. - + !fn: $listen([<port>[,<interface>[,<force_ipv6>]]]) Attempts to listen on the specified <port> and <interface>.[br] If <port> is not passed it is assumed to be 0, if <interface> is not passed, it is assumed to be @@ -111,24 +137,17 @@ On some systems listening in the IPV6 namespace allows to accept also IPV4 connections (this includes linux but not windows afaik).[br] When an incoming connection will arrive, $incomingConnectionEvent() will be called. - - !fn: $accept(<socketId>) - This function can be called only from inside $incomingConnectionEvent().[br] - <socketId> must be a newly created socket sub-class instance object.[br] - The passed object will be set up to handle the incoming connection and this object - will remain in listening state (unless you explicitly close it).[br] - This function returns '1' in case of success and '0' in case of failure. - - !fn: $connectEvent() + + !fn: $connectedEvent() This function is called when a connection attempt has been successfully completed. The socket is actually connected to [classfnc:socket]$remoteIp[/classfnc]() on [classfnc:socket]$remotePort[/classfnc](). You can start writing data and you may expect [classfnc:socket]$dataAvailableEvent[/classfnc]() to be triggered. - - !fn: $incomingConnectionEvent() + + !fn: $incomingConnectionEvent(<socket:h_object>) This function is called when an incoming connection arrives over a socket in listening state.[br] - You must call [classfnc:socket]$accept[/classfnc]() passing a newly created socket object + You must return 1 if you to terminad this incoming connectioncall [classfnc:socket]$accept[/classfnc]() passing a newly created socket object to accept and handle the connection.[br] If you don't call [classfnc:socket]$accept[/classfnc]() the incoming connection will be automatically terminated. @@ -146,25 +165,25 @@ !fn: $dataAvailableEvent(<data_length>) This function is called when some data is available to be read: the <data_length> parameter specifies the length of the available data in bytes.[br] - You can use one of the $read* functions to obtain the data. - - !fn: $read(<length>[,<hobject>]) + You can use one of the $read* functions to obtain the data + + !fn: $read(<length>[,<hobject>]) Reads at most <length> bytes of data from the socket. If <length> is anything "outside" the available data range (<length> < 0 or <length> > available_data_length), this function returns all the available data.[br] - By default this function can deal ascii data only: NULL characters are transformed to - ASCII characters 255. You can pass a [class]memorybuffer[/class] object to read binary data. - - !fn: $write(<data, array,files or hobject>[,length]) + By default this function can deal ascii data only: NULL characters are transformed to + ASCII characters 255. You can pass a [class]memorybuffer[/class] object to read binary data. + + !fn: $write(<data, array,files or hobject>[,length]) Writes <data> to the socket.[br] - This function can deal with binary data passing a [class]memorybuffer[/class] object[br] + This function can deal with binary data passing a [class]memorybuffer[/class] object[br] Please note that when this function finishes it does not mean that the data has reached the remote end.[br] Basically it does not even mean that the data has been sent to the remote host.[br] The data is enqueued for sending and will be sent as soon as possible.[br] - Using an array you can pass bytes or data string like this: @$write($array($(0xff),$(0xff),$(0xff),$(0xff),"This is an example")); + Using an array you can pass bytes or data string like this: @$write($array($(0xff),$(0xff),$(0xff),$(0xff),"This is an example")); If you're going to [cmd]delete[/cmd] this object just after the $write call, you should call [classfnc:socket]$close[/classfnc]() just before [cmd]delete[/cmd] to ensure the data delivery. - + !fn: $close() Resets this socket state: kills any pending or active connection. After a close() call the socket may be used for a new connection.[br] @@ -172,22 +191,22 @@ You don't need to call $close() if you [cmd]delete[/cmd] the socket: KVIrc will reset the socket state automatically and free the memory. But if you want to ensure data delivery after a $write call sequece and just before a [cmd]delete[/cmd], $close() is the only chance to do it. - + !fn: $remoteIp() Returns the IP address of the remote end of this socket.[br] The return value is meaningful only if the socket is in connected or connecting state. - + !fn: $setProtocol(<protocol>) - Let KVIrc use TCP or UDP protocol - + Let KVIrc use TCP or UDP protocol + !fn: $remotePort() Returns the port of the remote end of this socket.[br] The return value is meaningful only if the socket is in connected or connecting state. - + !fn: $localIp() Returns the IP address of the local end of this socket.[br] The return value is meaningful only if the socket is in connected, listening or connecting state. - + !fn: $localPort() Returns the port of the local end of this socket.[br] The return value is meaningful only if the socket is in connected, listening or connecting state. @@ -268,142 +287,93 @@ KVSO_BEGIN_REGISTERCLASS(KvsObject_socket,"socket","object") KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,localIp) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,localPort) KVSO_REGISTER_HANDLER(KvsObject_socket,"connect",functionConnect) - KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,connectTimeout) - KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,setConnectTimeout) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,close) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,read) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,write) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,setProtocol) KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,listen) - KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,accept) - - KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KvsObject_socket,"connectEvent") - KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KvsObject_socket,"connectFailedEvent") - KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KvsObject_socket,"disconnectEvent") - KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KvsObject_socket,"dataAvailableEvent") - KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KvsObject_socket,"incomingConnectionEvent") + KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,dataAvailableEvent) + KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,incomingConnectionEvent) + KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,connectedEvent) + KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,disconnectedEvent) + KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,errorEvent) + KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,hostFoundEvent) + KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_socket,stateChangedEvent) KVSO_END_REGISTERCLASS(KvsObject_socket) +bool KvsObject_socket::init(KviKvsRunTimeContext *c,KviKvsVariantList *) +{ + m_pSocket = new QTcpSocket(); + m_pServer = 0; + m_pContext = c ; + makeConnections(); + return true; +} + KVSO_BEGIN_CONSTRUCTOR(KvsObject_socket,KviKvsObject) - m_bUdp = false; - m_uConnectionId = 0; - m_sock = KVI_INVALID_SOCKET; - m_iStatus = KVI_SCRIPT_SOCKET_STATUS_DISCONNECTED; - m_uRemotePort = 0; - m_uSecondaryPort = 0; - m_pSn = 0; - m_pDns = 0; - m_pDelayTimer = 0; - m_uConnectTimeout = 60000; - m_pInBuffer = 0; - m_uInBufferLen = 0; - m_uInDataLen = 0; - m_pOutBuffer = new KviDataBuffer(); - m_pFlushTimer = new QTimer(); - m_bIPv6 = false; - m_uLocalPort = 0; - m_secondarySock = KVI_INVALID_SOCKET; - connect(m_pFlushTimer,SIGNAL(timeout()),this,SLOT(tryFlush())); KVSO_END_CONSTRUCTOR(KvsObject_socket) KVSO_BEGIN_DESTRUCTOR(KvsObject_socket) - delete m_pOutBuffer; - delete m_pFlushTimer; - m_pOutBuffer=0; - m_pFlushTimer=0; - - - if(m_pInBuffer)KviMemory::free(m_pInBuffer); - if(m_pDelayTimer)delete m_pDelayTimer; - if(m_pDns)delete m_pDns; - if(m_pSn)delete m_pSn; - if(m_sock != KVI_INVALID_SOCKET)kvi_socket_close(m_sock); - if(m_secondarySock != KVI_INVALID_SOCKET)kvi_socket_close(m_secondarySock); + if (m_pSocket)delete m_pSocket; + m_pSocket = 0; + if (m_pServer) delete m_pServer; + m_pServer = 0; KVSO_END_DESTRUCTOR(KvsObject_socket) //---------------------- KVSO_CLASS_FUNCTION(socket,status) { - c->returnValue()->setInteger(m_iStatus); + int state=m_pSocket->state(); + c->returnValue()->setString(sockstate_tbl[state]); return true; } KVSO_CLASS_FUNCTION(socket,close) { Q_UNUSED(c); - - if (!m_pOutBuffer) return true; - if((m_pOutBuffer->size() != 0) && (m_iStatus == KVI_SCRIPT_SOCKET_STATUS_CONNECTED)) - tryFlush(); - - reset(); - return true; -} - -KVSO_CLASS_FUNCTION(socket,connectTimeout) -{ - c->returnValue()->setInteger(m_uConnectTimeout); - return true; -} - -KVSO_CLASS_FUNCTION(socket,setConnectTimeout) -{ - kvs_uint_t uTimeout; - KVSO_PARAMETERS_BEGIN(c) - KVSO_PARAMETER("time_out",KVS_PT_UNSIGNEDINTEGER,0,uTimeout) - KVSO_PARAMETERS_END(c) - m_uConnectTimeout = uTimeout; + m_pSocket->disconnectFromHost(); return true; } KVSO_CLASS_FUNCTION(socket,remotePort) { - c->returnValue()->setInteger(m_uRemotePort); + c->returnValue()->setInteger(m_pSocket->peerPort()); return true; } KVSO_CLASS_FUNCTION(socket,remoteIp) { - c->returnValue()->setString(m_szRemoteIp); + c->returnValue()->setString(m_pSocket->peerAddress().toString()); return true; } KVSO_CLASS_FUNCTION(socket,localPort) { - c->returnValue()->setInteger(m_uLocalPort); + c->returnValue()->setInteger(m_pSocket->localPort()); return true; } KVSO_CLASS_FUNCTION(socket,localIp) { - c->returnValue()->setString(m_szLocalIp); + c->returnValue()->setString(m_pSocket->localAddress().toString()); return true; } -unsigned int KvsObject_socket::readGetLength(KviKvsObjectFunctionCall * c) -{ - kvs_uint_t uLen; - KVSO_PARAMETERS_BEGIN(c) - KVSO_PARAMETER("length",KVS_PT_UNSIGNEDINTEGER,KVS_PF_OPTIONAL,uLen) - KVSO_PARAMETERS_END(c) - if (uLen>m_uInDataLen || !uLen) return m_uInDataLen; - else return uLen; -} KVSO_CLASS_FUNCTION(socket,read) { - kvs_uint_t uLen; + kvs_int_t iLen; KviKvsObject * pObject; kvs_hobject_t hObject; KVSO_PARAMETERS_BEGIN(c) - KVSO_PARAMETER("length",KVS_PT_UNSIGNEDINTEGER,KVS_PF_OPTIONAL,uLen) + KVSO_PARAMETER("length",KVS_PT_INTEGER,KVS_PF_OPTIONAL,iLen) KVSO_PARAMETER("hobject",KVS_PT_HOBJECT,KVS_PF_OPTIONAL,hObject) KVSO_PARAMETERS_END(c) - if (uLen>m_uInDataLen || !uLen) uLen=m_uInDataLen; + if (iLen>m_pSocket->bytesAvailable() || !iLen) iLen=m_pSocket->bytesAvailable(); if (hObject) { pObject=KviKvsKernel::instance()->objectController()->lookupObject(hObject); @@ -416,10 +386,10 @@ KVSO_CLASS_FUNCTION(socket,read) { QByteArray *pBuffer=((KvsObject_memoryBuffer *)pObject)->pBuffer(); int oldsize=pBuffer->size(); - pBuffer->resize(oldsize+uLen); - KviMemory::move(pBuffer->data()+oldsize,m_pInBuffer,uLen); - - } else if(pObject->inheritsClass("file")) + pBuffer->resize(oldsize+iLen); + m_pSocket->read(pBuffer->data()+oldsize,iLen); + } + else if(pObject->inheritsClass("file")) { KviFile *pFile=((KvsObject_file *)pObject)->file(); if (!pFile->isOpen()) @@ -427,26 +397,26 @@ KVSO_CLASS_FUNCTION(socket,read) c->warning(__tr2qs_ctx("File is not open!","objects")); return true; } - pFile->write(m_pInBuffer,uLen); - } else + pFile->write(m_pSocket->read(iLen)); + } + else { c->warning(__tr2qs_ctx("Buffer parameter is not a memorybuffer object","objects")); return true; } - eatInData(uLen); return true; } - if(uLen > 0) + if(iLen > 0) { // convert NULLS to char 255 - for(unsigned int i = 0;i < uLen;i++) + char buffer[iLen]; + m_pSocket->read(buffer,iLen); + for(unsigned int i = 0;i < iLen;i++) { - if(!m_pInBuffer[i])m_pInBuffer[i] = (char)(255); + if(!buffer[i]) buffer[i] = (char)(255); } - QString tmpBuffer = QString::fromUtf8(m_pInBuffer,uLen); + QString tmpBuffer = QString::fromUtf8(buffer,iLen); c->returnValue()->setString(tmpBuffer); - - eatInData(uLen); } return true; } @@ -475,8 +445,9 @@ KVSO_CLASS_FUNCTION(socket,write) if(pObject->inheritsClass("memorybuffer")) { QByteArray *p=((KvsObject_memoryBuffer *)pObject)->pBuffer(); - m_pOutBuffer->append((const unsigned char *)p->data(),p->size()); - } else if(pObject->inheritsClass("file")) + m_pSocket->write(*p); + } + else if(pObject->inheritsClass("file")) { KviFile * pFile = ((KvsObject_file *)pObject)->file(); if(!pFile->isOpen()) @@ -484,12 +455,11 @@ KVSO_CLASS_FUNCTION(socket,write) c->warning(__tr2qs_ctx("File is not open!","objects")); return true; } - if(!uLen) - uLen = pFile->size(); - kvs_int_t size = pFile->size(); + if(!uLen) uLen = pFile->size(); + kvs_int_t size = pFile->size(); pFile->flush(); - m_pOutBuffer->append((const unsigned char*)pFile->read(uLen).data(),uLen); - c->returnValue()->setBoolean((size-pFile->pos()==0)); + m_pSocket->write((const char*)pFile->read(uLen).data(),uLen); + c->returnValue()->setBoolean((size-pFile->pos()==0)); } else { c->warning(__tr2qs_ctx("Buffer parameter is not a memorybuffer or file object","objects")); return true; @@ -506,7 +476,7 @@ KVSO_CLASS_FUNCTION(socket,write) { if(iValue < 256 && iValue >= 0) { - m_pOutBuffer->append((unsigned char)iValue); + m_pSocket->putChar(iValue); continue; } else { c->warning(__tr2qs_ctx("Only values in the range of 0-255 are allowed: integer %d is out of range","objects"),iValue); @@ -518,18 +488,16 @@ KVSO_CLASS_FUNCTION(socket,write) QString szData; pVar->asString(szData); QByteArray szData8 = szData.toUtf8(); - m_pOutBuffer->append((const unsigned char*)szData8.data(),szData8.length()); + m_pSocket->write((const char*)szData8.data(),szData8.length()); } else { c->warning(__tr2qs_ctx("Datatype not supported","objects")); return true; } } } - delayedFlush(0); return true; } - - QString szData; + QString szData; pVariantData->asString(szData); if(!KviFileUtils::fileExists(szData)) { @@ -537,756 +505,181 @@ KVSO_CLASS_FUNCTION(socket,write) if(szData8.length() > 0) { qDebug("write on socket %s",szData8.data()); - m_pOutBuffer->append((const unsigned char*)szData8.data(),szData8.length()); + kvs_int_t bytes=m_pSocket->write((const char*)szData8.data(),szData8.length()); + c->returnValue()->setInteger(bytes); + m_pSocket->flush(); } } else { KviFile f(szData); f.open(QIODevice::ReadOnly); QByteArray ar = f.readAll(); - m_pOutBuffer->append((const unsigned char*)ar.data(),ar.size()); + m_pSocket->write((const char*)ar.data(),ar.size()); f.close(); } } - delayedFlush(0); - return true; -} - - -KVSO_CLASS_FUNCTION(socket,accept) -{ - KviKvsObject * pObject; - kvs_hobject_t hObject; - KVSO_PARAMETERS_BEGIN(c) - KVSO_PARAMETER("object_socket",KVS_PT_HOBJECT,0,hObject) - KVSO_PARAMETERS_END(c) - - pObject = KviKvsKernel::instance()->objectController()->lookupObject(hObject); - - if(!pObject) - { - c->warning(__tr2qs_ctx("No socket object specified","objects")); - return true; - } - - if(!pObject->inheritsClass("socket")) - { - c->warning(__tr2qs_ctx("Invalid socket object specified (it doesn't inherit from socket)","objects")); - return true; - } - - if(m_secondarySock != KVI_INVALID_SOCKET) - { - ((KvsObject_socket *)pObject)->acceptConnection(m_secondarySock,m_uSecondaryPort,m_szSecondaryIp.toUtf8().data()); - - m_secondarySock = KVI_INVALID_SOCKET; - m_uSecondaryPort = 0; - m_szSecondaryIp=""; - } else { - c->warning(__tr2qs_ctx("There is no connection to accept!","objects")); - } return true; } - - KVSO_CLASS_FUNCTION(socket,setProtocol) { QString szProto; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("protocol",KVS_PT_STRING,0,szProto) KVSO_PARAMETERS_END(c) - - m_bUdp = KviQString::equalCI(szProto,"udp"); + if (m_pSocket) delete m_pSocket; + if(KviQString::equalCI(szProto,"udp")) m_pSocket = new QUdpSocket(); + else m_pSocket = new QTcpSocket(); + makeConnections(); return true; } - KVSO_CLASS_FUNCTION(socket,functionConnect) { + kvs_uint_t uRemotePort; + QString szRemoteIp; KVSO_PARAMETERS_BEGIN(c) - KVSO_PARAMETER("remote_ip",KVS_PT_STRING,0,m_szRemoteIp) - KVSO_PARAMETER("remote_port",KVS_PT_UNSIGNEDINTEGER,0,m_uRemotePort) + KVSO_PARAMETER("remote_ip",KVS_PT_STRING,0,szRemoteIp) + KVSO_PARAMETER("remote_port",KVS_PT_UNSIGNEDINTEGER,0,uRemotePort) KVSO_PARAMETERS_END(c) - qDebug("Function connect"); - - if (m_uRemotePort>65535) + if (uRemotePort>65535) { - c->warning(__tr2qs_ctx("Value %d for port is out of range (values allowed are from 0 to 65535)","objects"),m_uRemotePort); + c->warning(__tr2qs_ctx("Value %d for port is out of range (values allowed are from 0 to 65535)","objects"),uRemotePort); return true; } - if((m_sock != KVI_INVALID_SOCKET) || (m_iStatus != KVI_SCRIPT_SOCKET_STATUS_DISCONNECTED)) - { - c->warning(__tr2qs_ctx("Another connection in progress","objects")); - c->returnValue()->setBoolean(true); - return true; - } - - -#ifdef COMPILE_IPV6_SUPPORT - if(KviNetUtils::isValidStringIp(m_szRemoteIp) || KviNetUtils::isValidStringIPv6(m_szRemoteIp)) -#else - if(KviNetUtils::isValidStringIp(m_szRemoteIp)) -#endif - { - qDebug("ok connecting"); - qDebug("connecting to ip %s ",m_szRemoteIp.toUtf8().data()); - qDebug("no ip"); - m_iStatus = KVI_SCRIPT_SOCKET_STATUS_CONNECTING; - delayedConnect(); - } else { - qDebug("connecting on ip %s port %d",m_szRemoteIp.toUtf8().data(),(int) m_uRemotePort); - m_iStatus = KVI_SCRIPT_SOCKET_STATUS_DNS; - delayedLookupRemoteIp(); - } + m_pSocket->connectToHost(szRemoteIp,uRemotePort); c->returnValue()->setBoolean(true); return true; } - KVSO_CLASS_FUNCTION(socket,listen) { - if((m_sock != KVI_INVALID_SOCKET) || (m_iStatus != KVI_SCRIPT_SOCKET_STATUS_DISCONNECTED)) - { - c->warning(__tr2qs_ctx("Another connection in progress","objects")); - c->returnValue()->setBoolean(false); - return true; - } kvs_uint_t uLocalPort; QString m_szLocalIp; - bool m_bIPv6; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("local_port",KVS_PT_UNSIGNEDINTEGER,0,uLocalPort) - KVSO_PARAMETER("local_ip",KVS_PT_STRING,KVS_PF_OPTIONAL,m_szLocalIp) - KVSO_PARAMETER("bool_ipV6",KVS_PT_BOOLEAN,KVS_PF_OPTIONAL,m_bIPv6) + KVSO_PARAMETER("interface",KVS_PT_STRING,KVS_PF_OPTIONAL,m_szLocalIp) KVSO_PARAMETERS_END(c) - m_uLocalPort=uLocalPort; - -#ifndef COMPILE_IPV6_SUPPORT - if(m_bIPv6) - { - c->warning(__tr2qs_ctx("No IPv6 support in this executable","objects")); - c->returnValue()->setBoolean(false); - reset(); - return true; - } -#endif - - if(!m_szLocalIp.isEmpty()) - { - - // Check the address type - if(!KviNetUtils::isValidStringIp(m_szLocalIp)) - { -#ifdef COMPILE_IPV6_SUPPORT - if(KviNetUtils::isValidStringIPv6(m_szLocalIp)) - { - m_bIPv6 = true; - } else { -#else - c->warning(__tr2qs_ctx("Invalid IP address (%Q)","objects"),&m_szLocalIp); - c->returnValue()->setBoolean(false); - reset(); - return true; -#endif -#ifdef COMPILE_IPV6_SUPPORT - } -#endif - } - } - - -#ifdef COMPILE_IPV6_SUPPORT - m_sock = kvi_socket_create(m_bIPv6 ? KVI_SOCKET_PF_INET6 : KVI_SOCKET_PF_INET, - m_bUdp ? KVI_SOCKET_TYPE_DGRAM : KVI_SOCKET_TYPE_STREAM,KVI_SOCKET_PROTO_TCP); -#else - m_sock = kvi_socket_create(KVI_SOCKET_PF_INET,m_bUdp ? KVI_SOCKET_TYPE_DGRAM : KVI_SOCKET_TYPE_STREAM,KVI_SOCKET_PROTO_TCP); -#endif - - if(m_sock == KVI_INVALID_SOCKET) - { - c->warning(__tr2qs_ctx("Socket creation failed","objects")); - c->returnValue()->setBoolean(false); - reset(); - return true; - } - - if(!m_szLocalIp.isEmpty()) - { -#ifdef COMPILE_IPV6_SUPPORT - KviSockaddr sa(m_szLocalIp.toUtf8().data(),m_uLocalPort,m_bIPv6,m_bUdp); -#else - KviSockaddr sa(m_szLocalIp.toUtf8().data(),m_uLocalPort,false,m_bUdp); -#endif - if(!sa.socketAddress()) - { - c->warning(__tr2qs_ctx("Invalid socket address","objects")); - reset(); - c->returnValue()->setBoolean(false); - return true; - } - - if(!kvi_socket_bind(m_sock,sa.socketAddress(),((int)(sa.addressLength())))) - { - c->warning(__tr2qs_ctx("Bind failure","objects")); - reset(); - c->returnValue()->setBoolean(false); - return true; - } - } else { -#ifdef COMPILE_IPV6_SUPPORT - KviSockaddr sa(m_uLocalPort,m_bIPv6,m_bUdp); -#else - KviSockaddr sa(m_uLocalPort,false,m_bUdp); -#endif - if(!sa.socketAddress()) - { - c->warning(__tr2qs_ctx("Invalid socket address","objects")); - reset(); - c->returnValue()->setBoolean(false); - return true; - } - - if(!kvi_socket_bind(m_sock,sa.socketAddress(),((int)(sa.addressLength())))) - { - c->warning(__tr2qs_ctx("Bind failure","objects")); - reset(); - c->returnValue()->setBoolean(false); - return true; - } - } - - if(!kvi_socket_listen(m_sock,5)) + if (uLocalPort>65535) { - c->warning(__tr2qs_ctx("Listen failure","objects")); - reset(); - c->returnValue()->setBoolean(false); - return true; + 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); + uLocalPort=0; } - - - // Reread the port in case we're binding to a random one (0) - -#ifdef COMPILE_IPV6_SUPPORT - KviSockaddr sareal(0,m_bIPv6,m_bUdp); -#else - KviSockaddr sareal(0,false,m_bUdp); -#endif - - int size = (int)sareal.addressLength(); - - if(kvi_socket_getsockname(m_sock,sareal.socketAddress(),&size)) - { - m_uLocalPort = sareal.port(); - sareal.getStringAddress(m_szLocalIp); - } - - // and setup the READ notifier... - m_pSn = new QSocketNotifier(m_sock,QSocketNotifier::Read); - QObject::connect(m_pSn,SIGNAL(activated(int)),this,SLOT(incomingConnection(int))); - m_pSn->setEnabled(true); - - m_iStatus = KVI_SCRIPT_SOCKET_STATUS_LISTENING; - - c->returnValue()->setBoolean(true); + if(m_pServer) delete m_pServer; + m_pServer = new QTcpServer(); + QHostAddress address(m_szLocalIp); + bool bOk=m_pServer->listen(address,uLocalPort); + connect(m_pServer,SIGNAL(newConnection()),this,SLOT(slotNewConnection())); + c->returnValue()->setBoolean(bOk); return true; } - -void KvsObject_socket::incomingConnection(int) +void KvsObject_socket::makeConnections() { -#ifdef COMPILE_IPV6_SUPPORT - struct sockaddr_in6 hostSockAddr6; -#endif - struct sockaddr_in hostSockAddr; - - int size = sizeof(hostSockAddr); - struct sockaddr * addr = (struct sockaddr *)&hostSockAddr; - -#ifdef COMPILE_IPV6_SUPPORT - if(m_bIPv6) - { - addr = (struct sockaddr *)&hostSockAddr6; - size = sizeof(hostSockAddr6); - } -#endif - - // Incoming connection - m_secondarySock = kvi_socket_accept(m_sock,addr,&size); - if(m_secondarySock != KVI_INVALID_SOCKET) - { - // Connected -#ifdef COMPILE_IPV6_SUPPORT - if(m_bIPv6) - { - m_uSecondaryPort = ntohs(((struct sockaddr_in6 *)addr)->sin6_port); - if(!KviNetUtils::binaryIpToStringIp_V6(((struct sockaddr_in6 *)addr)->sin6_addr,m_szSecondaryIp)) - m_szSecondaryIp = __tr("unknown"); - } else { -#endif - m_uSecondaryPort = ntohs(((struct sockaddr_in *)addr)->sin_port); - if(!KviNetUtils::binaryIpToStringIp(((struct sockaddr_in *)addr)->sin_addr,m_szSecondaryIp)) - m_szSecondaryIp = __tr("unknown"); -#ifdef COMPILE_IPV6_SUPPORT - } -#endif - KviKvsVariantList *params=0; - callFunction(this,"incomingConnectionEvent",params); - if(m_secondarySock != KVI_INVALID_SOCKET) - { - kvi_socket_close(m_secondarySock); - m_secondarySock = KVI_INVALID_SOCKET; - m_uSecondaryPort = 0; - m_szSecondaryIp=""; - } - - } // else..huh ?... wait for the next notifier call + connect(m_pSocket,SIGNAL(connected()),this,SLOT(slotConnected())); + connect(m_pSocket,SIGNAL(readyRead()),this,SLOT(slotReadyRead())); + connect(m_pSocket,SIGNAL(disconnected()),this,SLOT(slotDisconnected())); + connect(m_pSocket,SIGNAL(error( QAbstractSocket::SocketError)),this,SLOT(slotError(QAbstractSocket::SocketError))); + connect(m_pSocket,SIGNAL(hostFound()),this,SLOT(slotHostFound())); + connect(m_pSocket,SIGNAL(stateChanged(QAbstractSocket::SocketState)),this,SLOT(slotStateChanged(QAbstractSocket::SocketState))); + //proxyAuthenticationRequired ( const QNetworkProxy & proxy, QAuthenticator * authenticator ) } -void KvsObject_socket::acceptConnection(kvi_socket_t s,kvi_u32_t uPort,const char * szIp) +// slots +void KvsObject_socket::slotReadyRead() { - reset(); - m_sock = s; - m_uRemotePort = uPort; - m_szRemoteIp = szIp; -#ifdef COMPILE_IPV6_SUPPORT - KviSockaddr sareal(0,m_bIPv6,m_bUdp); -#else - KviSockaddr sareal(0,false,m_bUdp); -#endif - - int size = (int)sareal.addressLength(); - - if(kvi_socket_getsockname(m_sock,sareal.socketAddress(),&size)) - { - m_uLocalPort = sareal.port(); - sareal.getStringAddress(m_szLocalIp); - } - - m_iStatus = KVI_SCRIPT_SOCKET_STATUS_CONNECTED; - - m_pSn = new QSocketNotifier((int)m_sock,QSocketNotifier::Read); - QObject::connect(m_pSn,SIGNAL(activated(int)),this,SLOT(readNotifierFired(int))); - m_pSn->setEnabled(true); + KviKvsVariantList lParams; + lParams.append(new KviKvsVariant((kvs_int_t)m_pSocket->bytesAvailable())); + callFunction(this,"dataAvailableEvent",&lParams); } - -void KvsObject_socket::delayedConnect() +void KvsObject_socket::slotConnected() { - if(m_pDelayTimer)delete m_pDelayTimer; - m_pDelayTimer = new QTimer(); - connect(m_pDelayTimer,SIGNAL(timeout()),this,SLOT(doConnect())); - m_pDelayTimer->setInterval(0); - m_pDelayTimer->setSingleShot(true); - m_pDelayTimer->start(); + KviKvsVariantList *lParams=0; + callFunction(this,"connectedEvent",lParams); } -void KvsObject_socket::doConnect() +void KvsObject_socket::slotDisconnected() { - qDebug("doConnect function"); - if(m_pDelayTimer)delete m_pDelayTimer; - m_pDelayTimer = 0; - - - KviSockaddr sa(m_szRemoteIp.toUtf8().data(),m_uRemotePort,!KviNetUtils::isValidStringIp(m_szRemoteIp),m_bUdp); - - if(!sa.socketAddress()) - { - unsigned int uOldConnectionId = m_uConnectionId; - QString ipAddressError=__tr2qs_ctx("Invalid IP address ","objects"); - - ipAddressError.append(m_szRemoteIp); - - KviKvsVariantList params; - QString tmp; - KviQString::sprintf(tmp,__tr2qs_ctx("Invalid IP address (%Q)","objects"),&m_szRemoteIp); - params.append(new KviKvsVariant(tmp)); - callFunction(this,"connectFailedEvent",¶ms); - if(m_uConnectionId == uOldConnectionId)reset(); - // else it has already been called! - return; - } -qDebug("Socket created"); - - // create the socket -#ifdef COMPILE_IPV6_SUPPORT - m_bIPv6 = sa.isIPv6(); - m_sock = kvi_socket_create(sa.isIPv6() ? KVI_SOCKET_PF_INET6 : KVI_SOCKET_PF_INET,m_bUdp ? KVI_SOCKET_TYPE_DGRAM : KVI_SOCKET_TYPE_STREAM,KVI_SOCKET_PROTO_TCP); -#else - m_bIPv6 = false; - m_sock = kvi_socket_create(KVI_SOCKET_PF_INET,m_bUdp ? KVI_SOCKET_TYPE_DGRAM : KVI_SOCKET_TYPE_STREAM,KVI_SOCKET_PROTO_TCP); -#endif - - if(m_sock == KVI_INVALID_SOCKET) - { - unsigned int uOldConnectionId = m_uConnectionId; - KviKvsVariantList lParams; - lParams.append(new KviKvsVariant(__tr2qs_ctx("Failed to create the socket","objects"))); - callFunction(this,"connectFailedEvent",&lParams); - if(m_uConnectionId == uOldConnectionId)reset(); - // else it has already been called! - return; - } - qDebug("Valid socket"); - - if(!kvi_socket_setNonBlocking(m_sock)) - { - unsigned int uOldConnectionId = m_uConnectionId; - KviKvsVariantList lParams; - lParams.append(new KviKvsVariant(__tr2qs_ctx("Failed to setup a nonblocking socket","objects"))); - callFunction(this,"connectFailedEvent",&lParams); - if(m_uConnectionId == uOldConnectionId)reset(); - // else it has already been called! - return; - } - - if(!kvi_socket_connect(m_sock,sa.socketAddress(),((int)(sa.addressLength())))) - { - int err = kvi_socket_error(); - if(!kvi_socket_recoverableConnectError(err)) - { - // Ops... - int sockError=err; - if(sockError==0) - { - // Zero error ?...let's look closer - int iSize=sizeof(int); - if(!kvi_socket_getsockopt(m_sock,SOL_SOCKET,SO_ERROR, - (void *)&sockError,&iSize))sockError=0; - } - unsigned int uOldConnectionId = m_uConnectionId; - QString callBackError=__tr2qs_ctx("Connect failure: ","objects"); - - callBackError.append((KviError::getDescription(KviError::translateSystemError(sockError)).toUtf8().data())); - KviKvsVariantList lParams; - lParams.append(new KviKvsVariant(callBackError)); - callFunction(this,"connectFailedEvent",&lParams); - if(m_uConnectionId == uOldConnectionId)reset(); - // else it has already been called! - return; - } - } - qDebug("Socket connected"); - m_pDelayTimer = new QTimer(); - connect(m_pDelayTimer,SIGNAL(timeout()),this,SLOT(connectTimeoutSlot())); - m_pDelayTimer->setInterval(m_uConnectTimeout); - m_pDelayTimer->setSingleShot(true); - m_pDelayTimer->start(); - - m_pSn = new QSocketNotifier((int)m_sock,QSocketNotifier::Write); - QObject::connect(m_pSn,SIGNAL(activated(int)),this,SLOT(writeNotifierFired(int))); - m_pSn->setEnabled(true); + KviKvsVariantList *lParams=0; + callFunction(this,"disconnectedEvent",lParams); } -void KvsObject_socket::connectTimeoutSlot() +void KvsObject_socket::slotError( QAbstractSocket::SocketError socketError ) { - unsigned int uOldConnectionId = m_uConnectionId; KviKvsVariantList lParams; - lParams.append(new KviKvsVariant(__tr2qs_ctx("Connect attempt timed out","objects"))); - callFunction(this,"connectFailedEvent",&lParams); - if(m_uConnectionId == uOldConnectionId)reset(); - // else it has already been called! + QString szError = sockerrors_tbl[socketError]; + lParams.append(new KviKvsVariant(szError)); + callFunction(this,"errorEvent",&lParams); } -void KvsObject_socket::delayedLookupRemoteIp() +void KvsObject_socket::slotHostFound() { - if(m_pDelayTimer)delete m_pDelayTimer; - m_pDelayTimer = new QTimer(); - connect(m_pDelayTimer,SIGNAL(timeout()),this,SLOT(lookupRemoteIp())); - - m_pDelayTimer->setInterval(0); - m_pDelayTimer->setSingleShot(true); - m_pDelayTimer->start(); + KviKvsVariantList *lParams=0; + callFunction(this,"hostFoundEvent",lParams); } -void KvsObject_socket::lookupRemoteIp() +void KvsObject_socket::slotStateChanged( QAbstractSocket::SocketState socketState ) { - qDebug("Resolve dns"); - if(m_pDelayTimer)delete m_pDelayTimer; - m_pDelayTimer = 0; - if(m_pDns)delete m_pDns; - m_pDns = new KviDnsResolver(); - connect(m_pDns,SIGNAL(lookupDone(KviDnsResolver *)),this,SLOT(lookupDone(KviDnsResolver *))); - if(!m_pDns->lookup(m_szRemoteIp,KviDnsResolver::Any)) - { - unsigned int uOldConnectionId = m_uConnectionId; - KviKvsVariantList lParams; - lParams.append(new KviKvsVariant(__tr2qs_ctx("Can't start the DNS thread","objects"))); - callFunction(this,"connectFailedEvent",&lParams); - if(m_uConnectionId == uOldConnectionId)reset(); - // else it has already been called! - } + KviKvsVariantList lParams; + QString szState = sockstate_tbl[socketState]; + lParams.append(new KviKvsVariant(szState)); + callFunction(this,"stateChangedEvent",&lParams); } -void KvsObject_socket::lookupDone(KviDnsResolver *pDns) +void KvsObject_socket::slotNewConnection() { - - if(pDns->state() != KviDnsResolver::Success) - { - unsigned int uOldConnectionId = m_uConnectionId; - KviKvsVariantList lParams; - lParams.append(new KviKvsVariant(KviError::getDescription(pDns->error()))); - callFunction(this,"connectFailedEvent",&lParams); - - if(m_uConnectionId == uOldConnectionId)reset(); - // else it has already been called! - return; + qDebug ("New connection"); + QTcpSocket *pSocket = m_pServer->nextPendingConnection(); + KviKvsObjectClass * pClass = KviKvsKernel::instance()->objectController()->lookupClass("socket"); + KviKvsVariantList lParams; + KviKvsObject * pObject = pClass->allocateInstance(0,"internalsocket",m_pContext,&lParams); + ((KvsObject_socket *)pObject)->setInternalSocket(pSocket); + kvs_hobject_t hobj=pObject->handle(); + KviKvsVariantList params(new KviKvsVariant(hobj)); + bool ret=false; + KviKvsVariant *retv=new KviKvsVariant(ret); + callFunction(this,"incomingConnectionEvent",retv,¶ms); + if (retv){ + pObject=KviKvsKernel::instance()->objectController()->lookupObject(hobj); + if (pObject) pObject->dieNow(); } - m_szRemoteIp = pDns->firstIpAddress(); - qDebug("Dns resolved in %s",m_szRemoteIp.toUtf8().data()); - - delete m_pDns; - m_pDns = 0; - doConnect(); } - -void KvsObject_socket::writeNotifierFired(int) +KVSO_CLASS_FUNCTION(socket,incomingConnectionEvent) { - if(m_pSn) - { - delete m_pSn; - m_pSn = 0; - } - if(m_pDelayTimer) - { - delete m_pDelayTimer; - m_pDelayTimer = 0; - } - - // Check for errors... - int sockError; - int iSize=sizeof(int); - if(!kvi_socket_getsockopt(m_sock,SOL_SOCKET,SO_ERROR,(void *)&sockError,&iSize))sockError = -1; - //sockError = 0; - if(sockError != 0) - { - //qDebug("Failed here %d",sockError); - //failed - KviError::Code eError; - if(sockError > 0) - eError = KviError::translateSystemError(sockError); - else - eError = KviError::UnknownError; //Error 0 ? - unsigned int uOldConnectionId = m_uConnectionId; - KviKvsVariantList lParams; - lParams.append(new KviKvsVariant(KviError::getDescription(eError))); - callFunction(this,"connectFailedEvent",&lParams); - if(m_uConnectionId == uOldConnectionId)reset(); - // else it has already been called! - } else { - // Succesfully connected - // create the correct read notifier now... - m_pSn = new QSocketNotifier((int)m_sock,QSocketNotifier::Read); - QObject::connect(m_pSn,SIGNAL(activated(int)),this,SLOT(readNotifierFired(int))); - m_pSn->setEnabled(true); - -#ifdef COMPILE_IPV6_SUPPORT - KviSockaddr sareal(0,m_bIPv6,m_bUdp); -#else - KviSockaddr sareal(0,false,m_bUdp); -#endif - int size = (int)sareal.addressLength(); - if(kvi_socket_getsockname(m_sock,sareal.socketAddress(),&size)) - { - m_uLocalPort = sareal.port(); - sareal.getStringAddress(m_szLocalIp); - } - unsigned int uOldConnectionId = m_uConnectionId; - KviKvsVariantList *params=0; - callFunction(this,"connectEvent",params); - if(m_uConnectionId == uOldConnectionId) - m_iStatus = KVI_SCRIPT_SOCKET_STATUS_CONNECTED; - // else the connection has been already changed! - } + emitSignal("incomingConnection",c,c->params()); + return true; } - -void KvsObject_socket::readNotifierFired(int) +KVSO_CLASS_FUNCTION(socket,dataAvailableEvent) { - //read da - if((m_uInBufferLen - m_uInDataLen) < KVI_READ_CHUNK) - { - m_uInBufferLen += KVI_IN_BUFFER_ALLOC_CHUNK; - //m_pInBuffer->resize(m_uInBufferLen); - m_pInBuffer = (char *)KviMemory::reallocate(m_pInBuffer,m_uInBufferLen); - } - - //int readLength = kvi_socket_recv(m_sock,m_pInBuffer->data() + m_uInDataLen,KVI_READ_CHUNK); - int readLength = kvi_socket_recv(m_sock,m_pInBuffer + m_uInDataLen,KVI_READ_CHUNK); - - if(readLength <= 0) - { - if(readLength==0) - { - unsigned int uOldConnectionId = m_uConnectionId; - KviKvsVariantList *params=0; - callFunction(this,"disconnectEvent",params); - if(m_uConnectionId == uOldConnectionId)reset(); - // else it has already been called! - return; - } else { - //check for transmission errors - int err = kvi_socket_error(); -#if defined(COMPILE_ON_WINDOWS) || defined(COMPILE_ON_MINGW) - if((err != EAGAIN) && (err != EINTR) && (err != WSAEWOULDBLOCK)) -#else - if((err != EAGAIN) && (err != EINTR)) -#endif - { - unsigned int uOldConnectionId = m_uConnectionId; - if(err > 0) - { - // QString error=KviError::translateSystemError(err); - KviKvsVariantList lParams; - lParams.append(new KviKvsVariant((kvs_int_t)KviError::translateSystemError(err))); - callFunction(this,"disconnectEvent",&lParams); - } else { - KviKvsVariantList lParams; - lParams.append(new KviKvsVariant(KviError::getDescription(KviError::RemoteEndClosedConnection))); - callFunction(this,"disconnectEvent",&lParams); - - } - if(m_uConnectionId == uOldConnectionId)reset(); - // else it has already been called! - return; - } //else transient error...wait again... - } - return; // can do nothing - } - // readLength > 0 - m_uInDataLen += readLength; - KviKvsVariantList lParams; - lParams.append(new KviKvsVariant((kvs_int_t)readLength)); - callFunction(this,"dataAvailableEvent",&lParams); - unsigned int uOldConnectionId = m_uConnectionId; - if(m_uConnectionId == uOldConnectionId) - { - if(m_uInDataLen > (4096 * 1024)) // too much data in buffer (not reading) - { - KviKvsVariantList lParams; - lParams.append(new KviKvsVariant(new KviKvsVariant(__tr2qs_ctx("Too much unprocessed incoming data (you've left this socket unmanaged ?)","objects")))); - callFunction(this,"disconnectEvent",&lParams); - reset(); - } - } + emitSignal("dataAvailable",c,c->params()); + return true; } -void KvsObject_socket::eatInData(unsigned int uLen) +KVSO_CLASS_FUNCTION(socket,connectedEvent) { - if(uLen > m_uInDataLen)uLen = m_uInDataLen; - - m_uInDataLen -= uLen; - - if(m_uInDataLen > 0) - { - KviMemory::move(m_pInBuffer,m_pInBuffer + uLen,m_uInDataLen); - } - - unsigned int uSpace = m_uInBufferLen - m_uInDataLen; - - if(uSpace > KVI_IN_BUFFER_ALLOC_CHUNK) - { - m_uInBufferLen -= KVI_IN_BUFFER_ALLOC_CHUNK; - m_pInBuffer = (char *)KviMemory::reallocate(m_pInBuffer,m_uInBufferLen); - } + emitSignal("connected",c,c->params()); + return true; } -void KvsObject_socket::delayedFlush(unsigned int uTimeout) +KVSO_CLASS_FUNCTION(socket,disconnectedEvent) { - if(m_pFlushTimer->isActive())m_pFlushTimer->stop(); - m_pFlushTimer->start(uTimeout); + emitSignal("disconnected",c,c->params()); + return true; } -void KvsObject_socket::tryFlush() +KVSO_CLASS_FUNCTION(socket,errorEvent) { - if(m_pFlushTimer->isActive())m_pFlushTimer->stop(); - - if(m_pOutBuffer->size() == 0) - { - return; - } - - int result = kvi_socket_send(m_sock,m_pOutBuffer->data(),m_pOutBuffer->size()); - - if(result >= 0) - { - if(result == m_pOutBuffer->size()) - { - m_pOutBuffer->clear(); - } else { - if(result > 0)m_pOutBuffer->remove(result); - delayedFlush(500); - } - } else { - // Oops...error ? - int err = kvi_socket_error(); -#if defined(COMPILE_ON_WINDOWS) || defined(COMPILE_ON_MINGW) - if((err == EAGAIN) || (err == EINTR) || (err = WSAEWOULDBLOCK)) -#else - if((err == EAGAIN)||(err == EINTR)) -#endif - { - // Transient error...partial send as before... - // Async continue... - delayedFlush(500); - return; - } else { - // Disconnected... :( - unsigned int uOldConnectionId = m_uConnectionId; - KviKvsVariantList lParams; - lParams.append(new KviKvsVariant(KviError::getDescription(KviError::translateSystemError(err)))); - callFunction(this,"disconnectEvent",&lParams); - if(m_uConnectionId == uOldConnectionId)reset(); - // else it has already been called! - return; - } - } + emitSignal("error",c,c->params()); + return true; } -void KvsObject_socket::reset() + +KVSO_CLASS_FUNCTION(socket,hostFoundEvent) { - m_uConnectionId++; // this is the only place where this is incremented! - if(m_pDelayTimer) - { - delete m_pDelayTimer; - m_pDelayTimer = 0; - } - if(m_pDns) - { - delete m_pDns; - m_pDns = 0; - } - if(m_pSn) - { - delete m_pSn; - m_pSn = 0; - } - if(m_sock != KVI_INVALID_SOCKET) - { - kvi_socket_close(m_sock); - m_sock = KVI_INVALID_SOCKET; - } - if(m_pInBuffer) - { - KviMemory::free(m_pInBuffer); - m_pInBuffer = 0; - } - if(m_secondarySock) - { - kvi_socket_close(m_secondarySock); - m_secondarySock = KVI_INVALID_SOCKET; - } - m_uSecondaryPort = 0; - m_szSecondaryIp=""; - delete m_pOutBuffer; - if(m_pFlushTimer->isActive())m_pFlushTimer->stop(); - m_pOutBuffer = new KviDataBuffer(); - m_uInBufferLen = 0; - m_uInDataLen = 0; - m_iStatus = KVI_SCRIPT_SOCKET_STATUS_DISCONNECTED; - m_uRemotePort = 0; - m_szRemoteIp=""; - m_uLocalPort = 0; - m_szLocalIp=""; - m_bIPv6 = false; + emitSignal("hostFound",c,c->params()); + return true; } - - -//-------------- +KVSO_CLASS_FUNCTION(socket,stateChangedEvent) +{ + emitSignal("stateChanged",c,c->params()); + return true; +} #ifndef COMPILE_USE_STANDALONE_MOC_SOURCES #include "m_KvsObject_socket.moc" |
