func CreateSession(conns net.Conn, imDB imdatabase.ImDb) *Session { //sqlerr := make(chan (error)) //当数据库读写出错,则返回nil,ErrorMysql ClientSession := setSession(conns) //初始化session publicPacket := MakePacket(PublicCMD, 0) //type=0的包 也就是发公钥的包 ClientSession.outgoing <- *publicPacket //首先把RSA的Public Key 发过去 for { //等待一定时间 回馈包,里面要求 username,appkey,aeskey。时间超过,或者里面内容不符合直接关掉conn select { case requestPacket := <-ClientSession.incoming: { //对进来的包进行检验 //isloged, userUid := receiveLoginPacket(ClientSession, requestPacket) if requestPacket.GetType() != 1 { *returnCMD.Sender = 0 *returnCMD.Receiver = 1 *returnCMD.Message.Data = "1:Please login first!" returnPacket := MakePacket(returnCMD, 3) ClientSession.outgoing <- *returnPacket //ImServerLog("A user didn't use a type 1 packet to login.") break } //if requestPacket.GetType() == 1 { //mean that this is a requestPacket requestCMD, err := GetCommand(&requestPacket) //Type=1的包,包含uid+APPKEY+AESKEY if err != nil { //回馈?? ImServerLog("RequestCMD get login command error ", err) /////////////////////////////////////////// break } //验证名字是否登陆了,验证APPKEY是否正确,如果都正确,纪录AESKEY,返回AESKEY加密的回馈包:uid appKey := requestCMD.Message.GetPassword() userUid := requestCMD.GetSender() token := requestCMD.Message.GetName() random := requestCMD.Message.GetRandom() aesKey := requestCMD.Message.GetData() //先看有没token _, fla := UserTable[userUid] if fla == false { //fmt.Println("*****************************用户不存在") //用户未先登录业务服务器 ClientSession.packetReader.AESKEY = []byte(aesKey) ClientSession.packetWriter.AESKEY = []byte(aesKey) *returnCMD.Sender = 0 *returnCMD.Receiver = userUid *returnCMD.Message.Random = random *returnCMD.Message.Data = "1:User don't login successfully!" notokenreturnPacket := MakePacket(returnCMD, 3) ClientSession.outgoing <- *notokenreturnPacket break } var userToken string userToken = UserTable[userUid].AToken if appKey != APPKEY || token != userToken { *returnCMD.Sender = 0 *returnCMD.Receiver = userUid *returnCMD.Message.Random = random *returnCMD.Message.Data = "1:Wrong AppKey or Token." wrongkeyreturnPacket := MakePacket(returnCMD, 3) ClientSession.outgoing <- *wrongkeyreturnPacket break } //if appKey == APPKEY && token == userToken { //have the same appkey and online and have the same token //从这里开始可以对imDB操作 ClientSession.packetReader.AESKEY = []byte(aesKey) ClientSession.packetWriter.AESKEY = []byte(aesKey) ClientSession.uid = userUid //如果存在旧的session tcp 则先关掉旧的,释放tcp资源 oldSession, flags := SessionTable[userUid] if flags == true { *returnCMD.Sender = 0 *returnCMD.Receiver = userUid *returnCMD.Message.Random = random *returnCMD.Message.Data = "1:Old session is replacing" placingreturnPacket := MakePacket(returnCMD, 3) oldSession.outgoing <- *placingreturnPacket SessionTable[userUid].quit() ImServerLog("User: "******" has logined before. Quit the earlier session.") ////////////////////////////////////////////// } SessionTable[userUid] = ClientSession UserTable[userUid] = Token{UserTable[userUid].AToken, 1} *returnCMD.Sender = 0 *returnCMD.Receiver = userUid *returnCMD.Message.Random = random *returnCMD.Message.Data = "1:Connect successfully." successreturnPacket := MakePacket(returnCMD, 3) ClientSession.outgoing <- *successreturnPacket //********************************************************************************* //goThroughOutLineMessage(userUid, imDB) outLineMessageTableFromSql, err := imDB.Db.Query("select type,packet,timestamp from outlinemessage where receiver_id=? order by timestamp asc", userUid) if err != nil { DatabaseLog("database error in prepare reading outlinemesssage:" + err.Error()) } defer outLineMessageTableFromSql.Close() if err == nil { //DatabaseLog("select from outlinemessage receiver_id = ", userUid) //在离线表找到数据 var outLineMsgType uint32 var outLineMsgePacket []byte var outLineMsgTime string //切片存储所有扫描出来的离线包信息 var allOutLineMsgType []uint32 var allOutLineMsgePacket []string //string类型 //var allOutLineMsgTime []string allOutLineMsgType = make([]uint32, 0, MaxOutLineMsg) allOutLineMsgePacket = make([]string, 0, MaxOutLineMsg) //allOutLineMsgTime = make([]string, 0, MaxOutLineMsg) for outLineMessageTableFromSql.Next() { err := outLineMessageTableFromSql.Scan(&outLineMsgType, &outLineMsgePacket, &outLineMsgTime) if err != nil { DatabaseLog("database error in reading outlinemesssage:" + err.Error()) continue } allOutLineMsgType = append(allOutLineMsgType, outLineMsgType) allOutLineMsgePacket = append(allOutLineMsgePacket, string(outLineMsgePacket)) } outLineMessageTableFromSql.Close() for i, _ := range allOutLineMsgType { var outLinePacket Packet outLinePacket.SetType(allOutLineMsgType[i]) outLinePacket.SetData([]byte(allOutLineMsgePacket[i])) outLineCMD, err := GetCommand(&outLinePacket) if err != nil { ImServerLog("Outlinemessage GetCommand err : ", err) continue } *outLineCMD.Message.Random = GenRandom() outPacket := MakePacket(outLineCMD, outLinePacket.GetType()) _, fl := SessionTable[userUid] if fl { SessionTable[userUid].outgoing <- *outPacket } } err = imDB.DeleteDbTable("delete from outlinemessage where receiver_id=?", userUid) if err != nil { DatabaseLog("Delete from outlinemessage error", err) } } //ImBusinessLog("Delete outlinemessage receiver_id = ", userUid) //return true //if isGetOutLineMessage == false { // SessionTable[userUid].quit() // return nil, ErrorMysql //} else { SessionTable[userUid] = ClientSession go receiveMessagePacket(userUid, imDB) return ClientSession //} } //case <-time.After(time.Second * MaxDelayTime): //{ // _, flag := SessionTable[userUid] // if flag { // SessionTable[userUid].quit() // ImServerLog("Client didn't login after receiving rsa key in MaxDelayTime.") /////////////////////////////////////////////////// // } // return nil, nil //} //case caseerr := <-sqlerr: // { // if caseerr == ErrorMysql { // return nil, ErrorMysql // } // } } } return nil }