コード例 #1
0
ファイル: dispatch.go プロジェクト: ducktsmt/snova-gae
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
}
コード例 #2
0
ファイル: c4s.go プロジェクト: juju2013/gsnova
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
		}
	}
}
コード例 #3
0
ファイル: dispatch.go プロジェクト: ducktsmt/snova-gae
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
}
コード例 #4
0
ファイル: c4.go プロジェクト: juju2013/gsnova
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
}
コード例 #5
0
ファイル: ssh.go プロジェクト: juju2013/gsnova
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
}
コード例 #6
0
ファイル: c4s.go プロジェクト: juju2013/gsnova
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
}
コード例 #7
0
ファイル: gae_tunnel.go プロジェクト: juju2013/gsnova
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
}
コード例 #8
0
ファイル: gae_tunnel.go プロジェクト: juju2013/gsnova
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
}
コード例 #9
0
ファイル: forward.go プロジェクト: juju2013/gsnova
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
}
コード例 #10
0
ファイル: google.go プロジェクト: juju2013/gsnova
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
}
コード例 #11
0
ファイル: gae.go プロジェクト: juju2013/gsnova
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)
}
コード例 #12
0
ファイル: gae.go プロジェクト: juju2013/gsnova
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
}
コード例 #13
0
ファイル: c4.go プロジェクト: juju2013/gsnova
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
}