func CheckTimeout(client *ClientRep) {
	defer func() {
		if r := recover(); r != nil {
			log.Debugf("got panic, will print stack")
			debug.PrintStack()
			panic(r)
		}
	}()
	interval := client.Mqtt.KeepAliveTimer
	client_id := client.ClientId
	ticker := time.NewTicker(time.Duration(interval) * time.Second)
	for {
		select {
		case <- ticker.C:
			now := time.Now().Unix()
			lastTimestamp := client.LastTime
			deadline := int64(float64(lastTimestamp) + float64(interval) * 1.5)
			if deadline < now {
				ForceDisconnect(client, G_clients_lock, SEND_WILL)
				log.Debugf("client(%s) is timeout, kicked out",
					client_id)
			} else {
				log.Debugf("client(%s) will be kicked out in %d seconds",
					client_id,
					deadline - now)
			}
		case <- client.Shuttingdown:
			log.Debugf("client(%s) is being shutting down, stopped timeout checker", client_id)
			return
		}
	}
}
/* Checking timeout
package mqtt
import (
	"net"
	log "github.com/cihub/seelog"
	"time"
	"sync"
	"fmt"
	"runtime/debug"
)
const (
	SEND_WILL = uint8(iota)
	DONT_SEND_WILL
)
func HandleConnect(mqtt *Mqtt, conn *net.Conn, client **ClientRep) {
	client_id := mqtt.ClientId
	log.Debugf("Hanling CONNECT, client id:(%s)", client_id)
	if len(client_id) > 23 {
		log.Debugf("client id(%s) is longer than 23, will send IDENTIFIER_REJECTED", client_id)
		SendConnack(IDENTIFIER_REJECTED, conn, nil)
		return
	}
	if mqtt.ProtocolName != "MQIsdp" || mqtt.ProtocolVersion != 3 {
		log.Debugf("ProtocolName(%s) and/or version(%d) not supported, will send UNACCEPTABLE_PROTOCOL_VERSION",
			mqtt.ProtocolName, mqtt.ProtocolVersion)
		SendConnack(UNACCEPTABLE_PROTOCOL_VERSION, conn, nil)
		return
	}
	G_clients_lock.Lock()
	client_rep, existed := G_clients[client_id]
	if existed {
		log.Debugf("%s existed, will close old connection", client_id)
		ForceDisconnect(client_rep, nil, DONT_SEND_WILL)
	} else {
		log.Debugf("Appears to be new client, will create ClientRep")
	}
	client_rep = CreateClientRep(client_id, conn, mqtt)
	G_clients[client_id] = client_rep
	G_clients_lock.Unlock()
	*client = client_rep
	go CheckTimeout(client_rep)
	log.Debugf("Timeout checker go-routine started")
	if !client_rep.Mqtt.ConnectFlags.CleanSession {
		DeliverOnConnection(client_id)
		subs := make(map[string]uint8)
		key := fmt.Sprintf("gossipd.client-subs.%s", client_id)
		G_redis_client.Fetch(key, &subs)
		client_rep.Subscriptions = subs
	} else {
		RemoveAllSubscriptionsOnConnect(client_id)
		empty := make(map[uint16]FlyingMessage)
		G_redis_client.SetFlyingMessagesForClient(client_id, &empty)
	}
	SendConnack(ACCEPTED, conn, client_rep.WriteLock)
	log.Debugf("New client is all set and CONNACK is sent")
}
func SendConnack(rc uint8, conn *net.Conn, lock *sync.Mutex) {
	resp := CreateMqtt(CONNACK)
	resp.ReturnCode = rc
	bytes, _ := Encode(resp)
	MqttSendToClient(bytes, conn, lock)
}
func HandlePublish(mqtt *Mqtt, conn *net.Conn, client **ClientRep) {
	if *client == nil {
		panic("client_resp is nil, that means we don't have ClientRep for this client sending PUBLISH")
		return
	}
	client_id := (*client).Mqtt.ClientId
	client_rep := *client
	client_rep.UpdateLastTime()
	topic := mqtt.TopicName
	payload := string(mqtt.Data)
	qos := mqtt.FixedHeader.QosLevel
	retain := mqtt.FixedHeader.Retain
	message_id := mqtt.MessageId
	timestamp := time.Now().Unix()
	log.Debugf("Handling PUBLISH, client_id: %s, topic:(%s), payload:(%s), qos=%d, retain=%t, message_id=%d",
		client_id, topic, payload, qos, retain, message_id)
	mqtt_msg := CreateMqttMessage(topic, payload, client_id, qos, message_id, timestamp, retain)
	msg_internal_id := mqtt_msg.InternalId
	log.Debugf("Created new MQTT message, internal id:(%s)", msg_internal_id)
	PublishMessage(mqtt_msg)
	if qos == 1 {
		SendPuback(message_id, conn, client_rep.WriteLock)
		log.Debugf("PUBACK sent to client(%s)", client_id)
	}
}
func SendPuback(msg_id uint16, conn *net.Conn, lock *sync.Mutex) {
	resp := CreateMqtt(PUBACK)
	resp.MessageId = msg_id
	bytes, _ := Encode(resp)
	MqttSendToClient(bytes, conn, lock)
}
func HandleSubscribe(mqtt *Mqtt, conn *net.Conn, client **ClientRep) {
	if *client == nil {
		panic("client_resp is nil, that means we don't have ClientRep for this client sending SUBSCRIBE")
		return
	}
	client_id := (*client).Mqtt.ClientId
	log.Debugf("Handling SUBSCRIBE, client_id: %s", client_id)
	client_rep := *client
	client_rep.UpdateLastTime()
	defer func() {
		G_subs_lock.Unlock()
		SendSuback(mqtt.MessageId, mqtt.Topics_qos, conn, client_rep.WriteLock)
	}()
	G_subs_lock.Lock()
	for i := 0; i < len(mqtt.Topics); i++ {
		topic := mqtt.Topics[i]
		qos := mqtt.Topics_qos[i]
		log.Debugf("will subscribe client(%s) to topic(%s) with qos=%d",
			client_id, topic, qos)
		subs := G_subs[topic]
		if subs == nil {
			log.Debugf("current subscription is the first client to topic:(%s)", topic)
			subs = make(map[string]uint8)
			G_subs[topic] = subs
		}
		subs[client_id] = qos
		client_rep.Subscriptions[topic] = qos
		if !client_rep.Mqtt.ConnectFlags.CleanSession {
			key := fmt.Sprintf("gossipd.client-subs.%s", client_id)
			G_redis_client.Store(key, client_rep.Subscriptions)			
		}
		log.Debugf("finding retained message for (%s)", topic)
		retained_msg := G_redis_client.GetRetainMessage(topic)
		if retained_msg != nil {
			go Deliver(client_id, qos, retained_msg)
			log.Debugf("delivered retained message for (%s)", topic)
		}
	}
	log.Debugf("Subscriptions are all processed, will send SUBACK")
	showSubscriptions()
}
func SendSuback(msg_id uint16, qos_list []uint8, conn *net.Conn, lock *sync.Mutex) {
	resp := CreateMqtt(SUBACK)
	resp.MessageId = msg_id
	resp.Topics_qos = qos_list
	bytes, _ := Encode(resp)
	MqttSendToClient(bytes, conn, lock)
}
func HandleUnsubscribe(mqtt *Mqtt, conn *net.Conn, client **ClientRep) {
	if *client == nil {
		panic("client_resp is nil, that means we don't have ClientRep for this client sending UNSUBSCRIBE")
		return
	}
	client_id := (*client).Mqtt.ClientId
	log.Debugf("Handling UNSUBSCRIBE, client_id: %s", client_id)
	client_rep := *client
	client_rep.UpdateLastTime()
	defer func() {
		G_subs_lock.Unlock()
		SendUnsuback(mqtt.MessageId, conn, client_rep.WriteLock)
	}()
	G_subs_lock.Lock()
	for i := 0; i < len(mqtt.Topics); i++ {
		topic := mqtt.Topics[i]
		log.Debugf("unsubscribing client(%s) from topic(%s)",
			client_id, topic)
		delete(client_rep.Subscriptions, topic)
		subs := G_subs[topic]
		if subs == nil {
			log.Debugf("topic(%s) has no subscription, no need to unsubscribe", topic)
		} else {
			delete(subs, client_id)
			if len(subs) == 0 {
				delete(G_subs, topic)
				log.Debugf("last subscription of topic(%s) is removed, so this topic is removed as well", topic)
			}
		}
	}
	log.Debugf("unsubscriptions are all processed, will send UNSUBACK")
	showSubscriptions()
}
func SendUnsuback(msg_id uint16, conn *net.Conn, lock *sync.Mutex) {
	resp := CreateMqtt(UNSUBACK)
	resp.MessageId = msg_id
	bytes, _ := Encode(resp)
	MqttSendToClient(bytes, conn, lock)
}
func HandlePingreq(mqtt *Mqtt, conn *net.Conn, client **ClientRep) {
	if *client == nil {
		panic("client_resp is nil, that means we don't have ClientRep for this client sending PINGREQ")
		return
	}
	client_id := (*client).Mqtt.ClientId
	log.Debugf("Handling PINGREQ, client_id: %s", client_id)
	client_rep := *client
	client_rep.UpdateLastTime()
	SendPingresp(conn, client_rep.WriteLock)
	log.Debugf("Sent PINGRESP, client_id: %s", client_id)
}
func SendPingresp(conn *net.Conn, lock *sync.Mutex) {
	resp := CreateMqtt(PINGRESP)
	bytes, _ := Encode(resp)
	MqttSendToClient(bytes, conn, lock)
}
func HandleDisconnect(mqtt *Mqtt, conn *net.Conn, client **ClientRep) {
	if *client == nil {
		panic("client_resp is nil, that means we don't have ClientRep for this client sending DISCONNECT")
		return
	}
	ForceDisconnect(*client, G_clients_lock, DONT_SEND_WILL)
}
func HandlePuback(mqtt *Mqtt, conn *net.Conn, client **ClientRep) {
	if *client == nil {
		panic("client_resp is nil, that means we don't have ClientRep for this client sending DISCONNECT")
		return
	}
	client_id := (*client).Mqtt.ClientId
	message_id := mqtt.MessageId
	log.Debugf("Handling PUBACK, client:(%s), message_id:(%d)", client_id, message_id)
	messages := G_redis_client.GetFlyingMessagesForClient(client_id)
	flying_msg, found := (*messages)[message_id]
	if !found || flying_msg.Status != PENDING_ACK {
		log.Debugf("message(id=%d, client=%s) is not PENDING_ACK, will ignore this PUBACK",
			message_id, client_id)
	} else {
		delete(*messages, message_id)
		G_redis_client.SetFlyingMessagesForClient(client_id, messages)
		log.Debugf("acked flying message(id=%d), client:(%s)", message_id, client_id)
	}	
}
func MqttSendToClient(bytes []byte, conn *net.Conn, lock *sync.Mutex) {
	if lock != nil {
		lock.Lock()
		defer func() {
			lock.Unlock()
		}()
	}
	(*conn).Write(bytes)
}