Commit 3226bcb7 authored by Pavel Vainerman's avatar Pavel Vainerman

UNet2: сделал защиту от переполнения счётчика пакетов

parent 4b33b1ce
......@@ -4,6 +4,7 @@
#define UDPPacket_H_
// -----------------------------------------------------------------------------
#include <list>
#include <limits>
#include <ostream>
#include "UniSetTypes.h"
// -----------------------------------------------------------------------------
......@@ -20,6 +21,8 @@ namespace UniSetUDP
friend std::ostream& operator<<( std::ostream& os, UDPHeader& p );
}__attribute__((packed));
static unsigned long MaxPacketNum = 50; // std::numeric_limits<unsigned long>::max();
struct UDPData
{
UDPData():id(UniSetTypes::DefaultObjectId),val(0){}
......
......@@ -253,15 +253,6 @@ bool UNetReceiver::recv()
// cerr << myname << "(receive): recv DATA OK. ret=" << ret << " sizeof=" << sz
// << " header: " << pack.msg.header << endl;
/*
if( labs(pack.msg.header.num - pnum) > 1 )
{
cerr << "************ FAILED! ORDER PACKETS! recv.num=" << pack.msg.header.num
<< " num=" << pnum << endl;
}
pnum = pack.msg.header.num;
*/
{
uniset_mutex_lock l(packMutex);
qpack.push(pack);
......
......@@ -134,25 +134,37 @@ void UNetSender::real_send()
h.procID = shm->ID();
h.dcount = mypack.msg.header.dcount;
h.num = packetnum++;
mypack.msg.header = h;
// cout << "************* send header: " << mypack.msg.header << endl;
int sz = mypack.byte_size() + sizeof(UniSetUDP::UDPHeader);
if( udp->isPending(ost::Socket::pendingOutput) )
{
// ssize_t ret = udp->send( (char*)&(mypack.msg),sizeof(mypack.msg));
// if( ret<sizeof(mypack.msg) )
if( !udp->isPending(ost::Socket::pendingOutput) )
return;
ssize_t ret = udp->send( (char*)&(mypack.msg),sz);
if( ret < sz )
{
// cerr << myname << "(send data header): ret=" << ret << " sizeof=" << sz << endl;
dlog[Debug::CRIT] << myname << "(send): FAILED ret=" << ret << " < sizeof=" << sz << endl;
return;
}
// cout << "send OK. byte count=" << ret << endl;
// если вышли за границы..
// посылаем несколько одинаковых пакетов с новыми номерами..
// т.к. первый будет откинут (см. UNetReceiver::update)
if( packetnum >= UniSetUDP::MaxPacketNum )
{
packetnum = 1;
for( int i=0; i<3; i++ )
{
mypack.msg.header.num = packetnum++;
if( udp->isPending(ost::Socket::pendingOutput) )
{
ssize_t ret = udp->send( (char*)&(mypack.msg),sz);
if( res < sz )
dlog[Debug::CRIT] << myname << "(send): FAILED. ret=" << ret << " < sizeof=" << sz << endl;
}
}
}
}
// -----------------------------------------------------------------------------
void UNetSender::start()
......
......@@ -14,6 +14,14 @@
#include "UDPPacket.h"
#include "UDPNReceiver.h"
// -----------------------------------------------------------------------------
/*
* Для защиты от потери пакета при переполнении "номера пакета".
* UNetReceiver при обнаружении "разырва" в последовательнности, просто игнорирует пакет, обновляет счётчик
* и начинает обработку уже со следующего.
* Соотвественно здесь, реализован следующий механизм: При переходе номера пакета через maxnum,
* в сеть посылается один и тоже пакет данных с номерами идущими подряд.
* В результате первй будет откинут, как идущий "не подряд", а второй - будет обработан.
*/
class UNetSender
{
public:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment