aboutsummaryrefslogtreecommitdiffstats
path: root/src/modules/objects/KvsObject_socket.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/objects/KvsObject_socket.cpp')
-rw-r--r--src/modules/objects/KvsObject_socket.cpp1041
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",&params);
- 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,&params);
+ 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"