Add base class for capture packet class.

Add base classes for capturing packets: CaptureInfo and Capture.
Allow installing filter in sockets for sending packets also.
This commit is contained in:
Ioana Stanciu 2023-05-15 16:47:07 +03:00
parent c7e3515eed
commit 75bd7e1ee6
3 changed files with 153 additions and 8 deletions

View File

@ -2000,6 +2000,7 @@ int Socket::sendTo(const void* buffer, int length, const struct sockaddr* addr,
length = 0;
int res = ::sendto(m_handle,(const char*)buffer,length,flags,addr,adrlen);
checkError(res,true);
applyFilters(buffer,res,flags,addr,adrlen,false);
return res;
}
@ -2009,6 +2010,7 @@ int Socket::send(const void* buffer, int length, int flags)
length = 0;
int res = ::send(m_handle,(const char*)buffer,length,flags);
checkError(res,true);
applyFilters(buffer,res,flags,0,0,false);
return res;
}
@ -2021,6 +2023,7 @@ int Socket::writeData(const void* buffer, int length)
length = 0;
int res = ::write(m_handle,buffer,length);
checkError(res,true);
applyFilters(buffer,res,0,0,0,false);
return res;
#endif
}
@ -2070,6 +2073,7 @@ int Socket::readData(void* buffer, int length)
length = 0;
int res = ::read(m_handle,buffer,length);
checkError(res,true);
applyFilters(buffer,res,0);
return res;
#endif
}
@ -2329,12 +2333,18 @@ void Socket::removeFilter(SocketFilter* filter, bool delobj)
filter->m_socket = 0;
}
void Socket::clearFilters()
void Socket::clearFilters(bool del)
{
for (ObjList* l = m_filters.skipNull(); l; l = l->skipNext()) {
SocketFilter* filter = static_cast<SocketFilter*>(l->get());
filter->m_socket = 0;
}
m_filters.setDelete(del);
m_filters.clear();
}
bool Socket::applyFilters(void* buffer, int length, int flags, const struct sockaddr* addr, socklen_t adrlen)
bool Socket::applyFilters(const void* buffer, int length, int flags, const struct sockaddr* addr,
socklen_t adrlen, bool rx)
{
if ((length <= 0) || !buffer)
return false;
@ -2342,7 +2352,9 @@ bool Socket::applyFilters(void* buffer, int length, int flags, const struct sock
adrlen = 0;
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))
if (filter &&
(rx ? filter->received(buffer, length, flags, addr, adrlen)
: filter->sent(buffer, length, flags, addr, adrlen)))
return true;
}
return false;

View File

@ -381,7 +381,7 @@ public:
YStunSocketFilter();
virtual ~YStunSocketFilter();
// Received: call by the socket
virtual bool received(void* buffer, int length, int flags,
virtual bool received(const void* buffer, int length, int flags,
const struct sockaddr* addr, socklen_t addrlen);
// Timer handler: Handle retransmission for binding request
virtual void timerTick(const Time& when);
@ -953,7 +953,7 @@ YStunSocketFilter::~YStunSocketFilter()
DDebug(&iplugin,DebugAll,"~YStunSocketFilter. [%p]",this);
}
bool YStunSocketFilter::received(void* buffer, int length, int flags,
bool YStunSocketFilter::received(const void* buffer, int length, int flags,
const struct sockaddr* addr, socklen_t addrlen)
{
bool isStun = false;

View File

@ -8491,7 +8491,19 @@ public:
* @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;
virtual bool received(const void* buffer, int length, int flags, const struct sockaddr* addr, socklen_t adrlen) = 0;
/**
* Notify this filter about a sent block of data
* @param buffer Buffer with sent data
* @param length Length of the data in buffer
* @param flags Operating system specific bit flags of the operation
* @param addr Address where the data was sent, may be NULL
* @param adrlen Length of the valid data in address structure
* @return True if this filter claimed the data
*/
virtual bool sent(const void* buffer, int length, int flags, const struct sockaddr* addr, socklen_t adrlen)
{ return false; }
/**
* Get the socket to which the filter is currently attached
@ -9547,8 +9559,9 @@ public:
/**
* Removes and destroys all packet filters
* @param del True to delete packet filters
*/
void clearFilters();
void clearFilters(bool del = true);
/**
* Run whatever actions required on idle thread runs.
@ -9596,9 +9609,11 @@ protected:
* @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
* @param rx True if data was received, false if data was transmitted
* @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);
bool applyFilters(const void* buffer, int length, int flags, const struct sockaddr* addr = 0,
socklen_t adrlen = 0, bool rx = true);
SOCKET m_handle;
ObjList m_filters;
@ -10469,6 +10484,124 @@ public:
};
/**
* CaptureInfo class allows passing information about a captured packet
* @short Data associated with a captured packet
*/
class YATE_API CaptureInfo
{
public:
/**
* Constructor
* @param ts Timestamp when packet was captures/created in microseconds
* @param srcAddr Source address of the packet
* @param dstAddr Destination address of the packet
* @param extra Extra parameters
*/
CaptureInfo(uint64_t ts = Time::now(), SocketAddr* srcAddr = 0,
SocketAddr* dstAddr = 0, const NamedList& extra = NamedList::empty())
: m_ts(ts), m_srcAddr(srcAddr), m_dstAddr(dstAddr), m_extraInfo(extra)
{ }
/**
* Retrieve the source address
* @return The source address of the packet
*/
inline SocketAddr* srcAddr() const
{ return m_srcAddr; }
/**
* Retrieve the destination address of this packet
* @return The destination address of the packet
*/
inline SocketAddr* dstAddr() const
{ return m_dstAddr; }
/**
* Get the extra information parameters
* @return The extra information parameters
*/
inline const NamedList& extraInfo() const
{ return m_extraInfo; }
/**
* Timestamp in microseconds when this packet was captured
* @return The timestamp of this packet
*/
inline uint64_t ts() const
{ return m_ts; }
/**
* Source port of this packet
* @return Source port of this packet, 0 if not known
*/
inline uint16_t srcPort() const
{ return srcAddr() ? srcAddr()->port() : 0; }
/**
* Destination port of this packet
* @return Destination port of this packet, 0 if not known
*/
inline uint16_t dstPort() const
{ return dstAddr() ? dstAddr()->port() : 0; }
private:
uint64_t m_ts;
SocketAddr* m_srcAddr;
SocketAddr* m_dstAddr;
NamedList m_extraInfo;
};
/**
* Capture class allows implementing capturing of packets
* @short Packet capture class
*/
class YATE_API Capture : public RefObject
{
YCLASS(Capture,RefObject);
public:
/**
* Constructor
* @param name Name of capture
*/
Capture(const char* name)
: m_name(name)
{ }
/**
* Initialize this capture
* @param params Parameters for initializing this capture
* @return True on succesful initialization, false otherwise
*/
virtual bool initialize(const NamedList& params) = 0;
/**
* Write to capture a packet
* @param data Packet data
* @param len Length of packet data
* @param info Captured packet associated information
* @return True if written in capture, false otherwise
*/
virtual bool write(const uint8_t* data, unsigned int len, const CaptureInfo& info) = 0;
/**
* Check if capture is still valid
* @return True if still valid, false otherwise
*/
virtual bool valid() const = 0;
/**
* Get the name of the capture
* @return Name of the capture
*/
virtual const String& name() const
{ return m_name; }
private:
String m_name;
};
}; // namespace TelEngine
#endif /* __YATECLASS_H */