diff options
| author | Přemysl Janouch <p@janouch.name> | 2018-07-30 10:04:05 +0200 | 
|---|---|---|
| committer | Přemysl Janouch <p@janouch.name> | 2018-07-30 10:07:02 +0200 | 
| commit | 24f1c4413a6e26aa05c642a462ce77d70d478e92 (patch) | |
| tree | 82f9110beb3c81e6bcfa0a460edb2fa250b5bcfa /hid | |
| parent | 40370702d4189a30905e3eba70a2f01d09918cf1 (diff) | |
| download | haven-24f1c4413a6e26aa05c642a462ce77d70d478e92.tar.gz haven-24f1c4413a6e26aa05c642a462ce77d70d478e92.tar.xz haven-24f1c4413a6e26aa05c642a462ce77d70d478e92.zip | |
hid: use time.Time and time.Duration
It improves the code significantly over explicit int64 conversions.
Despite carrying unnecessary timezone information, time.Time also
carries a monotonic reading of time, which allows for more precise
measurement of time differences.
Diffstat (limited to 'hid')
| -rw-r--r-- | hid/main.go | 87 | 
1 files changed, 42 insertions, 45 deletions
| diff --git a/hid/main.go b/hid/main.go index ff6a84a..1c72fca 100644 --- a/hid/main.go +++ b/hid/main.go @@ -46,11 +46,6 @@ const (  	projectVersion = "0"  ) -// TODO: Consider using time.Time directly instead of storing Unix epoch -// timestamps with nanosecond precision. Despite carrying unnecessary timezone -// information, it also carries a monotonic reading of the time, which allows -// for more precise measurement of time differences. -  // --- Utilities ---------------------------------------------------------------  // Split a string by a set of UTF-8 delimiters, optionally ignoring empty items. @@ -207,23 +202,23 @@ func readConfigFile(name string, output interface{}) error {  // --- Rate limiter ------------------------------------------------------------  type floodDetector struct { -	interval   uint    // interval for the limit in seconds -	limit      uint    // maximum number of events allowed -	timestamps []int64 // timestamps of last events -	pos        uint    // index of the oldest event +	interval   time.Duration // interval for the limit in seconds +	limit      uint          // maximum number of events allowed +	timestamps []time.Time   // timestamps of last events +	pos        uint          // index of the oldest event  } -func newFloodDetector(interval, limit uint) *floodDetector { +func newFloodDetector(interval time.Duration, limit uint) *floodDetector {  	return &floodDetector{  		interval:   interval,  		limit:      limit, -		timestamps: make([]int64, limit+1), +		timestamps: make([]time.Time, limit+1),  		pos:        0,  	}  }  func (fd *floodDetector) check() bool { -	now := time.Now().UnixNano() +	now := time.Now()  	fd.timestamps[fd.pos] = now  	fd.pos++ @@ -232,9 +227,9 @@ func (fd *floodDetector) check() bool {  	}  	var count uint -	begin := now - int64(time.Second)*int64(fd.interval) +	begin := now.Add(-fd.interval)  	for _, ts := range fd.timestamps { -		if ts >= begin { +		if ts.After(begin) {  			count++  		}  	} @@ -402,11 +397,11 @@ type client struct {  	closing   bool           // whether we're closing the connection  	killTimer *time.Timer    // hard kill timeout -	opened            int64 // when the connection was opened -	nSentMessages     uint  // number of sent messages total -	sentBytes         int   // number of sent bytes total -	nReceivedMessages uint  // number of received messages total -	receivedBytes     int   // number of received bytes total +	opened            time.Time // when the connection was opened +	nSentMessages     uint      // number of sent messages total +	sentBytes         int       // number of sent bytes total +	nReceivedMessages uint      // number of received messages total +	receivedBytes     int       // number of received bytes total  	hostname string // hostname or IP shown to the network  	port     string // port of the peer as a string @@ -427,9 +422,9 @@ type client struct {  	mode        uint            // user's mode  	awayMessage string          // away message -	lastActive  int64           // last PRIVMSG, to get idle time +	lastActive  time.Time       // last PRIVMSG, to get idle time  	invites     map[string]bool // channel invitations by operators -	antiflood   floodDetector   // flood detector +	antiflood   *floodDetector  // flood detector  }  // --- Channels ---------------------------------------------------------------- @@ -450,15 +445,15 @@ const (  )  type channel struct { -	name      string // channel name -	modes     uint   // channel modes -	key       string // channel key -	userLimit int    // user limit or -1 -	created   int64  // creation time +	name      string    // channel name +	modes     uint      // channel modes +	key       string    // channel key +	userLimit int       // user limit or -1 +	created   time.Time // creation time -	topic     string // channel topic -	topicWho  string // who set the topic -	topicTime int64  // when the topic was set +	topic     string    // channel topic +	topicWho  string    // who set the topic +	topicTime time.Time // when the topic was set  	userModes map[*client]uint // modes for all channel users @@ -557,7 +552,7 @@ type writeEvent struct {  // XXX: Beware that maps with identifier keys need to be indexed correctly.  // We might want to enforce accessor functions for users and channels.  var ( -	started int64 // when has the server been started +	started time.Time // when has the server been started  	users    map[string]*client  // maps nicknames to clients  	channels map[string]*channel // maps channel names to data @@ -616,7 +611,7 @@ func initiateQuit() {  func ircChannelCreate(name string) *channel {  	ch := &channel{  		name:      name, -		created:   time.Now().UnixNano(), +		created:   time.Now(),  		userLimit: -1,  	}  	channels[ircToCanon(name)] = ch @@ -941,7 +936,7 @@ func (c *client) tryFinishRegistration() {  	c.sendReply(RPL_YOURHOST, serverName, projectVersion)  	// The purpose of this message eludes me. -	c.sendReply(RPL_CREATED, time.Unix(started, 0).Format("Mon, 02 Jan 2006")) +	c.sendReply(RPL_CREATED, started.Format("Mon, 02 Jan 2006"))  	c.sendReply(RPL_MYINFO, serverName, projectVersion,  		ircSupportedUserModes, ircSupportedChanModes) @@ -1691,8 +1686,7 @@ func ircHandleMODE(msg *message, c *client) {  		if len(msg.params) < 2 {  			_, present := ch.userModes[c]  			c.sendReply(RPL_CHANNELMODEIS, target, ch.getMode(present)) -			c.sendReply(RPL_CREATIONTIME, -				target, ch.created/int64(time.Second)) +			c.sendReply(RPL_CREATIONTIME, target, ch.created.Unix())  		} else {  			ircHandleChanModeChange(c, ch, msg.params[1:])  		} @@ -1752,8 +1746,7 @@ func ircHandleUserMessage(msg *message, c *client,  func ircHandlePRIVMSG(msg *message, c *client) {  	ircHandleUserMessage(msg, c, "PRIVMSG", true /* allowAwayReply */) -	// Let's not care too much about success or failure. -	c.lastActive = time.Now().UnixNano() +	c.lastActive = time.Now()  }  func ircHandleNOTICE(msg *message, c *client) { @@ -1980,7 +1973,7 @@ func ircSendWHOISReply(c, target *client) {  		c.sendReply(RPL_WHOISOPERATOR, nick)  	}  	c.sendReply(RPL_WHOISIDLE, nick, -		(time.Now().UnixNano()-target.lastActive)/int64(time.Second)) +		time.Now().Sub(target.lastActive)/time.Second)  	if target.awayMessage != "" {  		c.sendReply(RPL_AWAY, nick, target.awayMessage)  	} @@ -2073,7 +2066,7 @@ func ircSendRPLTOPIC(c *client, ch *channel) {  	} else {  		c.sendReply(RPL_TOPIC, ch.name, ch.topic)  		c.sendReply(RPL_TOPICWHOTIME, -			ch.name, ch.topicWho, ch.topicTime/int64(time.Second)) +			ch.name, ch.topicWho, ch.topicTime.Unix())  	}  } @@ -2109,7 +2102,7 @@ func ircHandleTOPIC(msg *message, c *client) {  	ch.topic = msg.params[1]  	ch.topicWho = fmt.Sprintf("%s@%s@%s", c.nickname, c.username, c.hostname) -	ch.topicTime = time.Now().UnixNano() +	ch.topicTime = time.Now()  	message := fmt.Sprintf(":%s!%s@%s TOPIC %s :%s",  		c.nickname, c.username, c.hostname, target, ch.topic) @@ -2418,7 +2411,7 @@ func ircHandleStatsLinks(c *client, msg *message) {  			len(client.sendQ), // sendq  			client.nSentMessages, client.sentBytes/1024,  			client.nReceivedMessages, client.receivedBytes/1024, -			(time.Now().UnixNano()-client.opened)/int64(time.Second)) +			time.Now().Sub(client.opened)/time.Second)  	}  } @@ -2440,7 +2433,7 @@ func init() {  }  func ircHandleStatsUptime(c *client) { -	uptime := (time.Now().UnixNano() - started) / int64(time.Second) +	uptime := time.Now().Sub(started) / time.Second  	days := uptime / 60 / 60 / 24  	hours := (uptime % (60 * 60 * 24)) / 60 / 60 @@ -2811,10 +2804,13 @@ func processOneEvent() {  		}  		c := &client{ -			transport: conn, -			address:   address, -			hostname:  host, -			port:      port, +			transport:  conn, +			address:    address, +			hostname:   host, +			port:       port, +			capVersion: 301, +			// TODO: Make this configurable and more fine-grained. +			antiflood: newFloodDetector(10*time.Second, 20),  		}  		clients[c] = true  		go prepare(c) @@ -2875,6 +2871,7 @@ func main() {  		log.Fatalln(err)  	} +	started = time.Now()  	go accept(listener)  	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) | 
