5
5
"context"
6
6
"errors"
7
7
"fmt"
8
+ "hash/crc64"
8
9
"io"
10
+ "net"
9
11
"time"
10
12
11
13
"github.com/dsnet/golib/memfile"
@@ -131,14 +133,17 @@ type Client interface {
131
133
AcquireMessage (ctx context.Context ) * pool.Message
132
134
// return back the message to the pool for next use
133
135
ReleaseMessage (m * pool.Message )
136
+
137
+ // The remote address for determining the endpoint pair
138
+ RemoteAddr () net.Addr
134
139
}
135
140
136
141
type BlockWise [C Client ] struct {
137
142
cc C
138
143
receivingMessagesCache * cache.Cache [uint64 , * messageGuard ]
139
144
sendingMessagesCache * cache.Cache [uint64 , * pool.Message ]
140
145
errors func (error )
141
- getSentRequestFromOutside func (token message. Token ) (* pool.Message , bool )
146
+ getSentRequestFromOutside func (hash uint64 ) (* pool.Message , bool )
142
147
expiration time.Duration
143
148
}
144
149
@@ -160,10 +165,10 @@ func New[C Client](
160
165
cc C ,
161
166
expiration time.Duration ,
162
167
errors func (error ),
163
- getSentRequestFromOutside func (token message. Token ) (* pool.Message , bool ),
168
+ getSentRequestFromOutside func (hash uint64 ) (* pool.Message , bool ),
164
169
) * BlockWise [C ] {
165
170
if getSentRequestFromOutside == nil {
166
- getSentRequestFromOutside = func (message. Token ) (* pool.Message , bool ) { return nil , false }
171
+ getSentRequestFromOutside = func (uint64 ) (* pool.Message , bool ) { return nil , false }
167
172
}
168
173
return & BlockWise [C ]{
169
174
cc : cc ,
@@ -214,11 +219,12 @@ func (b *BlockWise[C]) Do(r *pool.Message, maxSzx SZX, maxMessageSize uint32, do
214
219
if ! ok {
215
220
expire = time .Now ().Add (b .expiration )
216
221
}
217
- _ , loaded := b .sendingMessagesCache .LoadOrStore (r .Token ().Hash (), cache .NewElement (r , expire , nil ))
222
+ matchableHash := generateMatchableHash (r .Options (), b .cc .RemoteAddr (), r .Code ())
223
+ _ , loaded := b .sendingMessagesCache .LoadOrStore (matchableHash , cache .NewElement (r , expire , nil ))
218
224
if loaded {
219
225
return nil , errors .New ("invalid token" )
220
226
}
221
- defer b .sendingMessagesCache .Delete (r . Token (). Hash () )
227
+ defer b .sendingMessagesCache .Delete (matchableHash )
222
228
if r .Body () == nil {
223
229
return do (r )
224
230
}
@@ -282,9 +288,9 @@ func (b *BlockWise[C]) WriteMessage(request *pool.Message, maxSZX SZX, maxMessag
282
288
if err != nil {
283
289
return fmt .Errorf ("cannot encode start sending message block option(%v,%v,%v): %w" , maxSZX , 0 , true , err )
284
290
}
285
-
291
+ matchableHash := generateMatchableHash ( request . Options (), b . cc . RemoteAddr (), request . Code ())
286
292
w := newWriteRequestResponse (b .cc , request )
287
- err = b .startSendingMessage (w , maxSZX , maxMessageSize , startSendingMessageBlock )
293
+ err = b .startSendingMessage (w , maxSZX , maxMessageSize , startSendingMessageBlock , matchableHash )
288
294
if err != nil {
289
295
return fmt .Errorf ("cannot start writing request: %w" , err )
290
296
}
@@ -333,8 +339,8 @@ func wantsToBeReceived(r *pool.Message) bool {
333
339
return true
334
340
}
335
341
336
- func (b * BlockWise [C ]) getSendingMessageCode (token uint64 ) (codes.Code , bool ) {
337
- v := b .sendingMessagesCache .Load (token )
342
+ func (b * BlockWise [C ]) getSendingMessageCode (hash uint64 ) (codes.Code , bool ) {
343
+ v := b .sendingMessagesCache .Load (hash )
338
344
if v == nil {
339
345
return codes .Empty , false
340
346
}
@@ -348,19 +354,20 @@ func (b *BlockWise[C]) Handle(w *responsewriter.ResponseWriter[C], r *pool.Messa
348
354
}
349
355
token := r .Token ()
350
356
357
+ matchableHash := generateMatchableHash (r .Options (), w .Conn ().RemoteAddr (), r .Code ())
358
+
351
359
if len (token ) == 0 {
352
- err := b .handleReceivedMessage (w , r , maxSZX , maxMessageSize , next )
360
+ err := b .handleReceivedMessage (w , r , maxSZX , maxMessageSize , next , matchableHash )
353
361
if err != nil {
354
362
b .sendEntityIncomplete (w , token )
355
363
b .errors (fmt .Errorf ("handleReceivedMessage(%v): %w" , r , err ))
356
364
}
357
365
return
358
366
}
359
- tokenStr := token .Hash ()
360
367
361
- sendingMessageCode , sendingMessageExist := b .getSendingMessageCode (tokenStr )
368
+ sendingMessageCode , sendingMessageExist := b .getSendingMessageCode (matchableHash )
362
369
if ! sendingMessageExist || wantsToBeReceived (r ) {
363
- err := b .handleReceivedMessage (w , r , maxSZX , maxMessageSize , next )
370
+ err := b .handleReceivedMessage (w , r , maxSZX , maxMessageSize , next , matchableHash )
364
371
if err != nil {
365
372
b .sendEntityIncomplete (w , token )
366
373
b .errors (fmt .Errorf ("handleReceivedMessage(%v): %w" , r , err ))
@@ -369,17 +376,17 @@ func (b *BlockWise[C]) Handle(w *responsewriter.ResponseWriter[C], r *pool.Messa
369
376
}
370
377
more , err := b .continueSendingMessage (w , r , maxSZX , maxMessageSize , sendingMessageCode )
371
378
if err != nil {
372
- b .sendingMessagesCache .Delete (tokenStr )
379
+ b .sendingMessagesCache .Delete (matchableHash )
373
380
b .errors (fmt .Errorf ("continueSendingMessage(%v): %w" , r , err ))
374
381
return
375
382
}
376
383
// For codes GET,POST,PUT,DELETE, we want them to wait for pairing response and then delete them when the full response comes in or when timeout occurs.
377
384
if ! more && sendingMessageCode > codes .DELETE {
378
- b .sendingMessagesCache .Delete (tokenStr )
385
+ b .sendingMessagesCache .Delete (matchableHash )
379
386
}
380
387
}
381
388
382
- func (b * BlockWise [C ]) handleReceivedMessage (w * responsewriter.ResponseWriter [C ], r * pool.Message , maxSZX SZX , maxMessageSize uint32 , next func (w * responsewriter.ResponseWriter [C ], r * pool.Message )) error {
389
+ func (b * BlockWise [C ]) handleReceivedMessage (w * responsewriter.ResponseWriter [C ], r * pool.Message , maxSZX SZX , maxMessageSize uint32 , next func (w * responsewriter.ResponseWriter [C ], r * pool.Message ), rx_hash uint64 ) error {
383
390
startSendingMessageBlock , err := EncodeBlockOption (maxSZX , 0 , true )
384
391
if err != nil {
385
392
return fmt .Errorf ("cannot encode start sending message block option(%v,%v,%v): %w" , maxSZX , 0 , true , err )
@@ -411,7 +418,7 @@ func (b *BlockWise[C]) handleReceivedMessage(w *responsewriter.ResponseWriter[C]
411
418
return errP
412
419
}
413
420
}
414
- return b .startSendingMessage (w , maxSZX , maxMessageSize , startSendingMessageBlock )
421
+ return b .startSendingMessage (w , maxSZX , maxMessageSize , startSendingMessageBlock , rx_hash )
415
422
}
416
423
417
424
func (b * BlockWise [C ]) createSendingMessage (sendingMessage * pool.Message , maxSZX SZX , maxMessageSize uint32 , block uint32 ) (sendMessage * pool.Message , more bool , err error ) {
@@ -504,7 +511,8 @@ func (b *BlockWise[C]) continueSendingMessage(w *responsewriter.ResponseWriter[C
504
511
}
505
512
var sendMessage * pool.Message
506
513
var more bool
507
- b .sendingMessagesCache .LoadWithFunc (r .Token ().Hash (), func (value * cache.Element [* pool.Message ]) * cache.Element [* pool.Message ] {
514
+ matchableHash := generateMatchableHash (r .Options (), w .Conn ().RemoteAddr (), r .Code ())
515
+ b .sendingMessagesCache .LoadWithFunc (matchableHash , func (value * cache.Element [* pool.Message ]) * cache.Element [* pool.Message ] {
508
516
sendMessage , more , err = b .createSendingMessage (value .Data (), maxSZX , maxMessageSize , block )
509
517
if err != nil {
510
518
err = fmt .Errorf ("cannot create sending message: %w" , err )
@@ -529,7 +537,7 @@ func isObserveResponse(msg *pool.Message) bool {
529
537
return msg .Code () >= codes .Created
530
538
}
531
539
532
- func (b * BlockWise [C ]) startSendingMessage (w * responsewriter.ResponseWriter [C ], maxSZX SZX , maxMessageSize uint32 , block uint32 ) error {
540
+ func (b * BlockWise [C ]) startSendingMessage (w * responsewriter.ResponseWriter [C ], maxSZX SZX , maxMessageSize uint32 , block uint32 , rx_hash uint64 ) error {
533
541
payloadSize , err := w .Message ().BodySize ()
534
542
if err != nil {
535
543
return payloadSizeError (err )
@@ -552,16 +560,16 @@ func (b *BlockWise[C]) startSendingMessage(w *responsewriter.ResponseWriter[C],
552
560
if ! ok {
553
561
expire = time .Now ().Add (b .expiration )
554
562
}
555
- el , loaded := b .sendingMessagesCache .LoadOrStore (sendingMessage . Token (). Hash () , cache .NewElement (originalSendingMessage , expire , nil ))
563
+ el , loaded := b .sendingMessagesCache .LoadOrStore (rx_hash , cache .NewElement (originalSendingMessage , expire , nil ))
556
564
if loaded {
557
565
defer b .cc .ReleaseMessage (originalSendingMessage )
558
566
return fmt .Errorf ("cannot add message (%v) to sending message cache: message(%v) with token(%v) already exist" , originalSendingMessage , el .Data (), sendingMessage .Token ())
559
567
}
560
568
return nil
561
569
}
562
570
563
- func (b * BlockWise [C ]) getSentRequest (token message. Token ) * pool.Message {
564
- data , ok := b .sendingMessagesCache .LoadWithFunc (token . Hash () , func (value * cache.Element [* pool.Message ]) * cache.Element [* pool.Message ] {
571
+ func (b * BlockWise [C ]) getSentRequest (hash uint64 ) * pool.Message {
572
+ data , ok := b .sendingMessagesCache .LoadWithFunc (hash , func (value * cache.Element [* pool.Message ]) * cache.Element [* pool.Message ] {
565
573
if value == nil {
566
574
return nil
567
575
}
@@ -576,7 +584,7 @@ func (b *BlockWise[C]) getSentRequest(token message.Token) *pool.Message {
576
584
if ok {
577
585
return data .Data ()
578
586
}
579
- globalRequest , ok := b .getSentRequestFromOutside (token )
587
+ globalRequest , ok := b .getSentRequestFromOutside (hash )
580
588
if ok {
581
589
return globalRequest
582
590
}
@@ -595,7 +603,8 @@ func (b *BlockWise[C]) handleObserveResponse(sentRequest *pool.Message) (message
595
603
validUntil := time .Now ().Add (b .expiration ) // context of observation can be expired.
596
604
bwSentRequest := b .cloneMessage (sentRequest )
597
605
bwSentRequest .SetToken (token )
598
- _ , loaded := b .sendingMessagesCache .LoadOrStore (token .Hash (), cache .NewElement (bwSentRequest , validUntil , nil ))
606
+ matchableHash := generateMatchableHash (sentRequest .Options (), b .cc .RemoteAddr (), sentRequest .Code ())
607
+ _ , loaded := b .sendingMessagesCache .LoadOrStore (matchableHash , cache .NewElement (bwSentRequest , validUntil , nil ))
599
608
if loaded {
600
609
return nil , time.Time {}, errors .New ("cannot process message: message with token already exist" )
601
610
}
@@ -674,7 +683,7 @@ func copyToPayloadFromOffset(r *pool.Message, payloadFile *memfile.File, offset
674
683
return payloadSize , nil
675
684
}
676
685
677
- func (b * BlockWise [C ]) getCachedReceivedMessage (mg * messageGuard , r * pool.Message , tokenStr uint64 , validUntil time.Time ) (* pool.Message , func (), error ) {
686
+ func (b * BlockWise [C ]) getCachedReceivedMessage (mg * messageGuard , r * pool.Message , tokenStr uint64 , matchableHash uint64 , validUntil time.Time ) (* pool.Message , func (), error ) {
678
687
cannotLockError := func (err error ) error {
679
688
return fmt .Errorf ("processReceivedMessage: cannot lock message: %w" , err )
680
689
}
@@ -708,11 +717,11 @@ func (b *BlockWise[C]) getCachedReceivedMessage(mg *messageGuard, r *pool.Messag
708
717
return nil , nil , cannotLockError (errA )
709
718
}
710
719
appendToClose (mg )
711
- element , loaded := b .receivingMessagesCache .LoadOrStore (tokenStr , cache .NewElement (mg , validUntil , func (d * messageGuard ) {
720
+ element , loaded := b .receivingMessagesCache .LoadOrStore (matchableHash , cache .NewElement (mg , validUntil , func (d * messageGuard ) {
712
721
if d == nil {
713
722
return
714
723
}
715
- b .sendingMessagesCache .Delete (tokenStr )
724
+ b .sendingMessagesCache .Delete (matchableHash )
716
725
}))
717
726
// request was already stored in cache, silently
718
727
if loaded {
@@ -732,6 +741,41 @@ func (b *BlockWise[C]) getCachedReceivedMessage(mg *messageGuard, r *pool.Messag
732
741
return mg .Message , closeFn , nil
733
742
}
734
743
744
+ /*
745
+ RFC9175 1.1:
746
+ Two request messages are said to be "matchable" if they occur between
747
+ the same endpoint pair, have the same code, and have the same set of
748
+ options, with the exception that elective NoCacheKey options and
749
+ options involved in block-wise transfer (Block1, Block2, and Request-
750
+ Tag) need not be the same. Two blockwise request operations are said
751
+ to be matchable if their request messages are matchable.
752
+
753
+ This function concatenates the IDs and values of relevant options, the string representation of the remote address,
754
+ and the code of the message to generate a hash that can be used to match requests.
755
+ */
756
+ func generateMatchableHash (options message.Options , remoteAddr net.Addr , code codes.Code ) uint64 {
757
+ options_str := ""
758
+
759
+ input := make ([]byte , 0 , 512 )
760
+
761
+ for _ , opt := range options {
762
+ options_str += opt .ID .String () + ","
763
+ switch opt .ID {
764
+ // Skip Blockwise Options and NoCacheKey Options
765
+ case message .Block1 , message .Block2 , message .Size1 , message .Size2 , message .RequestTag :
766
+ continue
767
+ }
768
+ input = append (input , byte (opt .ID ))
769
+ input = append (input , opt .Value ... )
770
+ }
771
+
772
+ input = append (input , []byte (remoteAddr .Network ())... )
773
+ input = append (input , []byte (remoteAddr .String ())... )
774
+ input = append (input , byte (code ))
775
+
776
+ return crc64 .Checksum (input , crc64 .MakeTable (crc64 .ISO ))
777
+ }
778
+
735
779
//nolint:gocyclo,gocognit
736
780
func (b * BlockWise [C ]) processReceivedMessage (w * responsewriter.ResponseWriter [C ], r * pool.Message , maxSzx SZX , next func (w * responsewriter.ResponseWriter [C ], r * pool.Message ), blockType message.OptionID , sizeType message.OptionID ) error {
737
781
token := r .Token ()
@@ -755,7 +799,8 @@ func (b *BlockWise[C]) processReceivedMessage(w *responsewriter.ResponseWriter[C
755
799
if err != nil {
756
800
return fmt .Errorf ("cannot decode block option: %w" , err )
757
801
}
758
- sentRequest := b .getSentRequest (token )
802
+ matchableHash := generateMatchableHash (r .Options (), w .Conn ().RemoteAddr (), r .Code ())
803
+ sentRequest := b .getSentRequest (matchableHash )
759
804
if sentRequest != nil {
760
805
defer b .cc .ReleaseMessage (sentRequest )
761
806
}
@@ -772,7 +817,7 @@ func (b *BlockWise[C]) processReceivedMessage(w *responsewriter.ResponseWriter[C
772
817
773
818
tokenStr := token .Hash ()
774
819
var cachedReceivedMessageGuard * messageGuard
775
- if e := b .receivingMessagesCache .Load (tokenStr ); e != nil {
820
+ if e := b .receivingMessagesCache .Load (matchableHash ); e != nil {
776
821
cachedReceivedMessageGuard = e .Data ()
777
822
}
778
823
if cachedReceivedMessageGuard == nil {
@@ -783,15 +828,15 @@ func (b *BlockWise[C]) processReceivedMessage(w *responsewriter.ResponseWriter[C
783
828
return nil
784
829
}
785
830
}
786
- cachedReceivedMessage , closeCachedReceivedMessage , err := b .getCachedReceivedMessage (cachedReceivedMessageGuard , r , tokenStr , validUntil )
831
+ cachedReceivedMessage , closeCachedReceivedMessage , err := b .getCachedReceivedMessage (cachedReceivedMessageGuard , r , tokenStr , matchableHash , validUntil )
787
832
if err != nil {
788
833
return err
789
834
}
790
835
defer closeCachedReceivedMessage ()
791
836
792
837
defer func (err * error ) {
793
838
if * err != nil {
794
- b .receivingMessagesCache .Delete (tokenStr )
839
+ b .receivingMessagesCache .Delete (matchableHash )
795
840
}
796
841
}(& err )
797
842
payloadFile , payloadSize , err := b .getPayloadFromCachedReceivedMessage (r , cachedReceivedMessage )
@@ -805,12 +850,12 @@ func (b *BlockWise[C]) processReceivedMessage(w *responsewriter.ResponseWriter[C
805
850
return fmt .Errorf ("cannot copy data to payload: %w" , err )
806
851
}
807
852
if ! more {
808
- b .receivingMessagesCache .Delete (tokenStr )
853
+ b .receivingMessagesCache .Delete (matchableHash )
809
854
cachedReceivedMessage .Remove (blockType )
810
855
cachedReceivedMessage .Remove (sizeType )
811
856
cachedReceivedMessage .SetType (r .Type ())
812
857
if ! bytes .Equal (cachedReceivedMessage .Token (), token ) {
813
- b .sendingMessagesCache .Delete (tokenStr )
858
+ b .sendingMessagesCache .Delete (matchableHash )
814
859
}
815
860
_ , errS := cachedReceivedMessage .Body ().Seek (0 , io .SeekStart )
816
861
if errS != nil {
0 commit comments