Skip to content

feat: パケットフィールド拡充・バグ修正・テスト強化 - #86

Merged
9c5s merged 16 commits into
mainfrom
feat/packet-improvements
Apr 12, 2026
Merged

9c5s merged 16 commits into
mainfrom
feat/packet-improvements

Conversation

@9c5s

@9c5s 9c5s commented Apr 12, 2026

Copy link
Copy Markdown
Owner

概要

TCNetパケットの7つのissueを一括対応し、レビュー指摘・実機検証結果を反映した。

バグ修正

機能追加

破壊的変更

テスト・品質改善

ドキュメント

  • Implementation-Status.md: 全対応issueの実装状況を反映
  • PRO-DJ-LINK-Bridge.md: Mixer データ制限をTCNetマスター種類別に更新 (実機検証に基づく)

実機検証結果

Bridge (BRIDGE22) + ShowKontrol (TCS-SK8) + CDJ-3000 環境で全issueを検証済み。

Issue 検証結果
#73 クラッシュ修正 コード修正確認
#72 Mixer ID mixerId=0, layer=0 正常マッチ
#75 Mixer全フィールド 16/16定義、11非ゼロ
#76 Timecode SKマスターで8レイヤー全てstate=Running確認
#77 Error構造化 30B固定、code=255 (UInt16LE)
#78 ヘッダー公開 BeatGrid/SmallWaveForm/BigWaveForm/Artwork全確認
#80 APP SPECIFIC 72B、"PRODJLINK BR..."含む

テスト

300テスト全通過、typecheck/lint/build全通過。

closes #72, closes #73, closes #75, closes #76, closes #77, closes #78, closes #80, closes #84, closes #85

9c5s added 13 commits April 13, 2026 01:24
BREAKING CHANGE: errorDataプロパティを廃止し、dataType/layerId/code/messageTypeに分割

closes #77
- parsePacketのnullチェックを!= nullに統一 (#73と同根のバグ)
- changeset本文にBREAKING CHANGE注記を追加
- auth.test.tsのテスト名を実態に合わせて修正
- TCNetTimecode.modeをsmpteModeにリネーム
- TCNetTimePacketTimecode型を削除しTCNetTimecodeクラスで置換
- TimePacket.read()でTCNetTimecode.read()を活用
- StatusPacket.appSpecificの防御的ガードに意図コメント追加
マスター種類によるフィールド取得可否の差異を表で記載
- masterAudioLevel: 常に0 (マスター種類に依らない)
- チャンネルaudioLevel: SKマスターのみ取得可能
- EQ/Filter/Trim等: Bridgeマスターのみ取得可能
- フェーダー位置: 両方で取得可能
BREAKING CHANGE: MixerChannel.crossfaderAssignをcrossFaderAssignに変更

- MixerData側のcrossFader/crossFaderCurveと命名規則を統一
- Implementation-Status.mdのSmallWaveForm備考を他行と統一
- Bridge WikiにTCNetマスター種類の説明を追加
- readMultiPacketHeaderに42バイト未満ガードを追加 (短バッファでRangeError防止)
- receiveUnicastに24バイト未満の早期リターンを追加
- マルチパケットアセンブラ分岐に42バイト未満ガードを追加
- テスト: 短バッファ/未定義dataType/requestDataバリデーションを網羅

closes #85
@changeset-bot

changeset-bot Bot commented Apr 12, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: ae48cd9

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@9c5s/node-tcnet Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Apr 12, 2026 •

Copy link
Copy Markdown

Summary by CodeRabbit

  • バグ修正

    • undefined なデータタイプを含む受信パケットでのクラッシュを修正
    • Mixer ID 変換の誤りを修正
    • 受信処理の不正サイズデータ耐性を強化(短い/不完全なデータによる例外回避)
  • 新機能

    • Status パケットの APP SPECIFIC 領域を取得・公開
    • エラーパケットを構造化して解析・判定可能に改善
    • Time パケットのタイムコードセクション対応
    • マルチパケットヘッダー情報の公開
    • Mixer の取得項目を大幅拡張(EQ/FX/ヘッドフォン/ブース/クロスフェーダ等)
  • ドキュメント

    • 実装状況と Mixer/Bridge の仕様説明を詳細化
  • テスト

    • 解析・受信処理を網羅するテスト群を追加・更新

Walkthrough

複数のTCNetパケット解析と受信フローを拡張・堅牢化します。Mixer ID/フィールド拡張、Timecode/APP SPECIFIC/マルチパケットヘッダー公開、Errorパケットの構造化、短バッファ・未定義 dataType のクラッシュ防止、認証判定ロジックの更新を行います。

Changes

Cohort / File(s) Summary
Changesetファイル
​.changeset/brave-dots-play.md, ​.changeset/mixer-id-and-fields.md, ​.changeset/packet-field-extensions.md
リリース用メタデータ追加。patch/minor/minor+breaking として変更点を記録(Errorフィールドの構造化は破壊的変更として宣言)。
ドキュメント
docs/wiki/Implementation-Status.md, docs/wiki/PRO-DJ-LINK-Bridge.md
実装状況とBridge/ShowKontrol差の説明を詳細化(Status/Error/Time の備考更新、Master別フィールド可用性の明示)。
パケット解析ロジック
src/network.ts
Statusに`appSpecific: Buffer
受信・制御ロジック
src/tcnet.ts
パケットクラス検査を!= nullに変更してundefinedを除外、receiveUnicastに最小バッファ長ガード(短いdatagramでの固定オフセット読取防止)追加、マルチパケット組立完了時にmultiPacketHeaderを設定、認証エラー処理を生バイト参照から構造化フィールド比較へ変更。
型定義
src/types.ts
MixerChannel.crossfaderAssign→crossFaderAssignに改名。MixerDataにmic EQ、cue/link、send FX系、sendReturn3系、beatFx周波数、headphones/booth EQ/mix、crossFader等多数フィールドを追加(フィールド順入替あり)。
テスト
tests/auth.test.ts, tests/beatgrid-mixer.test.ts, tests/packet-fields.test.ts, tests/packet-parsers.test.ts, tests/receive-unicast.test.ts
Errorパケットの構造化フィールド検証、マルチパケットヘッダー公開・条件分岐テスト、Timecodeレイヤ別解析テスト、Status.appSpecificのコピー検証、短バッファ・未定義dataType受信の非例外化テスト、認証フローテストのヘルパ整理等を追加・更新。

Sequence Diagram(s)

sequenceDiagram
    participant Socket as UDP Socket
    participant Receiver as receiveUnicast
    participant Parser as Packet Parser
    participant Assembler as MultiPacketAssembler
    participant Auth as Auth Handler

    Socket->>Receiver: datagram(msg)
    Receiver->>Receiver: validate length (>=24, multi-header >=42)
    Receiver->>Parser: parse management header -> base Packet
    alt packet.type == Data
        Parser->>Parser: lookup dataPacketClass (nw.TCNetDataPackets[dataType])
        alt dataPacketClass != null
            Parser->>Parser: new dataPacketClass()
            Parser->>Parser: assign buffer/header
            Parser->>Assembler: append chunk / try assemble
            Assembler->>Parser: assembled finalPacket
            Parser->>Parser: if "multiPacketHeader" in finalPacket -> readMultiPacketHeader(msg)
            Parser->>Parser: packet.read()
        else
            Parser->>Receiver: ignore / do not construct
        end
    end
    alt packet is Error
        Parser->>Auth: provide structured fields (dataType, layerId, code, messageType)
        Auth->>Auth: evaluate auth success/fail -> update state
    end
    Parser->>Receiver: emit parsed packet (if applicable)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed PR タイトルは「パケットフィールド拡充・バグ修正・テスト強化」であり、複数の主要な変更(バグ修正、機能追加、テスト強化)を含むため、タイトルはこの大規模な変更セットの概要をよく反映しています。
Description check ✅ Passed PR 説明は詳細に概要・バグ修正・機能追加・破壊的変更・テスト改善・ドキュメント更新および実機検証結果を記載しており、変更セット全体に関連した充実した説明となっています。
Linked Issues check ✅ Passed PR は #72, #73, #75, #76, #77, #78, #80, #84, #85 の 9 つの issue をカバーしており、各 issue の要件(Mixer ID 修正、未定義 dataType クラッシュ修正、MixerData フィールド追加、Timecode 読み取り、Error 構造化、マルチパケットヘッダー公開、APP SPECIFIC 読 取、テスト改善)が実装されています。
Out of Scope Changes check ✅ Passed すべての変更が指定された issue の要件に関連しており、バグ修正、機能追加、テスト強化、ドキュメント更新が一貫して issue オブジェクティブに沿っています。

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

📋 Issue Planner

Built with CodeRabbit's Coding Plans for faster development and fewer bugs.

View plans used: #72, #73, #75, #76, #77, #78, #80, #84, #85

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/packet-improvements

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request significantly expands the TCNet protocol implementation by structuring packet fields for Error, Status, and Time packets, and adding comprehensive fields to the Mixer data structure. It also exposes multi-packet headers for various data types and includes documentation updates and bug fixes for Mixer ID conversion and crash prevention on undefined data types. The review feedback identifies a potential regression in authentication logic where stricter code checks might fail against certain hardware responses, an inconsistency between test data and implementation expectations, and a redundant buffer read in the artwork packet parser.

Comment thread src/tcnet.ts
Comment thread src/network.ts Outdated
Comment thread tests/auth.test.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d9d6be46d9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/network.ts
- readAssembledパスでmultiPacketHeaderを設定 (CodeRabbit P2)
- Artwork.read()のreadUInt32LE(38)をmultiPacketHeader経由に変更
- readMultiPacketHeaderをexportしてtcnet.tsから利用可能に
- ErrorPacketパーサーテストのデータを非認証値(0x1234)に変更

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: af849b9a3d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/tcnet.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/tcnet.ts (1)

714-727: ⚠️ Potential issue | 🟠 Major

短バッファ防御が Data/File の実読込まで届いていません。

msg.length < 24 では TCNetDataPacket.read() が参照する byte 24/25 を守れないので、24B/25B の Data/File でまだ RangeError になります。さらに既知 dataType でも TCNetDataPacketMetrics / TCNetDataPacketMetadata / TCNetDataPacketCUE は dataPacket.read() 内で固定オフセットを読むため、26B 以上でも短いパケットで同様に落ちます。parsePacket() 前に Data/File の 26B ガードを入れ、具象パケット生成後は length() を使って最小長を満たす場合だけ read() してください。

💡 修正案
-        if (msg.length < 24) return;
+        if (msg.length < 24) return;
         const mgmtHeader = new nw.TCNetManagementHeader(msg);
         mgmtHeader.read();
+        if (
+            (mgmtHeader.messageType === nw.TCNetMessageType.Data ||
+                mgmtHeader.messageType === nw.TCNetMessageType.File) &&
+            msg.length < 26
+        ) {
+            return;
+        }
         const packet = this.parsePacket(mgmtHeader);
@@
                 const dataPacket: nw.TCNetDataPacket = new dataPacketClass();
                 dataPacket.buffer = msg;
                 dataPacket.header = mgmtHeader;
                 dataPacket.dataType = packet.dataType;
                 dataPacket.layer = packet.layer;
+                const expectedLength = dataPacket.length();
+                if (expectedLength !== -1 && msg.length < expectedLength) {
+                    return;
+                }
                 dataPacket.read();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/tcnet.ts` around lines 714 - 727, 現在の msg.length < 24 ガードだと Data/File
系の実読込で byte 24/25 や固定オフセット参照により RangeError が発生するので、parsePacket() を呼ぶ前に
packet.dataType が Data/File 系の場合は msg.length >= 26 をチェックして早期リターンするロジックを追加し、既知の
dataType から具象クラスを生成した後は必ず dataPacket.length() を用いて最小バッファ長を満たしている場合のみ
dataPacket.read() を呼ぶように変更してください(参照シンボル: parsePacket, nw.TCNetDataPacket,
nw.TCNetDataPackets, TCNetDataPacket.read, TCNetManagementHeader)。
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/tcnet.ts`:
- Around line 749-751: finalPacket の multiPacketHeader が、assembler 経路では設定されるが
totalPackets===0 の File 経路(handleFileChunkPacket が finalPacket を組み立てるケース)では設定されず
null が返る不整合があるため、handleFileChunkPacket 関数内で finalPacket に multiPacketHeader
を引き継ぐ処理を追加してください;具体的には handleFileChunkPacket 内で受信データから
nw.readMultiPacketHeader(...) を使ってヘッダーを取得するか、呼び元から渡された既存ヘッダー値を
finalPacket.multiPacketHeader に代入して、assembler 完了分岐と同じように
finalPacket.multiPacketHeader が常に設定されるようにします(参照シンボル: finalPacket,
multiPacketHeader, handleFileChunkPacket, nw.readMultiPacketHeader,
totalPackets)。

---

Outside diff comments:
In `@src/tcnet.ts`:
- Around line 714-727: 現在の msg.length < 24 ガードだと Data/File 系の実読込で byte 24/25
や固定オフセット参照により RangeError が発生するので、parsePacket() を呼ぶ前に packet.dataType が Data/File
系の場合は msg.length >= 26 をチェックして早期リターンするロジックを追加し、既知の dataType から具象クラスを生成した後は必ず
dataPacket.length() を用いて最小バッファ長を満たしている場合のみ dataPacket.read()
を呼ぶように変更してください(参照シンボル: parsePacket, nw.TCNetDataPacket, nw.TCNetDataPackets,
TCNetDataPacket.read, TCNetManagementHeader)。
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: ac5d449e-d81f-4824-8c2e-c55af8459139

📥 Commits

Reviewing files that changed from the base of the PR and between d9d6be4 and af849b9.

📒 Files selected for processing (3)
  • src/network.ts
  • src/tcnet.ts
  • tests/auth.test.ts
📜 Review details
🧰 Additional context used
🧠 Learnings (13)
📓 Common learnings
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 83
File: docs/wiki/PRO-DJ-LINK-Bridge.md:70-70
Timestamp: 2026-04-12T15:27:49.300Z
Learning: In `docs/wiki/PRO-DJ-LINK-Bridge.md` (node-tcnet, documentation in Japanese), the "未再検証" (unre-verified) annotation in the Time section ("以下のフィールドが0で返される (未再検証)。") is intentional: no Time packets were captured during the PR#83 verification session (0 packets), so re-verification was not possible. The maintainer (9c5s) plans to update this notation once verification becomes possible. Do not flag this wording as needing immediate resolution in future reviews.
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 83
File: docs/wiki/PRO-DJ-LINK-Bridge.md:30-32
Timestamp: 2026-04-12T15:27:25.846Z
Learning: In `docs/wiki/PRO-DJ-LINK-Bridge.md` (node-tcnet, documentation in Japanese), the asymmetry in certainty wording for the Metrics section is intentional: "別マシンのBridgeでは全フィールドが正常に取得可能であることを実機で確認済み" uses definitive language because it is a confirmed fact from actual hardware testing in the PR; "同一マシン上のBridgeではこれらのフィールドが0で返されることがある" uses hedged language ("ことがある") because it is based on a past observation whose reproduction conditions are unknown. Do not flag this wording inconsistency in future reviews.
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 2
File: src/tcnet.ts:249-255
Timestamp: 2026-03-21T05:30:31.035Z
Learning: In `src/network.ts` of the `node-tcnet` repository: `TCNetDataPacket.read()` (class defined at line 321, read() at line 330) converts the wire-format 1-based layer to 0-based by doing `this.layer = this.buffer.readUInt8(25) - 1`. In contrast, `TCNetRequestPacket.read()` (class defined at line 225, read() at line 231) does NOT subtract 1: `this.layer = this.buffer.readUInt8(25)`. Therefore, `dataPacket.layer` from a received `TCNetDataPacket` is already 0-based and correctly matches the 0-based key stored in `requestData()`. Flagging a missing `-1` in `TCNetDataPacket.read()` is a false positive.
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 2
File: src/tcnet.ts:397-400
Timestamp: 2026-03-21T05:02:27.762Z
Learning: In the `node-tcnet` repository (`src/network.ts`, `src/tcnet.ts`), `TCNetDataPacket.write()` has no callers. `TCNetDataPacket` objects are only ever deserialized on receive paths (`read()`), never serialized and sent. The only outbound packet carrying a layer field is `TCNetRequestPacket`, constructed inside `requestData()` in `src/tcnet.ts`. Suggesting to move layer conversion logic into `TCNetDataPacket.write()` is inappropriate because that method is dead code.
📚 Learning: 2026-04-09T23:09:19.524Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 65
File: src/tcnet.ts:1158-1167
Timestamp: 2026-04-09T23:09:19.524Z
Learning: In `src/tcnet.ts` (node-tcnet, TypeScript), the race condition where a stale `sendAuthSequence` from an old auth generation could call `resetAuthSession` and destroy a newly-started pending auth state is resolved by: (1) adding `expectedToken: number` parameter to `sendAuthSequence` and checking `this.sessionToken !== expectedToken` at every async boundary (entry, after cmd=0 send, after 50ms wait, after prepareAuthPayload) — silently returning without calling `resetAuthSession` when stale; (2) capturing `tokenForThisAttempt` in `handleInitialAuthRequest` and only calling `resetAuthSession` in the catch block when `this.sessionToken === tokenForThisAttempt`; (3) keeping the `tokenBeforePing` guard inside `prepareAuthPayload` as a secondary defense. The maintainer (9c5s) intentionally uses this two-layer guard design.

Applied to files:

  • src/tcnet.ts
  • tests/auth.test.ts
  • src/network.ts
📚 Learning: 2026-03-21T05:30:31.035Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 2
File: src/tcnet.ts:249-255
Timestamp: 2026-03-21T05:30:31.035Z
Learning: In `src/network.ts` of the `node-tcnet` repository: `TCNetDataPacket.read()` (class defined at line 321, read() at line 330) converts the wire-format 1-based layer to 0-based by doing `this.layer = this.buffer.readUInt8(25) - 1`. In contrast, `TCNetRequestPacket.read()` (class defined at line 225, read() at line 231) does NOT subtract 1: `this.layer = this.buffer.readUInt8(25)`. Therefore, `dataPacket.layer` from a received `TCNetDataPacket` is already 0-based and correctly matches the 0-based key stored in `requestData()`. Flagging a missing `-1` in `TCNetDataPacket.read()` is a false positive.

Applied to files:

  • src/tcnet.ts
  • tests/auth.test.ts
  • src/network.ts
📚 Learning: 2026-04-09T16:28:34.323Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 64
File: src/tcnet.ts:31-35
Timestamp: 2026-04-09T16:28:34.323Z
Learning: In node-tcnet, the changeset bump type is kept as `patch` even for breaking changes (removal of `autoReauth`/`reauthInterval`, `reauthenticated`/`reauthFailed` events, `AuthState` `"refreshing"`, addition of `TCNetLogger.warn`) because the library is pre-release (0.x semver), and the maintainer (9c5s) considers strict semver minor/major bumps unnecessary at this stage.

Applied to files:

  • src/tcnet.ts
  • tests/auth.test.ts
  • src/network.ts
📚 Learning: 2026-04-09T17:09:02.148Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 64
File: src/tcnet.ts:961-966
Timestamp: 2026-04-09T17:09:02.148Z
Learning: In `src/tcnet.ts` (node-tcnet, TypeScript), the TOCTOU race condition in `performBridgeOsDetection` (where an in-flight ping could overwrite `bridgeIsWindows` with a stale result after a Bridge switch) is resolved by capturing `bridgeIp = this.server?.address` at detection start and checking `this.server?.address === bridgeIp` immediately before writing to `this.bridgeIsWindows`. The maintainer (9c5s) deliberately rejected clearing `bridgeOsDetectionPromise` in `resetAuthSession` (doesn't stop internal execution) and a generation-counter approach (triggers on same-Bridge resets too) in favor of this simpler address-comparison guard.

Applied to files:

  • src/tcnet.ts
  • tests/auth.test.ts
  • src/network.ts
📚 Learning: 2026-03-21T05:02:27.762Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 2
File: src/tcnet.ts:397-400
Timestamp: 2026-03-21T05:02:27.762Z
Learning: In the `node-tcnet` repository (`src/network.ts`, `src/tcnet.ts`), `TCNetDataPacket.write()` has no callers. `TCNetDataPacket` objects are only ever deserialized on receive paths (`read()`), never serialized and sent. The only outbound packet carrying a layer field is `TCNetRequestPacket`, constructed inside `requestData()` in `src/tcnet.ts`. Suggesting to move layer conversion logic into `TCNetDataPacket.write()` is inappropriate because that method is dead code.

Applied to files:

  • src/tcnet.ts
  • tests/auth.test.ts
  • src/network.ts
📚 Learning: 2026-03-27T08:24:18.571Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 50
File: src/network.ts:1010-1024
Timestamp: 2026-03-27T08:24:18.571Z
Learning: In the `node-tcnet` repository (`src/network.ts`), `Buffer.allocUnsafe()` is never used — only `Buffer.alloc()` is used throughout the codebase. Reserved fields in packet `write()` methods do not need explicit zero-initialization because `Buffer.alloc()` always zero-initializes. Suggesting defensive zero-writes for reserved packet offsets is unnecessary (YAGNI) for this codebase.

Applied to files:

  • src/tcnet.ts
  • tests/auth.test.ts
  • src/network.ts
📚 Learning: 2026-03-24T19:15:40.455Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 41
File: src/utils.ts:94-94
Timestamp: 2026-03-24T19:15:40.455Z
Learning: In the `node-tcnet` repository (`src/utils.ts`), the project targets ES2022 + NodeNext and does not need to support Node.js 18.0.0. The temporary numeric `family` field (4/6) in `os.networkInterfaces()` introduced in Node.js 18.0.0 and fixed in 18.1.0 does not need to be handled. Suggesting numeric `family` handling for defensive programming is unnecessary for this project.

Applied to files:

  • src/tcnet.ts
  • tests/auth.test.ts
  • src/network.ts
📚 Learning: 2026-03-21T11:31:23.742Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 8
File: README.MD:31-33
Timestamp: 2026-03-21T11:31:23.742Z
Learning: In `src/network.ts` of the `node-tcnet` repository: `TCNetDataPacketMetadata` (line 389) has an `info` property (not `data`). `data` property belongs to the sibling class `TCNetDataPacketMetrics` (line 352). Flagging `meta.info` in README/docs examples as wrong and suggesting `meta.data` is a false positive.

Applied to files:

  • src/tcnet.ts
  • tests/auth.test.ts
  • src/network.ts
📚 Learning: 2026-04-08T12:28:37.297Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 63
File: src/tcnet.ts:960-1010
Timestamp: 2026-04-08T12:28:37.297Z
Learning: In `src/tcnet.ts` (node-tcnet, TypeScript), the `cleanup?.()` call in the catch block of `executeReauth` is intentionally kept as defensive programming. The maintainer (9c5s) prefers this pattern because `removeListener`/`clearTimeout` are idempotent, so the redundant call costs nothing and provides safety against future changes to the control flow.

Applied to files:

  • src/tcnet.ts
  • tests/auth.test.ts
📚 Learning: 2026-04-09T16:28:34.323Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 64
File: src/tcnet.ts:31-35
Timestamp: 2026-04-09T16:28:34.323Z
Learning: In `src/tcnet.ts` (node-tcnet, TypeScript), `TCNetLogger.warn` is intentionally a required method (not optional). The maintainer (9c5s) made it required so that TypeScript catches missing logger implementations at compile time; making it optional would silently drop warn-level messages (e.g., unexpected token changes during reauth). The library is pre-release, so this breaking change is acceptable and is documented in the PR and changeset.

Applied to files:

  • src/tcnet.ts
  • tests/auth.test.ts
  • src/network.ts
📚 Learning: 2026-04-12T15:27:49.300Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 83
File: docs/wiki/PRO-DJ-LINK-Bridge.md:70-70
Timestamp: 2026-04-12T15:27:49.300Z
Learning: In `docs/wiki/PRO-DJ-LINK-Bridge.md` (node-tcnet, documentation in Japanese), the "未再検証" (unre-verified) annotation in the Time section ("以下のフィールドが0で返される (未再検証)。") is intentional: no Time packets were captured during the PR#83 verification session (0 packets), so re-verification was not possible. The maintainer (9c5s) plans to update this notation once verification becomes possible. Do not flag this wording as needing immediate resolution in future reviews.

Applied to files:

  • src/tcnet.ts
  • tests/auth.test.ts
  • src/network.ts
📚 Learning: 2026-04-12T15:27:25.846Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 83
File: docs/wiki/PRO-DJ-LINK-Bridge.md:30-32
Timestamp: 2026-04-12T15:27:25.846Z
Learning: In `docs/wiki/PRO-DJ-LINK-Bridge.md` (node-tcnet, documentation in Japanese), the asymmetry in certainty wording for the Metrics section is intentional: "別マシンのBridgeでは全フィールドが正常に取得可能であることを実機で確認済み" uses definitive language because it is a confirmed fact from actual hardware testing in the PR; "同一マシン上のBridgeではこれらのフィールドが0で返されることがある" uses hedged language ("ことがある") because it is based on a past observation whose reproduction conditions are unknown. Do not flag this wording inconsistency in future reviews.

Applied to files:

  • src/tcnet.ts

Comment thread src/tcnet.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3d835956c0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/tcnet.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/tcnet.ts`:
- Around line 717-720: The current short-buffer guard (if (msg.length < 24)
return) still allows 25-byte messages to reach TCNetDataPacket.read() and throw
a RangeError; after constructing and calling read() on TCNetManagementHeader,
check mgmtHeader.messageType for the Data case and reject packets with
msg.length < 26 (e.g., return early) before calling this.parsePacket or
instantiating TCNetDataPacket so Data packets have the correct minimum length;
refer to TCNetManagementHeader, messageType (Data), TCNetDataPacket.read(), and
parsePacket when making the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 25b90c64-a78e-49fd-918d-d48bf87d4cca

📥 Commits

Reviewing files that changed from the base of the PR and between af849b9 and 3d83595.

📒 Files selected for processing (1)
  • src/tcnet.ts
📜 Review details
🧰 Additional context used
🧠 Learnings (13)
📓 Common learnings
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 83
File: docs/wiki/PRO-DJ-LINK-Bridge.md:70-70
Timestamp: 2026-04-12T15:27:49.300Z
Learning: In `docs/wiki/PRO-DJ-LINK-Bridge.md` (node-tcnet, documentation in Japanese), the "未再検証" (unre-verified) annotation in the Time section ("以下のフィールドが0で返される (未再検証)。") is intentional: no Time packets were captured during the PR#83 verification session (0 packets), so re-verification was not possible. The maintainer (9c5s) plans to update this notation once verification becomes possible. Do not flag this wording as needing immediate resolution in future reviews.
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 83
File: docs/wiki/PRO-DJ-LINK-Bridge.md:30-32
Timestamp: 2026-04-12T15:27:25.846Z
Learning: In `docs/wiki/PRO-DJ-LINK-Bridge.md` (node-tcnet, documentation in Japanese), the asymmetry in certainty wording for the Metrics section is intentional: "別マシンのBridgeでは全フィールドが正常に取得可能であることを実機で確認済み" uses definitive language because it is a confirmed fact from actual hardware testing in the PR; "同一マシン上のBridgeではこれらのフィールドが0で返されることがある" uses hedged language ("ことがある") because it is based on a past observation whose reproduction conditions are unknown. Do not flag this wording inconsistency in future reviews.
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 2
File: src/tcnet.ts:249-255
Timestamp: 2026-03-21T05:30:31.035Z
Learning: In `src/network.ts` of the `node-tcnet` repository: `TCNetDataPacket.read()` (class defined at line 321, read() at line 330) converts the wire-format 1-based layer to 0-based by doing `this.layer = this.buffer.readUInt8(25) - 1`. In contrast, `TCNetRequestPacket.read()` (class defined at line 225, read() at line 231) does NOT subtract 1: `this.layer = this.buffer.readUInt8(25)`. Therefore, `dataPacket.layer` from a received `TCNetDataPacket` is already 0-based and correctly matches the 0-based key stored in `requestData()`. Flagging a missing `-1` in `TCNetDataPacket.read()` is a false positive.
📚 Learning: 2026-04-09T23:09:19.524Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 65
File: src/tcnet.ts:1158-1167
Timestamp: 2026-04-09T23:09:19.524Z
Learning: In `src/tcnet.ts` (node-tcnet, TypeScript), the race condition where a stale `sendAuthSequence` from an old auth generation could call `resetAuthSession` and destroy a newly-started pending auth state is resolved by: (1) adding `expectedToken: number` parameter to `sendAuthSequence` and checking `this.sessionToken !== expectedToken` at every async boundary (entry, after cmd=0 send, after 50ms wait, after prepareAuthPayload) — silently returning without calling `resetAuthSession` when stale; (2) capturing `tokenForThisAttempt` in `handleInitialAuthRequest` and only calling `resetAuthSession` in the catch block when `this.sessionToken === tokenForThisAttempt`; (3) keeping the `tokenBeforePing` guard inside `prepareAuthPayload` as a secondary defense. The maintainer (9c5s) intentionally uses this two-layer guard design.

Applied to files:

  • src/tcnet.ts
📚 Learning: 2026-03-21T05:30:31.035Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 2
File: src/tcnet.ts:249-255
Timestamp: 2026-03-21T05:30:31.035Z
Learning: In `src/network.ts` of the `node-tcnet` repository: `TCNetDataPacket.read()` (class defined at line 321, read() at line 330) converts the wire-format 1-based layer to 0-based by doing `this.layer = this.buffer.readUInt8(25) - 1`. In contrast, `TCNetRequestPacket.read()` (class defined at line 225, read() at line 231) does NOT subtract 1: `this.layer = this.buffer.readUInt8(25)`. Therefore, `dataPacket.layer` from a received `TCNetDataPacket` is already 0-based and correctly matches the 0-based key stored in `requestData()`. Flagging a missing `-1` in `TCNetDataPacket.read()` is a false positive.

Applied to files:

  • src/tcnet.ts
📚 Learning: 2026-04-09T16:28:34.323Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 64
File: src/tcnet.ts:31-35
Timestamp: 2026-04-09T16:28:34.323Z
Learning: In node-tcnet, the changeset bump type is kept as `patch` even for breaking changes (removal of `autoReauth`/`reauthInterval`, `reauthenticated`/`reauthFailed` events, `AuthState` `"refreshing"`, addition of `TCNetLogger.warn`) because the library is pre-release (0.x semver), and the maintainer (9c5s) considers strict semver minor/major bumps unnecessary at this stage.

Applied to files:

  • src/tcnet.ts
📚 Learning: 2026-04-09T17:09:02.148Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 64
File: src/tcnet.ts:961-966
Timestamp: 2026-04-09T17:09:02.148Z
Learning: In `src/tcnet.ts` (node-tcnet, TypeScript), the TOCTOU race condition in `performBridgeOsDetection` (where an in-flight ping could overwrite `bridgeIsWindows` with a stale result after a Bridge switch) is resolved by capturing `bridgeIp = this.server?.address` at detection start and checking `this.server?.address === bridgeIp` immediately before writing to `this.bridgeIsWindows`. The maintainer (9c5s) deliberately rejected clearing `bridgeOsDetectionPromise` in `resetAuthSession` (doesn't stop internal execution) and a generation-counter approach (triggers on same-Bridge resets too) in favor of this simpler address-comparison guard.

Applied to files:

  • src/tcnet.ts
📚 Learning: 2026-03-21T05:02:27.762Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 2
File: src/tcnet.ts:397-400
Timestamp: 2026-03-21T05:02:27.762Z
Learning: In the `node-tcnet` repository (`src/network.ts`, `src/tcnet.ts`), `TCNetDataPacket.write()` has no callers. `TCNetDataPacket` objects are only ever deserialized on receive paths (`read()`), never serialized and sent. The only outbound packet carrying a layer field is `TCNetRequestPacket`, constructed inside `requestData()` in `src/tcnet.ts`. Suggesting to move layer conversion logic into `TCNetDataPacket.write()` is inappropriate because that method is dead code.

Applied to files:

  • src/tcnet.ts
📚 Learning: 2026-03-27T08:24:18.571Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 50
File: src/network.ts:1010-1024
Timestamp: 2026-03-27T08:24:18.571Z
Learning: In the `node-tcnet` repository (`src/network.ts`), `Buffer.allocUnsafe()` is never used — only `Buffer.alloc()` is used throughout the codebase. Reserved fields in packet `write()` methods do not need explicit zero-initialization because `Buffer.alloc()` always zero-initializes. Suggesting defensive zero-writes for reserved packet offsets is unnecessary (YAGNI) for this codebase.

Applied to files:

  • src/tcnet.ts
📚 Learning: 2026-03-21T11:31:23.742Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 8
File: README.MD:31-33
Timestamp: 2026-03-21T11:31:23.742Z
Learning: In `src/network.ts` of the `node-tcnet` repository: `TCNetDataPacketMetadata` (line 389) has an `info` property (not `data`). `data` property belongs to the sibling class `TCNetDataPacketMetrics` (line 352). Flagging `meta.info` in README/docs examples as wrong and suggesting `meta.data` is a false positive.

Applied to files:

  • src/tcnet.ts
📚 Learning: 2026-04-09T16:28:34.323Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 64
File: src/tcnet.ts:31-35
Timestamp: 2026-04-09T16:28:34.323Z
Learning: In `src/tcnet.ts` (node-tcnet, TypeScript), `TCNetLogger.warn` is intentionally a required method (not optional). The maintainer (9c5s) made it required so that TypeScript catches missing logger implementations at compile time; making it optional would silently drop warn-level messages (e.g., unexpected token changes during reauth). The library is pre-release, so this breaking change is acceptable and is documented in the PR and changeset.

Applied to files:

  • src/tcnet.ts
📚 Learning: 2026-04-08T12:28:37.297Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 63
File: src/tcnet.ts:960-1010
Timestamp: 2026-04-08T12:28:37.297Z
Learning: In `src/tcnet.ts` (node-tcnet, TypeScript), the `cleanup?.()` call in the catch block of `executeReauth` is intentionally kept as defensive programming. The maintainer (9c5s) prefers this pattern because `removeListener`/`clearTimeout` are idempotent, so the redundant call costs nothing and provides safety against future changes to the control flow.

Applied to files:

  • src/tcnet.ts
📚 Learning: 2026-03-24T19:15:40.455Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 41
File: src/utils.ts:94-94
Timestamp: 2026-03-24T19:15:40.455Z
Learning: In the `node-tcnet` repository (`src/utils.ts`), the project targets ES2022 + NodeNext and does not need to support Node.js 18.0.0. The temporary numeric `family` field (4/6) in `os.networkInterfaces()` introduced in Node.js 18.0.0 and fixed in 18.1.0 does not need to be handled. Suggesting numeric `family` handling for defensive programming is unnecessary for this project.

Applied to files:

  • src/tcnet.ts
📚 Learning: 2026-04-12T15:27:49.300Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 83
File: docs/wiki/PRO-DJ-LINK-Bridge.md:70-70
Timestamp: 2026-04-12T15:27:49.300Z
Learning: In `docs/wiki/PRO-DJ-LINK-Bridge.md` (node-tcnet, documentation in Japanese), the "未再検証" (unre-verified) annotation in the Time section ("以下のフィールドが0で返される (未再検証)。") is intentional: no Time packets were captured during the PR#83 verification session (0 packets), so re-verification was not possible. The maintainer (9c5s) plans to update this notation once verification becomes possible. Do not flag this wording as needing immediate resolution in future reviews.

Applied to files:

  • src/tcnet.ts
📚 Learning: 2026-04-12T15:27:25.846Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 83
File: docs/wiki/PRO-DJ-LINK-Bridge.md:30-32
Timestamp: 2026-04-12T15:27:25.846Z
Learning: In `docs/wiki/PRO-DJ-LINK-Bridge.md` (node-tcnet, documentation in Japanese), the asymmetry in certainty wording for the Metrics section is intentional: "別マシンのBridgeでは全フィールドが正常に取得可能であることを実機で確認済み" uses definitive language because it is a confirmed fact from actual hardware testing in the PR; "同一マシン上のBridgeではこれらのフィールドが0で返されることがある" uses hedged language ("ことがある") because it is based on a past observation whose reproduction conditions are unknown. Do not flag this wording inconsistency in future reviews.

Applied to files:

  • src/tcnet.ts

Comment thread src/tcnet.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/tcnet.ts (1)

1431-1449: ⚠️ Potential issue | 🟠 Major

認証成否の判定に messageType が抜けています。

この PR で TCNetErrorPacket を構造化したのに、ここでは dataType / layerId / code だけで pending session を成功・失敗へ遷移させています。別用途の Error パケットが同じ値を持つと誤認証になるので、auth 応答で期待する packet.messageType も条件に含めるべきです。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/tcnet.ts` around lines 1431 - 1449, The auth success/failure checks
currently only test packet.dataType/layerId/code and can misinterpret unrelated
error packets; update the conditional branches that set this._authState and
emit("authenticated") / emit("authFailed") to also require packet.messageType to
equal the auth-response message type used for TCNetErrorPacket (i.e. add &&
packet.messageType === <auth-response-messageType-constant-or-enum> to both the
success and failure conditions), and keep the existing cleanup (clearing
this.authTimeoutId, setting this.sessionToken/null, and logging) intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/receive-unicast.test.ts`:
- Around line 56-74: The test doesn't actually assert that requestData() settles
after receiving the short packet because it only calls requestPromise.catch(()
=> {}), leaving timers running; modify the test to either use fake timers
(advance timers until the requestPromise settles) or pass a short requestTimeout
to the TestTCNetClient/requestData invocation, then await the returned promise
and assert its final state (resolve or reject) and clear timers; target symbols:
requestData(), requestPromise, simulateUnicast, requestTimeout (or the test
harness' fake timer utilities) to ensure the promise is awaited and timers are
cleaned up.

---

Outside diff comments:
In `@src/tcnet.ts`:
- Around line 1431-1449: The auth success/failure checks currently only test
packet.dataType/layerId/code and can misinterpret unrelated error packets;
update the conditional branches that set this._authState and
emit("authenticated") / emit("authFailed") to also require packet.messageType to
equal the auth-response message type used for TCNetErrorPacket (i.e. add &&
packet.messageType === <auth-response-messageType-constant-or-enum> to both the
success and failure conditions), and keep the existing cleanup (clearing
this.authTimeoutId, setting this.sessionToken/null, and logging) intact.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6d655541-1a8b-4d82-9937-664bac0fc9c0

📥 Commits

Reviewing files that changed from the base of the PR and between 3d83595 and ae48cd9.

📒 Files selected for processing (2)
  • src/tcnet.ts
  • tests/receive-unicast.test.ts
📜 Review details
🧰 Additional context used
🧠 Learnings (13)
📓 Common learnings
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 83
File: docs/wiki/PRO-DJ-LINK-Bridge.md:70-70
Timestamp: 2026-04-12T15:27:49.300Z
Learning: In `docs/wiki/PRO-DJ-LINK-Bridge.md` (node-tcnet, documentation in Japanese), the "未再検証" (unre-verified) annotation in the Time section ("以下のフィールドが0で返される (未再検証)。") is intentional: no Time packets were captured during the PR#83 verification session (0 packets), so re-verification was not possible. The maintainer (9c5s) plans to update this notation once verification becomes possible. Do not flag this wording as needing immediate resolution in future reviews.
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 83
File: docs/wiki/PRO-DJ-LINK-Bridge.md:30-32
Timestamp: 2026-04-12T15:27:25.846Z
Learning: In `docs/wiki/PRO-DJ-LINK-Bridge.md` (node-tcnet, documentation in Japanese), the asymmetry in certainty wording for the Metrics section is intentional: "別マシンのBridgeでは全フィールドが正常に取得可能であることを実機で確認済み" uses definitive language because it is a confirmed fact from actual hardware testing in the PR; "同一マシン上のBridgeではこれらのフィールドが0で返されることがある" uses hedged language ("ことがある") because it is based on a past observation whose reproduction conditions are unknown. Do not flag this wording inconsistency in future reviews.
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 2
File: src/tcnet.ts:249-255
Timestamp: 2026-03-21T05:30:31.035Z
Learning: In `src/network.ts` of the `node-tcnet` repository: `TCNetDataPacket.read()` (class defined at line 321, read() at line 330) converts the wire-format 1-based layer to 0-based by doing `this.layer = this.buffer.readUInt8(25) - 1`. In contrast, `TCNetRequestPacket.read()` (class defined at line 225, read() at line 231) does NOT subtract 1: `this.layer = this.buffer.readUInt8(25)`. Therefore, `dataPacket.layer` from a received `TCNetDataPacket` is already 0-based and correctly matches the 0-based key stored in `requestData()`. Flagging a missing `-1` in `TCNetDataPacket.read()` is a false positive.
📚 Learning: 2026-03-27T08:24:18.571Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 50
File: src/network.ts:1010-1024
Timestamp: 2026-03-27T08:24:18.571Z
Learning: In the `node-tcnet` repository (`src/network.ts`), `Buffer.allocUnsafe()` is never used — only `Buffer.alloc()` is used throughout the codebase. Reserved fields in packet `write()` methods do not need explicit zero-initialization because `Buffer.alloc()` always zero-initializes. Suggesting defensive zero-writes for reserved packet offsets is unnecessary (YAGNI) for this codebase.

Applied to files:

  • tests/receive-unicast.test.ts
  • src/tcnet.ts
📚 Learning: 2026-03-21T05:02:27.762Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 2
File: src/tcnet.ts:397-400
Timestamp: 2026-03-21T05:02:27.762Z
Learning: In the `node-tcnet` repository (`src/network.ts`, `src/tcnet.ts`), `TCNetDataPacket.write()` has no callers. `TCNetDataPacket` objects are only ever deserialized on receive paths (`read()`), never serialized and sent. The only outbound packet carrying a layer field is `TCNetRequestPacket`, constructed inside `requestData()` in `src/tcnet.ts`. Suggesting to move layer conversion logic into `TCNetDataPacket.write()` is inappropriate because that method is dead code.

Applied to files:

  • tests/receive-unicast.test.ts
  • src/tcnet.ts
📚 Learning: 2026-04-09T23:09:19.524Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 65
File: src/tcnet.ts:1158-1167
Timestamp: 2026-04-09T23:09:19.524Z
Learning: In `src/tcnet.ts` (node-tcnet, TypeScript), the race condition where a stale `sendAuthSequence` from an old auth generation could call `resetAuthSession` and destroy a newly-started pending auth state is resolved by: (1) adding `expectedToken: number` parameter to `sendAuthSequence` and checking `this.sessionToken !== expectedToken` at every async boundary (entry, after cmd=0 send, after 50ms wait, after prepareAuthPayload) — silently returning without calling `resetAuthSession` when stale; (2) capturing `tokenForThisAttempt` in `handleInitialAuthRequest` and only calling `resetAuthSession` in the catch block when `this.sessionToken === tokenForThisAttempt`; (3) keeping the `tokenBeforePing` guard inside `prepareAuthPayload` as a secondary defense. The maintainer (9c5s) intentionally uses this two-layer guard design.

Applied to files:

  • tests/receive-unicast.test.ts
  • src/tcnet.ts
📚 Learning: 2026-03-21T05:30:31.035Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 2
File: src/tcnet.ts:249-255
Timestamp: 2026-03-21T05:30:31.035Z
Learning: In `src/network.ts` of the `node-tcnet` repository: `TCNetDataPacket.read()` (class defined at line 321, read() at line 330) converts the wire-format 1-based layer to 0-based by doing `this.layer = this.buffer.readUInt8(25) - 1`. In contrast, `TCNetRequestPacket.read()` (class defined at line 225, read() at line 231) does NOT subtract 1: `this.layer = this.buffer.readUInt8(25)`. Therefore, `dataPacket.layer` from a received `TCNetDataPacket` is already 0-based and correctly matches the 0-based key stored in `requestData()`. Flagging a missing `-1` in `TCNetDataPacket.read()` is a false positive.

Applied to files:

  • tests/receive-unicast.test.ts
  • src/tcnet.ts
📚 Learning: 2026-04-09T16:28:34.323Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 64
File: src/tcnet.ts:31-35
Timestamp: 2026-04-09T16:28:34.323Z
Learning: In node-tcnet, the changeset bump type is kept as `patch` even for breaking changes (removal of `autoReauth`/`reauthInterval`, `reauthenticated`/`reauthFailed` events, `AuthState` `"refreshing"`, addition of `TCNetLogger.warn`) because the library is pre-release (0.x semver), and the maintainer (9c5s) considers strict semver minor/major bumps unnecessary at this stage.

Applied to files:

  • src/tcnet.ts
📚 Learning: 2026-04-09T17:09:02.148Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 64
File: src/tcnet.ts:961-966
Timestamp: 2026-04-09T17:09:02.148Z
Learning: In `src/tcnet.ts` (node-tcnet, TypeScript), the TOCTOU race condition in `performBridgeOsDetection` (where an in-flight ping could overwrite `bridgeIsWindows` with a stale result after a Bridge switch) is resolved by capturing `bridgeIp = this.server?.address` at detection start and checking `this.server?.address === bridgeIp` immediately before writing to `this.bridgeIsWindows`. The maintainer (9c5s) deliberately rejected clearing `bridgeOsDetectionPromise` in `resetAuthSession` (doesn't stop internal execution) and a generation-counter approach (triggers on same-Bridge resets too) in favor of this simpler address-comparison guard.

Applied to files:

  • src/tcnet.ts
📚 Learning: 2026-03-24T19:15:40.455Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 41
File: src/utils.ts:94-94
Timestamp: 2026-03-24T19:15:40.455Z
Learning: In the `node-tcnet` repository (`src/utils.ts`), the project targets ES2022 + NodeNext and does not need to support Node.js 18.0.0. The temporary numeric `family` field (4/6) in `os.networkInterfaces()` introduced in Node.js 18.0.0 and fixed in 18.1.0 does not need to be handled. Suggesting numeric `family` handling for defensive programming is unnecessary for this project.

Applied to files:

  • src/tcnet.ts
📚 Learning: 2026-04-09T16:28:34.323Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 64
File: src/tcnet.ts:31-35
Timestamp: 2026-04-09T16:28:34.323Z
Learning: In `src/tcnet.ts` (node-tcnet, TypeScript), `TCNetLogger.warn` is intentionally a required method (not optional). The maintainer (9c5s) made it required so that TypeScript catches missing logger implementations at compile time; making it optional would silently drop warn-level messages (e.g., unexpected token changes during reauth). The library is pre-release, so this breaking change is acceptable and is documented in the PR and changeset.

Applied to files:

  • src/tcnet.ts
📚 Learning: 2026-03-21T11:31:23.742Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 8
File: README.MD:31-33
Timestamp: 2026-03-21T11:31:23.742Z
Learning: In `src/network.ts` of the `node-tcnet` repository: `TCNetDataPacketMetadata` (line 389) has an `info` property (not `data`). `data` property belongs to the sibling class `TCNetDataPacketMetrics` (line 352). Flagging `meta.info` in README/docs examples as wrong and suggesting `meta.data` is a false positive.

Applied to files:

  • src/tcnet.ts
📚 Learning: 2026-04-08T12:28:37.297Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 63
File: src/tcnet.ts:960-1010
Timestamp: 2026-04-08T12:28:37.297Z
Learning: In `src/tcnet.ts` (node-tcnet, TypeScript), the `cleanup?.()` call in the catch block of `executeReauth` is intentionally kept as defensive programming. The maintainer (9c5s) prefers this pattern because `removeListener`/`clearTimeout` are idempotent, so the redundant call costs nothing and provides safety against future changes to the control flow.

Applied to files:

  • src/tcnet.ts
📚 Learning: 2026-04-12T15:27:49.300Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 83
File: docs/wiki/PRO-DJ-LINK-Bridge.md:70-70
Timestamp: 2026-04-12T15:27:49.300Z
Learning: In `docs/wiki/PRO-DJ-LINK-Bridge.md` (node-tcnet, documentation in Japanese), the "未再検証" (unre-verified) annotation in the Time section ("以下のフィールドが0で返される (未再検証)。") is intentional: no Time packets were captured during the PR#83 verification session (0 packets), so re-verification was not possible. The maintainer (9c5s) plans to update this notation once verification becomes possible. Do not flag this wording as needing immediate resolution in future reviews.

Applied to files:

  • src/tcnet.ts
📚 Learning: 2026-04-12T15:27:25.846Z
Learnt from: 9c5s
Repo: 9c5s/node-tcnet PR: 83
File: docs/wiki/PRO-DJ-LINK-Bridge.md:30-32
Timestamp: 2026-04-12T15:27:25.846Z
Learning: In `docs/wiki/PRO-DJ-LINK-Bridge.md` (node-tcnet, documentation in Japanese), the asymmetry in certainty wording for the Metrics section is intentional: "別マシンのBridgeでは全フィールドが正常に取得可能であることを実機で確認済み" uses definitive language because it is a confirmed fact from actual hardware testing in the PR; "同一マシン上のBridgeではこれらのフィールドが0で返されることがある" uses hedged language ("ことがある") because it is based on a past observation whose reproduction conditions are unknown. Do not flag this wording inconsistency in future reviews.

Applied to files:

  • src/tcnet.ts
🔇 Additional comments (3)
src/tcnet.ts (3)

537-538: lookup miss を undefined まで含めて安全に弾けています。

TCNetPackets / TCNetDataPackets の参照結果が undefined のケースでも new に進まなくなるので、unknown type のクラッシュ経路をきちんと塞げています。

Also applies to: 724-725


692-694: multiPacketHeader の引き継ぎが経路間で揃っています。

file chunk 経路と assembler 完了経路の両方で finalPacket.multiPacketHeader を設定しているので、assembled 応答の戻り値 shape が一貫しました。

Also applies to: 752-754


717-720: 短バッファを header parse 前に落とすのは良いです。

TCNetDataPacket.read() に到達する前に 26 バイト未満を除外できていて、防御として十分に直接的です。

Comment thread tests/receive-unicast.test.ts
@9c5s
9c5s merged commit 4b902ee into main Apr 12, 2026
2 checks passed
@9c5s
9c5s deleted the feat/packet-improvements branch April 12, 2026 19:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment