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()
|
Stream::~Stream()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -650,6 +674,7 @@ Socket::Socket(int domain, int type, int protocol)
|
||||||
Socket::~Socket()
|
Socket::~Socket()
|
||||||
{
|
{
|
||||||
DDebug(DebugAll,"Socket::~Socket() handle=%d [%p]",m_handle,this);
|
DDebug(DebugAll,"Socket::~Socket() handle=%d [%p]",m_handle,this);
|
||||||
|
clearFilters();
|
||||||
terminate();
|
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)
|
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)
|
if (!buffer)
|
||||||
length = 0;
|
length = 0;
|
||||||
int res = ::sendto(m_handle,(const char*)buffer,length,flags,addr,adrlen);
|
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)
|
if (adrlen && !addr)
|
||||||
*adrlen = 0;
|
*adrlen = 0;
|
||||||
int res = ::recvfrom(m_handle,(char*)buffer,length,flags,addr,adrlen);
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -946,7 +976,10 @@ int Socket::recv(void* buffer, int length, int flags)
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
length = 0;
|
length = 0;
|
||||||
int res = ::recv(m_handle,(char*)buffer,length,flags);
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1108,4 +1141,36 @@ bool Socket::createPair(Socket& sock1, Socket& sock2, int domain)
|
||||||
return false;
|
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: */
|
/* vi: set ts=8 sw=4 sts=4 noet: */
|
||||||
|
|
87
yateclass.h
87
yateclass.h
|
@ -3258,6 +3258,8 @@ private:
|
||||||
bool m_locking;
|
bool m_locking;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Socket;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper class to keep a socket address
|
* Wrapper class to keep a socket address
|
||||||
* @short A socket address holder
|
* @short A socket address holder
|
||||||
|
@ -3425,6 +3427,59 @@ protected:
|
||||||
String m_host;
|
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
|
* Base class for encapsulating system dependent stream capable objects
|
||||||
* @short An abstract stream class capable of reading and writing
|
* @short An abstract stream class capable of reading and writing
|
||||||
|
@ -3954,7 +4009,7 @@ public:
|
||||||
* Send a message over a connected or unconnected socket
|
* Send a message over a connected or unconnected socket
|
||||||
* @param buffer Buffer for data transfer
|
* @param buffer Buffer for data transfer
|
||||||
* @param length Length of the buffer
|
* @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 adrlen Length of the address structure
|
||||||
* @param flags Operating system specific bit flags that change the behaviour
|
* @param flags Operating system specific bit flags that change the behaviour
|
||||||
* @return Number of bytes transferred, @ref socketError() if an error occurred
|
* @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);
|
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
|
* Create a pair of bidirectionally connected sockets
|
||||||
* @param sock1 Reference to first Socket to be paired
|
* @param sock1 Reference to first Socket to be paired
|
||||||
|
@ -4071,7 +4144,19 @@ protected:
|
||||||
*/
|
*/
|
||||||
bool checkError(int retcode, bool strict = false);
|
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;
|
SOCKET m_handle;
|
||||||
|
ObjList m_filters;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue