OSDN Git Service

生命キャスト対策コード(VPdiff20071223)マージ。 IM0026-patch071223
authoreru <eru01@users.sourceforge.jp>
Tue, 25 Dec 2007 17:45:02 +0000 (17:45 +0000)
committereru <eru01@users.sourceforge.jp>
Tue, 25 Dec 2007 17:45:02 +0000 (17:45 +0000)
20 files changed:
PeerCast.root/PeerCast/core/common/channel.cpp
PeerCast.root/PeerCast/core/common/channel.h
PeerCast.root/PeerCast/core/common/cstream.h
PeerCast.root/PeerCast/core/common/pcp.cpp
PeerCast.root/PeerCast/core/common/pcp.h
PeerCast.root/PeerCast/core/common/servent.cpp
PeerCast.root/PeerCast/core/common/servent.h
PeerCast.root/PeerCast/core/common/servmgr.cpp
PeerCast.root/PeerCast/core/common/servmgr.h
PeerCast.root/PeerCast/core/common/version2.h
c:/Git/PeerCast.root/PeerCast/core/common/channel.cpp
c:/Git/PeerCast.root/PeerCast/core/common/channel.h
c:/Git/PeerCast.root/PeerCast/core/common/cstream.h
c:/Git/PeerCast.root/PeerCast/core/common/pcp.cpp
c:/Git/PeerCast.root/PeerCast/core/common/pcp.h
c:/Git/PeerCast.root/PeerCast/core/common/servent.cpp
c:/Git/PeerCast.root/PeerCast/core/common/servent.h
c:/Git/PeerCast.root/PeerCast/core/common/servmgr.cpp
c:/Git/PeerCast.root/PeerCast/core/common/servmgr.h
c:/Git/PeerCast.root/PeerCast/core/common/version2.h

index 4ca13be..665f690 100644 (file)
@@ -537,6 +537,7 @@ int Channel::handshakeFetch()
        sock->writeLineF("GET /channel/%s HTTP/1.0",idStr);
        sock->writeLineF("%s %d",PCX_HS_POS,streamPos);
        sock->writeLineF("%s %d",PCX_HS_PCP,1);
+       sock->writeLineF("%s %d",PCX_HS_PORT,servMgr->serverHost.port);
 
        sock->writeLine("");
 
@@ -1475,8 +1476,11 @@ bool ChannelStream::getStatus(Channel *ch,ChanPacket &pack)
 // -----------------------------------
 bool   Channel::checkBump()
 {
+       unsigned int maxIdleTime = 30;
+       if (isIndexTxt(this)) maxIdleTime = 60;
+
        if (!isBroadcasting() && (!sourceHost.tracker))
-               if (rawData.lastWriteTime && ((sys->getTime() - rawData.lastWriteTime) > 30))
+           if (rawData.lastWriteTime && ((sys->getTime() - rawData.lastWriteTime) > maxIdleTime))
                {
                        LOG_ERROR("Channel Auto bumped");
                        bump = true;
@@ -1509,6 +1513,9 @@ int Channel::readStream(Stream &in,ChannelStream *source)
 
        unsigned int receiveStartTime = 0;
 
+       unsigned int ptime = 0;
+       unsigned int upsize = 0;
+
        try
        {
                while (thread.active && !peercastInst->isQuitting)
@@ -1573,7 +1580,14 @@ int Channel::readStream(Stream &in,ChannelStream *source)
                                }
                        }
 
-                       source->flush(in);
+                       unsigned int t = sys->getTime();
+                       if (t != ptime) {
+                               ptime = t;
+                               upsize = Servent::MAX_OUTWARD_SIZE;
+                       }
+
+                       unsigned int len = source->flushUb(in, upsize);
+                       upsize -= len;
 
                        sys->sleepIdle();
                }
@@ -1733,9 +1747,12 @@ void ChanPacket::init(ChanPacketv &p)
 {
        type = p.type;
        len = p.len;
+       if (len > MAX_DATALEN)
+               throw StreamException("Packet data too large");
        pos = p.pos;
        sync = p.sync;
        skip = p.skip;
+       priority = p.priority;
        memcpy(data, p.data, len);
 }
 // -----------------------------------
@@ -1748,6 +1765,7 @@ void ChanPacket::init(TYPE t, const void *p, unsigned int l,unsigned int _pos)
        memcpy(data,p,len);
        pos = _pos;
        skip = false;
+       priority = 0;
 }
 // -----------------------------------
 void ChanPacket::writeRaw(Stream &out)
@@ -1970,10 +1988,34 @@ void    ChanPacketBuffer::readPacket(ChanPacket &pack)
        pack.init(packets[readPos%MAX_PACKETS]);
        readPos++;
        lock.off();
+}
 
-       sys->sleepIdle();
+// -----------------------------------
+void   ChanPacketBuffer::readPacketPri(ChanPacket &pack)
+{
+       unsigned int tim = sys->getTime();
+
+       if (readPos < firstPos) 
+               throw StreamException("Read too far behind");
+       while (readPos >= writePos)
+       {
+               sys->sleepIdle();
+               if ((sys->getTime() - tim) > 30)
+                       throw TimeoutException();
+       }
+       lock.on();
+       ChanPacketv *best = &packets[readPos % MAX_PACKETS];
+       for (unsigned int i = readPos + 1; i < writePos; i++) {
+               if (packets[i % MAX_PACKETS].priority > best->priority)
+                       best = &packets[i % MAX_PACKETS];
+       }
+       pack.init(*best);
+       best->init(packets[readPos % MAX_PACKETS]);
+       readPos++;
+       lock.off();
+ }
 
-}
 // -----------------------------------
 bool   ChanPacketBuffer::willSkip()
 {
@@ -2898,6 +2940,35 @@ ChanHit *ChanMgr::addHit(ChanHit &h)
 }
 
 // -----------------------------------
+bool ChanMgr::findParentHit(ChanHit &p)
+{
+       ChanHitList *hl=NULL;
+
+       chanMgr->hitlistlock.on();
+
+       hl = findHitListByID(p.chanID);
+
+       if (hl)
+       {
+               ChanHit *ch = hl->hit;
+               while (ch)
+               {
+                       if (!ch->dead && (ch->rhost[0].ip == p.uphost.ip)
+                               && (ch->rhost[0].port == p.uphost.port))
+                       {
+                               chanMgr->hitlistlock.off();
+                               return 1;
+                       }
+                       ch = ch->next;
+               }
+       }
+
+       chanMgr->hitlistlock.off();
+
+       return 0;
+}
+
+// -----------------------------------
 class ChanFindInfo : public ThreadInfo
 {
 public:
@@ -3064,6 +3135,7 @@ void ChanHit::init()
        version_ex_number = 0;
 
        status = 0;
+       servent_id = 0;
 
        sessionID.clear();
        chanID.clear();
@@ -4503,6 +4575,22 @@ int ChanHitSearch::getRelayHost(Host host1, Host host2, GnuID exID, ChanHitList
        riSequence &= 0xffffff;
        seqLock.off();
 
+       Servent *s = servMgr->servents;
+       while (s) {
+               if (s->serventHit.rhost[0].port && s->type == Servent::T_RELAY
+                       && s->chanID.isSame(chl->info.id)) {
+                               int i = index % MAX_RESULTS;
+                               if (index < MAX_RESULTS
+                                       || tmpHit[i].lastSendSeq > s->serventHit.lastSendSeq) {
+                                               s->serventHit.lastSendSeq = seq;
+                                               tmpHit[i] = s->serventHit;
+                                               tmpHit[i].host = s->serventHit.rhost[0];
+                                               index++;
+                               }
+               }
+               s = s->next;
+       }
+
        ChanHit *hit = chl->hit;
 
        while(hit){
@@ -4534,6 +4622,7 @@ int ChanHitSearch::getRelayHost(Host host1, Host host2, GnuID exID, ChanHitList
                                //rnd = (float)rand() / (float)RAND_MAX;
                                rnd = rand() % base;
                                if (hit->numHops == 1){
+#if 0
                                        if (tmpHit[index % MAX_RESULTS].numHops == 1){
                                                if (rnd < prob){
                                                        tmpHit[index % MAX_RESULTS] = *hit;
@@ -4545,8 +4634,9 @@ int ChanHitSearch::getRelayHost(Host host1, Host host2, GnuID exID, ChanHitList
                                                tmpHit[index % MAX_RESULTS].host = hit->rhost[0];
                                                index++;
                                        }
+#endif
                                } else {
-                                       if ((tmpHit[index % MAX_RESULTS].numHops != 1) && (rnd < prob)){
+                                       if ((tmpHit[index % MAX_RESULTS].numHops != 1) && (rnd < prob) || rnd == 0){
                                                tmpHit[index % MAX_RESULTS] = *hit;
                                                tmpHit[index % MAX_RESULTS].host = hit->rhost[0];
                                                index++;
index d1d00fb..5bf81f1 100644 (file)
@@ -207,6 +207,8 @@ public:
 
        char                            version_ex_prefix[2];
        unsigned int            version_ex_number;
+
+       unsigned int lastSendSeq;
 };
 // ----------------------------------
 class ChanHitList
@@ -603,7 +605,7 @@ public:
 
        int                     pickHits(ChanHitSearch &);
 
-
+       bool findParentHit(ChanHit &p);
 
        Channel         *channel;
        ChanHitList     *hitlist;
index f1a228b..795cd6b 100644 (file)
@@ -58,6 +58,7 @@ public:
                pos = 0;
                sync = 0;
                skip = false;
+               priority = 0;
        }
        void    init(ChanPacketv &p);
        void    init(TYPE t, const void *, unsigned int , unsigned int );
@@ -74,6 +75,7 @@ public:
        char data[MAX_DATALEN];
        bool skip;
 
+       int priority;
 };
 // ----------------------------------
 class ChanPacketv
@@ -111,6 +113,7 @@ public:
                skip = false;
                data = NULL;
                datasize = 0;
+               priority = 0;
        }
        void init(ChanPacket &p)
        {
@@ -124,6 +127,7 @@ public:
                pos = p.pos;
                sync = p.sync;
                skip = p.skip;
+               priority = p.priority;
                if (!data) {
                        datasize = (len & ~(BSIZE - 1)) + BSIZE;
                        data = new char[datasize];
@@ -149,6 +153,7 @@ public:
        unsigned int datasize;
        bool skip;
 
+       int priority;
 };
 // ----------------------------------
 class ChanPacketBuffer 
@@ -176,6 +181,7 @@ public:
 
        bool    writePacket(ChanPacket &,bool = false);
        void    readPacket(ChanPacket &);
+       void readPacketPri(ChanPacket &);
 
        bool    willSkip();
 
@@ -221,6 +227,7 @@ public:
        virtual void kill() {}
        virtual bool sendPacket(ChanPacket &,GnuID &) {return false;}
        virtual void flush(Stream &) {}
+       virtual unsigned int flushUb(Stream &, unsigned int) { return 0; }
        virtual void readHeader(Stream &,Channel *)=0;
        virtual int  readPacket(Stream &,Channel *)=0;
        virtual void readEnd(Stream &,Channel *)=0;
index fdf5d8b..08e8485 100644 (file)
@@ -84,6 +84,30 @@ void PCPStream::flush(Stream &in)
                pack.writeRaw(in);
        }
 }
+
+// ------------------------------------------
+unsigned int PCPStream::flushUb(Stream &in, unsigned int size)
+{
+       ChanPacket pack;
+       unsigned int len = 0, skip = 0;
+
+       while (outData.numPending())
+       {
+               outData.readPacketPri(pack);
+
+               if (size >= len + pack.len) {
+                       len += pack.len;
+                       pack.writeRaw(in);
+               } else {
+                       skip++;
+               }
+       }
+       if (skip > 0)
+               LOG_DEBUG("PCPStream::flushUb: skip %d packets", skip);
+
+       return len;
+}
+
 // ------------------------------------------
 int PCPStream::readPacket(Stream &in,Channel *)
 {
@@ -433,9 +457,17 @@ void PCPStream::readHostAtoms(AtomStream &atom, int numc, BroadcastState &bcs, C
                                ipNum = 1;
                }
                else if (id == PCP_HOST_NUML)
+               {
                        hit.numListeners = atom.readInt();
+                       if (hit.numListeners > 10)
+                               hit.numListeners = 10;
+               }
                else if (id == PCP_HOST_NUMR)
+               {
                        hit.numRelays = atom.readInt();
+                       if (hit.numRelays > 100)
+                               hit.numRelays = 100;
+               }
                else if (id == PCP_HOST_UPTIME)
                        hit.upTime = atom.readInt();
                else if (id == PCP_HOST_OLDPOS)
@@ -500,9 +532,11 @@ void PCPStream::readHostAtoms(AtomStream &atom, int numc, BroadcastState &bcs, C
 
        if (hit.numHops == 1){
                Servent *sv = servMgr->findServentByServentID(hit.servent_id);
-               if (sv){
+               if (sv && sv->getHost().ip == hit.host.ip){
 //                     LOG_DEBUG("set servent's waitPort = %d", hit.host.port);
                        sv->waitPort = hit.host.port;
+                       hit.lastSendSeq = sv->serventHit.lastSendSeq;
+                       sv->serventHit = hit;
                }
        }
 }
@@ -696,6 +730,7 @@ int PCPStream::readBroadcastAtoms(AtomStream &atom,int numc,BroadcastState &bcs)
                {
                        ChanHit hit;
                        readHostAtoms(atom,c,bcs,hit,false);
+                       Servent *sv = servMgr->findServentByServentID(bcs.servent_id);
                        if (hit.uphost.ip == 0){
 //                             LOG_DEBUG("bcs servent_id = %d", bcs.servent_id);
                                if (bcs.numHops == 1){
@@ -703,7 +738,7 @@ int PCPStream::readBroadcastAtoms(AtomStream &atom,int numc,BroadcastState &bcs)
                                        hit.uphost.port = servMgr->serverHost.port;
                                        hit.uphostHops = 1;
                                } else {
-                                       Servent *sv = servMgr->findServentByServentID(bcs.servent_id);
+                                       //Servent *sv = servMgr->findServentByServentID(bcs.servent_id);
                                        if (sv){
                                                hit.uphost.ip = sv->getHost().ip;
                                                hit.uphost.port = sv->waitPort;
@@ -711,10 +746,21 @@ int PCPStream::readBroadcastAtoms(AtomStream &atom,int numc,BroadcastState &bcs)
                                        }
                                }
                        }
-                       int oldPos = pmem.pos;
-                       hit.writeAtoms(patom, hit.chanID);
-                       pmem.pos = oldPos;
-                       r = readAtom(patom,bcs);
+                       if (sv &&
+                               ((hit.numHops == 1 && (hit.rhost[0].ip == sv->getHost().ip
+                               && hit.uphost.ip == servMgr->serverHost.ip && hit.uphost.port == servMgr->serverHost.port)
+                               || (hit.rhost[1].localIP() && hit.rhost[1].ip == sv->getHost().ip))
+                               || chanMgr->findParentHit(hit)))
+                       {
+                               int oldPos = pmem.pos;
+                               hit.writeAtoms(patom, hit.chanID);
+                               pmem.pos = oldPos;
+                               r = readAtom(patom,bcs);
+                       } else {
+                               LOG_DEBUG("### Invalid bcst: hops=%d, ver=%d(VP%04d), ttl=%d",
+                                       bcs.numHops,ver,ver_vp,ttl);
+                               ttl = 0;
+                       }
                } else {
                        // copy and process atoms
                        int oldPos = pmem.pos;
@@ -761,6 +807,7 @@ int PCPStream::readBroadcastAtoms(AtomStream &atom,int numc,BroadcastState &bcs)
 
                if (bcs.group & (/*PCP_BCST_GROUP_ROOT|*/PCP_BCST_GROUP_TRACKERS|PCP_BCST_GROUP_RELAYS))
                {
+                       pack.priority = 11 - bcs.numHops;
                        chanMgr->broadcastPacketUp(pack,bcs.chanID,remoteID,destID);
                }
 
index 4085941..770205b 100644 (file)
@@ -235,6 +235,7 @@ public:
 
        virtual bool sendPacket(ChanPacket &,GnuID &);
        virtual void flush(Stream &);
+       virtual unsigned int flushUb(Stream &, unsigned int);
        virtual void readHeader(Stream &,Channel *);
        virtual int readPacket(Stream &,Channel *);
        virtual void readEnd(Stream &,Channel *);
index ad18d0c..bd4c171 100644 (file)
@@ -240,6 +240,8 @@ void Servent::reset()
        type = T_NONE;
 
        channel_id = 0;
+
+       serventHit.init();
 }
 // -----------------------------------
 bool Servent::sendPacket(ChanPacket &pack,GnuID &cid,GnuID &sid,GnuID &did,Servent::TYPE t)
@@ -807,6 +809,7 @@ bool Servent::handshakeStream(ChanInfo &chanInfo)
 
        bool gotPCP=false;
        unsigned int reqPos=0;
+       unsigned short listenPort = 0;
 
        nsSwitchNum=0;
 
@@ -820,6 +823,8 @@ bool Servent::handshakeStream(ChanInfo &chanInfo)
                        gotPCP = atoi(arg)!=0;
                else if (http.isHeader(PCX_HS_POS))
                        reqPos = atoi(arg);
+               else if (http.isHeader(PCX_HS_PORT))
+                       listenPort = (unsigned short)atoi(arg);
                else if (http.isHeader("icy-metadata"))
                        addMetadata = atoi(arg) > 0;
                else if (http.isHeader(HTTP_HS_AGENT))
@@ -873,22 +878,23 @@ bool Servent::handshakeStream(ChanInfo &chanInfo)
                }
 
                chanID = chanInfo.id;
+               serventHit.rhost[0].ip = getHost().ip;
+               serventHit.rhost[0].port = listenPort;
+               serventHit.host = serventHit.rhost[0];
+               serventHit.chanID = chanID;
+
                canStreamLock.on();
                chanReady = canStream(ch);
-               if (0 && !chanReady)
+               if (/*0 && */!chanReady)
                {
                        if (servMgr->numStreams(chanID, Servent::T_RELAY, false) == 0)
                        {
                                sourceHit = &ch->sourceHost;  // send source host info
 
-                               if (ch->info.getUptime() > 60)  // if stable
+                               if (listenPort && ch->info.getUptime() > 60)  // if stable
                                {
                                        // connect "this" host later
-                                       ChanHit nh;
-                                       nh.init();
-                                       nh.chanID = chanID;
-                                       nh.rhost[0] = getHost();
-                                       chanMgr->addHit(nh);
+                                       chanMgr->addHit(serventHit);
                                }
 
                                char tmp[50];
@@ -896,11 +902,11 @@ bool Servent::handshakeStream(ChanInfo &chanInfo)
                                LOG_DEBUG("Bump channel, hand over sourceHost to %s", tmp);
                                ch->bump = true;
                        }
-                       else if (servMgr->kickUnrelayableHost(chanID, this) != 0)
+                       else if (servMgr->kickUnrelayableHost(chanID, serventHit) != 0)
                        {
                                chanReady = canStream(ch);
                                if (!chanReady)
-                                       LOG_DEBUG("Kicked unrelayable host, but still cannot stream");
+                                       LOG_DEBUG("*** Kicked unrelayable host, but still cannot stream");
                        }
                }
                if (!chanReady) type = T_INCOMING;
@@ -1114,8 +1120,8 @@ bool Servent::handshakeStream(ChanInfo &chanInfo)
                                if (sourceHit) {
                                        char tmp[50];
                                        sourceHit->writeAtoms(atom2, chanInfo.id);
-                                       chs.best[i].host.toStr(tmp);
-                                       LOG_DEBUG("relay info: %s hops = %d", tmp, chs.best[i].numHops);
+                                       sourceHit->host.toStr(tmp);
+                                       LOG_DEBUG("relay info(sourceHit): %s", tmp);
                                        best.host.ip = sourceHit->host.ip;
                                }
 
@@ -2792,6 +2798,8 @@ void Servent::sendPeercastChannel()
 void Servent::sendPCPChannel()
 {
        bool skipCheck = false;
+       unsigned int ptime = 0;
+       int npacket = 0, upsize = 0;
 
        Channel *ch = chanMgr->findChannelByID(chanID);
        if (!ch)
@@ -2929,11 +2937,23 @@ void Servent::sendPCPChannel()
                        BroadcastState bcs;
                        bcs.servent_id = servent_id;
 //                     error = pcpStream->readPacket(*sock,bcs);
-                       do {
+
+                       unsigned int t = sys->getTime();
+                       if (t != ptime) {
+                               ptime = t;
+                               npacket = MAX_PROC_PACKETS;
+                               upsize = MAX_OUTWARD_SIZE;
+                       }
+
+                       int len = pcpStream->flushUb(*sock, upsize);
+                       upsize -= len;
+
+                       while (npacket > 0 && sock->readReady()) {
+                               npacket--;
                                error = pcpStream->readPacket(*sock,bcs);
                                if (error)
                                        throw StreamException("PCP exception");
-                       } while (sock->readReady() || pcpStream->outData.numPending());
+                       }
 
                        sys->sleepIdle();
 
index e257e82..09aaac5 100644 (file)
@@ -46,6 +46,12 @@ public:
                MAX_OUTPACKETS = 32             // max. output packets per queue (normal/priority)
        };
 
+       enum
+       {
+               MAX_PROC_PACKETS = 300,
+               MAX_OUTWARD_SIZE = 1024 * 10
+       };
+
     enum TYPE                                  
     {
                T_NONE,                                 // Not allocated
@@ -288,6 +294,8 @@ public:
        unsigned int lastSkipCount;
        unsigned int waitPort;
 
+       ChanHit serventHit;
+
        int channel_id;
 };
 
index e8d57e2..3829168 100644 (file)
@@ -2623,6 +2623,7 @@ void ServMgr::banFirewalledHost()
 }
 
 // --------------------------------------------------
+#if 0
 static ChanHit *findServentHit(Servent *s)
 {
        ChanHitList *chl = chanMgr->findHitListByID(s->chanID);
@@ -2640,8 +2641,9 @@ static ChanHit *findServentHit(Servent *s)
        }
        return NULL;
 }
+#endif
 // --------------------------------------------------
-int ServMgr::kickUnrelayableHost(GnuID &chid, Servent *ns)
+int ServMgr::kickUnrelayableHost(GnuID &chid, ChanHit &sendhit)
 {
        Servent *ks = NULL;
        Servent *s = servMgr->servents;
@@ -2652,9 +2654,8 @@ int ServMgr::kickUnrelayableHost(GnuID &chid, Servent *ns)
                {
                        Host h = s->getHost();
 
-                       chanMgr->hitlistlock.on();
-                       ChanHit *hit = findServentHit(s);
-                       if (hit && !hit->relay && hit->numRelays == 0)
+                       ChanHit hit = s->serventHit;
+                       if (!hit.relay && hit.numRelays == 0)
                        {
                                char hostName[256];
                                h.toStr(hostName);
@@ -2663,25 +2664,18 @@ int ServMgr::kickUnrelayableHost(GnuID &chid, Servent *ns)
                                if (!ks || s->lastConnect < ks->lastConnect) // elder servent
                                        ks = s;
                        }
-                       chanMgr->hitlistlock.off();
                }
                s = s->next;
        }
 
        if (ks)
        {
-               if (ns)
+               if (sendhit.rhost[0].port)
                {
-                       Host h = ns->getHost();
-                       ChanHit nh;
-                       nh.init();
-                       nh.chanID = chid;
-                       nh.rhost[0] = h;
-
                        ChanPacket pack;
                        MemoryStream mem(pack.data,sizeof(pack.data));
                        AtomStream atom(mem);
-                       nh.writeAtoms(atom, chid);
+                       sendhit.writeAtoms(atom, chid);
                        pack.len = mem.pos;
                        pack.type = ChanPacket::T_PCP;
                        GnuID noID;
index f8832fc..e424a9d 100644 (file)
@@ -402,7 +402,7 @@ public:
        unsigned int kickPushTime;
        bool    isCheckPushStream(); //JP-EX
        void    banFirewalledHost(); //JP-EX
-       int kickUnrelayableHost(GnuID &, Servent * = NULL);
+       int kickUnrelayableHost(GnuID &, ChanHit &);
 
        bool    getModulePath; //JP-EX
        bool    clearPLS; //JP-EX
index fc9e7ec..28dd346 100644 (file)
@@ -29,22 +29,22 @@ static bool PCP_FORCE_YP                            = false;
 #endif
 // ------------------------------------------------
 static const int PCP_CLIENT_VERSION            = 1218;
-static const int PCP_CLIENT_VERSION_VP = 25;
+static const int PCP_CLIENT_VERSION_VP = 26;
 static const int PCP_ROOT_VERSION              = 1218;
 
 static const int PCP_CLIENT_MINVERSION = 1200;
 
 static const char *PCX_AGENT           = "PeerCast/0.1218";    
 static const char *PCX_AGENTJP                 = "PeerCast/0.1218-J";
-static const char *PCX_AGENTVP         = "PeerCast/0.1218(VP0025-1)";
-static const char *PCX_VERSTRING       = "v0.1218(VP0025-1)";
+static const char *PCX_AGENTVP         = "PeerCast/0.1218(VP0026)";
+static const char *PCX_VERSTRING       = "v0.1218(VP0026)";
 
 #if 1 /* for VP extend version */
 #define VERSION_EX 1
 static const char *PCP_CLIENT_VERSION_EX_PREFIX = "IM"; // 2bytes only
-static const int  PCP_CLIENT_VERSION_EX_NUMBER = 7650;
-static const char *PCX_AGENTEX = "PeerCast/0.1218(IM-VP25-1)";
-static const char *PCX_VERSTRING_EX = "v0.1218(IM765-VP25-1)";
+static const int  PCP_CLIENT_VERSION_EX_NUMBER = 26;
+static const char *PCX_AGENTEX = "PeerCast/0.1218(IM0026-patch071223)";
+static const char *PCX_VERSTRING_EX = "v0.1218(IM0026)";
 #endif
 
 // ------------------------------------------------
index 4ca13be..665f690 100644 (file)
@@ -537,6 +537,7 @@ int Channel::handshakeFetch()
        sock->writeLineF("GET /channel/%s HTTP/1.0",idStr);
        sock->writeLineF("%s %d",PCX_HS_POS,streamPos);
        sock->writeLineF("%s %d",PCX_HS_PCP,1);
+       sock->writeLineF("%s %d",PCX_HS_PORT,servMgr->serverHost.port);
 
        sock->writeLine("");
 
@@ -1475,8 +1476,11 @@ bool ChannelStream::getStatus(Channel *ch,ChanPacket &pack)
 // -----------------------------------
 bool   Channel::checkBump()
 {
+       unsigned int maxIdleTime = 30;
+       if (isIndexTxt(this)) maxIdleTime = 60;
+
        if (!isBroadcasting() && (!sourceHost.tracker))
-               if (rawData.lastWriteTime && ((sys->getTime() - rawData.lastWriteTime) > 30))
+           if (rawData.lastWriteTime && ((sys->getTime() - rawData.lastWriteTime) > maxIdleTime))
                {
                        LOG_ERROR("Channel Auto bumped");
                        bump = true;
@@ -1509,6 +1513,9 @@ int Channel::readStream(Stream &in,ChannelStream *source)
 
        unsigned int receiveStartTime = 0;
 
+       unsigned int ptime = 0;
+       unsigned int upsize = 0;
+
        try
        {
                while (thread.active && !peercastInst->isQuitting)
@@ -1573,7 +1580,14 @@ int Channel::readStream(Stream &in,ChannelStream *source)
                                }
                        }
 
-                       source->flush(in);
+                       unsigned int t = sys->getTime();
+                       if (t != ptime) {
+                               ptime = t;
+                               upsize = Servent::MAX_OUTWARD_SIZE;
+                       }
+
+                       unsigned int len = source->flushUb(in, upsize);
+                       upsize -= len;
 
                        sys->sleepIdle();
                }
@@ -1733,9 +1747,12 @@ void ChanPacket::init(ChanPacketv &p)
 {
        type = p.type;
        len = p.len;
+       if (len > MAX_DATALEN)
+               throw StreamException("Packet data too large");
        pos = p.pos;
        sync = p.sync;
        skip = p.skip;
+       priority = p.priority;
        memcpy(data, p.data, len);
 }
 // -----------------------------------
@@ -1748,6 +1765,7 @@ void ChanPacket::init(TYPE t, const void *p, unsigned int l,unsigned int _pos)
        memcpy(data,p,len);
        pos = _pos;
        skip = false;
+       priority = 0;
 }
 // -----------------------------------
 void ChanPacket::writeRaw(Stream &out)
@@ -1970,10 +1988,34 @@ void    ChanPacketBuffer::readPacket(ChanPacket &pack)
        pack.init(packets[readPos%MAX_PACKETS]);
        readPos++;
        lock.off();
+}
 
-       sys->sleepIdle();
+// -----------------------------------
+void   ChanPacketBuffer::readPacketPri(ChanPacket &pack)
+{
+       unsigned int tim = sys->getTime();
+
+       if (readPos < firstPos) 
+               throw StreamException("Read too far behind");
+       while (readPos >= writePos)
+       {
+               sys->sleepIdle();
+               if ((sys->getTime() - tim) > 30)
+                       throw TimeoutException();
+       }
+       lock.on();
+       ChanPacketv *best = &packets[readPos % MAX_PACKETS];
+       for (unsigned int i = readPos + 1; i < writePos; i++) {
+               if (packets[i % MAX_PACKETS].priority > best->priority)
+                       best = &packets[i % MAX_PACKETS];
+       }
+       pack.init(*best);
+       best->init(packets[readPos % MAX_PACKETS]);
+       readPos++;
+       lock.off();
+ }
 
-}
 // -----------------------------------
 bool   ChanPacketBuffer::willSkip()
 {
@@ -2898,6 +2940,35 @@ ChanHit *ChanMgr::addHit(ChanHit &h)
 }
 
 // -----------------------------------
+bool ChanMgr::findParentHit(ChanHit &p)
+{
+       ChanHitList *hl=NULL;
+
+       chanMgr->hitlistlock.on();
+
+       hl = findHitListByID(p.chanID);
+
+       if (hl)
+       {
+               ChanHit *ch = hl->hit;
+               while (ch)
+               {
+                       if (!ch->dead && (ch->rhost[0].ip == p.uphost.ip)
+                               && (ch->rhost[0].port == p.uphost.port))
+                       {
+                               chanMgr->hitlistlock.off();
+                               return 1;
+                       }
+                       ch = ch->next;
+               }
+       }
+
+       chanMgr->hitlistlock.off();
+
+       return 0;
+}
+
+// -----------------------------------
 class ChanFindInfo : public ThreadInfo
 {
 public:
@@ -3064,6 +3135,7 @@ void ChanHit::init()
        version_ex_number = 0;
 
        status = 0;
+       servent_id = 0;
 
        sessionID.clear();
        chanID.clear();
@@ -4503,6 +4575,22 @@ int ChanHitSearch::getRelayHost(Host host1, Host host2, GnuID exID, ChanHitList
        riSequence &= 0xffffff;
        seqLock.off();
 
+       Servent *s = servMgr->servents;
+       while (s) {
+               if (s->serventHit.rhost[0].port && s->type == Servent::T_RELAY
+                       && s->chanID.isSame(chl->info.id)) {
+                               int i = index % MAX_RESULTS;
+                               if (index < MAX_RESULTS
+                                       || tmpHit[i].lastSendSeq > s->serventHit.lastSendSeq) {
+                                               s->serventHit.lastSendSeq = seq;
+                                               tmpHit[i] = s->serventHit;
+                                               tmpHit[i].host = s->serventHit.rhost[0];
+                                               index++;
+                               }
+               }
+               s = s->next;
+       }
+
        ChanHit *hit = chl->hit;
 
        while(hit){
@@ -4534,6 +4622,7 @@ int ChanHitSearch::getRelayHost(Host host1, Host host2, GnuID exID, ChanHitList
                                //rnd = (float)rand() / (float)RAND_MAX;
                                rnd = rand() % base;
                                if (hit->numHops == 1){
+#if 0
                                        if (tmpHit[index % MAX_RESULTS].numHops == 1){
                                                if (rnd < prob){
                                                        tmpHit[index % MAX_RESULTS] = *hit;
@@ -4545,8 +4634,9 @@ int ChanHitSearch::getRelayHost(Host host1, Host host2, GnuID exID, ChanHitList
                                                tmpHit[index % MAX_RESULTS].host = hit->rhost[0];
                                                index++;
                                        }
+#endif
                                } else {
-                                       if ((tmpHit[index % MAX_RESULTS].numHops != 1) && (rnd < prob)){
+                                       if ((tmpHit[index % MAX_RESULTS].numHops != 1) && (rnd < prob) || rnd == 0){
                                                tmpHit[index % MAX_RESULTS] = *hit;
                                                tmpHit[index % MAX_RESULTS].host = hit->rhost[0];
                                                index++;
index d1d00fb..5bf81f1 100644 (file)
@@ -207,6 +207,8 @@ public:
 
        char                            version_ex_prefix[2];
        unsigned int            version_ex_number;
+
+       unsigned int lastSendSeq;
 };
 // ----------------------------------
 class ChanHitList
@@ -603,7 +605,7 @@ public:
 
        int                     pickHits(ChanHitSearch &);
 
-
+       bool findParentHit(ChanHit &p);
 
        Channel         *channel;
        ChanHitList     *hitlist;
index f1a228b..795cd6b 100644 (file)
@@ -58,6 +58,7 @@ public:
                pos = 0;
                sync = 0;
                skip = false;
+               priority = 0;
        }
        void    init(ChanPacketv &p);
        void    init(TYPE t, const void *, unsigned int , unsigned int );
@@ -74,6 +75,7 @@ public:
        char data[MAX_DATALEN];
        bool skip;
 
+       int priority;
 };
 // ----------------------------------
 class ChanPacketv
@@ -111,6 +113,7 @@ public:
                skip = false;
                data = NULL;
                datasize = 0;
+               priority = 0;
        }
        void init(ChanPacket &p)
        {
@@ -124,6 +127,7 @@ public:
                pos = p.pos;
                sync = p.sync;
                skip = p.skip;
+               priority = p.priority;
                if (!data) {
                        datasize = (len & ~(BSIZE - 1)) + BSIZE;
                        data = new char[datasize];
@@ -149,6 +153,7 @@ public:
        unsigned int datasize;
        bool skip;
 
+       int priority;
 };
 // ----------------------------------
 class ChanPacketBuffer 
@@ -176,6 +181,7 @@ public:
 
        bool    writePacket(ChanPacket &,bool = false);
        void    readPacket(ChanPacket &);
+       void readPacketPri(ChanPacket &);
 
        bool    willSkip();
 
@@ -221,6 +227,7 @@ public:
        virtual void kill() {}
        virtual bool sendPacket(ChanPacket &,GnuID &) {return false;}
        virtual void flush(Stream &) {}
+       virtual unsigned int flushUb(Stream &, unsigned int) { return 0; }
        virtual void readHeader(Stream &,Channel *)=0;
        virtual int  readPacket(Stream &,Channel *)=0;
        virtual void readEnd(Stream &,Channel *)=0;
index fdf5d8b..08e8485 100644 (file)
@@ -84,6 +84,30 @@ void PCPStream::flush(Stream &in)
                pack.writeRaw(in);
        }
 }
+
+// ------------------------------------------
+unsigned int PCPStream::flushUb(Stream &in, unsigned int size)
+{
+       ChanPacket pack;
+       unsigned int len = 0, skip = 0;
+
+       while (outData.numPending())
+       {
+               outData.readPacketPri(pack);
+
+               if (size >= len + pack.len) {
+                       len += pack.len;
+                       pack.writeRaw(in);
+               } else {
+                       skip++;
+               }
+       }
+       if (skip > 0)
+               LOG_DEBUG("PCPStream::flushUb: skip %d packets", skip);
+
+       return len;
+}
+
 // ------------------------------------------
 int PCPStream::readPacket(Stream &in,Channel *)
 {
@@ -433,9 +457,17 @@ void PCPStream::readHostAtoms(AtomStream &atom, int numc, BroadcastState &bcs, C
                                ipNum = 1;
                }
                else if (id == PCP_HOST_NUML)
+               {
                        hit.numListeners = atom.readInt();
+                       if (hit.numListeners > 10)
+                               hit.numListeners = 10;
+               }
                else if (id == PCP_HOST_NUMR)
+               {
                        hit.numRelays = atom.readInt();
+                       if (hit.numRelays > 100)
+                               hit.numRelays = 100;
+               }
                else if (id == PCP_HOST_UPTIME)
                        hit.upTime = atom.readInt();
                else if (id == PCP_HOST_OLDPOS)
@@ -500,9 +532,11 @@ void PCPStream::readHostAtoms(AtomStream &atom, int numc, BroadcastState &bcs, C
 
        if (hit.numHops == 1){
                Servent *sv = servMgr->findServentByServentID(hit.servent_id);
-               if (sv){
+               if (sv && sv->getHost().ip == hit.host.ip){
 //                     LOG_DEBUG("set servent's waitPort = %d", hit.host.port);
                        sv->waitPort = hit.host.port;
+                       hit.lastSendSeq = sv->serventHit.lastSendSeq;
+                       sv->serventHit = hit;
                }
        }
 }
@@ -696,6 +730,7 @@ int PCPStream::readBroadcastAtoms(AtomStream &atom,int numc,BroadcastState &bcs)
                {
                        ChanHit hit;
                        readHostAtoms(atom,c,bcs,hit,false);
+                       Servent *sv = servMgr->findServentByServentID(bcs.servent_id);
                        if (hit.uphost.ip == 0){
 //                             LOG_DEBUG("bcs servent_id = %d", bcs.servent_id);
                                if (bcs.numHops == 1){
@@ -703,7 +738,7 @@ int PCPStream::readBroadcastAtoms(AtomStream &atom,int numc,BroadcastState &bcs)
                                        hit.uphost.port = servMgr->serverHost.port;
                                        hit.uphostHops = 1;
                                } else {
-                                       Servent *sv = servMgr->findServentByServentID(bcs.servent_id);
+                                       //Servent *sv = servMgr->findServentByServentID(bcs.servent_id);
                                        if (sv){
                                                hit.uphost.ip = sv->getHost().ip;
                                                hit.uphost.port = sv->waitPort;
@@ -711,10 +746,21 @@ int PCPStream::readBroadcastAtoms(AtomStream &atom,int numc,BroadcastState &bcs)
                                        }
                                }
                        }
-                       int oldPos = pmem.pos;
-                       hit.writeAtoms(patom, hit.chanID);
-                       pmem.pos = oldPos;
-                       r = readAtom(patom,bcs);
+                       if (sv &&
+                               ((hit.numHops == 1 && (hit.rhost[0].ip == sv->getHost().ip
+                               && hit.uphost.ip == servMgr->serverHost.ip && hit.uphost.port == servMgr->serverHost.port)
+                               || (hit.rhost[1].localIP() && hit.rhost[1].ip == sv->getHost().ip))
+                               || chanMgr->findParentHit(hit)))
+                       {
+                               int oldPos = pmem.pos;
+                               hit.writeAtoms(patom, hit.chanID);
+                               pmem.pos = oldPos;
+                               r = readAtom(patom,bcs);
+                       } else {
+                               LOG_DEBUG("### Invalid bcst: hops=%d, ver=%d(VP%04d), ttl=%d",
+                                       bcs.numHops,ver,ver_vp,ttl);
+                               ttl = 0;
+                       }
                } else {
                        // copy and process atoms
                        int oldPos = pmem.pos;
@@ -761,6 +807,7 @@ int PCPStream::readBroadcastAtoms(AtomStream &atom,int numc,BroadcastState &bcs)
 
                if (bcs.group & (/*PCP_BCST_GROUP_ROOT|*/PCP_BCST_GROUP_TRACKERS|PCP_BCST_GROUP_RELAYS))
                {
+                       pack.priority = 11 - bcs.numHops;
                        chanMgr->broadcastPacketUp(pack,bcs.chanID,remoteID,destID);
                }
 
index 4085941..770205b 100644 (file)
@@ -235,6 +235,7 @@ public:
 
        virtual bool sendPacket(ChanPacket &,GnuID &);
        virtual void flush(Stream &);
+       virtual unsigned int flushUb(Stream &, unsigned int);
        virtual void readHeader(Stream &,Channel *);
        virtual int readPacket(Stream &,Channel *);
        virtual void readEnd(Stream &,Channel *);
index ad18d0c..bd4c171 100644 (file)
@@ -240,6 +240,8 @@ void Servent::reset()
        type = T_NONE;
 
        channel_id = 0;
+
+       serventHit.init();
 }
 // -----------------------------------
 bool Servent::sendPacket(ChanPacket &pack,GnuID &cid,GnuID &sid,GnuID &did,Servent::TYPE t)
@@ -807,6 +809,7 @@ bool Servent::handshakeStream(ChanInfo &chanInfo)
 
        bool gotPCP=false;
        unsigned int reqPos=0;
+       unsigned short listenPort = 0;
 
        nsSwitchNum=0;
 
@@ -820,6 +823,8 @@ bool Servent::handshakeStream(ChanInfo &chanInfo)
                        gotPCP = atoi(arg)!=0;
                else if (http.isHeader(PCX_HS_POS))
                        reqPos = atoi(arg);
+               else if (http.isHeader(PCX_HS_PORT))
+                       listenPort = (unsigned short)atoi(arg);
                else if (http.isHeader("icy-metadata"))
                        addMetadata = atoi(arg) > 0;
                else if (http.isHeader(HTTP_HS_AGENT))
@@ -873,22 +878,23 @@ bool Servent::handshakeStream(ChanInfo &chanInfo)
                }
 
                chanID = chanInfo.id;
+               serventHit.rhost[0].ip = getHost().ip;
+               serventHit.rhost[0].port = listenPort;
+               serventHit.host = serventHit.rhost[0];
+               serventHit.chanID = chanID;
+
                canStreamLock.on();
                chanReady = canStream(ch);
-               if (0 && !chanReady)
+               if (/*0 && */!chanReady)
                {
                        if (servMgr->numStreams(chanID, Servent::T_RELAY, false) == 0)
                        {
                                sourceHit = &ch->sourceHost;  // send source host info
 
-                               if (ch->info.getUptime() > 60)  // if stable
+                               if (listenPort && ch->info.getUptime() > 60)  // if stable
                                {
                                        // connect "this" host later
-                                       ChanHit nh;
-                                       nh.init();
-                                       nh.chanID = chanID;
-                                       nh.rhost[0] = getHost();
-                                       chanMgr->addHit(nh);
+                                       chanMgr->addHit(serventHit);
                                }
 
                                char tmp[50];
@@ -896,11 +902,11 @@ bool Servent::handshakeStream(ChanInfo &chanInfo)
                                LOG_DEBUG("Bump channel, hand over sourceHost to %s", tmp);
                                ch->bump = true;
                        }
-                       else if (servMgr->kickUnrelayableHost(chanID, this) != 0)
+                       else if (servMgr->kickUnrelayableHost(chanID, serventHit) != 0)
                        {
                                chanReady = canStream(ch);
                                if (!chanReady)
-                                       LOG_DEBUG("Kicked unrelayable host, but still cannot stream");
+                                       LOG_DEBUG("*** Kicked unrelayable host, but still cannot stream");
                        }
                }
                if (!chanReady) type = T_INCOMING;
@@ -1114,8 +1120,8 @@ bool Servent::handshakeStream(ChanInfo &chanInfo)
                                if (sourceHit) {
                                        char tmp[50];
                                        sourceHit->writeAtoms(atom2, chanInfo.id);
-                                       chs.best[i].host.toStr(tmp);
-                                       LOG_DEBUG("relay info: %s hops = %d", tmp, chs.best[i].numHops);
+                                       sourceHit->host.toStr(tmp);
+                                       LOG_DEBUG("relay info(sourceHit): %s", tmp);
                                        best.host.ip = sourceHit->host.ip;
                                }
 
@@ -2792,6 +2798,8 @@ void Servent::sendPeercastChannel()
 void Servent::sendPCPChannel()
 {
        bool skipCheck = false;
+       unsigned int ptime = 0;
+       int npacket = 0, upsize = 0;
 
        Channel *ch = chanMgr->findChannelByID(chanID);
        if (!ch)
@@ -2929,11 +2937,23 @@ void Servent::sendPCPChannel()
                        BroadcastState bcs;
                        bcs.servent_id = servent_id;
 //                     error = pcpStream->readPacket(*sock,bcs);
-                       do {
+
+                       unsigned int t = sys->getTime();
+                       if (t != ptime) {
+                               ptime = t;
+                               npacket = MAX_PROC_PACKETS;
+                               upsize = MAX_OUTWARD_SIZE;
+                       }
+
+                       int len = pcpStream->flushUb(*sock, upsize);
+                       upsize -= len;
+
+                       while (npacket > 0 && sock->readReady()) {
+                               npacket--;
                                error = pcpStream->readPacket(*sock,bcs);
                                if (error)
                                        throw StreamException("PCP exception");
-                       } while (sock->readReady() || pcpStream->outData.numPending());
+                       }
 
                        sys->sleepIdle();
 
index e257e82..09aaac5 100644 (file)
@@ -46,6 +46,12 @@ public:
                MAX_OUTPACKETS = 32             // max. output packets per queue (normal/priority)
        };
 
+       enum
+       {
+               MAX_PROC_PACKETS = 300,
+               MAX_OUTWARD_SIZE = 1024 * 10
+       };
+
     enum TYPE                                  
     {
                T_NONE,                                 // Not allocated
@@ -288,6 +294,8 @@ public:
        unsigned int lastSkipCount;
        unsigned int waitPort;
 
+       ChanHit serventHit;
+
        int channel_id;
 };
 
index e8d57e2..3829168 100644 (file)
@@ -2623,6 +2623,7 @@ void ServMgr::banFirewalledHost()
 }
 
 // --------------------------------------------------
+#if 0
 static ChanHit *findServentHit(Servent *s)
 {
        ChanHitList *chl = chanMgr->findHitListByID(s->chanID);
@@ -2640,8 +2641,9 @@ static ChanHit *findServentHit(Servent *s)
        }
        return NULL;
 }
+#endif
 // --------------------------------------------------
-int ServMgr::kickUnrelayableHost(GnuID &chid, Servent *ns)
+int ServMgr::kickUnrelayableHost(GnuID &chid, ChanHit &sendhit)
 {
        Servent *ks = NULL;
        Servent *s = servMgr->servents;
@@ -2652,9 +2654,8 @@ int ServMgr::kickUnrelayableHost(GnuID &chid, Servent *ns)
                {
                        Host h = s->getHost();
 
-                       chanMgr->hitlistlock.on();
-                       ChanHit *hit = findServentHit(s);
-                       if (hit && !hit->relay && hit->numRelays == 0)
+                       ChanHit hit = s->serventHit;
+                       if (!hit.relay && hit.numRelays == 0)
                        {
                                char hostName[256];
                                h.toStr(hostName);
@@ -2663,25 +2664,18 @@ int ServMgr::kickUnrelayableHost(GnuID &chid, Servent *ns)
                                if (!ks || s->lastConnect < ks->lastConnect) // elder servent
                                        ks = s;
                        }
-                       chanMgr->hitlistlock.off();
                }
                s = s->next;
        }
 
        if (ks)
        {
-               if (ns)
+               if (sendhit.rhost[0].port)
                {
-                       Host h = ns->getHost();
-                       ChanHit nh;
-                       nh.init();
-                       nh.chanID = chid;
-                       nh.rhost[0] = h;
-
                        ChanPacket pack;
                        MemoryStream mem(pack.data,sizeof(pack.data));
                        AtomStream atom(mem);
-                       nh.writeAtoms(atom, chid);
+                       sendhit.writeAtoms(atom, chid);
                        pack.len = mem.pos;
                        pack.type = ChanPacket::T_PCP;
                        GnuID noID;
index f8832fc..e424a9d 100644 (file)
@@ -402,7 +402,7 @@ public:
        unsigned int kickPushTime;
        bool    isCheckPushStream(); //JP-EX
        void    banFirewalledHost(); //JP-EX
-       int kickUnrelayableHost(GnuID &, Servent * = NULL);
+       int kickUnrelayableHost(GnuID &, ChanHit &);
 
        bool    getModulePath; //JP-EX
        bool    clearPLS; //JP-EX
index fc9e7ec..28dd346 100644 (file)
@@ -29,22 +29,22 @@ static bool PCP_FORCE_YP                            = false;
 #endif
 // ------------------------------------------------
 static const int PCP_CLIENT_VERSION            = 1218;
-static const int PCP_CLIENT_VERSION_VP = 25;
+static const int PCP_CLIENT_VERSION_VP = 26;
 static const int PCP_ROOT_VERSION              = 1218;
 
 static const int PCP_CLIENT_MINVERSION = 1200;
 
 static const char *PCX_AGENT           = "PeerCast/0.1218";    
 static const char *PCX_AGENTJP                 = "PeerCast/0.1218-J";
-static const char *PCX_AGENTVP         = "PeerCast/0.1218(VP0025-1)";
-static const char *PCX_VERSTRING       = "v0.1218(VP0025-1)";
+static const char *PCX_AGENTVP         = "PeerCast/0.1218(VP0026)";
+static const char *PCX_VERSTRING       = "v0.1218(VP0026)";
 
 #if 1 /* for VP extend version */
 #define VERSION_EX 1
 static const char *PCP_CLIENT_VERSION_EX_PREFIX = "IM"; // 2bytes only
-static const int  PCP_CLIENT_VERSION_EX_NUMBER = 7650;
-static const char *PCX_AGENTEX = "PeerCast/0.1218(IM-VP25-1)";
-static const char *PCX_VERSTRING_EX = "v0.1218(IM765-VP25-1)";
+static const int  PCP_CLIENT_VERSION_EX_NUMBER = 26;
+static const char *PCX_AGENTEX = "PeerCast/0.1218(IM0026-patch071223)";
+static const char *PCX_VERSTRING_EX = "v0.1218(IM0026)";
 #endif
 
 // ------------------------------------------------