func handDelBuddy(j *simplejson.Json, s kiwi.MessageSender, m *kiwi.Message) error { uid, err := j.Get("uid").Int() if err != nil { return ErrDeformedRequest } token, err := j.Get("token").String() if err != nil { return ErrDeformedRequest } buddyID, err := j.Get("buddyID").String() if err != nil { return ErrDeformedRequest } db, err := sql.Open("mysql", dbConnInfo) if err != nil { return err } defer db.Close() // validate request info stmtOut, err := db.Prepare("SELECT COUNT(*) FROM user WHERE id=? AND token=?") if err != nil { return err } defer stmtOut.Close() var count int err = stmtOut.QueryRow(uid, token).Scan(&count) if err != nil { return err } if count == 0 { return ErrIllegalRequest } // delete relation stmtUpe, err := db.Prepare("DELETE FROM user_buddy WHERE user=? AND buddy=?") if err != nil { return err } defer stmtUpe.Close() _, err = stmtUpe.Exec(uid, buddyID) if err != nil { return errors.New(fmt.Sprintf("cannot delete relation user %d buddy:%d err: %s", uid, buddyID, err.Error())) } retMsg := simplejson.New() retMsg.Set("action", "del-buddy-return") retMsg.Set("errCode", ErrNone) retMsg.Set("errMsg", ErrCodeMsg[ErrNone]) byts, _ := retMsg.MarshalJSON() s.SendWholeBytes(byts, false) return nil }
func handleCheckToken(j *simplejson.Json, s kiwi.MessageSender, m *kiwi.Message) error { uid, err := j.Get("uid").Int64() if err != nil { return ErrDeformedRequest } token, err := j.Get("token").String() if err != nil { return ErrDeformedRequest } network, err := j.Get("network").Int() if err != nil { return ErrDeformedRequest } db, err := sql.Open("mysql", dbConnInfo) if err != nil { return err } defer db.Close() // valid user and his token tokenIsValid, err := checkToken(uid, token) if err != nil { return err } if !tokenIsValid { sendNeedsLogin("check-token-return", s) return nil } // associate new conn id with user uidConnIdMap.add(uid, s.GetConn().ID) // update network stmtUpe, err := db.Prepare("UPDATE user SET network=? WHERE id=?") if err != nil { return err } defer stmtUpe.Close() _, err = stmtUpe.Exec(network, uid) if err != nil { return errors.New(fmt.Sprintf("cannot update conn id of user %d err: %s", uid, err.Error())) } retMsg := simplejson.New() retMsg.Set("action", "check-token-return") retMsg.Set("errCode", ErrNone) retMsg.Set("errMsg", ErrCodeMsg[ErrNone]) byts, _ := retMsg.MarshalJSON() s.SendWholeBytes(byts, false) return nil }
func sendNeedsLogin(action string, s kiwi.MessageSender) { retMsg := simplejson.New() retMsg.Set("action", action) retMsg.Set("errCode", ErrInvalidToken) retMsg.Set("errMsg", ErrCodeMsg[ErrInvalidToken]) byts, _ := retMsg.MarshalJSON() s.SendWholeBytes(byts, false) }
func sendUnreachable(msgID int, s kiwi.MessageSender) error { retMsg := simplejson.New() retMsg.Set("action", "send-message-return") retMsg.Set("msgID", msgID) retMsg.Set("errCode", ErrCodeUnreachable) retMsg.Set("errMsg", ErrCodeMsg[ErrCodeUnreachable]) byts, _ := retMsg.MarshalJSON() _, err := s.SendWholeBytes(byts, false) return err }
func handleLogout(j *simplejson.Json, s kiwi.MessageSender, m *kiwi.Message) error { uid, err := j.Get("uid").Int64() if err != nil { return ErrDeformedRequest } token, err := j.Get("token").String() if err != nil { return ErrDeformedRequest } db, err := sql.Open("mysql", dbConnInfo) if err != nil { return err } defer db.Close() // valid user and his token tokenIsValid, err := checkToken(uid, token) if err != nil { return err } if !tokenIsValid { sendNeedsLogin("logout-return", s) return nil } // remove connId from uid-connId map uidConnIdMap.delUid(uid) // logout user logoutUser(uid) retMsg := simplejson.New() retMsg.Set("action", "logout-return") retMsg.Set("errCode", ErrNone) retMsg.Set("errMsg", ErrCodeMsg[ErrNone]) byts, _ := retMsg.MarshalJSON() s.SendWholeBytes(byts, false) return nil }
func onConnOpen(r kiwi.MessageReceiver, s kiwi.MessageSender) { for { msg, err := r.ReadWhole(1 << 20) if err != nil { log.Println(err) s.SendClose(kiwi.CloseCodeGoingAway, "", true, false) break } if msg.IsText() { if err = router.Serve(msg, s); err != nil { log.Println(err) s.SendClose(kiwi.CloseCodeGoingAway, "", true, false) } } else if msg.IsClose() { s.SendClose(kiwi.CloseCodeNormalClosure, "", true, false) break } } }
func handleLogin(j *simplejson.Json, s kiwi.MessageSender, m *kiwi.Message) error { email, err := j.Get("email").String() if err != nil { return ErrDeformedRequest } password, err := j.Get("password").String() if err != nil { return ErrDeformedRequest } network, err := j.Get("network").Int() if err != nil { return ErrDeformedRequest } db, err := sql.Open("mysql", dbConnInfo) if err != nil { return err } defer db.Close() // validate login info stmtOut, err := db.Prepare("SELECT id,nickname,avatar FROM user WHERE email=? AND password=?") if err != nil { return err } defer stmtOut.Close() var uid int64 var nickname sql.NullString var avatar []byte err = stmtOut.QueryRow(email, makePassword(password)).Scan(&uid, &nickname, &avatar) if err != nil { if err == sql.ErrNoRows { retMsg := simplejson.New() retMsg.Set("action", "login-return") retMsg.Set("uid", -1) retMsg.Set("token", "") retMsg.Set("errCode", ErrInvalidLoginInfo) retMsg.Set("errMsg", ErrCodeMsg[ErrInvalidLoginInfo]) byts, _ := retMsg.MarshalJSON() s.SendWholeBytes(byts, false) return nil } return err } // associate new conn id with user uidConnIdMap.add(uid, s.GetConn().ID) // update token/network token := makeToken() stmtUpe, err := db.Prepare("UPDATE user SET token=?,network=? WHERE id=?") if err != nil { return err } defer stmtUpe.Close() _, err = stmtUpe.Exec(token, network, uid) if err != nil { return errors.New(fmt.Sprintf("cannot update token of user %d err: %s", uid, err.Error())) } retMsg := simplejson.New() retMsg.Set("action", "login-return") retMsg.Set("uid", uid) retMsg.Set("token", token) retMsg.Set("nickname", nickname.String) retMsg.Set("avatar", encodeAvatar(avatar)) retMsg.Set("errCode", ErrNone) retMsg.Set("errMsg", ErrCodeMsg[ErrNone]) byts, _ := retMsg.MarshalJSON() s.SendWholeBytes(byts, false) return nil }
func handRegister(j *simplejson.Json, s kiwi.MessageSender, m *kiwi.Message) error { email, err := j.Get("email").String() if err != nil { return ErrDeformedRequest } nickname, err := j.Get("nickname").String() if err != nil { return ErrDeformedRequest } password, err := j.Get("password").String() if err != nil { return ErrDeformedRequest } db, err := sql.Open("mysql", dbConnInfo) if err != nil { return err } defer db.Close() // validate login info stmtOut, err := db.Prepare("SELECT COUNT(*) FROM user WHERE email=?") if err != nil { return err } defer stmtOut.Close() var count int err = stmtOut.QueryRow(email).Scan(&count) if err != nil { return err } if count != 0 { retMsg := simplejson.New() retMsg.Set("action", "register-return") retMsg.Set("uid", -1) retMsg.Set("token", "") retMsg.Set("errCode", ErrEmailAlreadyExists) retMsg.Set("errMsg", ErrCodeMsg[ErrEmailAlreadyExists]) byts, _ := retMsg.MarshalJSON() s.SendWholeBytes(byts, false) return nil } // make a default avatar with random color avatar := makeDefaultAvatar() stmtIns, err := db.Prepare("INSERT INTO user (email, password, nickname, token, avatar) VALUES(?, ?, ?, ?, ?)") if err != nil { return err } defer stmtIns.Close() token := makeToken() res, err := stmtIns.Exec(email, makePassword(password), nickname, token, avatar) if err != nil { return err } uid, _ := res.LastInsertId() // associate new conn id with user uidConnIdMap.add(uid, s.GetConn().ID) retMsg := simplejson.New() retMsg.Set("action", "register-return") retMsg.Set("uid", uid) retMsg.Set("nickname", nickname) retMsg.Set("avatar", encodeAvatar(avatar)) retMsg.Set("token", token) retMsg.Set("errCode", ErrNone) retMsg.Set("errMsg", ErrCodeMsg[ErrNone]) byts, _ := retMsg.MarshalJSON() s.SendWholeBytes(byts, false) return nil }
func handleGetUserInfo(j *simplejson.Json, s kiwi.MessageSender, m *kiwi.Message) error { uid, err := j.Get("uid").Int64() if err != nil { return ErrDeformedRequest } token, err := j.Get("token").String() if err != nil { return ErrDeformedRequest } db, err := sql.Open("mysql", dbConnInfo) if err != nil { return err } defer db.Close() // valid user and his token tokenIsValid, err := checkToken(uid, token) if err != nil { return err } if !tokenIsValid { sendNeedsLogin("get-user-info-return", s) return nil } stmtOut, err := db.Prepare("SELECT nickname,avatar FROM user WHERE id=?") if err != nil { return err } defer stmtOut.Close() var nickname sql.NullString var avatar []byte err = stmtOut.QueryRow(uid).Scan(&nickname, &avatar) if err != nil { if err == sql.ErrNoRows { retMsg := simplejson.New() retMsg.Set("action", "get-user-info-return") retMsg.Set("uid", -1) retMsg.Set("token", "") retMsg.Set("errCode", ErrInvalidLoginInfo) retMsg.Set("errMsg", ErrCodeMsg[ErrInvalidLoginInfo]) byts, _ := retMsg.MarshalJSON() s.SendWholeBytes(byts, false) return nil } return err } retMsg := simplejson.New() retMsg.Set("action", "get-user-info-return") retMsg.Set("uid", uid) retMsg.Set("nickname", nickname.String) retMsg.Set("avatar", encodeAvatar(avatar)) retMsg.Set("errCode", ErrNone) retMsg.Set("errMsg", ErrCodeMsg[ErrNone]) byts, _ := retMsg.MarshalJSON() s.SendWholeBytes(byts, false) return nil }
func handAddBuddy(j *simplejson.Json, s kiwi.MessageSender, m *kiwi.Message) error { uid, err := j.Get("uid").Int() if err != nil { return ErrDeformedRequest } token, err := j.Get("token").String() if err != nil { return ErrDeformedRequest } buddyID, err := j.Get("buddyID").Int() if err != nil { return ErrDeformedRequest } db, err := sql.Open("mysql", dbConnInfo) if err != nil { return err } defer db.Close() // validate request info stmtOut, err := db.Prepare("SELECT COUNT(*) FROM user WHERE id=? AND token=?") if err != nil { return err } var count int err = stmtOut.QueryRow(uid, token).Scan(&count) if err != nil { return err } stmtOut.Close() if count == 0 { return ErrIllegalRequest } // check if buddy is exists or not stmtOut, err = db.Prepare("SELECT COUNT(*) FROM user WHERE id=?") if err != nil { return err } defer stmtOut.Close() err = stmtOut.QueryRow(buddyID).Scan(&count) if err != nil { return err } if count == 0 { retMsg := simplejson.New() retMsg.Set("action", "add-buddy-return") retMsg.Set("errCode", ErrBuddyNotFound) retMsg.Set("errMsg", ErrCodeMsg[ErrBuddyNotFound]) byts, _ := retMsg.MarshalJSON() s.SendWholeBytes(byts, false) return nil } // check if relation is exists or not stmtOut, err = db.Prepare("SELECT COUNT(*) FROM user_buddy WHERE user=? AND buddy=?") if err != nil { return err } defer stmtOut.Close() err = stmtOut.QueryRow(uid, buddyID).Scan(&count) if err != nil { return err } if count == 1 { retMsg := simplejson.New() retMsg.Set("action", "add-buddy-return") retMsg.Set("errCode", ErrBuddyAlreadyExists) retMsg.Set("errMsg", ErrCodeMsg[ErrBuddyAlreadyExists]) byts, _ := retMsg.MarshalJSON() s.SendWholeBytes(byts, false) return nil } stmtIns, err := db.Prepare("INSERT INTO user_buddy (user, buddy) VALUES(?, ?)") if err != nil { return err } defer stmtIns.Close() _, err = stmtIns.Exec(uid, buddyID) if err != nil { return err } // become friends each other _, err = stmtIns.Exec(buddyID, uid) if err != nil { return err } // return buddy info stmtOut, err = db.Prepare("SELECT nickname,network,avatar FROM user WHERE id=?") if err != nil { return err } var nickname sql.NullString var network sql.NullInt64 var avatar []byte err = stmtOut.QueryRow(buddyID).Scan(&nickname, &network, &avatar) if err != nil { return err } retMsg := simplejson.New() retMsg.Set("action", "add-buddy-return") retMsg.SetPath([]string{"buddy", "uid"}, buddyID) retMsg.SetPath([]string{"buddy", "nickname"}, nickname.String) retMsg.SetPath([]string{"buddy", "network"}, network.Int64) retMsg.SetPath([]string{"buddy", "avatar"}, encodeAvatar(avatar)) retMsg.Set("errCode", ErrNone) retMsg.Set("errMsg", ErrCodeMsg[ErrNone]) byts, _ := retMsg.MarshalJSON() s.SendWholeBytes(byts, false) return nil }
func handleSendMessage(j *simplejson.Json, s kiwi.MessageSender, m *kiwi.Message) error { token, err := j.Get("token").String() if err != nil { return ErrDeformedRequest } from, err := j.Get("from").Int64() if err != nil { return ErrDeformedRequest } to, err := j.Get("to").Int64() if err != nil { return ErrDeformedRequest } msgID, err := j.Get("msgID").Int() if err != nil { return ErrDeformedRequest } msgType, err := j.Get("msgType").Int() if err != nil { return ErrDeformedRequest } msgContent, err := j.Get("msgContent").String() if err != nil { return ErrDeformedRequest } // valid user and his token tokenIsValid, err := checkToken(from, token) if err != nil { return err } if !tokenIsValid { sendNeedsLogin("send-message-return", s) return nil } // retrieve buddy's conn id buddyConnId, ok := uidConnIdMap.getConnId(to) if !ok { sendUnreachable(msgID, s) return nil } conn, ok := s.GetConn().Server.ConnPool.Get(buddyConnId) if !ok { sendUnreachable(msgID, s) return nil } msg := simplejson.New() msg.Set("action", "new-message") msg.Set("from", from) msg.Set("msgType", msgType) msg.Set("msgContent", msgContent) msg.Set("errCode", ErrNone) msg.Set("errMsg", ErrCodeMsg[ErrNone]) sender := &kiwi.DefaultMessageSender{} sender.SetConn(conn) byts, _ := msg.MarshalJSON() _, err = sender.SendWholeBytes(byts, false) if err != nil { sendUnreachable(msgID, s) } return nil }
func handGetBuddies(j *simplejson.Json, s kiwi.MessageSender, m *kiwi.Message) error { uid, err := j.Get("uid").Int64() if err != nil { return ErrDeformedRequest } token, err := j.Get("token").String() if err != nil { return ErrDeformedRequest } db, err := sql.Open("mysql", dbConnInfo) if err != nil { return err } defer db.Close() // valid user and his token tokenIsValid, err := checkToken(uid, token) if err != nil { return err } if !tokenIsValid { sendNeedsLogin("get-buddies-return", s) return nil } // get buddies stmtOut, err := db.Prepare(`SELECT U.id, U.nickname, U.network, U.avatar FROM user AS U JOIN user_buddy as B ON U.id=B.buddy WHERE B.user=?`) if err != nil { return err } defer stmtOut.Close() rows, err := stmtOut.Query(uid) if err != nil { return err } buddies := []*simplejson.Json{} for rows.Next() { var uid int var nickname sql.NullString var network sql.NullInt64 var avatar sql.RawBytes err = rows.Scan(&uid, &nickname, &network, &avatar) if err != nil { return err } buddy := simplejson.New() buddy.Set("uid", uid) buddy.Set("nickname", nickname.String) buddy.Set("network", network.Int64) buddy.Set("avatar", encodeAvatar(avatar)) buddies = append(buddies, buddy) } retMsg := simplejson.New() retMsg.Set("action", "get-buddies-return") retMsg.Set("buddies", buddies) retMsg.Set("errCode", ErrNone) retMsg.Set("errMsg", ErrCodeMsg[ErrNone]) byts, _ := retMsg.MarshalJSON() s.SendWholeBytes(byts, false) return nil }