source: code/trunk/server.go@ 251

Last change on this file since 251 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
RevLine 
[98]1package soju
[1]2
3import (
4 "fmt"
[37]5 "log"
[1]6 "net"
[24]7 "sync"
[67]8 "time"
[1]9
10 "gopkg.in/irc.v3"
11)
12
[67]13// TODO: make configurable
14var keepAlivePeriod = time.Minute
[71]15var retryConnectMinDelay = time.Minute
[206]16var connectTimeout = 15 * time.Second
[205]17var writeTimeout = 10 * time.Second
[67]18
[9]19type Logger interface {
20 Print(v ...interface{})
21 Printf(format string, v ...interface{})
22}
23
[21]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
[10]41type Server struct {
[79]42 Hostname string
43 Logger Logger
44 RingCap int
[178]45 LogPath string
[79]46 Debug bool
[22]47
[77]48 db *DB
49
[172]50 lock sync.Mutex
51 users map[string]*user
[10]52}
53
[77]54func NewServer(db *DB) *Server {
[37]55 return &Server{
[50]56 Logger: log.New(log.Writer(), "", log.LstdFlags),
57 RingCap: 4096,
58 users: make(map[string]*user),
[77]59 db: db,
[37]60 }
61}
62
[5]63func (s *Server) prefix() *irc.Prefix {
64 return &irc.Prefix{Name: s.Hostname}
65}
66
[77]67func (s *Server) Run() error {
68 users, err := s.db.ListUsers()
69 if err != nil {
70 return err
71 }
[71]72
[77]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
[71]78
[77]79 go u.run()
[71]80 }
[37]81 s.lock.Unlock()
82
[77]83 select {}
[10]84}
85
[38]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
[3]93func (s *Server) Serve(ln net.Listener) error {
[154]94 var nextDownstreamID uint64 = 1
[1]95 for {
[22]96 netConn, err := ln.Accept()
[1]97 if err != nil {
98 return fmt.Errorf("failed to accept connection: %v", err)
99 }
100
[154]101 dc := newDownstreamConn(s, netConn, nextDownstreamID)
102 nextDownstreamID++
[1]103 go func() {
[103]104 if err := dc.runUntilRegistered(); err != nil {
105 dc.logger.Print(err)
106 } else {
[166]107 dc.user.events <- eventDownstreamConnected{dc}
[165]108 if err := dc.readMessages(dc.user.events); err != nil {
[103]109 dc.logger.Print(err)
110 }
[167]111 dc.user.events <- eventDownstreamDisconnected{dc}
[1]112 }
[65]113 dc.Close()
[1]114 }()
115 }
116}
Note: See TracBrowser for help on using the repository browser.