全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:2673
推到 Plurk!
推到 Facebook!

比特精靈v2.0 p2p BT軟體

 
conundrum
尊榮會員


發表:893
回覆:1272
積分:643
註冊:2004-01-06

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-07-05 00:45:42 IP:61.64.xxx.xxx 未訂閱
http://www.17yy.com/bs/ 比特精靈v2.0除了繼承比特精靈1.0首創的磁片讀寫緩存,文件選擇下載等現今被廣泛採用的BT技術,更是集穩定的程式表現、良好的程式性能、強大的附加功能於一身。 全平臺UPnP自動埠映射:第一個做到了真正的UPnP支援。 自動設置XP網路防火牆:保證網路安全的前提下盡情BT。 即時通訊功能:下載過程中方便地和網友進行即時交互。 種子市場功能:通過種子市場可以方便地和網友共用種子資訊。 資料壓縮傳輸功能:更加有效地利用有限的帶寬。 連接資訊共用:共用可用連接資訊,提高下載效率. 源代碼部分開放:除了開放一些插件的源代碼外,還公開了BS的全平臺UPnP支援的模組源代碼。更多源代碼,敬請訪問官方論壇的“使用手冊和開發指南”版塊 。
附加檔案:52663_bsup26ml.exe
conundrum
尊榮會員


發表:893
回覆:1272
積分:643
註冊:2004-01-06

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-08-11 23:04:57 IP:61.64.xxx.xxx 未訂閱
轉貼 比特精靈 官方討論區 upnp.h         
#ifndef MYUPNP_H_
#include "bt.h"
typedef bool (*PUPNPCALLBACK)(void* lp);
const int UPNPREPEAT = 5;
const int UPNPDELAY = 6;
class QMyUPNP
{
public:
        QMyUPNP();
    QMyUPNP(const QString& device);
        ~QMyUPNP();
        void                Clear();
        bool                Comfirmed()const{return (Valid()&&!m_controlurl.IsEmpty());}
        bool                Search(const QString& name, const char* type="service", int repeat=UPNPREPEAT, int delay=UPNPDELAY, int version=1, PUPNPCALLBACK lpCall=NULL);
        bool                GetDescription(int delay=UPNPDELAY);
        QString                GetProperty(const QString& name, const QString& rsp, int delay=UPNPDELAY);
        bool                InvokeCommand(const QString& name, QStringList& args,int delay=UPNPDELAY);
        bool                SetDescriptionUrl(const QString& name, const QString& descri);
        void                SetDeviceName(const QString& p){m_devicename = p;}
        QString                GetDeviceName()const{return m_devicename;}
        QString                GetDescriptionUrl()const{return m_description;}
        QString                GetControlUrl()const{return m_controlurl;}
        QString                GetBaseUrl()const{return m_baseurl;}
        QString                GetDescriptionName()const{return m_name;}
        QString                GetFriendlyName()const{return m_friendlyname;}
        QString                GetModelName()const{return m_modelname;}
        QMyUPNP&        operator=(const QMyUPNP& up);
protected:
        bool                Valid()const{return (!m_name.IsEmpty()&&!m_description.IsEmpty());}
        void                InternalClear();
        bool                InternalSearch(const QString& name, const char* type, int repeat, int delay, int version, ulong ip, PUPNPCALLBACK lpCall);
        bool                InternalSearch2(const QString& name, const char* type, int repeat, int delay, int version, ulong ip, PUPNPCALLBACK lpCall);
        QString                m_devicename;
        QString                m_name;
        QString                m_description;
        QString                m_baseurl;
        QString                m_controlurl;
        QString                m_friendlyname;
        QString                m_modelname;
        int                        m_version;
};
inline QMyUPNP& QMyUPNP::operator=(const QMyUPNP& upnp)
{
        if(this==&upnp)return *this;
        m_devicename = upnp.m_devicename;
        m_name = upnp.m_name;
        m_description = upnp.m_description;
        m_baseurl = upnp.m_baseurl;
        m_controlurl = upnp.m_controlurl;
        m_friendlyname = upnp.m_friendlyname;
        m_modelname = upnp.m_modelname;
        m_version = upnp.m_version;
        return *this;
}
#define UPNPPORTMAP0   "WANIPConnection"
#define UPNPPORTMAP1   "WANPPPConnection"
#define UPNPGETEXTERNALIP "GetExternalIPAddress","NewExternalIPAddress"
#define UPNPADDPORTMAP "AddPortMapping"
#define UPNPDELPORTMAP "DeletePortMapping"
void GetAddPortmapArgs(QStringList& args, int eport, int iport, const char* iclient,
                                           const char* descri, bool enabled = true, int dur = 0,
                                           const char* type = "TCP", const char* remote = NULL);
void GetDeletePortmapArgs(QStringList& args, int eport, const char* type = "TCP", const char* remote=NULL);
#endif
 
conundrum
尊榮會員


發表:893
回覆:1272
積分:643
註冊:2004-01-06

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-08-11 23:07:16 IP:61.64.xxx.xxx 未訂閱
轉貼 比特精靈 官方討論區 upnp.cpp         
#include "upnp.h"
#include "qsocket.h"
#include "qudp.h"
/*
ReloadIp: 獲取本機上最類似於192.168.0.x的內網IP
如果本機沒有內網IP,則返回INADDR_NONE
*/
static ulong ReloadIp()//get 192.168.0.x
{
        int                                len = 256;
        char                        name[256 1];
        hostent                        *host;
        ulong                        tmpip = INADDR_NONE, 
                                        retip = INADDR_NONE;
        memset(name, 0, len 1);
        if(gethostname(name,len)==0)
        {
                host = gethostbyname(name);
                if(host&&host->h_length>=sizeof(ulong))
                {
                        len = 0;
                        while(host->h_addr_list[len])
                        {
                                tmpip = *((ulong*)(host->h_addr_list[len  ]));
                                if(((tmpip&0xFF)==192&&((tmpip>>8)&0xFF)==168&&((tmpip>>16)&0xFF)==0)
                                        ||IsLAN(tmpip)||!is_validip(retip))
                                {
                                        retip = tmpip;
                                }
                        }
                }
        }
        return retip;
}    static const ulong        UPNPADDR = 0xFAFFFFEF;
static const int        UPNPPORT = 1900;
static const char*        URNPREFIX = "urn:schemas-upnp-org:";
static const char*  LCA = "Location:";
static const char*  LCB = "LOCATION:";
static const char*  LCC = "location:";
/*
LCA,LCB,LCC: 有些UPnP設備以LCA作為字段名稱,有些則用LCB,有些則用LCC,對於其他那些喜歡亂命名的廠商只好說抱歉了.
*/
QMyUPNP::QMyUPNP()
: m_version(1)
{
}
QMyUPNP::QMyUPNP(const QString& device)
: m_devicename(device), m_version(1)
{    }
QMyUPNP::~QMyUPNP()
{
        Clear();
}
/*InternalClear: 清空對像,但保留對像*/
void QMyUPNP::InternalClear()
{
        m_baseurl = "";
        m_controlurl = "";
        m_friendlyname = "";
        m_modelname = "";
}
/*Clear: 清空對像,同時對像失效.*/
void QMyUPNP::Clear()
{
        m_name = "";
        m_description = "";
        m_version = 1;
        InternalClear();
}
/*
InternalSearch: 查找UPnP設備
實現過程:首先調用InternalSearch2進行查找的操作,如果沒有找到,則設置對象的設備名為IGD,再次調用InternalSearch2查找.
之所以分兩次查找是因為有些設備支持以服務名查找,而有些設備則只支持以設備名查找.
參數含義:
name: 要查找的服務/設備的名稱
type: name表示的是服務或設備(service/device)
repeat: 嘗試查找的次數
delay: 查找結果的最長等待時間
version: UPnP版本,默認1
ip: 查詢的目標IP,默認為UPnP的廣播IP0xFAFFFFEF,也可以指定IP以便當程序運行在某些主機上時也能查找.
lpCall: 一個回調函數,在查找過程中隨機調用.
返回值: 成功返回true,否則返回false
*/
bool QMyUPNP::InternalSearch(const QString& name, const char* type, int repeat,
                                                         int delay, int version, ulong ip, PUPNPCALLBACK lpCall)
{
        if(InternalSearch2(name,type,repeat,delay,version,ip,lpCall))return true;
        QString back = m_devicename;
        m_devicename = QString("urn:schemas-upnp-org:device:InternetGatewayDevice:")   m_version;
        bool ok = InternalSearch2(name,type,repeat,delay,version,ip,lpCall);
        m_devicename = back;
        return ok;
}
/*
InternalSearch2: 執行查找操作.
實現過程:
創建UDP套接字,如果IP為0,則先對255.255.255.255的1900端口發送廣播消息,再對UPnP的廣播IP發送消息.
參數函數同InternalSearch.
*/
bool QMyUPNP::InternalSearch2(const QString& name, const char* type, int repeat,
                                                         int delay, int version, ulong ip, PUPNPCALLBACK lpCall)
{
        static const char*        USRS = "M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\n"
                                                          "MAN: \"ssdp:discover\"\r\nMX: ";
        const int                        RCVLEN = 4096;
        Clear();
        if(name.IsEmpty())return false;
        if(type==NULL)type = "service";
        if(repeat<=0)repeat = UPNPREPEAT;
        if(delay<=0)delay = UPNPDELAY;
        if(version<=0)version = 1;
        m_version = version;
        m_name = QString(URNPREFIX)   type   ":"   name   ":"   version;
        QString finding = m_devicename.IsEmpty() ? m_name : m_devicename;
        QString shrs = QString(USRS)   delay   "\r\nST: "   finding   "\r\n\r\n";
        QUdpSocket        udp(true);
        char                 a[50], b[50], c[50];
        char                rcv[RCVLEN   1];
        int                        rlen = 0;
        int                        retry = 0;
        const char* lc = "";
        const char* le = "";
        bool                broad = (!is_validip(ip)); //send to 255.255.255.255
        do
        {
                if(retry)sleep(1);
                if(!is_validip(ip)) ip = UPNPADDR;
                if(broad&&!udp.SendPacket(shrs.c_str(),shrs.Length(),INADDR_BROADCAST,UPNPPORT,delay/2))continue;
                if(!udp.SendPacket(shrs.c_str(),shrs.Length(),ip,UPNPPORT,delay/2)
                   ||(rlen=udp.RecvPacket(rcv,RCVLEN,delay))<=0)continue;
                if(lpCall&&!lpCall(NULL))break;
                if(rlen<=0||rlen>RCVLEN)continue;
                rcv[rlen] = 0;
                if(SplitterString(rcv,a,b,c,40,40,40)!=3||b[0]!='2')continue;
                if(strstr(rcv,finding.c_str())==NULL)continue;
                lc = strstr(rcv,LCA);
                if(lc==NULL) lc = strstr(rcv,LCB);
                if(lc==NULL) lc = strstr(rcv,LCC);
                if(lc==NULL)continue;
                lc  = strlen(LCA);
                while(lc[0]>0&&lc[0]<=0x20) lc  ;
                le = strchr(lc,'\n');
                if(le==NULL)continue;
                m_description = QString(lc,le - lc).Trim();
        }while(  retry='0'&&p<='9');
}
static int ParseInteger(const char* cstr)
{
        const unsigned char* str = (const unsigned char*) cstr;
        int value = 0;
        assert(str);
        if(str)
        {
                int retry = 20;
                bool neg = (str[0]=='-');
                if(neg)str  ;
                while(PPIsDigitChar(str[0])&&(--retry)>0)
                {
                        value*=10;
                        value =(str[0]-'0');
                        str  ;
                }
                if(neg)value = -value;
        }
        return value;
}    static QString NGetAddressFromUrl(const QString& str, QString& post, QString& host, int& port)
{
        port = 0;
        post = "";
        if(str.IsEmpty())return QString();
        const char* src = str.c_str();
        const char* start,
                          * pstart,
                          *        end;
        start = strstr(src,"://");
        start = (start==NULL)?src:(start 3);
        end = strchr(start,'/');
        if(end==NULL)end = src   strlen(src);
        host = QString(start,end-start);
        post = (end[0]=='/')?QString(end):QString("/");
        pstart = strchr(start,':');
        port = (pstart==NULL||pstart>=end)?80:ParseInteger(pstart 1);
        if(port==0)port = 80;
        if(pstart&&pstart=0&&tcp.SendLength()>0) sleep(1); //sleep(x) = Sleep(x * 1000)
        }while(  retry0);
        if(tcp.SendLength()>0||tcp.Read()<0)return false;
        retry = 0;
        do
        {
                if(retry)sleep(1);
        }while(tcp.Read()>=0&&  retry=0);
        char a[50], b[50], c[50];
        if(SplitterString(tcp.RecvBuffer(),a,b,c,40,40,40)!=3||b[0]!='2')return false;
        const char* lfe = NULL;
        const char* buf = tcp.RecvBuffer(); //如果當前沒有數據,返回"",RecvBuffer永遠不會返回NULL,所以不用擔心空指針
        const char* lfr = NULL;
        //get friendly name
        lfr = strstr(buf,"");
        if(lfr)
        {
                lfr  = (sizeof("") - 1);
                lfe = strstr(lfr,"");
                if(lfe)m_friendlyname = QString(lfr, lfe - lfr).Trim();
        }
        //get 
        lfr = strstr(buf,"");
        if(lfr)
        {
                lfr  = (sizeof("") - 1);
                lfe = strstr(lfr, "");
                if(lfe)m_modelname = QString(lfr, lfe - lfr).Trim();
        }
        //get 
        lfr = strstr(buf,"");
        if(lfr)
        {
                lfr  = (sizeof("") - 1);
                lfe = strstr(lfr,"");
                if(lfe)m_baseurl = QString(lfr, lfe - lfr).Trim();
        }
        if(m_baseurl.IsEmpty())m_baseurl = QString("http://")   host   "/";
        if(m_baseurl[m_baseurl.Length()]!='/')m_baseurl  = "/";
        //get service
        QString svrn = QString("")   m_name   "";
        lfr = strstr(buf,svrn.c_str());
        if(lfr)
        {
                lfe = strstr(lfr, "");
                if(lfe)
                {
                        QString tmp = QString(lfr, lfe - lfr);
                        lfr = strstr(tmp.c_str(),"");
                        if(lfr)
                        {
                                lfr  = (sizeof("") - 1);
                                lfe = strstr(lfr,"");
                                if(lfe&&lfe>lfr)
                                {
                                        if(lfr[0]=='/')
                                        {//relative url
                                                lfr  ;
                                                m_controlurl = m_baseurl   QString(lfr, lfe - lfr);
                                        }
                                        else
                                        {
                                                m_controlurl = QString(lfr, lfe - lfr);
                                        }
                                }
                        }
                }
        }
        return Comfirmed();
}
/*
GetProperty: 在對像已經有效的情況下獲取對象的某屬性.
實現過程: 通過對目標對象的控制URL發送UPnP規範定義的POST請求並解析返回數據來獲取相應的屬性.
參數: 
name: 針對該屬性的動作,如:GetExternalIPAddress
rsp: 屬性返回值的名稱,如:NewExternalIPAddress
delay: 最大等待時間
*/
QString QMyUPNP::GetProperty(const QString& name, const QString& rsp, int delay)
{
        if(!Comfirmed())return QString();
        QString post, host, addr;
        int port = 0;
        addr = NGetAddressFromUrl(m_controlurl, post, host, port);
        if(addr.IsEmpty()||!is_validport(port))return QString();
        QMemoryStream cnt; //QMemoryStream 內部有智能的內存算法可以避免頻繁的內存分配.
        QMemoryStream psr;
        cnt.Write("\r\n  \r\n    \r\n    \r\n  \r\n\r\n\r\n");
        psr.Write("POST ");
        psr.Write(post.c_str());
        psr.Write(" HTTP/1.1\r\nHOST: ");
        psr.Write(host.c_str());
        psr.Write("\r\nContent-Length: ");
        psr.Write(cnt.Size());
        psr.Write("\r\nContent-Type: text/xml; charset=\"utf-8\"\r\nSOAPACTION: ");
        psr.Write(m_name.c_str());
        psr.Write("#");
        psr.Write(name.c_str());
        psr.Write("\r\n\r\n");
        psr.Write(cnt.Data(),cnt.Size());
        QProxy        proxy;
        QSocket tcp;
        int                retry = 0;
        if(delay<=0)delay = UPNPDELAY;
        if(!tcp.Connect(addr.c_str(),port,false,&proxy))
        {
                return QString();//no proxy
        }
        tcp.SendData(psr.Data(),psr.Size());
        do
        {
                if(tcp.Write()>=0&&tcp.SendLength()>0) sleep(1);
        }while(  retry0);
        if(tcp.SendLength()>0||tcp.Read()<0)
        {
                return QString();
        }
        retry = 0;
        do
        {
                if(retry)sleep(1);
        }while(tcp.Read()>=0&&  retry=0);
        char a[50], b[50], c[50];
        if(SplitterString(tcp.RecvBuffer(),a,b,c,40,40,40)!=3||b[0]!='2')
        {
                return QString();
        }
        QString schr = QString("<")   rsp;
        QString echr = QString("";
        const char* lfe = NULL;
        const char* buf = tcp.RecvBuffer();
        const char* lfr = strstr(buf,schr.c_str());
        if(lfr)
        {        
                lfe = strstr(lfr, echr.c_str());
                if(lfe)
                {
                        QString ret = QString(lfr, lfe - lfr);
                        lfr = strchr(ret.c_str(),'>');
                        if(lfr)
                        {
                                lfr  ;
                                return QString(lfr);
                        }
                }
        }
        return QString();
}
/*
GetArgString: 將BS使用的一個QStringList的參數格式轉換成符合UPnP規範的字串型參數.
*/
QString GetArgString(QStringList& args)
{
        QMemoryStream ms;
        for(int i=0;i",1);
                ms.Write(args.Item(i 1).c_str());
                ms.Write("\r\n",3);
        }
        return QString(ms.Data(),ms.Size());
}
/*
InvokeCommand: 在對像有效的情況下調用對象的方法.
實現過程:通過向目標對象的控制URL發送UPnP規範定義的POST方法來調用對象的方法.
參數含義: 
name: 調用方法的名稱.如:AddPortMapping
args: QStringList類型,其組成結構為:偶數索引的值為參數名,奇數索引的值為參數值,從0開始索引.
delay: 最大等待時間.
*/
bool QMyUPNP::InvokeCommand(const QString& name, QStringList& args, int delay)
{
        if(!Comfirmed())return false;
        QString post, host, addr;
        int port = 0;
        addr = NGetAddressFromUrl(m_controlurl, post, host, port);
        if(addr.IsEmpty()||!is_validport(port))return false;
        QMemoryStream cnt;
        QMemoryStream psr;
        cnt.Write("\r\n  \r\n    \r\n");
        cnt.Write(GetArgString(args).c_str());
        cnt.Write("    \r\n  \r\n\r\n\r\n");
        psr.Write("POST ");
        psr.Write(post.c_str());
        psr.Write(" HTTP/1.1\r\nHOST: ");
        psr.Write(host.c_str());
        psr.Write("\r\nContent-Length: ");
        psr.Write(cnt.Size());
        psr.Write("\r\nContent-Type: text/xml; charset=\"utf-8\"\r\nSOAPACTION: ");
        psr.Write(m_name.c_str());
        psr.Write("#");
        psr.Write(name.c_str());
        psr.Write("\r\n\r\n");
        psr.Write(cnt.Data(),cnt.Size());
        QProxy        proxy;
        QSocket tcp;
        int                retry = 0;
        if(delay<=0)delay = UPNPDELAY;
        if(!tcp.Connect(addr.c_str(),port,false,&proxy))return false;//no proxy
        tcp.SendData(psr.Data(),psr.Size());
        do
        {
                if(tcp.Write()>=0&&tcp.SendLength()>0) sleep(1);
        }while(  retry0);
        if(tcp.SendLength()>0||tcp.Read()<0)return false;
        retry = 0;
        do
        {
                if(retry)sleep(1);
        }while(tcp.Read()>=0&&  retry=0);
        char a[50], b[50], c[50];
        if(SplitterString(tcp.RecvBuffer(),a,b,c,40,40,40)==3&&b[0]=='2')return true;
        return false;
}
/*
GetAddPortmapArgs: 生成相應可用於InvokeCommand的針對AddPortmapping的參數.
*/
void GetAddPortmapArgs(QStringList& args, int eport, int iport,
                                                                  const char* iclient, const char* descri,
                                                                  bool enabled, int dur, const char* type, const char* remote)
{
        args.Clear();
        args.Add("NewRemoteHost");
        args.Add(remote);
        args.Add("NewExternalPort");
        args.Add(QString(eport));
        args.Add("NewProtocol");
        args.Add(type);
        args.Add("NewInternalPort");
        args.Add(QString(iport));
        args.Add("NewInternalClient");
        args.Add(iclient);
        args.Add("NewEnabled");
        args.Add(enabled?"1":"0");
        args.Add("NewPortMappingDescription");
        args.Add(descri);
        args.Add("NewLeaseDuration");
        args.Add(QString(dur));
}
void GetDeletePortmapArgs(QStringList& args, int eport, const char* type, const char* remote)
{
        args.Clear();
        args.Add("NewRemoteHost");
        args.Add(remote);
        args.Add("NewExternalPort");
        args.Add(QString(eport));
        args.Add("NewProtocol");
        args.Add(type);
}    /*
附註:
1, 以上用到的QString,QUdpSocket,QStringList,QMemoryStream,QSocket,QProxy都是BS內部實現的類,功能與接口與一些流行的類庫如MFC,VCL類似.
2, 通過QMyUPNP類來查找支持自動端口映射的設備的示例代碼:
        QMyUPNP Tmp;
        //查找服務的示例
        if(!Tmp.Comfirmed()) Tmp.Search(UPNPPORTMAP1);
        if(!Tmp.Comfirmed()) Tmp.Search(UPNPPORTMAP0);
        if(Tmp.Comfirmed()) MessageBox(NULL,(QString("Found: ")   Tmp.GetModelName()).c_str(),"",MB_OK);
        //添加端口的示例
        QStringList args;
        GetAddPortmapArgs(args,FWANPort,FLocalPort,FLocalIP,FDescription,
                                          true,0,FType,FWANIP);//FWANIP為""表示默認公網IP
        Tmp.InvokeCommand(UPNPADDPORTMAP,args,6);
        //刪除端口的示例
        QStringList args;
        GetDeletePortmapArgs(args,FWANPort,FType,FWANIP);
        Tmp.InvokeCommand(UPNPDELPORTMAP,args,6);
        //獲取公網IP的示例
        QString ip = Tmp.GetProperty(UPNPGETEXTERNALIP,6);
        MessageBox(NULL,(QString("Your WAN IP: ")   ip).c_str(),"",MB_OK);
3, 聲明:以上代碼都是BS的作者自行實現的,你可以參考,但你最好不要將代碼直接拷貝到你的程序中,因為我們保留對這些代碼的所有權利.
   如果有任何問題,歡迎訪問我們的網站或Mail到: bitspirit@lanspirit.net
*/     
系統時間:2024-05-18 6:35:04
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!