14.3. Getting Started
Prev | Chapter 14. Lua Debugger | Next

## 14.3. Getting Started

A small postdissector is enough to exercise everything the debugger does. Save the following as `printer.lua`:

    local printer      = Proto("printer", "Demo Postdissector")
    local sessions     = {}  -- frame number -> {src, dst}
    local last_seen    = {}  -- Address -> frame number
    local opcode_names = { [0x10] = "ack", [0x11] = "syn-ack" }
    local handshake    = { syn = true, fin = false }
    local ip_src_F     = Field.new("ip.src")
    local tcp_flags_F  = Field.new("tcp.flags")

    function printer.dissector(tvb, pinfo, tree)
      local offset = 0

      sessions[pinfo.number] = { src = pinfo.src, dst = pinfo.dst }
      last_seen[tostring(pinfo.src)] = pinfo.number

      -- Reference each file-scope local at least once so Lua keeps
      -- them as upvalues of this closure (otherwise the watch
      -- examples below can't reach them).
      local _captured = { printer, opcode_names, handshake,
                          ip_src_F, tcp_flags_F }

      print(pinfo.number, tostring(pinfo.src), tostring(pinfo.dst))
    end

    register_postdissector(printer)

Every example later in this chapter resolves against names this script defines, so you can paste any of them into the Watch panel without setting up extra state. What’s in scope while `printer.dissector` is paused:

- Upvalues (file-scope locals captured by the dissector closure): `printer`, `sessions`, `last_seen`, `opcode_names`, `handshake`, `ip_src_F`, `tcp_flags_F`.
- Locals: `tvb`, `pinfo`, `tree`, `offset`.
- Globals of interest: `print`, `tostring`, `assert`, `string`, `type`, `getmetatable`, `Field`, `Proto`, `register_postdissector`, `get_version`.

The `local _captured = { …​ }` line in the dissector body is demo-only: Lua captures file-scope locals as upvalues only if the closure references them, so each name has to be mentioned at least once for it to show up under `Upvalues`. A real postdissector’s protocol logic does the same work organically. `opcode_names` and `handshake` are otherwise unused — they exist solely to seed hex-keyed and boolean-keyed tables for the path-watch examples below.

`Field.new(…​)` is called at file scope on purpose: extractors can only be constructed at script load, before any dissector or tap callback runs. Inside the dissector callback the script references `ip_src_F` / `tcp_flags_F` (and so do the watch examples below), but never calls `Field.new` again.

Drop it into your personal plugins directory (the exact path on your install is also shown under Help → About Wireshark → Folders → Personal Lua Plugins). The canonical locations are:

- Linux and macOS: `~/.local/lib/wireshark/plugins/`
- Windows: `%APPDATA%\Wireshark\plugins\`

Then:

1. Pick Analyze → Reload Lua Plugins (`Ctrl+Shift+L`) so Wireshark picks up the new file. The same shortcut also works from the Reload Lua Plugins toolbar action inside the Lua Debugger dialog once it’s open.
2. Open Tools → Lua Debugger and tick the Enabled checkbox in the dialog header.
3. Expand the Files section and double-click `printer.lua` to open it in the editor.
4. Click in the gutter on a line inside `printer.dissector` to toggle a breakpoint (a red circle appears).
5. Load any capture file. Dissection starts, the breakpoint hits, and the debugger pauses — the paused line gets a yellow stripe (and a yellow right-pointing triangle in the gutter), the Enabled checkbox dot turns yellow, the window title changes to Lua Debugger — Paused, and the main window grays out behind a "Lua debugger paused" banner.

6. Inspect the paused state:

   - Variables shows Locals (`tvb`, `pinfo`, `tree`), Upvalues, and Globals for the current frame.
   - Stack Trace shows the postdissector call on top of whatever frame drove the dissection.
   - Try Add Watch on `pinfo.src` (via the Variables context menu or the `＋` button in the Watch section header, `Ctrl+Shift+W`).
7. Use Step Over (`F10`), Step Into (`F11`), or Continue (`F5`) to advance. The Watch tree updates on every pause; values that changed since the previous pause are drawn in a bold accent color and briefly flash.

Prev | Up | Next
14.2. Pause Behavior | Home | 14.4. Toolbar