source: code/trunk/server.go@ 212

Last change on this file since 212 was 210, checked in by contact, 5 years ago

Introduce conn for common connection logic

This centralizes the common upstream & downstream bits.

File size: 2.1 KB
Line 
1package soju
2
3import (
4 "fmt"
5 "log"
6 "net"
7 "sync"
8 "time"
9
10 "gopkg.in/irc.v3"
11)
12
13// TODO: make configurable
14var keepAlivePeriod = time.Minute
15var retryConnectMinDelay = time.Minute
16var connectTimeout = 15 * time.Second
17var writeTimeout = 10 * time.Second
18
19type Logger interface {
20 Print(v ...interface{})
21 Printf(format string, v ...interface{})
22}
23
24type prefixLogger struct {
25 logger Logger
26 prefix string
27}
28
29var _ Logger = (*prefixLogger)(nil)
30
31func (l *prefixLogger) Print(v ...interface{}) {
32 v = append([]interface{}{l.prefix}, v...)
33 l.logger.Print(v...)
34}
35
36func (l *prefixLogger) Printf(format string, v ...interface{}) {
37 v = append([]interface{}{l.prefix}, v...)
38 l.logger.Printf("%v"+format, v...)
39}
40
41type Server struct {
42 Hostname string
43 Logger Logger
44 RingCap int
45 LogPath string
46 Debug bool
47
48 db *DB
49
50 lock sync.Mutex
51 users map[string]*user
52}
53
54func NewServer(db *DB) *Server {
55 return &Server{
56 Logger: log.New(log.Writer(), "", log.LstdFlags),
57 RingCap: 4096,
58 users: make(map[string]*user),
59 db: db,
60 }
61}
62
63func (s *Server) prefix() *irc.Prefix {
64 return &irc.Prefix{Name: s.Hostname}
65}
66
67func (s *Server) Run() error {
68 users, err := s.db.ListUsers()
69 if err != nil {
70 return err
71 }
72
73 s.lock.Lock()
74 for _, record := range users {
75 s.Logger.Printf("starting bouncer for user %q", record.Username)
76 u := newUser(s, &record)
77 s.users[u.Username] = u
78
79 go u.run()
80 }
81 s.lock.Unlock()
82
83 select {}
84}
85
86func (s *Server) getUser(name string) *user {
87 s.lock.Lock()
88 u := s.users[name]
89 s.lock.Unlock()
90 return u
91}
92
93func (s *Server) Serve(ln net.Listener) error {
94 var nextDownstreamID uint64 = 1
95 for {
96 netConn, err := ln.Accept()
97 if err != nil {
98 return fmt.Errorf("failed to accept connection: %v", err)
99 }
100
101 dc := newDownstreamConn(s, netConn, nextDownstreamID)
102 nextDownstreamID++
103 go func() {
104 if err := dc.runUntilRegistered(); err != nil {
105 dc.logger.Print(err)
106 } else {
107 dc.user.events <- eventDownstreamConnected{dc}
108 if err := dc.readMessages(dc.user.events); err != nil {
109 dc.logger.Print(err)
110 }
111 dc.user.events <- eventDownstreamDisconnected{dc}
112 }
113 dc.Close()
114 }()
115 }
116}
Note: See TracBrowser for help on using the repository browser.