//------------------------------------------------ Game Server Request Proxy
func GSProxy(hostid int32, reader *packet.Packet) (ret []byte) {
	defer helper.PrintPanicStack()

	// read protocol number
	b, err := reader.ReadS16()
	if err != nil {
		log.Println("read protocol error")
		return
	}

	// get handler
	handle := protos.ProtoHandler[b]
	if handle == nil {
		log.Println("service not bind", b)
		return
	}

	// call handler
	start := time.Now()
	ret = handle(hostid, reader)
	end := time.Now()
	log.Printf("code: %v %v TIME:%v\n", b, protos.RCode[b], end.Sub(start))

	return ret
}
Exemple #2
0
//----------------------------------------------- Start Agent when a client is connected
func StartAgent(sess *Session, in chan []byte, out *Buffer) {
	wg.Add(1)
	defer wg.Done()
	defer helper.PrintPanicStack()

	// init session
	sess.MQ = make(chan IPCObject, DEFAULT_MQ_SIZE)
	sess.ConnectTime = time.Now()
	sess.LastPacketTime = time.Now()

	// custom-sec timer, 60-sec
	custom_timer := make(chan int32, 1)
	timer.Add(-1, time.Now().Unix()+CUSTOM_TIMER, custom_timer)

	// cleanup work
	defer func() {
		close_work(sess)
	}()

	// the main message loop
	for {
		select {
		case msg, ok := <-in: // network protocol
			if !ok {
				return
			}

			sess.PacketTime = time.Now()
			if result := UserRequestProxy(sess, msg); result != nil {
				err := out.Send(result)
				if err != nil {
					helper.ERR("cannot send to client", err)
					return
				}
			}
			sess.LastPacketTime = sess.PacketTime
			sess.PacketCount++ // packet count
		case msg := <-sess.MQ: // internal IPC
			if result := IPCRequestProxy(sess, &msg); result != nil {
				err := out.Send(result)
				if err != nil {
					helper.ERR("cannot send ipc response", err)
					return
				}
			}
		case <-custom_timer: // 60-sec timer
			timer_work(sess)
			timer.Add(-1, time.Now().Unix()+CUSTOM_TIMER, custom_timer)
		case <-die:
			sess.Flag |= SESS_KICKED_OUT
		}

		// is the session been kicked out
		if sess.Flag&SESS_KICKED_OUT != 0 {
			return
		}
	}
}
Exemple #3
0
func HandleRequest(hostid int32, reader *packet.Packet, output chan []byte) {
	defer helper.PrintPanicStack()

	seqid, err := reader.ReadU64() // read seqid
	if err != nil {
		log.Println("Read Sequence Id failed.", err)
		return
	}

	b, err := reader.ReadS16()
	if err != nil {
		log.Println("read protocol error")
		return
	}

	handle := ProtoHandler[b]
	if handle != nil {
		ret := handle(hostid, reader)
		if len(ret) != 0 {
			helper.SendChan(seqid, ret, output)
		}
	}
}
Exemple #4
0
//----------------------------------------------- Start Agent when a client is connected
func StartAgent(in chan []byte, conn net.Conn) {
	defer helper.PrintPanicStack()

	config := cfg.Get()
	if config["profile"] == "true" {
		helper.SetMemProfileRate(1)
		defer func() {
			helper.GC()
			helper.DumpHeap()
			helper.PrintGCSummary()
		}()
	}

	var sess Session
	sess.IP = net.ParseIP(conn.RemoteAddr().String())
	sess.MQ = make(chan IPCObject, DEFAULT_MQ_SIZE)
	sess.ConnectTime = time.Now()
	sess.LastPacketTime = time.Now().Unix()
	sess.KickOut = false

	// standard 1-sec timer
	std_timer := make(chan int32, 1)
	timer.Add(1, time.Now().Unix()+1, std_timer)

	// write buffer
	bufctrl := make(chan bool)
	buf := NewBuffer(&sess, conn, bufctrl)
	go buf.Start()

	// max # of operartions allowed before flushing
	flush_ops, err := strconv.Atoi(config["flush_ops"])
	if err != nil {
		log.Println("cannot parse flush_ops from config", err)
		flush_ops = DEFAULT_FLUSH_OPS
	}

	// cleanup work
	defer func() {
		close_work(&sess)
		close(bufctrl)
	}()

	// the main message loop
	for {
		select {
		case msg, ok := <-in:
			if !ok {
				return
			}

			if result := UserRequestProxy(&sess, msg); result != nil {
				err := buf.Send(result)
				if err != nil {
					return
				}
			}
			sess.LastPacketTime = time.Now().Unix()

		case msg, ok := <-sess.MQ: // async
			if !ok {
				return
			}

			if result := IPCRequestProxy(&sess, &msg); result != nil {
				err := buf.Send(result)
				if err != nil {
					return
				}
			}

		case <-std_timer:
			timer_work(&sess)
			if session_timeout(&sess) {
				return
			}
			timer.Add(1, time.Now().Unix()+1, std_timer)
		}

		// 持久化逻辑#1: 超过一定的操作数量,刷入数据库
		if sess.OpCount > flush_ops {
			_flush(&sess)
		}

		// 是否被逻辑踢出
		if sess.KickOut {
			return
		}
	}
}