func HandleEvent(tags *event.EventHeaderTags, ev event.Event, ctx appengine.Context, sender EventSendService) error { res, err := handleRecvEvent(tags, ev, ctx) if nil != err { ctx.Errorf("Failed to handle event[%d:%d] for reason:%v", ev.GetType(), ev.GetVersion(), err) return err } if nil == res { var empty bytes.Buffer sender.Send(&empty) return nil } res.SetHash(ev.GetHash()) compressType := Cfg.CompressType if httpres, ok := res.(*event.HTTPResponseEvent); ok { v := httpres.GetHeader("Content-Type") if len(v) > 0 && Cfg.CompressType != event.COMPRESSOR_NONE { if isContentTypeInCompressFilter(v) { compressType = event.COMPRESSOR_NONE } } } x := new(event.CompressEvent) x.SetHash(ev.GetHash()) x.CompressType = compressType x.Ev = res y := new(event.EncryptEvent) y.SetHash(ev.GetHash()) y.EncryptType = Cfg.EncryptType y.Ev = x var buf bytes.Buffer tags.Encode(&buf) event.EncodeEvent(&buf, y) sender.Send(&buf) return nil }
func processRecvEvent(ev event.Event, user string) { serv := getProxySession(user, ev.GetHash()) ev = event.ExtractEvent(ev) switch ev.GetType() { case event.EVENT_USER_LOGIN_TYPE: req := ev.(*event.UserLoginEvent) closeProxyUser(req.User) case event.EVENT_TCP_CONNECTION_TYPE: req := ev.(*event.SocketConnectionEvent) if req.Status == event.TCP_CONN_CLOSED { deleteProxySession(user, ev.GetHash()) } case event.HTTP_REQUEST_EVENT_TYPE: req := ev.(*event.HTTPRequestEvent) err := serv.initConn(req.Method, req.GetHeader("Host")) if nil != err { log.Printf("Failed to init conn for reason:%v\n", err) } if strings.EqualFold(req.Method, "Connect") { res := &event.TCPChunkEvent{} res.SetHash(ev.GetHash()) if nil == serv.conn { res.Content = []byte("HTTP/1.1 503 ServiceUnavailable\r\n\r\n") } else { res.Content = []byte("HTTP/1.1 200 OK\r\n\r\n") //log.Printf("Return established.\n") } offerSendEvent(res, user) } else { if nil != serv.conn { err := req.Write(serv.conn) if nil != err { log.Printf("Failed to write http request %v\n", err) deleteProxySession(user, serv.id) return } } else { res := &event.TCPChunkEvent{} res.SetHash(ev.GetHash()) res.Content = []byte("HTTP/1.1 503 ServiceUnavailable\r\n\r\n") offerSendEvent(res, serv.user) } } case event.EVENT_TCP_CHUNK_TYPE: if nil == serv.conn { //log.Printf("[%d]No session conn %d", ev.GetHash()) deleteProxySession(serv.user, serv.id) return } chunk := ev.(*event.TCPChunkEvent) //.Printf("[%d]Chunk has %d", ev.GetHash(), len(chunk.Content)) _, err := serv.conn.Write(chunk.Content) if nil != err { log.Printf("Failed to write chunk %v\n", err) serv.closeSession() return } } }
func handleRecvEvent(tags *event.EventHeaderTags, ev event.Event, ctx appengine.Context) (event.Event, error) { var res event.Event switch ev.GetType() { case event.HTTP_REQUEST_EVENT_TYPE: res = Fetch(ctx, ev.(*event.HTTPRequestEvent)) case event.AUTH_REQUEST_EVENT_TYPE: auth := ev.(*event.AuthRequestEvent) ares := new(event.AuthResponseEvent) if isValidUser(auth.User, auth.Passwd) { ares.Token = generateRandomString(8) } else { ares.Error = "Invalid User/Passwd" } res = ares //res = Auth(ctx, ev.(*event.AuthRequestEvent)) case event.SHARE_APPID_EVENT_TYPE: res = HandleShareEvent(ctx, ev.(*event.ShareAppIDEvent)) case event.REQUEST_SHARED_APPID_EVENT_TYPE: res = RetrieveAppIds(ctx) case event.EVENT_TCP_CHUNK_TYPE: res = TunnelWrite(ctx, tags, ev.(*event.TCPChunkEvent)) case event.EVENT_TCP_CONNECTION_TYPE: res = TunnelSocketConnection(ctx, tags, ev.(*event.SocketConnectionEvent)) case event.EVENT_SOCKET_CONNECT_WITH_DATA_TYPE: res = TunnelConn(ctx, tags, ev.(*event.SocketConnectWithDataEvent)) case event.EVENT_SOCKET_READ_TYPE: res = TunnelRead(ctx, tags, ev.(*event.SocketReadEvent)) } return res, nil }
func wrapC4RequestEvent(ev event.Event) event.Event { var encrypt event.EncryptEventV2 encrypt.SetHash(ev.GetHash()) encrypt.EncryptType = c4_cfg.Encrypter encrypt.Ev = ev return &encrypt }
func (conn *SSHConnection) Request(sess *SessionConnection, ev event.Event) (err error, res event.Event) { f := func(local, remote net.Conn, ch chan int) { io.Copy(remote, local) local.Close() remote.Close() ch <- 1 } switch ev.GetType() { case event.HTTP_REQUEST_EVENT_TYPE: req := ev.(*event.HTTPRequestEvent) if err := conn.initProxyConn(req.RawReq.Host, sess.Type == HTTPS_TUNNEL); nil != err { return err, nil } if sess.Type == HTTPS_TUNNEL { log.Printf("Session[%d]Request %s\n", req.GetHash(), util.GetURLString(req.RawReq, true)) sess.LocalRawConn.Write([]byte("HTTP/1.1 200 Connection established\r\n\r\n")) ch := make(chan int) go f(sess.LocalRawConn, conn.proxy_conn, ch) go f(conn.proxy_conn, sess.LocalRawConn, ch) <-ch <-ch conn.Close() sess.State = STATE_SESSION_CLOSE } else { log.Printf("Session[%d]Request %s\n", req.GetHash(), util.GetURLString(req.RawReq, true)) err := req.RawReq.Write(conn.proxy_conn) if nil != err { conn.ssh_conn.CloseConn() return err, nil } conn.proxy_conn.SetReadDeadline(time.Now().Add(10 * time.Second)) resp, err := http.ReadResponse(conn.proxy_conn_reader, req.RawReq) if err != nil { conn.ssh_conn.CloseConn() return err, nil } var zero time.Time conn.proxy_conn.SetReadDeadline(zero) err = resp.Write(sess.LocalRawConn) if nil == err { err = resp.Body.Close() } if nil != err || !util.IsResponseKeepAlive(resp) || !util.IsRequestKeepAlive(req.RawReq) { sess.LocalRawConn.Close() conn.Close() sess.State = STATE_SESSION_CLOSE } else { sess.State = STATE_RECV_HTTP } } default: } return nil, nil }
func (c4 *C4RemoteSession) handleTunnelResponse(conn *SessionConnection, ev event.Event) error { switch ev.GetType() { case event.EVENT_TCP_CONNECTION_TYPE: cev := ev.(*event.SocketConnectionEvent) if cev.Status == event.TCP_CONN_CLOSED { log.Printf("Session[%d]Remote %s connection closed, current proxy addr:%s\n", conn.SessionID, cev.Addr, c4.remote_proxy_addr) if c4.remote_proxy_addr == cev.Addr { c4.closed = true conn.Close() c4.Close() return io.EOF } } case event.EVENT_TCP_CHUNK_TYPE: chunk := ev.(*event.TCPChunkEvent) log.Printf("Session[%d]Handle TCP chunk[%d-%d]\n", conn.SessionID, chunk.Sequence, len(chunk.Content)) n, err := conn.LocalRawConn.Write(chunk.Content) if nil != err { log.Printf("[%d]Failed to write chunk[%d-%d] to local client:%v.\n", ev.GetHash(), chunk.Sequence, len(chunk.Content), err) conn.Close() c4.Close() return err } if n < len(chunk.Content) { log.Printf("[%d]Less data written[%d-%d] to local client.\n", ev.GetHash(), n, len(chunk.Content)) } chunk.Content = nil case event.HTTP_RESPONSE_EVENT_TYPE: log.Printf("Session[%d]Handle HTTP Response event with range task:%p\n", conn.SessionID, c4.rangeWorker) res := ev.(*event.HTTPResponseEvent) httpres := res.ToResponse() //log.Printf("Session[%d]Recv res %d %v\n", ev.GetHash(), httpres.StatusCode, httpres.Header) if nil != c4.rangeWorker { httpWriter := func(preq *http.Request) error { return c4.writeHttpRequest(preq) } pres, err := c4.rangeWorker.ProcessAyncResponse(httpres, httpWriter) if nil == err { if nil != pres { //log.Printf("Session[%d] %d %v\n", ev.GetHash(), pres.StatusCode, pres.Header) go pres.Write(conn.LocalRawConn) } else { //log.Printf("Session[%d]NULLL\n", ev.GetHash()) } } else { log.Printf("####%v\n", err) c4.Close() conn.Close() } } else { httpres.Write(conn.LocalRawConn) } default: log.Printf("Unexpected event type:%d\n", ev.GetType()) } return nil }
func offerSendEvent(ev event.Event, user string) { switch ev.GetType() { case event.EVENT_TCP_CHUNK_TYPE: var compress event.CompressEventV2 compress.SetHash(ev.GetHash()) compress.Ev = ev compress.CompressType = event.COMPRESSOR_SNAPPY ev = &compress } var encrypt event.EncryptEventV2 encrypt.SetHash(ev.GetHash()) encrypt.EncryptType = event.ENCRYPTER_SE1 encrypt.Ev = ev ev = &encrypt idx := int(ev.GetHash()) % len(send_evs[user]) send_evs[user][idx] <- ev }
func (gae *GAEHttpConnection) handleTunnelResponse(conn *SessionConnection, ev event.Event) error { switch ev.GetType() { case event.EVENT_TCP_CONNECTION_TYPE: cev := ev.(*event.SocketConnectionEvent) log.Printf("[%d]Recv conn event:%v.\n", ev.GetHash(), cev.Status) if cev.Status == event.TCP_CONN_CLOSED { if gae.tunnel_remote_addr == cev.Addr { conn.Close() } } case event.EVENT_TCP_CHUNK_TYPE: chunk := ev.(*event.TCPChunkEvent) _, err := conn.LocalRawConn.Write(chunk.Content) if nil != err { log.Printf("[%d]Failed to write data to local client:%v.\n", ev.GetHash(), err) conn.Close() } default: log.Printf("Unexpected event type:%d\n", ev.GetType()) } return nil }
func (gae *GAEHttpConnection) requestOverTunnel(conn *SessionConnection, ev event.Event) (err error, res event.Event) { if nil == gae.tunnelChannel { gae.tunnelChannel = make(chan event.Event) go gae.tunnel_write(conn) //go gae.tunnel_read(conn) } switch ev.GetType() { case event.HTTP_REQUEST_EVENT_TYPE: req := ev.(*event.HTTPRequestEvent) default_port := "80" if strings.EqualFold(req.RawReq.Method, "CONNECT") { conn.State = STATE_RECV_HTTP_CHUNK default_port = "443" } else { conn.State = STATE_RECV_HTTP } log.Printf("Session[%d]Request %s\n", req.GetHash(), util.GetURLString(req.RawReq, true)) scd := &event.SocketConnectWithDataEvent{} scd.Content, err = httputil.DumpRequest(req.RawReq, true) if nil != err { log.Printf("Session[%d]Failed to encode request to bytes", req.GetHash()) return } scd.SetHash(ev.GetHash()) scd.Net = "tcp" scd.Addr = req.RawReq.Host if !strings.Contains(scd.Addr, ":") { scd.Addr = net.JoinHostPort(req.RawReq.Host, default_port) } gae.tunnel_remote_addr = scd.Addr gae.tunnelChannel <- scd case event.HTTP_CHUNK_EVENT_TYPE: chunk := ev.(*event.HTTPChunkEvent) tcp_chunk := &event.TCPChunkEvent{Content: chunk.Content} tcp_chunk.SetHash(ev.GetHash()) gae.tunnelChannel <- tcp_chunk conn.State = STATE_RECV_HTTP_CHUNK } return nil, nil }
func (auto *ForwardConnection) Request(conn *SessionConnection, ev event.Event) (err error, res event.Event) { f := func(local, remote net.Conn) { n, err := io.Copy(remote, local) if nil != err { local.Close() remote.Close() } auto.forwardChan <- int(n) } //L: auto.closed = false switch ev.GetType() { case event.HTTP_REQUEST_EVENT_TYPE: req := ev.(*event.HTTPRequestEvent) addr := req.RawReq.Host if !strings.Contains(addr, ":") { if conn.Type == HTTPS_TUNNEL { addr = net.JoinHostPort(addr, "443") } else { addr = net.JoinHostPort(addr, "80") } } err = auto.initForwardConn(addr, conn.Type == HTTPS_TUNNEL) if nil != err { log.Printf("Failed to connect forward address for %s.\n", addr) return err, nil } if conn.Type == HTTPS_TUNNEL { log.Printf("Session[%d]Request %s\n", req.GetHash(), util.GetURLString(req.RawReq, true)) if !auto.manager.overProxy || strings.HasPrefix(auto.conn_url.Scheme, "socks") { conn.LocalRawConn.Write([]byte("HTTP/1.1 200 Connection established\r\n\r\n")) } else { auto.writeHttpRequest(req.RawReq) } go f(conn.LocalRawConn, auto.forward_conn) go f(auto.forward_conn, conn.LocalRawConn) atomic.AddInt32(&total_forwared_routine_num, 2) <-auto.forwardChan <-auto.forwardChan atomic.AddInt32(&total_forwared_routine_num, -2) auto.Close() conn.State = STATE_SESSION_CLOSE } else { log.Printf("Session[%d]Request %s\n", req.GetHash(), util.GetURLString(req.RawReq, true)) if auto.manager.inject_crlf { log.Printf("Session[%d]Inject CRLF for %s", ev.GetHash(), req.RawReq.Host) auto.forward_conn.Write(CRLFs) } err := auto.writeHttpRequest(req.RawReq) if nil != err { return err, nil } if common.DebugEnable { var tmp bytes.Buffer req.RawReq.Write(&tmp) log.Printf("Session[%d]Send request \n%s\n", ev.GetHash(), tmp.String()) } resp, err := http.ReadResponse(auto.buf_forward_conn, req.RawReq) if err != nil { log.Printf("Session[%d]Recv response with error %v\n", ev.GetHash(), err) return err, nil } //log.Printf("Session[%d]Recv response %v\n", ev.GetHash(), resp) err = resp.Write(conn.LocalRawConn) resp.Body.Close() if common.DebugEnable { var tmp bytes.Buffer resp.Write(&tmp) log.Printf("Session[%d]Recv response \n%s\n", ev.GetHash(), tmp.String()) } if nil != err || !util.IsResponseKeepAlive(resp) || !util.IsRequestKeepAlive(req.RawReq) { conn.LocalRawConn.Close() auto.Close() conn.State = STATE_SESSION_CLOSE } else { conn.State = STATE_RECV_HTTP } } default: } return nil, nil }
func (google *GoogleConnection) Request(conn *SessionConnection, ev event.Event) (err error, res event.Event) { f := func(local, remote net.Conn, ch chan int) { io.Copy(remote, local) ch <- 1 local.Close() remote.Close() } //L: switch ev.GetType() { case event.HTTP_REQUEST_EVENT_TYPE: req := ev.(*event.HTTPRequestEvent) if conn.Type == HTTPS_TUNNEL { var proxyConn net.Conn if len(googleLocalProxy) > 0 { proxyURL, _ := url.Parse(googleLocalProxy) proxyConn, err = net.Dial("tcp", proxyURL.Host) addr, _ := getLocalHostMapping(GOOGLE_HTTPS) connreq := req.RawReq connreq.Host = addr if nil == err { connreq.Write(proxyConn) } } else { addr := getGoogleHostport(true) proxyConn, err = net.DialTimeout("tcp", addr, connTimeoutSecs) if nil != err { //try again addr = getGoogleHostport(true) proxyConn, err = net.DialTimeout("tcp", addr, connTimeoutSecs) } } log.Printf("Session[%d]Request %s\n", req.GetHash(), util.GetURLString(req.RawReq, true)) if nil == err { if len(googleLocalProxy) > 0 { } else { conn.LocalRawConn.Write([]byte("HTTP/1.1 200 Connection established\r\n\r\n")) } } else { return fmt.Errorf("No google proxy reachable:%v", err), nil } ch := make(chan int) go f(conn.LocalRawConn, proxyConn, ch) go f(proxyConn, conn.LocalRawConn, ch) atomic.AddInt32(&total_google_routine_num, 2) <-ch <-ch atomic.AddInt32(&total_google_routine_num, -2) proxyConn.Close() google.Close() conn.State = STATE_SESSION_CLOSE } else { google.proxyAddr = req.RawReq.Host log.Printf("Session[%d]Request %s\n", req.GetHash(), util.GetURLString(req.RawReq, true)) req.RawReq.URL.Scheme = "http" req.RawReq.RequestURI = "" var resp *http.Response tryProxy := func() (*http.Response, error) { if google.manager == httpGoogleManager { return httpGoogleClient.Do(req.RawReq) } return httpsGoogleClient.Do(req.RawReq) } resp, err = tryProxy() if nil != err && strings.EqualFold(req.Method, "GET") { //try proxy again resp, err = tryProxy() } if nil != err { var tmp bytes.Buffer req.RawReq.Write(&tmp) log.Printf("Session[%d]Request error:%v\n%s\n", req.GetHash(), err, tmp.String()) return err, nil } err = resp.Write(conn.LocalRawConn) if nil != err || !util.IsResponseKeepAlive(resp) || !util.IsRequestKeepAlive(req.RawReq) { conn.LocalRawConn.Close() conn.State = STATE_SESSION_CLOSE } else { log.Printf("Session[%d]Res %d %v\n", req.GetHash(), resp.StatusCode, resp.Header) conn.State = STATE_RECV_HTTP } } default: } return nil, nil }
func (gae *GAEHttpConnection) Request(conn *SessionConnection, ev event.Event) (err error, res event.Event) { gae.closed = false gae.sess = conn if gae.over_tunnel { return gae.requestOverTunnel(conn, ev) } if nil == gae.gaeAuth { gae.gaeAuth = gae.manager.auths.Select().(*GAEAuth) } if ev.GetType() == event.HTTP_REQUEST_EVENT_TYPE { httpreq := ev.(*event.HTTPRequestEvent) if strings.EqualFold(httpreq.Method, "CONNECT") { // //try https over tunnel // if gae.gaeAuth.support_tunnel { // gae.over_tunnel = true // return gae.requestOverTunnel(conn, ev) // } log.Printf("Session[%d]Request %s\n", httpreq.GetHash(), util.GetURLString(httpreq.RawReq, true)) conn.LocalRawConn.Write([]byte("HTTP/1.1 200 Connection established\r\n\r\n")) tlscfg, err := common.TLSConfig(httpreq.GetHeader("Host")) if nil != err { return err, nil } conn.LocalRawConn = tls.Server(conn.LocalRawConn, tlscfg) conn.LocalBufferConn = bufio.NewReader(conn.LocalRawConn) conn.State = STATE_RECV_HTTP conn.Type = HTTPS_TUNNEL return nil, nil } else { if httpreq.Content.Len() == 0 { body := make([]byte, httpreq.RawReq.ContentLength) io.ReadFull(httpreq.RawReq.Body, body) httpreq.Content.Write(body) } scheme := "http://" if conn.Type == HTTPS_TUNNEL { scheme = "https://" } if !strings.HasPrefix(httpreq.Url, scheme) { httpreq.Url = scheme + httpreq.RawReq.Host + httpreq.Url } log.Printf("Session[%d]Request %s\n", httpreq.GetHash(), util.GetURLString(httpreq.RawReq, true)) var httpres *http.Response if strings.EqualFold(httpreq.Method, "GET") { if hostPatternMatched(gae_cfg.InjectRange, httpreq.RawReq.Host) || gae.inject_range { //conn.State = STATE_RECV_HTTP gae.doRangeFetch(httpreq.RawReq, nil) return nil, nil } } err, res = gae.requestEvent(gaeHttpClient, conn, ev) if nil != err { //try again err, res = gae.requestEvent(gaeHttpClient, conn, ev) } if nil != err || nil == res { return } conn.State = STATE_RECV_HTTP httpresev := res.(*event.HTTPResponseEvent) if httpresev.Status == 403 { log.Printf("ERROR:Session[%d]Request %s %s is forbidon\n", httpreq.GetHash(), httpreq.Method, httpreq.RawReq.Host) } httpres, err = gae.handleHttpRes(conn, httpreq, httpresev) // if nil != httpres { // log.Printf("Session[%d]Response %d %v\n", httpreq.GetHash(), httpres.StatusCode, httpres.Header) // } if nil != err || !util.IsResponseKeepAlive(httpres) || !util.IsRequestKeepAlive(httpreq.RawReq) { conn.LocalRawConn.Close() conn.State = STATE_SESSION_CLOSE gae.Close() } return err, nil } } return gae.requestEvent(gaeHttpClient, conn, ev) }
func (gae *GAEHttpConnection) requestEvent(client *http.Client, conn *SessionConnection, ev event.Event) (err error, res event.Event) { auth := gae.gaeAuth if nil == auth { auth = gae.manager.auths.Select().(*GAEAuth) } domain := auth.appid + ".appspot.com" if strings.Contains(auth.appid, ".") { domain = auth.appid } addr, _ := getLocalHostMapping(domain) scheme := MODE_HTTP if strings.EqualFold(MODE_HTTPS, gae_cfg.ConnectionMode) { scheme = MODE_HTTPS } var buf bytes.Buffer var tags event.EventHeaderTags tags.Token = auth.token tags.Encode(&buf) if ev.GetType() == event.HTTP_REQUEST_EVENT_TYPE { var compress event.CompressEvent compress.SetHash(ev.GetHash()) compress.Ev = ev compress.CompressType = gae_cfg.Compressor var encrypt event.EncryptEvent encrypt.SetHash(ev.GetHash()) encrypt.EncryptType = gae_cfg.Encrypter encrypt.Ev = &compress event.EncodeEvent(&buf, &encrypt) } else { var encrypt event.EncryptEvent encrypt.SetHash(ev.GetHash()) encrypt.EncryptType = gae_cfg.Encrypter encrypt.Ev = ev event.EncodeEvent(&buf, &encrypt) } req := &http.Request{ Method: "POST", URL: &url.URL{Scheme: scheme, Host: addr, Path: "/invoke"}, ProtoMajor: 1, ProtoMinor: 1, Host: addr, Header: make(http.Header), Body: ioutil.NopCloser(&buf), ContentLength: int64(buf.Len()), } if len(gae_cfg.UA) > 0 { req.Header.Set("User-Agent", gae_cfg.UA) } req.Close = false req.Header.Set("Connection", "keep-alive") req.Header.Set("Content-Type", "image/jpeg") var response *http.Response response, err = gaeHttpClient.Do(req) if nil != err { log.Printf("Failed to request data from GAE:%s for:%s\n", domain, err.Error()) return err, nil } else { if response.StatusCode != 200 { log.Printf("Session[%d]Invalid response:%d\n", ev.GetHash(), response.StatusCode) return fmt.Errorf("Invalid response:%d", response.StatusCode), nil } else { var buf bytes.Buffer n, err := io.Copy(&buf, response.Body) if int64(n) < response.ContentLength { return fmt.Errorf("No sufficient space in body."), nil } if nil != err { return err, nil } response.Body.Close() if !tags.Decode(&buf) { return fmt.Errorf("Failed to decode event tag"), nil } err, res = event.DecodeEvent(&buf) if nil == err { res = event.ExtractEvent(res) } return err, res } } return nil, nil }
func wsOfferEvent(server string, ev event.Event) { chs := c4WsChannelTable[server] index := int(ev.GetHash()) % len(chs) chs[index] <- wrapC4RequestEvent(ev) }
func (c4 *C4RemoteSession) Request(conn *SessionConnection, ev event.Event) (err error, res event.Event) { c4.sess = conn if len(c4.server) == 0 { c4.server = c4.manager.servers.Select().(string) } c4.sess = conn c4.closed = false setC4SessionTable(c4) switch ev.GetType() { case event.HTTP_REQUEST_EVENT_TYPE: req := ev.(*event.HTTPRequestEvent) default_port := "80" if strings.EqualFold(req.RawReq.Method, "CONNECT") { conn.State = STATE_RECV_HTTP_CHUNK default_port = "443" } else { conn.State = STATE_RECV_HTTP } log.Printf("Session[%d] Request %s\n", req.GetHash(), util.GetURLString(req.RawReq, true)) if nil != err { log.Printf("Session[%d]Failed to encode request to bytes", req.GetHash()) return } remote_addr := req.RawReq.Host if !strings.Contains(remote_addr, ":") { remote_addr = net.JoinHostPort(req.RawReq.Host, default_port) } if strings.Contains(req.Url, "http://") { req.Url = req.Url[7+len(req.RawReq.Host):] } c4.rangeWorker = nil c4.remote_proxy_addr = remote_addr if strings.EqualFold(req.Method, "GET") && c4_cfg.MultiRangeFetchEnable { if c4.injectRange || hostPatternMatched(c4_cfg.InjectRange, req.RawReq.Host) { if nil == c4.doRangeFetch(req.RawReq) { return nil, nil } } } c4.offerRequestEvent(req) rest := req.RawReq.ContentLength tmpbuf := make([]byte, 8192) for rest > 0 { n, err := req.RawReq.Body.Read(tmpbuf) if nil == err { rest = rest - int64(n) chunk := &event.TCPChunkEvent{Content: tmpbuf[0:n]} chunk.SetHash(req.GetHash()) c4.offerRequestEvent(chunk) } else { break } } req.RawReq.Body.Close() case event.HTTP_CHUNK_EVENT_TYPE: //log.Printf("Session[%d]Offer chunk\n", conn.SessionID) chunk := ev.(*event.HTTPChunkEvent) tcp_chunk := &event.TCPChunkEvent{Content: chunk.Content} tcp_chunk.SetHash(ev.GetHash()) c4.offerRequestEvent(tcp_chunk) conn.State = STATE_RECV_HTTP_CHUNK } return nil, nil }