github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/p2p/nat/natupnp_test.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 12:09:44</date> 10 //</624342658935951360> 11 12 13 package nat 14 15 import ( 16 "fmt" 17 "io" 18 "net" 19 "net/http" 20 "runtime" 21 "strings" 22 "testing" 23 24 "github.com/huin/goupnp/httpu" 25 ) 26 27 func TestUPNP_DDWRT(t *testing.T) { 28 if runtime.GOOS == "windows" { 29 t.Skipf("disabled to avoid firewall prompt") 30 } 31 32 dev := &fakeIGD{ 33 t: t, 34 ssdpResp: "HTTP/1.1 200 OK\r\n" + 35 "Cache-Control: max-age=300\r\n" + 36 "Date: Sun, 10 May 2015 10:05:33 GMT\r\n" + 37 "Ext: \r\n" + 38 "Location: http://listenaddr/internetgatewaydevice.xml\r\n“+ 39 "Server: POSIX UPnP/1.0 DD-WRT Linux/V24\r\n" + 40 "ST: urn:schemas-upnp-org:device:WANConnectionDevice:1\r\n" + 41 "USN: uuid:CB2471CC-CF2E-9795-8D9C-E87B34C16800::urn:schemas-upnp-org:device:WANConnectionDevice:1\r\n" + 42 "\r\n", 43 httpResps: map[string]string{ 44 "GET /InternetGatewayDevice.xml": ` 45 <?xml version="1.0"?> 46 <root xmlns="urn:schemas-upnp-org:device-1-0"> 47 <specVersion> 48 <major>1</major> 49 <minor>0</minor> 50 </specVersion> 51 <device> 52 <deviceType>urn:schemas-upnp-org:device:InternetGatewayDevice:1</deviceType> 53 <manufacturer>DD-WRT</manufacturer> 54 <manufacturerURL>http://www.dd-wrt.com</manufacturerurl> 55 <modelDescription>Gateway</modelDescription> 56 <friendlyName>Asus RT-N16:DD-WRT</friendlyName> 57 <modelName>Asus RT-N16</modelName> 58 <modelNumber>V24</modelNumber> 59 <serialNumber>0000001</serialNumber> 60 <modelURL>http://www.dd-wrt.com</modelurl> 61 <UDN>uuid:A13AB4C3-3A14-E386-DE6A-EFEA923A06FE</UDN> 62 <serviceList> 63 <service> 64 <serviceType>urn:schemas-upnp-org:service:Layer3Forwarding:1</serviceType> 65 <serviceId>urn:upnp-org:serviceId:L3Forwarding1</serviceId> 66 <SCPDURL>/x_layer3forwarding.xml</SCPDURL> 67 <controlURL>/control?Layer3Forwarding</controlURL> 68 <eventSubURL>/event?Layer3Forwarding</eventSubURL> 69 </service> 70 </serviceList> 71 <deviceList> 72 <device> 73 <deviceType>urn:schemas-upnp-org:device:WANDevice:1</deviceType> 74 <friendlyName>WANDevice</friendlyName> 75 <manufacturer>DD-WRT</manufacturer> 76 <manufacturerURL>http://www.dd-wrt.com</manufacturerurl> 77 <modelDescription>Gateway</modelDescription> 78 <modelName>router</modelName> 79 <modelURL>http://www.dd-wrt.com</modelurl> 80 <UDN>uuid:48FD569B-F9A9-96AE-4EE6-EB403D3DB91A</UDN> 81 <serviceList> 82 <service> 83 <serviceType>urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1</serviceType> 84 <serviceId>urn:upnp-org:serviceId:WANCommonIFC1</serviceId> 85 <SCPDURL>/x_wancommoninterfaceconfig.xml</SCPDURL> 86 <controlURL>/control?WANCommonInterfaceConfig</controlURL> 87 <eventSubURL>/event?WANCommonInterfaceConfig</eventSubURL> 88 </service> 89 </serviceList> 90 <deviceList> 91 <device> 92 <deviceType>urn:schemas-upnp-org:device:WANConnectionDevice:1</deviceType> 93 <friendlyName>WAN Connection Device</friendlyName> 94 <manufacturer>DD-WRT</manufacturer> 95 <manufacturerURL>http://www.dd-wrt.com</manufacturerurl> 96 <modelDescription>Gateway</modelDescription> 97 <modelName>router</modelName> 98 <modelURL>http://www.dd-wrt.com</modelurl> 99 <UDN>uuid:CB2471CC-CF2E-9795-8D9C-E87B34C16800</UDN> 100 <serviceList> 101 <service> 102 <serviceType>urn:schemas-upnp-org:service:WANIPConnection:1</serviceType> 103 <serviceId>urn:upnp-org:serviceId:WANIPConn1</serviceId> 104 <SCPDURL>/x_wanipconnection.xml</SCPDURL> 105 <controlURL>/control?WANIPConnection</controlURL> 106 <eventSubURL>/event?WANIPConnection</eventSubURL> 107 </service> 108 </serviceList> 109 </device> 110 </deviceList> 111 </device> 112 <device> 113 <deviceType>urn:schemas-upnp-org:device:LANDevice:1</deviceType> 114 <friendlyName>LANDevice</friendlyName> 115 <manufacturer>DD-WRT</manufacturer> 116 <manufacturerURL>http://www.dd-wrt.com</manufacturerurl> 117 <modelDescription>Gateway</modelDescription> 118 <modelName>router</modelName> 119 <modelURL>http://www.dd-wrt.com</modelurl> 120 <UDN>uuid:04021998-3B35-2BDB-7B3C-99DA4435DA09</UDN> 121 <serviceList> 122 <service> 123 <serviceType>urn:schemas-upnp-org:service:LANHostConfigManagement:1</serviceType> 124 <serviceId>urn:upnp-org:serviceId:LANHostCfg1</serviceId> 125 <SCPDURL>/x_lanhostconfigmanagement.xml</SCPDURL> 126 <controlURL>/control?LANHostConfigManagement</controlURL> 127 <eventSubURL>/event?LANHostConfigManagement</eventSubURL> 128 </service> 129 </serviceList> 130 </device> 131 </deviceList> 132 <presentationURL>http://listenaddr<presentationurl> 133 </device> 134 </root> 135 `, 136 //对GetNatrSipstatus调用的响应。这个 137 //特定的实现有一个bug,其中元素 138 //U内:GetNatrSipstatusResponse不正确 139 //命名空间。 140 "POST /control?WANIPConnection": ` 141 <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/“s:encodingstyle=”http://schemas.xmlsoap.org/soap/encoding/“> 142 <s:Body> 143 <u:GetNATRSIPStatusResponse xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1"> 144 <NewRSIPAvailable>0</NewRSIPAvailable> 145 <NewNATEnabled>1</NewNATEnabled> 146 </u:GetNATRSIPStatusResponse> 147 </s:Body> 148 </s:Envelope> 149 `, 150 }, 151 } 152 if err := dev.listen(); err != nil { 153 t.Skipf("cannot listen: %v", err) 154 } 155 dev.serve() 156 defer dev.close() 157 158 //尝试发现假设备。 159 discovered := discoverUPnP() 160 if discovered == nil { 161 t.Fatalf("not discovered") 162 } 163 upnp, _ := discovered.(*upnp) 164 if upnp.service != "IGDv1-IP1" { 165 t.Errorf("upnp.service mismatch: got %q, want %q", upnp.service, "IGDv1-IP1") 166 } 167 wantURL := "http://“+dev.listener.addr().string()+”/internetgatewaydevice.xml“ 168 if upnp.dev.URLBaseStr != wantURL { 169 t.Errorf("upnp.dev.URLBaseStr mismatch: got %q, want %q", upnp.dev.URLBaseStr, wantURL) 170 } 171 } 172 173 //Fakeigd将自己呈现为一个可发现的UPNP设备,它发送 174 //对httpu和http请求的屏蔽响应。 175 type fakeIGD struct { 176 t *testing.T //用于测井 177 178 listener net.Listener 179 mcastListener *net.UDPConn 180 181 //这应该是一个完整的HTTP响应(包括头)。 182 //它作为对任何SSPD包的响应发送。任何情况 183 //将“listenaddr”的替换为实际的TCP侦听 184 //HTTP服务器的地址。 185 ssdpResp string 186 //这个应该包含所有请求的XML有效负载 187 //进行。键包含方法和路径,例如“get/foo/bar”。 188 //与ssdprep一样,“listenaddr”替换为tcp 189 //听地址。 190 httpResps map[string]string 191 } 192 193 //处理程序 194 func (dev *fakeIGD) ServeMessage(r *http.Request) { 195 dev.t.Logf(`HTTPU request %s %s`, r.Method, r.RequestURI) 196 conn, err := net.Dial("udp4", r.RemoteAddr) 197 if err != nil { 198 fmt.Printf("reply Dial error: %v", err) 199 return 200 } 201 defer conn.Close() 202 io.WriteString(conn, dev.replaceListenAddr(dev.ssdpResp)) 203 } 204 205 //http处理程序 206 func (dev *fakeIGD) ServeHTTP(w http.ResponseWriter, r *http.Request) { 207 if resp, ok := dev.httpResps[r.Method+" "+r.RequestURI]; ok { 208 dev.t.Logf(`HTTP request "%s %s" --> %d`, r.Method, r.RequestURI, 200) 209 io.WriteString(w, dev.replaceListenAddr(resp)) 210 } else { 211 dev.t.Logf(`HTTP request "%s %s" --> %d`, r.Method, r.RequestURI, 404) 212 w.WriteHeader(http.StatusNotFound) 213 } 214 } 215 216 func (dev *fakeIGD) replaceListenAddr(resp string) string { 217 return strings.Replace(resp, "{{listenAddr}}", dev.listener.Addr().String(), -1) 218 } 219 220 func (dev *fakeIGD) listen() (err error) { 221 if dev.listener, err = net.Listen("tcp", "127.0.0.1:0"); err != nil { 222 return err 223 } 224 laddr := &net.UDPAddr{IP: net.ParseIP("239.255.255.250"), Port: 1900} 225 if dev.mcastListener, err = net.ListenMulticastUDP("udp", nil, laddr); err != nil { 226 dev.listener.Close() 227 return err 228 } 229 return nil 230 } 231 232 func (dev *fakeIGD) serve() { 233 go httpu.Serve(dev.mcastListener, dev) 234 go http.Serve(dev.listener, dev) 235 } 236 237 func (dev *fakeIGD) close() { 238 dev.mcastListener.Close() 239 dev.listener.Close() 240 } 241