@@ -5,7 +5,7 @@ package multistream
55
66import (
77 "bufio"
8- "encoding/hex "
8+ "bytes "
99 "errors"
1010 "fmt"
1111 "io"
@@ -26,6 +26,9 @@ var ErrUnknownPrefix = errors.New("unknown protocol hash prefix")
2626// the multistream muxers on both sides of a channel can work with each other.
2727const ProtocolID = "/multistream/1.0.0"
2828
29+ // ProtocolID identifies the multistream protocol abbreviation support
30+ var ProtocolAbbrev = []byte {0xff , 0x11 }
31+
2932// Multistream-select version that protocol abbreviation is supported
3033const AbbrevSupportedMSSVersion = 2
3134
@@ -186,24 +189,6 @@ func (msm *MultistreamMuxer[T]) Protocols() []T {
186189// fails because of a ProtocolID mismatch.
187190var ErrIncorrectVersion = errors .New ("client connected with incorrect version" )
188191
189- func (msm * MultistreamMuxer [T ]) decodeProtocol (s T ) (T , error ) {
190- msm .handlerlock .RLock ()
191- defer msm .handlerlock .RUnlock ()
192-
193- bytes , err := hex .DecodeString (string (s ))
194- // TODO: decide whether to compare strings or use abbrevTree by looking at
195- // multistream version instead.
196- if err != nil {
197- return s , nil
198- }
199-
200- proto , err := msm .abbrevTree .GetProtocolID (bytes )
201- if err != nil {
202- return "" , err
203- }
204- return proto , nil
205- }
206-
207192func (msm * MultistreamMuxer [T ]) findHandler (proto T ) * Handler [T ] {
208193 msm .handlerlock .RLock ()
209194 defer msm .handlerlock .RUnlock ()
@@ -227,35 +212,49 @@ func (msm *MultistreamMuxer[T]) Negotiate(rwc io.ReadWriteCloser) (proto T, hand
227212 }
228213 }()
229214
230- // Send the multistream protocol ID
231- // Ignore the error here. We want the handshake to finish, even if the
232- // other side has closed this rwc for writing. They may have sent us a
233- // message and closed. Future writers will get an error anyways.
234- _ = delimWriteBuffered (rwc , []byte (ProtocolID ))
235- line , err := ReadNextToken [T ](rwc )
215+ token , err := ReadNextTokenBytes (rwc )
236216 if err != nil {
237217 return "" , nil , err
238218 }
239-
240- if line != ProtocolID {
219+ supportAbbrev := false
220+ // Send the multistream protocol ID or the mulstream protocol abbreviation
221+ // Ignore the error here. We want the handshake to finish, even if the
222+ // other side has closed this rwc for writing. They may have sent us a
223+ // message and closed. Future writers will get an error anyways.
224+ if bytes .Equal (token , ProtocolAbbrev ) {
225+ supportAbbrev = true
226+ _ = delimWriteBuffered (rwc , ProtocolAbbrev )
227+ } else if T (token ) == ProtocolID {
228+ _ = delimWriteBuffered (rwc , []byte (ProtocolID ))
229+ } else {
241230 rwc .Close ()
242231 return "" , nil , ErrIncorrectVersion
243232 }
244233
245234loop:
246235 for {
247236 // Now read and respond to commands until they send a valid protocol id
248- tok , err := ReadNextToken [T ](rwc )
237+ var proto T
238+
239+ tok , err := ReadNextTokenBytes (rwc )
249240 if err != nil {
250241 return "" , nil , err
251242 }
252243
253- p , err := msm .decodeProtocol (tok )
254- if err != nil {
255- return "" , nil , err
244+ if supportAbbrev {
245+ // decode the protocol abbreviation using the abbreviation tree
246+ msm .handlerlock .RLock ()
247+ proto , err = msm .abbrevTree .GetProtocolID (tok )
248+ msm .handlerlock .RUnlock ()
249+
250+ if err != nil {
251+ return "" , nil , err
252+ }
253+ } else {
254+ proto = T (tok )
256255 }
257256
258- h := msm .findHandler (p )
257+ h := msm .findHandler (proto )
259258 if h == nil {
260259 if err := delimWriteBuffered (rwc , []byte ("na" )); err != nil {
261260 return "" , nil , err
@@ -266,10 +265,10 @@ loop:
266265 // Ignore the error here. We want the handshake to finish, even if the
267266 // other side has closed this rwc for writing. They may have sent us a
268267 // message and closed. Future writers will get an error anyways.
269- _ = delimWriteBuffered (rwc , [] byte ( tok ) )
268+ _ = delimWriteBuffered (rwc , tok )
270269
271270 // hand off processing to the sub-protocol handler
272- return p , h .Handle , nil
271+ return proto , h .Handle , nil
273272 }
274273
275274}
0 commit comments