github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/p2p/nat/natupnp_test.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //版权所有2015 Go Ethereum作者
    10  //此文件是Go以太坊库的一部分。
    11  //
    12  //Go-Ethereum库是免费软件:您可以重新分发它和/或修改
    13  //根据GNU发布的较低通用公共许可证的条款
    14  //自由软件基金会,或者许可证的第3版,或者
    15  //(由您选择)任何更高版本。
    16  //
    17  //Go以太坊图书馆的发行目的是希望它会有用,
    18  //但没有任何保证;甚至没有
    19  //适销性或特定用途的适用性。见
    20  //GNU较低的通用公共许可证,了解更多详细信息。
    21  //
    22  //你应该收到一份GNU较低级别的公共许可证副本
    23  //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。
    24  
    25  package nat
    26  
    27  import (
    28  	"fmt"
    29  	"io"
    30  	"net"
    31  	"net/http"
    32  	"runtime"
    33  	"strings"
    34  	"testing"
    35  
    36  	"github.com/huin/goupnp/httpu"
    37  )
    38  
    39  func TestUPNP_DDWRT(t *testing.T) {
    40  	if runtime.GOOS == "windows" {
    41  		t.Skipf("disabled to avoid firewall prompt")
    42  	}
    43  
    44  	dev := &fakeIGD{
    45  		t: t,
    46  		ssdpResp: "HTTP/1.1 200 OK\r\n" +
    47  			"Cache-Control: max-age=300\r\n" +
    48  			"Date: Sun, 10 May 2015 10:05:33 GMT\r\n" +
    49  			"Ext: \r\n" +
    50  "Location: http://listenaddr/internetgatewaydevice.xml\r\n“+
    51  			"Server: POSIX UPnP/1.0 DD-WRT Linux/V24\r\n" +
    52  			"ST: urn:schemas-upnp-org:device:WANConnectionDevice:1\r\n" +
    53  			"USN: uuid:CB2471CC-CF2E-9795-8D9C-E87B34C16800::urn:schemas-upnp-org:device:WANConnectionDevice:1\r\n" +
    54  			"\r\n",
    55  		httpResps: map[string]string{
    56  			"GET /InternetGatewayDevice.xml": `
    57  				 <?xml version="1.0"?>
    58  				 <root xmlns="urn:schemas-upnp-org:device-1-0">
    59  					 <specVersion>
    60  						 <major>1</major>
    61  						 <minor>0</minor>
    62  					 </specVersion>
    63  					 <device>
    64  						 <deviceType>urn:schemas-upnp-org:device:InternetGatewayDevice:1</deviceType>
    65  						 <manufacturer>DD-WRT</manufacturer>
    66  <manufacturerURL>http://www.dd-wrt.com</manufacturerurl>
    67  						 <modelDescription>Gateway</modelDescription>
    68  						 <friendlyName>Asus RT-N16:DD-WRT</friendlyName>
    69  						 <modelName>Asus RT-N16</modelName>
    70  						 <modelNumber>V24</modelNumber>
    71  						 <serialNumber>0000001</serialNumber>
    72  <modelURL>http://www.dd-wrt.com</modelurl>
    73  						 <UDN>uuid:A13AB4C3-3A14-E386-DE6A-EFEA923A06FE</UDN>
    74  						 <serviceList>
    75  							 <service>
    76  								 <serviceType>urn:schemas-upnp-org:service:Layer3Forwarding:1</serviceType>
    77  								 <serviceId>urn:upnp-org:serviceId:L3Forwarding1</serviceId>
    78  								 <SCPDURL>/x_layer3forwarding.xml</SCPDURL>
    79  								 <controlURL>/control?Layer3Forwarding</controlURL>
    80  								 <eventSubURL>/event?Layer3Forwarding</eventSubURL>
    81  							 </service>
    82  						 </serviceList>
    83  						 <deviceList>
    84  							 <device>
    85  								 <deviceType>urn:schemas-upnp-org:device:WANDevice:1</deviceType>
    86  								 <friendlyName>WANDevice</friendlyName>
    87  								 <manufacturer>DD-WRT</manufacturer>
    88  <manufacturerURL>http://www.dd-wrt.com</manufacturerurl>
    89  								 <modelDescription>Gateway</modelDescription>
    90  								 <modelName>router</modelName>
    91  <modelURL>http://www.dd-wrt.com</modelurl>
    92  								 <UDN>uuid:48FD569B-F9A9-96AE-4EE6-EB403D3DB91A</UDN>
    93  								 <serviceList>
    94  									 <service>
    95  										 <serviceType>urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1</serviceType>
    96  										 <serviceId>urn:upnp-org:serviceId:WANCommonIFC1</serviceId>
    97  										 <SCPDURL>/x_wancommoninterfaceconfig.xml</SCPDURL>
    98  										 <controlURL>/control?WANCommonInterfaceConfig</controlURL>
    99  										 <eventSubURL>/event?WANCommonInterfaceConfig</eventSubURL>
   100  									 </service>
   101  								 </serviceList>
   102  								 <deviceList>
   103  									 <device>
   104  										 <deviceType>urn:schemas-upnp-org:device:WANConnectionDevice:1</deviceType>
   105  										 <friendlyName>WAN Connection Device</friendlyName>
   106  										 <manufacturer>DD-WRT</manufacturer>
   107  <manufacturerURL>http://www.dd-wrt.com</manufacturerurl>
   108  										 <modelDescription>Gateway</modelDescription>
   109  										 <modelName>router</modelName>
   110  <modelURL>http://www.dd-wrt.com</modelurl>
   111  										 <UDN>uuid:CB2471CC-CF2E-9795-8D9C-E87B34C16800</UDN>
   112  										 <serviceList>
   113  											 <service>
   114  												 <serviceType>urn:schemas-upnp-org:service:WANIPConnection:1</serviceType>
   115  												 <serviceId>urn:upnp-org:serviceId:WANIPConn1</serviceId>
   116  												 <SCPDURL>/x_wanipconnection.xml</SCPDURL>
   117  												 <controlURL>/control?WANIPConnection</controlURL>
   118  												 <eventSubURL>/event?WANIPConnection</eventSubURL>
   119  											 </service>
   120  										 </serviceList>
   121  									 </device>
   122  								 </deviceList>
   123  							 </device>
   124  							 <device>
   125  								 <deviceType>urn:schemas-upnp-org:device:LANDevice:1</deviceType>
   126  								 <friendlyName>LANDevice</friendlyName>
   127  								 <manufacturer>DD-WRT</manufacturer>
   128  <manufacturerURL>http://www.dd-wrt.com</manufacturerurl>
   129  								 <modelDescription>Gateway</modelDescription>
   130  								 <modelName>router</modelName>
   131  <modelURL>http://www.dd-wrt.com</modelurl>
   132  								 <UDN>uuid:04021998-3B35-2BDB-7B3C-99DA4435DA09</UDN>
   133  								 <serviceList>
   134  									 <service>
   135  										 <serviceType>urn:schemas-upnp-org:service:LANHostConfigManagement:1</serviceType>
   136  										 <serviceId>urn:upnp-org:serviceId:LANHostCfg1</serviceId>
   137  										 <SCPDURL>/x_lanhostconfigmanagement.xml</SCPDURL>
   138  										 <controlURL>/control?LANHostConfigManagement</controlURL>
   139  										 <eventSubURL>/event?LANHostConfigManagement</eventSubURL>
   140  									 </service>
   141  								 </serviceList>
   142  							 </device>
   143  						 </deviceList>
   144  <presentationURL>http://listenaddr<presentationurl>
   145  					 </device>
   146  				 </root>
   147  			`,
   148  //对GetNatrSipstatus调用的响应。这个
   149  //特定的实现有一个bug,其中元素
   150  //U内:GetNatrSipstatusResponse不正确
   151  //命名空间。
   152  			"POST /control?WANIPConnection": `
   153  <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/“s:encodingstyle=”http://schemas.xmlsoap.org/soap/encoding/“>
   154  				 <s:Body>
   155  				 <u:GetNATRSIPStatusResponse xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1">
   156  				 <NewRSIPAvailable>0</NewRSIPAvailable>
   157  				 <NewNATEnabled>1</NewNATEnabled>
   158  				 </u:GetNATRSIPStatusResponse>
   159  				 </s:Body>
   160  				 </s:Envelope>
   161  			`,
   162  		},
   163  	}
   164  	if err := dev.listen(); err != nil {
   165  		t.Skipf("cannot listen: %v", err)
   166  	}
   167  	dev.serve()
   168  	defer dev.close()
   169  
   170  //尝试发现假设备。
   171  	discovered := discoverUPnP()
   172  	if discovered == nil {
   173  		t.Fatalf("not discovered")
   174  	}
   175  	upnp, _ := discovered.(*upnp)
   176  	if upnp.service != "IGDv1-IP1" {
   177  		t.Errorf("upnp.service mismatch: got %q, want %q", upnp.service, "IGDv1-IP1")
   178  	}
   179  wantURL := "http://“+dev.listener.addr().string()+”/internetgatewaydevice.xml“
   180  	if upnp.dev.URLBaseStr != wantURL {
   181  		t.Errorf("upnp.dev.URLBaseStr mismatch: got %q, want %q", upnp.dev.URLBaseStr, wantURL)
   182  	}
   183  }
   184  
   185  //Fakeigd将自己呈现为一个可发现的UPNP设备,它发送
   186  //对httpu和http请求的屏蔽响应。
   187  type fakeIGD struct {
   188  t *testing.T //用于测井
   189  
   190  	listener      net.Listener
   191  	mcastListener *net.UDPConn
   192  
   193  //这应该是一个完整的HTTP响应(包括头)。
   194  //它作为对任何SSPD包的响应发送。任何情况
   195  //将“listenaddr”的替换为实际的TCP侦听
   196  //HTTP服务器的地址。
   197  	ssdpResp string
   198  //这个应该包含所有请求的XML有效负载
   199  //进行。键包含方法和路径,例如“get/foo/bar”。
   200  //与ssdprep一样,“listenaddr”替换为tcp
   201  //听地址。
   202  	httpResps map[string]string
   203  }
   204  
   205  //处理程序
   206  func (dev *fakeIGD) ServeMessage(r *http.Request) {
   207  	dev.t.Logf(`HTTPU request %s %s`, r.Method, r.RequestURI)
   208  	conn, err := net.Dial("udp4", r.RemoteAddr)
   209  	if err != nil {
   210  		fmt.Printf("reply Dial error: %v", err)
   211  		return
   212  	}
   213  	defer conn.Close()
   214  	io.WriteString(conn, dev.replaceListenAddr(dev.ssdpResp))
   215  }
   216  
   217  //http处理程序
   218  func (dev *fakeIGD) ServeHTTP(w http.ResponseWriter, r *http.Request) {
   219  	if resp, ok := dev.httpResps[r.Method+" "+r.RequestURI]; ok {
   220  		dev.t.Logf(`HTTP request "%s %s" --> %d`, r.Method, r.RequestURI, 200)
   221  		io.WriteString(w, dev.replaceListenAddr(resp))
   222  	} else {
   223  		dev.t.Logf(`HTTP request "%s %s" --> %d`, r.Method, r.RequestURI, 404)
   224  		w.WriteHeader(http.StatusNotFound)
   225  	}
   226  }
   227  
   228  func (dev *fakeIGD) replaceListenAddr(resp string) string {
   229  	return strings.Replace(resp, "{{listenAddr}}", dev.listener.Addr().String(), -1)
   230  }
   231  
   232  func (dev *fakeIGD) listen() (err error) {
   233  	if dev.listener, err = net.Listen("tcp", "127.0.0.1:0"); err != nil {
   234  		return err
   235  	}
   236  	laddr := &net.UDPAddr{IP: net.ParseIP("239.255.255.250"), Port: 1900}
   237  	if dev.mcastListener, err = net.ListenMulticastUDP("udp", nil, laddr); err != nil {
   238  		dev.listener.Close()
   239  		return err
   240  	}
   241  	return nil
   242  }
   243  
   244  func (dev *fakeIGD) serve() {
   245  	go httpu.Serve(dev.mcastListener, dev)
   246  	go http.Serve(dev.listener, dev)
   247  }
   248  
   249  func (dev *fakeIGD) close() {
   250  	dev.mcastListener.Close()
   251  	dev.listener.Close()
   252  }