Added a socket packet data filter - preparing for a nice STUN implementation.

git-svn-id: http://yate.null.ro/svn/yate/trunk@1058 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2006-09-26 18:26:36 +00:00
parent f4c653b5c7
commit 14161da7a1
2 changed files with 153 additions and 3 deletions

View File

@ -295,6 +295,30 @@ bool SocketAddr::supports(int family)
}
SocketFilter::SocketFilter()
: m_socket(0)
{
}
SocketFilter::~SocketFilter()
{
if (m_socket)
m_socket->removeFilter(this);
}
void* SocketFilter::getObject(const String& name) const
{
if (name == "SocketFilter")
return const_cast<SocketFilter*>(this);
return GenObject::getObject(name);
}
bool SocketFilter::valid() const
{
return m_socket && m_socket->valid();
}
Stream::~Stream()
{
}
@ -650,6 +674,7 @@ Socket::Socket(int domain, int type, int protocol)
Socket::~Socket()
{
DDebug(DebugAll,"Socket::~Socket() handle=%d [%p]",m_handle,this);
clearFilters();
terminate();
}
@ -891,6 +916,8 @@ bool Socket::getPeerName(SocketAddr& addr)
int Socket::sendTo(const void* buffer, int length, const struct sockaddr* addr, socklen_t adrlen, int flags)
{
if (!addr)
return send(buffer,length,flags);
if (!buffer)
length = 0;
int res = ::sendto(m_handle,(const char*)buffer,length,flags,addr,adrlen);
@ -927,7 +954,10 @@ int Socket::recvFrom(void* buffer, int length, struct sockaddr* addr, socklen_t*
if (adrlen && !addr)
*adrlen = 0;
int res = ::recvfrom(m_handle,(char*)buffer,length,flags,addr,adrlen);
checkError(res,true);
if (checkError(res,true) && applyFilters(buffer,res,flags,addr,(adrlen ? *adrlen : 0))) {
m_error = EAGAIN;
res = socketError();
}
return res;
}
@ -946,7 +976,10 @@ int Socket::recv(void* buffer, int length, int flags)
if (!buffer)
length = 0;
int res = ::recv(m_handle,(char*)buffer,length,flags);
checkError(res,true);
if (checkError(res,true) && applyFilters(buffer,res,flags)) {
m_error = EAGAIN;
res = socketError();
}
return res;
}
@ -1108,4 +1141,36 @@ bool Socket::createPair(Socket& sock1, Socket& sock2, int domain)
return false;
}
bool Socket::installFilter(SocketFilter* filter)
{
if (!filter || filter->socket())
return false;
if (m_filters.find(filter))
return false;
filter->m_socket = this;
m_filters.append(filter);
return true;
}
void Socket::removeFilter(SocketFilter* filter, bool delobj)
{
if (m_filters.remove(filter,delobj))
filter->m_socket = 0;
}
void Socket::clearFilters()
{
m_filters.clear();
}
bool Socket::applyFilters(void* buffer, int length, int flags, const struct sockaddr* addr, socklen_t adrlen)
{
for (ObjList* l = &m_filters; l; l = l->next()) {
SocketFilter* filter = static_cast<SocketFilter*>(l->get());
if (filter && filter->received(buffer,length,flags,addr,adrlen))
return true;
}
return false;
}
/* vi: set ts=8 sw=4 sts=4 noet: */

View File

@ -3258,6 +3258,8 @@ private:
bool m_locking;
};
class Socket;
/**
* Wrapper class to keep a socket address
* @short A socket address holder
@ -3425,6 +3427,59 @@ protected:
String m_host;
};
/**
* Abstract interface for an object that filters socket received data packets
* @short A filter for received socket data
*/
class YATE_API SocketFilter : public GenObject
{
friend class Socket;
public:
/**
* Constructor
*/
SocketFilter();
/**
* Destructor, unregisters from socket
*/
virtual ~SocketFilter();
/**
* Get a pointer to a derived class given that class name
* @param name Name of the class we are asking for
* @return Pointer to the requested class or NULL if this object doesn't implement it
*/
virtual void* getObject(const String& name) const;
/**
* Notify this filter about a received block of data
* @param buffer Buffer for received data
* @param length Length of the data in buffer
* @param flags Operating system specific bit flags of the operation
* @param addr Address of the incoming data, may be NULL
* @param adrlen Length of the valid data in address structure
* @return True if this filter claimed the data
*/
virtual bool received(void* buffer, int length, int flags, const struct sockaddr* addr, socklen_t adrlen) = 0;
/**
* Get the socket to which the filter is currently attached
* @return Pointer to the socket of this filter
*/
inline Socket* socket() const
{ return m_socket; }
/**
* Check if the socket of this filter is valid
* @return True if the filter has a valid socket
*/
bool valid() const;
private:
Socket* m_socket;
};
/**
* Base class for encapsulating system dependent stream capable objects
* @short An abstract stream class capable of reading and writing
@ -3954,7 +4009,7 @@ public:
* Send a message over a connected or unconnected socket
* @param buffer Buffer for data transfer
* @param length Length of the buffer
* @param addr Address to send the message to
* @param addr Address to send the message to, if NULL will behave like @ref send()
* @param adrlen Length of the address structure
* @param flags Operating system specific bit flags that change the behaviour
* @return Number of bytes transferred, @ref socketError() if an error occurred
@ -4047,6 +4102,24 @@ public:
*/
bool select(bool* readok, bool* writeok, bool* except, int64_t timeout);
/**
* Install a new packet filter in the socket
* @param filter Pointer to the packet filter to install
* @return True if the filter was installed
*/
bool installFilter(SocketFilter* filter);
/**
* Removes a packet filter and optionally destroys it
* @param delobj Set to true to also delete the filter
*/
void removeFilter(SocketFilter* filter, bool delobj = false);
/**
* Removes and destroys all packet filters
*/
void clearFilters();
/**
* Create a pair of bidirectionally connected sockets
* @param sock1 Reference to first Socket to be paired
@ -4071,7 +4144,19 @@ protected:
*/
bool checkError(int retcode, bool strict = false);
/**
* Apply installed filters to a received block of data
* @param buffer Buffer for received data
* @param length Length of the data in buffer
* @param flags Operating system specific bit flags of the operation
* @param addr Address of the incoming data, may be NULL
* @param adrlen Length of the valid data in address structure
* @return True if one of the filters claimed the data
*/
bool applyFilters(void* buffer, int length, int flags, const struct sockaddr* addr = 0, socklen_t adrlen = 0);
SOCKET m_handle;
ObjList m_filters;
};
/**