| 171 | } |
| 172 | |
| 173 | func (proxy *HTTPProxy) Dial() (net.Conn, error) { |
| 174 | var SERVER_ERROR = errors.New("proxy server error") |
| 175 | var RESPONSE_TOO_LARGE = errors.New("http connect response is too large > 40KB") |
| 176 | |
| 177 | proxyConn, err := net.Dial("tcp", proxy.ProxyAddr) |
| 178 | if err != nil { |
| 179 | return proxyConn, SERVER_ERROR |
| 180 | } |
| 181 | |
| 182 | var http_proxy_payload_template = "CONNECT %s HTTP/1.1\r\n" + |
| 183 | "Content-Length: 0\r\n\r\n" |
| 184 | var payload = fmt.Sprintf(http_proxy_payload_template, proxy.PeerAddr) |
| 185 | var buf = []byte(payload) |
| 186 | |
| 187 | proxyConn.Write(buf) |
| 188 | |
| 189 | var done = "\r\n\r\n" |
| 190 | var success = "HTTP/1.1 200" |
| 191 | var begin = 0 |
| 192 | var resultBuf = make([]byte, 40960) |
| 193 | |
| 194 | for { |
| 195 | count, err := proxyConn.Read(resultBuf[begin:]) |
| 196 | if err != nil { |
| 197 | return proxyConn, SERVER_ERROR |
| 198 | } |
| 199 | |
| 200 | begin += count |
| 201 | if begin >= 40960 { |
| 202 | return proxyConn, RESPONSE_TOO_LARGE |
| 203 | } |
| 204 | |
| 205 | if string(resultBuf[begin-4:begin]) == done { |
| 206 | if string(resultBuf[:len(success)]) == success { |
| 207 | return proxyConn, nil |
| 208 | } |
| 209 | return proxyConn, SERVER_ERROR |
| 210 | } |
| 211 | } |
| 212 | } |