func (fieldContext *FieldContextDef) queueMessageToClient(sessionId string, messageToClient *message.MessageToClientDef) { var websocketConnectionContext *websocketConnectionContextDef var gkErr *gkerr.GkErrDef gklog.LogTrace("queu up message " + messageToClient.Command) websocketConnectionContext, gkErr = fieldContext.getWebsocketConnectionContextById(sessionId) if gkErr != nil { gklog.LogGkErr("", gkErr) } else { var localSize int websocketConnectionContext.toClientQueue.mutex.Lock() localSize = websocketConnectionContext.toClientQueue.queueSize websocketConnectionContext.toClientQueue.mutex.Unlock() if localSize > MAX_MESSAGES_TO_CLIENT_QUEUE { gkErr = gkerr.GenGkErr("messageToClient queue overflow, dropping message", nil, ERROR_ID_MESSAGE_TO_CLIENT_QUEUE_OVERFLOW) gklog.LogGkErr("", gkErr) } else { websocketConnectionContext.toClientQueue.mutex.Lock() websocketConnectionContext.toClientQueue.queueSize += 1 websocketConnectionContext.toClientQueue.mutex.Unlock() websocketConnectionContext.toClientQueue.messagesChan <- messageToClient } } }
func (httpContext *httpContextDef) handleGameInitial(res http.ResponseWriter, req *http.Request) { var gameData gameDataDef var gkErr *gkerr.GkErrDef var singleSession *ses.SingleSessionDef var token string token = req.Form.Get(_tokenParam) gklog.LogTrace("got token: " + token) var userName string userName = httpContext.tokenContext.getUserFromToken(token) gklog.LogTrace("got username: "******"not valid token", res, req) return } var lastPodId int32 lastPodId, gkErr = httpContext.persistenceContext.GetLastPodId(userName) if gkErr != nil { errorMessage := "persistenceContext.getLastPodName" gklog.LogGkErr(errorMessage, gkErr) httpContext.redirectToError(errorMessage, res, req) return } singleSession = httpContext.sessionContext.NewSingleSession(userName, lastPodId, req.RemoteAddr) gameData.Title = "game" gameData.WebAddressPrefix = httpContext.gameConfig.WebAddressPrefix gameData.WebsocketAddressPrefix = httpContext.gameConfig.WebsocketAddressPrefix gameData.AudioAddressPrefix = httpContext.gameConfig.AudioAddressPrefix gameData.WebsocketPath = httpContext.gameConfig.WebsocketPath gameData.SessionId = singleSession.GetSessionId() gkErr = _gameTemplate.Build(gameData) if gkErr != nil { errorMessage := "_gameTemplate.Build" gklog.LogGkErr(errorMessage, gkErr) httpContext.redirectToError(errorMessage, res, req) return } gkErr = _gameTemplate.Send(res, req) if gkErr != nil { gklog.LogGkErr("_gameTemplate.Send", gkErr) return } }
func LoginServerStart() { var fileName *string = flag.String("config", "", "config file name") var loginConfig loginConfigDef var gkErr *gkerr.GkErrDef flag.Parse() if *fileName == "" { flag.PrintDefaults() return } loginConfig, gkErr = loadConfigFile(*fileName) if gkErr != nil { fmt.Printf("error before log setup %s\n", gkErr.String()) return } gklog.LogInit(loginConfig.LogDir) gkErr = loginConfig.loginInit() if gkErr != nil { gklog.LogGkErr("loginConfig.loginInit", gkErr) return } address := fmt.Sprintf(":%d", loginConfig.Port) http.ListenAndServe(address, &loginConfig) }
func NewGkRandContext() *GkRandContextDef { var gkRandContext *GkRandContextDef = new(GkRandContextDef) var seed int64 var err error var gkErr *gkerr.GkErrDef seed = time.Now().UnixNano() buf := make([]byte, 6, 6) _, err = c_rand.Read(buf) if err != nil { // log the error // but this error is not fatal gkErr = gkerr.GenGkErr("c_rand.Read", err, ERROR_ID_RAND_READ) gklog.LogGkErr("", gkErr) } seed ^= int64(buf[0]) << 16 seed ^= int64(buf[1]) << 24 seed ^= int64(buf[2]) << 32 seed ^= int64(buf[3]) << 40 seed ^= int64(buf[4]) << 48 seed ^= int64(buf[5]) << 56 gkRandContext.mRandContext = m_rand.New(m_rand.NewSource(seed)) return gkRandContext }
func redirectToError(message string, res http.ResponseWriter, req *http.Request) { var errorData errorDataDef var gkErr *gkerr.GkErrDef errorData.Title = "Error" errorData.Message = message gkErr = _errorTemplate.Build(errorData) if gkErr != nil { gklog.LogGkErr("_errorTemplate.Build", gkErr) } gkErr = _errorTemplate.Send(res, req) if gkErr != nil { gklog.LogGkErr("_errorTemplate.Send", gkErr) } }
func (httpContext *httpContextDef) redirectToError(message string, res http.ResponseWriter, req *http.Request) { var errorData errorDataDef var gkErr *gkerr.GkErrDef errorData.Title = "Error" errorData.Message = message errorData.WebAddressPrefix = httpContext.gameConfig.WebAddressPrefix gkErr = _errorTemplate.Build(errorData) if gkErr != nil { gklog.LogGkErr("_errorTemplate.Build", gkErr) } gkErr = _errorTemplate.Send(res, req) if gkErr != nil { gklog.LogGkErr("_errorTemplate.Send", gkErr) } }
func handleLoginForgotPasswordInitial(loginConfig *loginConfigDef, res http.ResponseWriter, req *http.Request) { var forgotPasswordData forgotPasswordDataDef var gkErr *gkerr.GkErrDef forgotPasswordData.Title = "forgotPassword" forgotPasswordData.LoginWebAddressPrefix = loginConfig.LoginWebAddressPrefix gkErr = _forgotPasswordTemplate.Build(forgotPasswordData) if gkErr != nil { gklog.LogGkErr("_forgotPasswordTemplate.Build", gkErr) redirectToError("_forgotPasswordTemplate.Build", res, req) return } gkErr = _forgotPasswordTemplate.Send(res, req) if gkErr != nil { gklog.LogGkErr("_forgotPasswordTemplate.send", gkErr) } }
func handleLoginInitial(loginConfig *loginConfigDef, res http.ResponseWriter, req *http.Request) { var loginData loginDataDef var gkErr *gkerr.GkErrDef loginData.Title = "login" loginData.LoginWebAddressPrefix = loginConfig.LoginWebAddressPrefix gkErr = _loginTemplate.Build(loginData) if gkErr != nil { gklog.LogGkErr("_loginTemplate.Build", gkErr) redirectToError("_loginTemplate.Build", res, req) return } gkErr = _loginTemplate.Send(res, req) if gkErr != nil { gklog.LogGkErr("_loginTemplate.Send", gkErr) return } }
func handleLoginRegisterInitial(loginConfig *loginConfigDef, res http.ResponseWriter, req *http.Request, userName string) { var registerData registerDataDef var gkErr *gkerr.GkErrDef registerData.Title = "register" registerData.LoginWebAddressPrefix = loginConfig.LoginWebAddressPrefix registerData.UserName = userName gkErr = _registerTemplate.Build(registerData) if gkErr != nil { gklog.LogGkErr("_registerTemplate.Build", gkErr) redirectToError("_registerTemplate.Build", res, req) return } gkErr = _registerTemplate.Send(res, req) if gkErr != nil { gklog.LogGkErr("_registerTemplate.send", gkErr) } }
func (gkRandContext *GkRandContextDef) GetRandomByte() byte { gkRandContext.mutex.Lock() defer gkRandContext.mutex.Unlock() var err error var gkErr *gkerr.GkErrDef buf := make([]byte, 1, 1) _, err = c_rand.Read(buf) if err != nil { // log the error // but this error is not fatal gkErr = gkerr.GenGkErr("c_rand.Read", err, ERROR_ID_RAND_READ) gklog.LogGkErr("", gkErr) } var r int64 r = gkRandContext.mRandContext.Int63() r ^= int64(buf[0]) return byte(r) }
func (gkRandContext *GkRandContextDef) GetRandomString(length int) string { result := make([]byte, 0, length) gkRandContext.mutex.Lock() defer gkRandContext.mutex.Unlock() for len(result) < length { var r int64 var err error var gkErr *gkerr.GkErrDef buf := make([]byte, 6, 6) _, err = c_rand.Read(buf) if err != nil { // log the error // but this error is not fatal gkErr = gkerr.GenGkErr("c_rand.Read", err, ERROR_ID_RAND_READ) gklog.LogGkErr("", gkErr) } r = gkRandContext.mRandContext.Int63() r ^= int64(buf[0]) << 16 r ^= int64(buf[1]) << 24 r ^= int64(buf[2]) << 32 r ^= int64(buf[3]) << 40 for i := 0; i < 10; i++ { var c int c = int(r & 0x3f) if c < len(validDataSet) { result = append(result, validDataSet[c]) if len(result) >= length { break } } r = r >> 6 } } return string(result) }
func (fieldContext *FieldContextDef) handleSetAvatarSvgReq(messageFromClient *message.MessageFromClientDef) *gkerr.GkErrDef { var gkErr *gkerr.GkErrDef var err error var setSvg setSvgDef gklog.LogTrace("json raw: " + string(messageFromClient.JsonData)) err = json.Unmarshal(messageFromClient.JsonData, &setSvg) if err != nil { gkErr = gkerr.GenGkErr("json.Unmarshal", err, ERROR_ID_JSON_UNMARSHAL) return gkErr } var singleSession *ses.SingleSessionDef singleSession = fieldContext.sessionContext.GetSessionFromId(messageFromClient.SessionId) var podId int32 = singleSession.GetCurrentPodId() var fieldObject *fieldObjectDef var ok bool fieldObject, ok = fieldContext.podMap[podId].avatarMap[setSvg.Id] if ok { var cord int cord, _ = strconv.Atoi(setSvg.X) fieldObject.isoXYZ.X = int16(cord) cord, _ = strconv.Atoi(setSvg.Y) fieldObject.isoXYZ.Y = int16(cord) cord, _ = strconv.Atoi(setSvg.Z) fieldObject.isoXYZ.Z = int16(cord) gklog.LogTrace("one") fieldContext.setAllAvatars(messageFromClient.SessionId, fieldObject) } else { gkErr = gkerr.GenGkErr("move object", nil, ERROR_ID_COULD_NOT_FIND_OBJECT_TO_MOVE) gklog.LogGkErr("", gkErr) } return nil }
func sendWebsocketMessage(ws *websocket.Conn, messageToClient *message.MessageToClientDef) *gkerr.GkErrDef { var websocketMessage []byte var err error var gkErr *gkerr.GkErrDef websocketMessage = make([]byte, 0, 0) websocketMessage = append(websocketMessage, []byte(messageToClient.Command)...) websocketMessage = append(websocketMessage, '~') websocketMessage = append(websocketMessage, messageToClient.JsonData...) websocketMessage = append(websocketMessage, '~') websocketMessage = append(websocketMessage, messageToClient.Data...) err = websocket.Message.Send(ws, string(websocketMessage)) if err != nil { gkErr = gkerr.GenGkErr("websocket.Message.Send", err, ERROR_ID_WEBSOCKET_SEND) gklog.LogGkErr("websocket.Message.Send", gkErr) return gkErr } return nil }
// websocketConnectionContext entry must be moved from old pod to new pod func (fieldContext *FieldContextDef) handleUserPrefReq(messageFromClient *message.MessageFromClientDef) *gkerr.GkErrDef { var userPrefReq userPrefReqDef var gkErr *gkerr.GkErrDef var err error var singleSession *ses.SingleSessionDef singleSession = fieldContext.sessionContext.GetSessionFromId(messageFromClient.SessionId) err = json.Unmarshal(messageFromClient.JsonData, &userPrefReq) if err != nil { gkErr = gkerr.GenGkErr("json.Unmarshal", err, ERROR_ID_JSON_UNMARSHAL) return gkErr } gkErr = fieldContext.persistenceContext.SetUserPref(singleSession.GetUserName(), userPrefReq.PrefName, userPrefReq.PrefValue) if gkErr != nil { // inserting user preferences is non critical // so just log the error gklog.LogGkErr("fieldContext.persistenceContext.SetUserPref", gkErr) } return nil }
func handleLoginLogin(loginConfig *loginConfigDef, res http.ResponseWriter, req *http.Request, userName string, password string) { var loginData loginDataDef var gkErr *gkerr.GkErrDef var gotError bool loginData.Title = "login" loginData.UserName = userName loginData.LoginWebAddressPrefix = loginConfig.LoginWebAddressPrefix if loginData.UserName == "" { loginData.ErrorList = append(loginData.ErrorList, "invalid user name") loginData.UserNameError = genErrorMarker() gotError = true } if password == "" { loginData.ErrorList = append(loginData.ErrorList, "invalid password") loginData.PasswordError = genErrorMarker() gotError = true } var passwordHashFromUser []byte var dbUser *database.DbUserDef var gkDbCon *database.GkDbConDef if !gotError { gkDbCon, gkErr = database.NewGkDbCon(loginConfig.DatabaseUserName, loginConfig.DatabasePassword, loginConfig.DatabaseHost, loginConfig.DatabasePort, loginConfig.DatabaseDatabase) if gkErr != nil { gklog.LogGkErr("database.NewGkDbCon", gkErr) redirectToError("database.NewGkDbCon", res, req) return } defer gkDbCon.Close() dbUser, gkErr = gkDbCon.GetUser(loginData.UserName) if gkErr != nil { if gkErr.GetErrorId() == database.ERROR_ID_NO_ROWS_FOUND { var passwordSalt string password = "******" passwordSalt = "abc123QWE." // make it take the same amount of time // between no user and invalid password passwordHashFromUser = sec.GenPasswordHashSlow([]byte(password), []byte(passwordSalt)) loginData.ErrorList = append(loginData.ErrorList, "invalid username/password") loginData.UserNameError = genErrorMarker() loginData.PasswordError = genErrorMarker() gotError = true } else { gklog.LogGkErr("gkDbCon.GetPasswordHashAndSalt", gkErr) redirectToError("gkDbCon.GetPasswordhashAndSalt", res, req) return } } } if !gotError { passwordHashFromUser = sec.GenPasswordHashSlow([]byte(password), []byte(dbUser.PasswordSalt)) gklog.LogTrace(fmt.Sprintf("dbUser: %v fromUser: %s", dbUser, passwordHashFromUser)) if dbUser.PasswordHash != string(passwordHashFromUser) { loginData.ErrorList = append(loginData.ErrorList, "invalid username/password") loginData.UserNameError = genErrorMarker() loginData.PasswordError = genErrorMarker() gotError = true } } if gotError { // for security, to slow down an attack that is guessing passwords, // sleep between 100 and 190 milliseconds time.Sleep(sec.GetSleepDurationPasswordInvalid()) gkErr = _loginTemplate.Build(loginData) if gkErr != nil { gklog.LogGkErr("_loginTemplate.Build", gkErr) redirectToError("_loginTemplate.Build", res, req) return } gkErr = _loginTemplate.Send(res, req) if gkErr != nil { gklog.LogGkErr("_loginTemplate.Send", gkErr) return } } else { gkErr = gkDbCon.UpdateUserLoginDate(dbUser.UserName) if gkErr != nil { // this error is going to be logged // but the user is not going to be redirected to an error // because they are going to be redirected to the game server // and it is not critical that their login date be updated. gklog.LogGkErr("_loginTemplate.Send", gkErr) } var gameRedirect string gameRedirect, gkErr = getGameRedirect(loginConfig, loginData.UserName) if gkErr != nil { gklog.LogGkErr("getGameRedirect", gkErr) return } http.Redirect(res, req, gameRedirect, http.StatusFound) } }
func handleLoginResetPassword(loginConfig *loginConfigDef, res http.ResponseWriter, req *http.Request, token string, userName string, password string) { var resetPasswordData resetPasswordDataDef var gkErr *gkerr.GkErrDef resetPasswordData.Title = "resetPassword" resetPasswordData.LoginWebAddressPrefix = loginConfig.LoginWebAddressPrefix resetPasswordData.Token = token resetPasswordData.UserName = userName if !CheckToken(token, userName) { redirectToError("token expired", res, req) return } gklog.LogTrace("reset password: "******"" { gklog.LogTrace("password blank") gkErr = _resetPasswordTemplate.Build(resetPasswordData) if gkErr != nil { gklog.LogGkErr("_resetPasswordTemplate.Build", gkErr) redirectToError("_resetPasswordTemplate.Build", res, req) return } gkErr = _resetPasswordTemplate.Send(res, req) if gkErr != nil { gklog.LogGkErr("_resetPasswordTemplate.send", gkErr) } return } var gkDbCon *database.GkDbConDef gkDbCon, gkErr = database.NewGkDbCon(loginConfig.DatabaseUserName, loginConfig.DatabasePassword, loginConfig.DatabaseHost, loginConfig.DatabasePort, loginConfig.DatabaseDatabase) if gkErr != nil { gklog.LogGkErr("database.NewGkDbCon", gkErr) redirectToError("database.NewGkDbCon", res, req) return } defer gkDbCon.Close() var passwordHash, passwordSalt []byte var err error passwordSalt, err = sec.GenSalt() if err != nil { gkErr = gkerr.GenGkErr("sec.GenSalt", err, ERROR_ID_GEN_SALT) gklog.LogGkErr("sec.GenSalt", gkErr) redirectToError("sec.GenSalt", res, req) } passwordHash = sec.GenPasswordHashSlow([]byte(password), passwordSalt) gklog.LogTrace("change password") gkDbCon.ChangePassword(userName, string(passwordHash), string(passwordSalt)) if gkErr != nil { gklog.LogGkErr("gkDbCon.ChangePassword", gkErr) redirectToError("gbDbCon.ChangePassword", res, req) return } gklog.LogTrace("redirect to login") http.Redirect(res, req, loginConfig.LoginWebAddressPrefix+_loginServer, http.StatusFound) }
func handleLoginForgotPassword(loginConfig *loginConfigDef, res http.ResponseWriter, req *http.Request, userName string) { var forgotPasswordData forgotPasswordDataDef var gkErr *gkerr.GkErrDef forgotPasswordData.Title = "forgotPassword" forgotPasswordData.LoginWebAddressPrefix = loginConfig.LoginWebAddressPrefix forgotPasswordData.UserName = userName forgotPasswordData.ErrorList = make([]string, 0, 0) var gotError bool if userName == "" { forgotPasswordData.ErrorList = append(forgotPasswordData.ErrorList, "user name cannot be blank") forgotPasswordData.UserNameError = genErrorMarker() gotError = true } var dbUser *database.DbUserDef if !gotError { var gkDbCon *database.GkDbConDef gkDbCon, gkErr = database.NewGkDbCon(loginConfig.DatabaseUserName, loginConfig.DatabasePassword, loginConfig.DatabaseHost, loginConfig.DatabasePort, loginConfig.DatabaseDatabase) if gkErr != nil { gklog.LogGkErr("database.NewGkDbCon", gkErr) redirectToError("database.NewGkDbCon", res, req) return } defer gkDbCon.Close() dbUser, gkErr = gkDbCon.GetUser( forgotPasswordData.UserName) if gkErr != nil { if gkErr.GetErrorId() == database.ERROR_ID_NO_ROWS_FOUND { forgotPasswordData.ErrorList = append(forgotPasswordData.ErrorList, "no such user") forgotPasswordData.UserNameError = genErrorMarker() gotError = true } else { gklog.LogGkErr("gbDbCon.GetUser", gkErr) redirectToError("gbDbCon.GetUser", res, req) return } } } var err error if !gotError { // create temporary forgot password token //var token []byte var forgotPasswordEmailData forgotPasswordEmailDataDef forgotPasswordEmailData.LoginWebAddressPrefix = loginConfig.LoginWebAddressPrefix forgotPasswordEmailData.UserName = userName var token []byte token, err = sec.GenForgotPasswordToken() if err != nil { gkErr = gkerr.GenGkErr("GenForgotPasswordToken", err, ERROR_ID_GEN_TOKEN) gklog.LogGkErr("GenForgotPasswordToken", gkErr) redirectToError("GenForgotPasswordToken", res, req) return } forgotPasswordEmailData.Token = string(token) gkErr = _forgotPasswordEmailTemplate.Build(forgotPasswordEmailData) if gkErr != nil { gklog.LogGkErr("_forgotPasswordEmailTemplate.Build", gkErr) redirectToError("_forgotPasswordEmailTemplate.Build", res, req) return } var message []byte message, gkErr = _forgotPasswordEmailTemplate.GetBytes() if gkErr != nil { gklog.LogGkErr("_forgotPasswordEmailTemplate.GetBytes", gkErr) redirectToError("_forgotPasswordEmailTemplate.GetBytes", res, req) return } toArray := make([]string, 1, 1) toArray[0] = dbUser.Email var sendId string AddNewToken(string(token), userName) sendId, gkErr = gknet.SendEmail(loginConfig.EmailServer, loginConfig.ServerFromEmail, toArray, "gourdian knot forgotten password", message) if gkErr != nil { gklog.LogGkErr("gknet.SendEmail", gkErr) } else { gklog.LogTrace("forgot email sent to: " + toArray[0] + " sendId: [" + sendId + "]") } } if gotError { gkErr = _forgotPasswordTemplate.Build(forgotPasswordData) if gkErr != nil { gklog.LogGkErr("_forgotPasswordTemplate.Build", gkErr) redirectToError("_forgotPasswordTemplate.Build", res, req) return } gkErr = _forgotPasswordTemplate.Send(res, req) if gkErr != nil { gklog.LogGkErr("_forgotPasswordTemplate.send", gkErr) } } else { http.Redirect(res, req, _loginServer, http.StatusFound) } }
func handleLoginRegister(loginConfig *loginConfigDef, res http.ResponseWriter, req *http.Request, userName string, password string, email string) { var registerData registerDataDef var gkErr *gkerr.GkErrDef var err error registerData.Title = "register" registerData.LoginWebAddressPrefix = loginConfig.LoginWebAddressPrefix registerData.UserName = userName registerData.Email = email registerData.ErrorList = make([]string, 0, 0) var gotError bool if !isNewUserNameValid(userName) { registerData.ErrorList = append(registerData.ErrorList, "invalid user name") registerData.UserNameError = genErrorMarker() gotError = true } if !isPasswordValid(password) { registerData.ErrorList = append(registerData.ErrorList, "invalid password") registerData.PasswordError = genErrorMarker() gotError = true } if !isEmailValid(email) { registerData.ErrorList = append(registerData.ErrorList, "invalid email") registerData.EmailError = genErrorMarker() gotError = true } if !gotError { var gkDbCon *database.GkDbConDef gkDbCon, gkErr = database.NewGkDbCon(loginConfig.DatabaseUserName, loginConfig.DatabasePassword, loginConfig.DatabaseHost, loginConfig.DatabasePort, loginConfig.DatabaseDatabase) if gkErr != nil { gklog.LogGkErr("database.NewGkDbCon", gkErr) redirectToError("database.NewGkDbCon", res, req) return } defer gkDbCon.Close() var passwordHash, passwordSalt []byte passwordSalt, err = sec.GenSalt() if err != nil { gkErr = gkerr.GenGkErr("sec.GenSalt", err, ERROR_ID_GEN_SALT) gklog.LogGkErr("sec.GenSalt", gkErr) redirectToError("sec.GenSalt", res, req) } passwordHash = sec.GenPasswordHashSlow([]byte(password), passwordSalt) gkErr = gkDbCon.AddNewUser( registerData.UserName, string(passwordHash), string(passwordSalt), email) if gkErr != nil { if gkErr.GetErrorId() == database.ERROR_ID_UNIQUE_VIOLATION { registerData.ErrorList = append(registerData.ErrorList, "user name already in use") registerData.UserNameError = genErrorMarker() gotError = true } else { gklog.LogGkErr("gbDbCon.AddNewUser", gkErr) redirectToError("gbDbCon.AddNewUser", res, req) return } } } if gotError { gkErr = _registerTemplate.Build(registerData) if gkErr != nil { gklog.LogGkErr("_registerTemplate.Build", gkErr) redirectToError("_registerTemplate.Build", res, req) return } gkErr = _registerTemplate.Send(res, req) if gkErr != nil { gklog.LogGkErr("_registerTemplate.send", gkErr) } } else { http.Redirect(res, req, _loginServer, http.StatusFound) // var gameRedirect string // gameRedirect = getGameRedirect(loginConfig, loginData.UserName) // http.Redirect(res, req, gameRedirect, http.StatusFound) } }
func WebsocketHandler(ws *websocket.Conn) { var url *url.URL = ws.Request().URL var gkErr *gkerr.GkErrDef defer ws.Close() gklog.LogTrace("WebsocketHandler start") defer gklog.LogTrace("WebsocketHandler end") // var websocketConfig *websocket.Config // websocketConfig = ws.Config() if url.Path != _wsContext.gameConfig.WebsocketPath { gkErr = gkerr.GenGkErr("invalid websocket path: "+url.Path, nil, ERROR_ID_WEBSOCKET_INVALID_PATH) gklog.LogGkErr("", gkErr) return } var sessionId string sessionId = _wsContext.sessionContext.OpenSessionWebsocket(url.RawQuery, ws.Request().RemoteAddr) if sessionId == "" { gkErr = gkerr.GenGkErr("session not valid", nil, ERROR_ID_WEBSOCKET_INVALID_SESSION) gklog.LogGkErr("", gkErr) return } defer func() { _wsContext.sessionContext.CloseSessionWebsocket(sessionId) }() var singleSession *ses.SingleSessionDef var singleWs *singleWsDef singleSession = _wsContext.sessionContext.GetSessionFromId(sessionId) singleWs = _wsContext.newSingleWs(singleSession) var websocketOpenedMessage field.WebsocketOpenedMessageDef websocketOpenedMessage.SessionId = sessionId websocketOpenedMessage.MessageToClientChan = singleWs.messageToClientChan _wsContext.fieldContext.WebsocketOpenedChan <- websocketOpenedMessage defer func() { var websocketClosedMessage field.WebsocketClosedMessageDef websocketClosedMessage.SessionId = sessionId _wsContext.fieldContext.WebsocketClosedChan <- websocketClosedMessage }() var receiveWebsocketChan chan *receiveWebsocketDef = make(chan *receiveWebsocketDef) go goGetMessage(ws, receiveWebsocketChan) var done bool = false for !done { var receiveWebsocket *receiveWebsocketDef select { case receiveWebsocket = <-receiveWebsocketChan: if receiveWebsocket.err != nil { if receiveWebsocket.err == io.EOF { gklog.LogTrace(fmt.Sprintf("closing websocket got eof sessionId: %s", sessionId)) done = true break } gkErr = gkerr.GenGkErr(fmt.Sprintf("got websocket input error sessionId %s", sessionId), receiveWebsocket.err, ERROR_ID_WEBSOCKET_RECEIVE) gklog.LogGkErr("websocket error", gkErr) return } else { var messageFromClient *message.MessageFromClientDef = new(message.MessageFromClientDef) messageFromClient.PopulateFromMessage(sessionId, receiveWebsocket.message) _wsContext.fieldContext.MessageFromClientChan <- messageFromClient } case messageToClient := <-singleWs.messageToClientChan: gkErr = sendWebsocketMessage(ws, messageToClient) if gkErr != nil { gklog.LogGkErr(fmt.Sprintf("sendWebsocketMessage sessionId: %s", sessionId), gkErr) return } } } }
// websocketConnectionContext entry must be moved from old pod to new pod func (fieldContext *FieldContextDef) handleNewPodReq(messageFromClient *message.MessageFromClientDef) *gkerr.GkErrDef { var newPodReq newPodReqDef var gkErr *gkerr.GkErrDef var err error err = json.Unmarshal(messageFromClient.JsonData, &newPodReq) if err != nil { gkErr = gkerr.GenGkErr("json.Unmarshal", err, ERROR_ID_JSON_UNMARSHAL) return gkErr } var destinationX, destinationY, destinationZ int destinationX, _ = strconv.Atoi(newPodReq.X) destinationY, _ = strconv.Atoi(newPodReq.Y) destinationZ, _ = strconv.Atoi(newPodReq.Z) var websocketConnectionContext *websocketConnectionContextDef websocketConnectionContext, gkErr = fieldContext.getWebsocketConnectionContextById(messageFromClient.SessionId) if gkErr != nil { return gkErr } var singleSession *ses.SingleSessionDef singleSession = fieldContext.sessionContext.GetSessionFromId(websocketConnectionContext.sessionId) var oldPodId int32 = singleSession.GetCurrentPodId() var newPodId int64 newPodId, _ = strconv.ParseInt(newPodReq.PodId, 10, 32) if (fieldContext.isPodIdValid(int32(newPodId))) && (oldPodId != int32(newPodId)) { gkErr = fieldContext.moveAllAvatarBySessionId(messageFromClient.SessionId, oldPodId, int32(newPodId), int16(destinationX), int16(destinationY), int16(destinationZ)) if gkErr != nil { gklog.LogGkErr("", gkErr) return gkErr } delete(fieldContext.podMap[oldPodId].websocketConnectionMap, messageFromClient.SessionId) singleSession.SetCurrentPodId(int32(newPodId)) fieldContext.podMap[int32(newPodId)].websocketConnectionMap[messageFromClient.SessionId] = websocketConnectionContext gkErr = fieldContext.uploadNewPodInfo(websocketConnectionContext, int32(newPodId)) if gkErr != nil { gklog.LogGkErr("", gkErr) return gkErr } gkErr = fieldContext.reAddAvatarBySessionId(messageFromClient.SessionId, int32(newPodId)) if gkErr != nil { gklog.LogGkErr("", gkErr) return gkErr } } else { gkErr = gkerr.GenGkErr(fmt.Sprintf("invalid podId: %d", newPodId), nil, ERROR_ID_INVALID_POD_ID) gklog.LogGkErr("", gkErr) return gkErr } return nil }
func GameServerStart() { var fileName *string = flag.String("config", "", "config file name") var gameConfig *config.GameConfigDef var gkErr *gkerr.GkErrDef flag.Parse() if *fileName == "" { flag.PrintDefaults() return } gameConfig, gkErr = config.LoadConfigFile(*fileName) if gkErr != nil { fmt.Print(gkErr.String()) return } gklog.LogInit(gameConfig.LogDir) var randContext *gkrand.GkRandContextDef var persistenceContext *persistence.PersistenceContextDef var tokenContext *tokenContextDef var sessionContext *ses.SessionContextDef var httpContext *httpContextDef randContext = gkrand.NewGkRandContext() persistenceContext, gkErr = persistence.NewPersistenceContext(gameConfig) if gkErr != nil { gklog.LogGkErr("persistence.NewPersisenceContext", gkErr) return } tokenContext = NewTokenContext(gameConfig, randContext, sessionContext) sessionContext = ses.NewSessionContext(randContext) httpContext = NewHttpContext(gameConfig, persistenceContext, sessionContext, tokenContext) gkErr = httpContext.gameInit() if gkErr != nil { gklog.LogGkErr("httpContext.gameInit", gkErr) return } gkErr = tokenContext.gameInit() if gkErr != nil { gklog.LogGkErr("tokenContext.gameInit", gkErr) return } gklog.LogTrace("game server started") var wsContext *ws.WsContextDef var fieldContext *field.FieldContextDef fieldContext, gkErr = field.NewFieldContext(gameConfig.AvatarSvgDir, gameConfig.TerrainSvgDir, sessionContext, persistenceContext) if gkErr != nil { gklog.LogGkErr("field.NewFieldContext", gkErr) return } wsContext = ws.NewWsContext(gameConfig, sessionContext, fieldContext) ws.SetGlobalWsContext(wsContext) go fieldContext.StartFieldHandler() httpAddress := fmt.Sprintf(":%d", gameConfig.HttpPort) tokenAddress := fmt.Sprintf(":%d", gameConfig.TokenPort) var err error go func() { err = http.ListenAndServe(tokenAddress, tokenContext) if err != nil { gkErr = gkerr.GenGkErr("http.ListenAndServer token", err, ERROR_ID_TOKEN_SERVER_START) gklog.LogGkErr("", gkErr) return } gklog.LogTrace("token listener ended, this is probably bad") }() go func() { err = http.ListenAndServe(httpAddress, httpContext) if err != nil { gkErr = gkerr.GenGkErr("http.ListenAndServer http", err, ERROR_ID_HTTP_SERVER_START) gklog.LogGkErr("", gkErr) return } gklog.LogTrace("http listener ended, this is probably bad") }() go func() { websocketAddress := fmt.Sprintf(":%d", gameConfig.WebsocketPort) gklog.LogTrace("starting web socket listener") if gameConfig.CertificatePath == "" { err = http.ListenAndServe(websocketAddress, websocket.Handler(ws.WebsocketHandler)) } else { err = http.ListenAndServeTLS(websocketAddress, gameConfig.CertificatePath, gameConfig.PrivateKeyPath, websocket.Handler(ws.WebsocketHandler)) } if err != nil { gkErr = gkerr.GenGkErr("http.ListenAndServer websocket", err, ERROR_ID_WEBSOCKET_SERVER_START) gklog.LogGkErr("", gkErr) return } gklog.LogTrace("websocket listener ended, this is probably bad") }() // give it time for the servers to start time.Sleep(time.Second * 60) // wait for all go routines to finish select {} gklog.LogTrace("game server ended") }