Peercast接收到GnuPacket的处理过程

对于包是丢弃、广播或者是继续路由是通过设置R_TYPE类型来判断的。

这是在GnuStream类中定义的,其中GnuStream完成收包、发包、处理包等操作

enum R_TYPE
 {
  R_PROCESS,
  R_DEAD,
  R_DISCARD,  //丢弃
  R_ACCEPTED, //接受
  R_BROADCAST, //广播
  R_ROUTE, //路由
  R_DUPLICATE, /复制
  R_BADVERSION,
  R_DROP
 };

通过GnuStream::R_TYPE processPacket(GnuPacket &, Servent *, GnuID &)这个函数来执行处理进程,下面我们就这个函数进行具体的分析:

接收到包时,首先把TTL值递减,HOP值递增

 in.ttl--;
 in.hops++;

通过读取包中的func值来判断命令的类型(Ping/Pong/Query/QueryHit/Push),再执行相应处理

switch(in.func)
 {
  case GNU_FUNC_PING:
  case GNU_FUNC_PONG:

收到Ping消息应返回一个Pong消息,并将消息设置为广播方式

     GnuPacket pong;
     pong.initPong(sh,true,in);
     serv->outputPacket(pong,true)) //发出消息
     ret = R_BROADCAST;

收到Pong消息应进行判断,若是对本机发出的Ping消息的回复,则表明与远端主机建立连接;若否,则路由返回

if (servMgr->isReplyID(in.id))
      {
       servMgr->addHost(h,ServHost::T_SERVENT,sys->getTime());  //建立连接
       ret = R_ACCEPTED;
      }else
       ret = R_ROUTE;

收到Query消息,首先应把消息广播出去.然后若本机存在Query要寻找的频道,则返回一个QueryHit消息

注意Gnutella中的文件在Peercast中相对应的是一个频道,因此文件名相对应的是频道的ID

ret = R_BROADCAST;

numHits = chanMgr->findChannels(info,hits,16); //info是一个频道信息结构,此时保存着Query消息中寻找的频道信息

for(int i=0; i<numHits; i++)
    {
     GnuPacket hit;
     if (hit.initHit(sh,hits[i],&in,push,busy,stable,tracker,in.hops))
      serv->outputPacket(hit,true);
    }

收到QueryHit消息,则表示频道已找到,加入收听.若位于防火墙后面,则加上PUSH消息

if (hit.firewalled) strcat(flstr,"Push,");

readHit(data,hit,in.hops,in.id)

其中readHit()中加入收听的执行语句为

if (info.id.isSet())
  {
   if (!chanMgr->findHitList(info))
    chanMgr->addHitList(info);

}

收到Push消息,则新分配servent类,按GIV方式进行传送

Servent *s = servMgr->allocServent();
       if (s)
        s->initGIV(h,c->info.id);

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值