Changeset 488 in code for trunk


Ignore:
Timestamp:
Mar 31, 2021, 3:57:24 PM (4 years ago)
Author:
contact
Message:

Use BARE for internal message IDs

This allows to have shorter and more future-proof IDs. This also
guarantees the IDs will only use reasonable ASCII characters (no
spaces), removing the need to encode them for PING/PONG tokens.

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/downstream.go

    r486 r488  
    351351// ackMsgID acknowledges that a message has been received.
    352352func (dc *downstreamConn) ackMsgID(id string) {
    353         netID, entity, _, err := parseMsgID(id)
     353        netID, entity, err := parseMsgID(id, nil)
    354354        if err != nil {
    355355                dc.logger.Printf("failed to ACK message ID %q: %v", id, err)
     
    366366
    367367func (dc *downstreamConn) sendPing(msgID string) {
    368         token := "soju-msgid-" + base64.RawURLEncoding.EncodeToString([]byte(msgID))
     368        token := "soju-msgid-" + msgID
    369369        dc.SendMessage(&irc.Message{
    370370                Command: "PING",
     
    378378                return
    379379        }
    380         token = strings.TrimPrefix(token, "soju-msgid-")
    381         b, err := base64.RawURLEncoding.DecodeString(token)
    382         if err != nil {
    383                 dc.logger.Printf("received malformed PONG token: %v", err)
    384                 return
    385         }
    386         msgID := string(b)
    387 
     380        msgID := strings.TrimPrefix(token, "soju-msgid-")
    388381        dc.ackMsgID(msgID)
    389382}
  • trunk/go.mod

    r445 r488  
    55require (
    66        git.sr.ht/~emersion/go-scfg v0.0.0-20201019143924-142a8aa629fc
     7        git.sr.ht/~sircmpwn/go-bare v0.0.0-20210331145808-46f9b5e5bcf9
    78        github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21
    89        github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
  • trunk/go.sum

    r445 r488  
    11git.sr.ht/~emersion/go-scfg v0.0.0-20201019143924-142a8aa629fc h1:51BD67xFX+bozd3ZRuOUfalrhx4/nQSh6A9lI08rYOk=
    22git.sr.ht/~emersion/go-scfg v0.0.0-20201019143924-142a8aa629fc/go.mod h1:t+Ww6SR24yYnXzEWiNlOY0AFo5E9B73X++10lrSpp4U=
    3 github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
     3git.sr.ht/~sircmpwn/getopt v0.0.0-20191230200459-23622cc906b3/go.mod h1:wMEGFFFNuPos7vHmWXfszqImLppbc0wEhh6JBfJIUgw=
     4git.sr.ht/~sircmpwn/go-bare v0.0.0-20210331145808-46f9b5e5bcf9 h1:GpgMhmmlPgaKOSU3WnoaSpZGWgnprcS+ss2w9SchYu4=
     5git.sr.ht/~sircmpwn/go-bare v0.0.0-20210331145808-46f9b5e5bcf9/go.mod h1:BVJwbDfVjCjoFiKrhkei6NdGcZYpkDkdyCdg1ukytRA=
    46github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
    57github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
     
    3739github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
    3840github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
    39 github.com/klauspost/compress v1.10.3 h1:OP96hzwJVBIHYU52pVTI6CczrxPvrGfgqF9N5eTO0Q8=
    4041github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
    4142github.com/klauspost/compress v1.11.7 h1:0hzRabrMN4tSTvMfnL3SCv1ZGeAP23ynzodBgaHeMeg=
     
    5758github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
    5859github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
    59 github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
    6060github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
     61github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
     62github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
    6163github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
    6264github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
     
    7375golang.org/x/sys v0.0.0-20210113181707-4bcb84eeeb78 h1:nVuTkr9L6Bq62qpUqKo/RnZCFfzDBL0bYo6w9OJUqZY=
    7476golang.org/x/sys v0.0.0-20210113181707-4bcb84eeeb78/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    75 golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM=
    7677golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
    7778golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf h1:MZ2shdL+ZM/XzY3ZGOnh4Nlpnxz5GSOhOmtHo3iPU6M=
     
    9091gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
    9192gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
     93gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
     94gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
    9295nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k=
    9396nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
  • trunk/msgstore.go

    r441 r488  
    22
    33import (
     4        "bytes"
     5        "encoding/base64"
    46        "fmt"
    5         "strconv"
    6         "strings"
    77        "time"
    88
     9        "git.sr.ht/~sircmpwn/go-bare"
    910        "gopkg.in/irc.v3"
    1011)
     
    3031}
    3132
    32 func formatMsgID(netID int64, entity, extra string) string {
    33         return fmt.Sprintf("%v %v %v", netID, entity, extra)
     33type msgIDType uint
     34
     35const (
     36        msgIDNone msgIDType = iota
     37        msgIDMemory
     38        msgIDFS
     39)
     40
     41const msgIDVersion uint = 0
     42
     43type msgIDHeader struct {
     44        Version uint
     45        Network bare.Int
     46        Target  string
     47        Type    msgIDType
    3448}
    3549
    36 func parseMsgID(s string) (netID int64, entity, extra string, err error) {
    37         l := strings.SplitN(s, " ", 3)
    38         if len(l) != 3 {
    39                 return 0, "", "", fmt.Errorf("invalid message ID %q: expected 3 fields", s)
     50type msgIDBody interface {
     51        msgIDType() msgIDType
     52}
     53
     54func formatMsgID(netID int64, target string, body msgIDBody) string {
     55        var buf bytes.Buffer
     56        w := bare.NewWriter(&buf)
     57
     58        header := msgIDHeader{
     59                Version: msgIDVersion,
     60                Network: bare.Int(netID),
     61                Target:  target,
     62                Type:    body.msgIDType(),
    4063        }
    41         netID, err = strconv.ParseInt(l[0], 10, 64)
     64        if err := bare.MarshalWriter(w, &header); err != nil {
     65                panic(err)
     66        }
     67        if err := bare.MarshalWriter(w, body); err != nil {
     68                panic(err)
     69        }
     70        return base64.RawURLEncoding.EncodeToString(buf.Bytes())
     71}
     72
     73func parseMsgID(s string, body msgIDBody) (netID int64, target string, err error) {
     74        b, err := base64.RawURLEncoding.DecodeString(s)
    4275        if err != nil {
    43                 return 0, "", "", fmt.Errorf("invalid message ID %q: %v", s, err)
     76                return 0, "", fmt.Errorf("invalid internal message ID: %v", err)
    4477        }
    45         return netID, l[1], l[2], nil
     78
     79        r := bare.NewReader(bytes.NewReader(b))
     80
     81        var header msgIDHeader
     82        if err := bare.UnmarshalBareReader(r, &header); err != nil {
     83                return 0, "", fmt.Errorf("invalid internal message ID: %v", err)
     84        }
     85
     86        if header.Version != msgIDVersion {
     87                return 0, "", fmt.Errorf("invalid internal message ID: got version %v, want %v", header.Version, msgIDVersion)
     88        }
     89
     90        if body != nil {
     91                typ := body.msgIDType()
     92                if header.Type != typ {
     93                        return 0, "", fmt.Errorf("invalid internal message ID: got type %v, want %v", header.Type, typ)
     94                }
     95
     96                if err := bare.UnmarshalBareReader(r, body); err != nil {
     97                        return 0, "", fmt.Errorf("invalid internal message ID: %v", err)
     98                }
     99        }
     100
     101        return int64(header.Network), header.Target, nil
    46102}
  • trunk/msgstore_fs.go

    r440 r488  
    1010        "time"
    1111
     12        "git.sr.ht/~sircmpwn/go-bare"
    1213        "gopkg.in/irc.v3"
    1314)
     
    1617
    1718var escapeFilename = strings.NewReplacer("/", "-", "\\", "-")
     19
     20type date struct {
     21        Year, Month, Day int
     22}
     23
     24func newDate(t time.Time) date {
     25        year, month, day := t.Date()
     26        return date{year, int(month), day}
     27}
     28
     29func (d date) Time() time.Time {
     30        return time.Date(d.Year, time.Month(d.Month), d.Day, 0, 0, 0, 0, time.Local)
     31}
     32
     33type fsMsgID struct {
     34        Date   date
     35        Offset bare.Int
     36}
     37
     38func (fsMsgID) msgIDType() msgIDType {
     39        return msgIDFS
     40}
     41
     42func parseFSMsgID(s string) (netID int64, entity string, t time.Time, offset int64, err error) {
     43        var id fsMsgID
     44        netID, entity, err = parseMsgID(s, &id)
     45        if err != nil {
     46                return 0, "", time.Time{}, 0, err
     47        }
     48        return netID, entity, id.Date.Time(), int64(id.Offset), nil
     49}
     50
     51func formatFSMsgID(netID int64, entity string, t time.Time, offset int64) string {
     52        id := fsMsgID{
     53                Date:   newDate(t),
     54                Offset: bare.Int(offset),
     55        }
     56        return formatMsgID(netID, entity, &id)
     57}
    1858
    1959// fsMessageStore is a per-user on-disk store for IRC messages.
     
    3575        filename := fmt.Sprintf("%04d-%02d-%02d.log", year, month, day)
    3676        return filepath.Join(ms.root, escapeFilename.Replace(network.GetName()), escapeFilename.Replace(entity), filename)
    37 }
    38 
    39 func parseFSMsgID(s string) (netID int64, entity string, t time.Time, offset int64, err error) {
    40         netID, entity, extra, err := parseMsgID(s)
    41         if err != nil {
    42                 return 0, "", time.Time{}, 0, err
    43         }
    44 
    45         var year, month, day int
    46         _, err = fmt.Sscanf(extra, "%04d-%02d-%02d %d", &year, &month, &day, &offset)
    47         if err != nil {
    48                 return 0, "", time.Time{}, 0, fmt.Errorf("invalid message ID %q: %v", s, err)
    49         }
    50         t = time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.Local)
    51         return netID, entity, t, offset, nil
    52 }
    53 
    54 func formatFSMsgID(netID int64, entity string, t time.Time, offset int64) string {
    55         year, month, day := t.Date()
    56         extra := fmt.Sprintf("%04d-%02d-%02d %d", year, month, day, offset)
    57         return formatMsgID(netID, entity, extra)
    5877}
    5978
  • trunk/msgstore_memory.go

    r444 r488  
    33import (
    44        "fmt"
    5         "strconv"
    65        "time"
    76
     7        "git.sr.ht/~sircmpwn/go-bare"
    88        "gopkg.in/irc.v3"
    99)
     
    1111const messageRingBufferCap = 4096
    1212
     13type memoryMsgID struct {
     14        Seq bare.Uint
     15}
     16
     17func (memoryMsgID) msgIDType() msgIDType {
     18        return msgIDMemory
     19}
     20
    1321func parseMemoryMsgID(s string) (netID int64, entity string, seq uint64, err error) {
    14         netID, entity, extra, err := parseMsgID(s)
     22        var id memoryMsgID
     23        netID, entity, err = parseMsgID(s, &id)
    1524        if err != nil {
    1625                return 0, "", 0, err
    1726        }
    18         seq, err = strconv.ParseUint(extra, 10, 64)
    19         if err != nil {
    20                 return 0, "", 0, fmt.Errorf("failed to parse message ID %q: %v", s, err)
    21         }
    22         return netID, entity, seq, nil
     27        return netID, entity, uint64(id.Seq), nil
    2328}
    2429
    2530func formatMemoryMsgID(netID int64, entity string, seq uint64) string {
    26         extra := strconv.FormatUint(seq, 10)
    27         return formatMsgID(netID, entity, extra)
     31        id := memoryMsgID{bare.Uint(seq)}
     32        return formatMsgID(netID, entity, &id)
    2833}
    2934
Note: See TracChangeset for help on using the changeset viewer.