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 }