Feature/fix blockwise requires message#619
Conversation
WalkthroughIntroduces IDE configuration files under .idea, adjusts example client port, and overhauls blockwise logic to use an exchangeKey derived from remote address, path, and code. BlockWise Do/Handle signatures gain a net.Addr parameter, with TCP/UDP clients updated to pass RemoteAddr(). Token-based cache keys are replaced or complemented by exchangeKey. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant App as Client Code
participant Conn as Conn (TCP/UDP)
participant BW as BlockWise
participant XKey as getExchangeKey
participant Cache as BW Caches
participant Net as Transport
App->>Conn: Send CoAP request
Conn->>BW: Do(req, szx, maxMsg, remoteAddr, inner)
BW->>XKey: compute(addr, path, code)
XKey-->>BW: exchangeKey
BW->>Cache: lookup/store by exchangeKey
BW->>Net: inner(req)
Net-->>BW: response (blocks/complete)
BW->>Cache: assemble/track by exchangeKey
BW-->>Conn: final response
Note over BW,XKey: If token missing, exchangeKey ensures routing per addr+path+code
Conn->>BW: Handle(w, msg, szx, maxMsg, remoteAddr, next)
BW->>XKey: compute if needed
BW->>Cache: route receive/send via exchangeKey
BW-->>Conn: next or continued transfer
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Suggested reviewers
Pre-merge checks (2 passed, 1 warning)❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
Poem
Pre-merge checks (2 passed, 1 warning)❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
Poem
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
tcp/client/conn.go (1)
210-214: Include Uri-Query in the fallback exchange key; Token is already used when present
- BlockWise already uses r.Token().Hash() when Token != 0, so Token is handled.
- getExchangeKey(addr, r) (net/blockwise/blockwise.go:getExchangeKey) currently hashes addr + Path only — it omits Uri‑Query (and request Code). When Token is empty this can cause concurrent exchanges to collide (same path, different queries).
- Change the fallback to hash addr + full-URI (Path + Uri‑Query) + Code (or at minimum include Uri‑Query), and ensure identical key derivation is used everywhere that computes/uses exchangeKey (Do/handle/start/continue/getSentRequest paths in net/blockwise/blockwise.go).
♻️ Duplicate comments (3)
.idea/modules.xml (1)
1-8: Remove IDE module configurationIDE-specific module configuration files should not be part of the repository.
.idea/vcs.xml (1)
1-6: Remove VCS configuration fileVCS mappings are IDE-specific and should be handled locally by each developer.
udp/client/conn.go (1)
443-449: Mirror the exchange-key uniqueness fix here as well.Same concern as TCP: if exchangeKey ignores
Token/Uri-Query, parallel requests to the same resource can interfere. Ensure blockwise.Do uses a key that includesTokenwhen present.See tcp/client/conn.go Lines 210-214.
🧹 Nitpick comments (4)
net/blockwise/blockwise.go (4)
887-888: Address the TODO comment about hash domain separationThe TODO comment indicates a potential hash collision concern that should be addressed to avoid systematic overlaps between token hashes and path/address hashes.
The TODO suggests separating hash domains to avoid collisions. Would you like me to implement a solution that uses different prefixes or hash spaces for token-based vs exchange-based keys?
585-588: Validate exchangeKey assignment logicThe conditional assignment of
exchangeKeywhen it's 0 might mask issues where the exchange key should have been set earlier but wasn't.Consider adding validation or logging to ensure the exchange key is being set as expected:
if exchangeKey == 0 { + // This should only happen for observe responses or when token is used exchangeKey = sendingMessage.Token().Hash() + if exchangeKey == 0 { + return errors.New("invalid exchange key: both exchangeKey and token hash are zero") + } }
359-374: Improve error handling for exchange key generationThe path defaulting to "/" when empty might not be the intended behavior for all CoAP use cases. Also, the error message could be more informative.
path, _ := r.Path() if len(path) == 0 { - path = "/" - print(path) + // RFC 7252 allows empty paths, but we need a default for the exchange key + path = "/" } var exchangeKey uint64 if len(r.Token()) != 0 { exchangeKey = r.Token().Hash() } else { var err error exchangeKey, err = getExchangeKey(remoteAddr, r) if err != nil { - b.errors(fmt.Errorf("cannot get exchange key from request Parameters(%v): %w", r, err)) + b.errors(fmt.Errorf("cannot generate exchange key for tokenless request (path: %s, addr: %v): %w", path, remoteAddr, err)) return } }
161-179: Update function documentationThe comment on line 161 mentions that
getSentRequestFromOutsidemust return a copy, but doesn't explain the newremoteAddrparameter's purpose in the blockwise context.Add documentation explaining why
remoteAddris now required for blockwise transfers:// New provides blockwise. -// getSentRequestFromOutside must return a copy of request which will be released after use. +// remoteAddr is required to generate unique exchange keys for tokenless requests. +// getSentRequestFromOutside must return a copy of request which will be released after use.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
.idea/.gitignore(1 hunks).idea/go-coap.iml(1 hunks).idea/modules.xml(1 hunks).idea/vcs.xml(1 hunks)examples/simple/client/main.go(1 hunks)net/blockwise/blockwise.go(19 hunks)tcp/client/conn.go(2 hunks)udp/client/conn.go(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
examples/simple/client/main.go (1)
udp/client.go (1)
Dial(25-40)
udp/client/conn.go (2)
tcp/client/conn.go (1)
Conn(44-57)mux/client.go (1)
Conn(17-51)
tcp/client/conn.go (2)
udp/client/conn.go (1)
Session(51-68)tcp/client/session.go (1)
Session(22-43)
net/blockwise/blockwise.go (5)
message/pool/message.go (1)
Message(26-41)message/message.go (1)
Message(12-21)pkg/cache/cache.go (2)
NewElement(32-39)Element(14-18)net/responsewriter/responseWriter.go (2)
New(23-38)ResponseWriter(17-21)message/option.go (5)
Block1(73-73)Size1(77-77)Block2(72-72)Size2(74-74)OptionID(27-27)
🔇 Additional comments (3)
net/blockwise/blockwise.go (1)
208-226: Incorrect — Do already validates token and keys cache by token.Hash(). Do returns an error if len(r.Token()) == 0 and then LoadOrStore uses r.Token().Hash(); getExchangeKey(remoteAddr, r) is used in Handle when the token is empty.Likely an incorrect or invalid review comment.
tcp/client/conn.go (1)
354-356: Good: remoteAddr threaded into BlockWise.Handle.This keeps Do/Handle symmetry for keying. No issues here.
udp/client/conn.go (1)
666-673: Good: remoteAddr passed to BlockWise.Handle.Matches the Do path; looks correct.
|
This PR is draft until:
I would greatly appreciate feedback! |
Hi @Theoyor, thank you for your contribution. Here are my two cents on what I think needs to be done. Of course, this should also be covered by tests. If the token is nil, only the remote address should be used as the exchange key. According to the CoAP blockwise transfer specification: Token usage (RFC 7252 §5.3) with blockwise
Summary:
Example with Nil Token |
|
Hi @jkralik, thanks for your review. Did you spot any issues with the code itself apart from the topic, you mentioned (and the tests)? Regarding your comment, I copuldn't find the exact information you mantioned at RFC 7257 §5.3, however it says: "The client SHOULD generate tokens in such a way that tokens currently in use for a given source/destination endpoint pair are unique. [...] An empty token value is appropriate e.g., when no other tokens are in use to a destination, [...]" From which I infer that your statement is still valid and I will change the implementation accordingly. |
…. unit-tests will be implemented later
35d9ce3 to
b4eb8a2
Compare
Hi @Theoyor , An empty token value is appropriate e.g., when no other tokens are in use to a destination, ...Please address the fixes for the test, and also create a test with an empty token. From my side, the MR seems fine. Once these changes are in place, I will test them with our products, and then we can proceed with the merge. |
b4eb8a2
into
plgd-dev:jkralik/fix/blockwise-requires-Message-ID
Fixes #512
Summary by CodeRabbit
New Features
Refactor
Chores