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:
parent
f4c653b5c7
commit
14161da7a1
|
@ -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: */
|
||||
|
|
87
yateclass.h
87
yateclass.h
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue