A webmail client. Forked from https://git.sr.ht/~migadu/alps
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

84 lines
1.4 KiB

  1. package koushin
  2. import (
  3. "crypto/rand"
  4. "encoding/base64"
  5. "errors"
  6. "sync"
  7. imapclient "github.com/emersion/go-imap/client"
  8. )
  9. func generateToken() (string, error) {
  10. b := make([]byte, 32)
  11. _, err := rand.Read(b)
  12. if err != nil {
  13. return "", err
  14. }
  15. return base64.URLEncoding.EncodeToString(b), nil
  16. }
  17. var ErrSessionExpired = errors.New("session expired")
  18. type Session struct {
  19. imapConn *imapclient.Client
  20. username, password string
  21. }
  22. // TODO: expiration timer
  23. type ConnPool struct {
  24. locker sync.Mutex
  25. sessions map[string]*Session
  26. }
  27. func NewConnPool() *ConnPool {
  28. return &ConnPool{
  29. sessions: make(map[string]*Session),
  30. }
  31. }
  32. func (pool *ConnPool) Get(token string) (*Session, error) {
  33. pool.locker.Lock()
  34. defer pool.locker.Unlock()
  35. session, ok := pool.sessions[token]
  36. if !ok {
  37. return nil, ErrSessionExpired
  38. }
  39. return session, nil
  40. }
  41. func (pool *ConnPool) Put(imapConn *imapclient.Client, username, password string) (token string, err error) {
  42. pool.locker.Lock()
  43. defer pool.locker.Unlock()
  44. for {
  45. var err error
  46. token, err = generateToken()
  47. if err != nil {
  48. imapConn.Logout()
  49. return "", err
  50. }
  51. if _, ok := pool.sessions[token]; !ok {
  52. break
  53. }
  54. }
  55. pool.sessions[token] = &Session{
  56. imapConn: imapConn,
  57. username: username,
  58. password: password,
  59. }
  60. go func() {
  61. <-imapConn.LoggedOut()
  62. pool.locker.Lock()
  63. delete(pool.sessions, token)
  64. pool.locker.Unlock()
  65. }()
  66. return token, nil
  67. }