You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

151 lines
4.2KB

  1. package main
  2. import (
  3. "encoding/json"
  4. "io/ioutil"
  5. "log"
  6. "os"
  7. "path/filepath"
  8. "time"
  9. )
  10. //openSession is the biggest description for a user's openID
  11. // | it contains a name called procedure, whose data is stored elsewhere
  12. // |
  13. // +-- a Procedure name is a alphanumerical string lessthan 128 bytes.
  14. // |
  15. // +--- state is part of procedure, a procedure consists of sequence of states
  16. //where to find session data
  17. var sessionDir = "sessions"
  18. //where to find the procedure state information
  19. var procedureDir = "procedure"
  20. //openIDSessionData openID user's session
  21. type openIDSessionData struct {
  22. OpenID string `json:"OpenID"` //who's session this is belongs to
  23. Procedure string `json:"Procedure"` //name of the current current process, alphanumerical
  24. CreateAt int32 `json:"CreateAt"` //when is this session created
  25. UpdateAt int32 `json:"UpdateAt"` //when is this session updated
  26. Expire int32 `json:"Expire"` //unix timestamp of when this Procedure expires
  27. KvPair map[string]string `json:"KvPair"` //key value pair persistant for this session
  28. }
  29. func writeSession(ss openIDSessionData) (err error) {
  30. openID := ss.OpenID
  31. path := getSessionPath(openID)
  32. r, err := json.Marshal(ss)
  33. if err == nil {
  34. err = ioutil.WriteFile(path, r, 0600)
  35. if err != nil {
  36. log.Printf("Error writing session %s: \r\n %s \r\n", openID, r)
  37. log.Println(err)
  38. } else {
  39. log.Println("write session to " + path)
  40. }
  41. } else {
  42. log.Printf("Error encoding session %s ", openID)
  43. log.Println(err)
  44. }
  45. return
  46. }
  47. func isExpired(timestamp int32) bool {
  48. now := int32(time.Now().Unix())
  49. return now > timestamp
  50. }
  51. func getSessionPath(openID string) (path string) {
  52. path = sessionDir + string(os.PathSeparator) + openID + ".json"
  53. ensurePathExist(path)
  54. return path
  55. }
  56. func getProcedurePath(openID, ProcedureName string) (path string) {
  57. path = procedureDir + string(os.PathSeparator) + ProcedureName + string(os.PathSeparator) + openID + ".json"
  58. ensurePathExist(path)
  59. return
  60. }
  61. func ensurePathExist(path string) {
  62. d := filepath.Dir(path)
  63. if !isFileExist(d) {
  64. log.Println("Creating path [" + d + "]")
  65. os.MkdirAll(d, 0700)
  66. }
  67. }
  68. func deleteSession(openID string) {
  69. path := getSessionPath(openID)
  70. if isFileExist(path) {
  71. err := os.Remove(path)
  72. if err != nil {
  73. log.Println(err)
  74. }
  75. }
  76. }
  77. type initProcFunc func(openid string) (newstate chatState)
  78. type sendProcMsgFunc func(openid string) (newstate chatState)
  79. type recvProcMsgFunc func(openid string) (newstate chatState)
  80. type cleanProcFunc func(openid string) (newstate chatState)
  81. //Procedure a description about all procedure
  82. type Procedure struct {
  83. init initProcFunc //init function
  84. send sendProcMsgFunc //function for sending customized message
  85. recv recvProcMsgFunc //function for receiving message, possibly transfer to new state
  86. clean cleanProcFunc //function for cleanning up
  87. }
  88. func (c *openIDSessionData) Save() {
  89. //invalid procedure
  90. if isExpired(c.Expire) || c.Procedure == "" {
  91. deleteSession(c.OpenID)
  92. } else {
  93. writeSession(*c)
  94. }
  95. }
  96. //read sessions/openID.json to check whether its a Procedure for ongoing dialog
  97. func getCurrentSesssion(openID string) (result openIDSessionData, err error) {
  98. result = createEmptySession(openID, 3600)
  99. path := getSessionPath(openID)
  100. if isFileExist(path) {
  101. log.Printf("read session from %s\r\n", path)
  102. body, err := ioutil.ReadFile(path)
  103. if err != nil { //read file error
  104. log.Println("Error session reading " + path)
  105. } else {
  106. err = json.Unmarshal(body, &result)
  107. if err != nil {
  108. log.Printf("Session Content [path=%s] not correct: ", path)
  109. result = createEmptySession(openID, 3600)
  110. }
  111. }
  112. }
  113. return
  114. }
  115. func createEmptySession(openID string, expire int32) (result openIDSessionData) {
  116. result.OpenID = openID
  117. result.Procedure = ""
  118. now := int32(time.Now().Unix())
  119. result.CreateAt = now
  120. result.UpdateAt = now
  121. result.Expire = now + expire
  122. result.KvPair = map[string]string{}
  123. return
  124. }
  125. func (c *openIDSessionData) setProcedure(procedure string) {
  126. c.Procedure = procedure
  127. c.UpdateAt = int32(time.Now().Unix())
  128. }
  129. func (c *openIDSessionData) setKvPair(key, val string) {
  130. c.KvPair[key] = val
  131. c.UpdateAt = int32(time.Now().Unix())
  132. }