Skip to content

Fix Homer search: correct src/dst IP field map + add Type selector#7

Open
simllll wants to merge 3 commits into
thinhdanggroup:mainfrom
simllll:fix/homer-search-filters
Open

Fix Homer search: correct src/dst IP field map + add Type selector#7
simllll wants to merge 3 commits into
thinhdanggroup:mainfrom
simllll:fix/homer-search-filters

Conversation

@simllll
Copy link
Copy Markdown

@simllll simllll commented May 11, 2026

Two bugs in the /homer search route silently dropped whole categories of search results because the request was wired against the wrong slice of Homer 7's schema.

1. Source / Destination IP filters always returned 0 rows

_build_homer_filters mapped source_ip / dst_ip to:

"source_ip": "data_header.src_ip",
"dst_ip":    "data_header.dst_ip",

But Homer 7 stores L3 addresses under protocol_header.srcIp / protocol_header.dstIp (camelCase). data_header only holds SIP-parsed fields (callid, from_user, method, …). Filtering on the wrong JSONB column silently returns nothing.

Notably, this file's own result rendering in app/routes/homer.py already reads srcIp / dstIp:

"src_ip": invite.get("srcIp") or invite.get("source_ip", ""),
"dst_ip": invite.get("dstIp") or invite.get("destination_ip", ""),

— so the same module was writing the filter as one path and reading the result back from another. Fixed the field map to match where the data actually lives.

2. REGISTER / OPTIONS / MESSAGE etc. were unsearchable

The search request hard-coded the protocol profile:

"protocol_profile": {"name": "call", "value": "call"},
...
"search": {"1_call": _build_homer_filters(filters)},

This pins the query to hep_proto_1_call. Homer 7 splits SIP into three tables by transaction type:

Profile Table Methods
call hep_proto_1_call INVITE / BYE / CANCEL / 200-for-INVITE …
registration hep_proto_1_registration REGISTER
default hep_proto_1_default OPTIONS / MESSAGE / NOTIFY …

method=REGISTER against the call table is always empty even when REGISTER traffic is being captured fine.

Added a Type dropdown (Call / Registration / Other) plumbed through routes → service → Homer payload. Defaults to call so existing bookmarks and links behave unchanged. The unbounded call/transaction callid shortcut is now skipped for non-call profiles, since that endpoint is call-table-specific.

Diff summary

  • app/services/homer.py
    • _build_homer_filters: fix source_ip / dst_ip field map
    • Add SUPPORTED_PROFILES, DEFAULT_PROFILE, _normalize_profile
    • search_calls / HomerClient.search_calls: accept profile, use it for protocol_profile and the search key
  • app/routes/homer.py
    • Add profile query param to homer_index
    • Pass through to hc.search_calls; skip callid-shortcut for non-call profiles
    • Expose profile + profile_choices in template context
  • app/templates/homer/index.html.j2
    • Add <select name="profile"> before the Time Range select

Testing

Tested against a Homer 7 deployment ingesting from heplify-server:

  • ?src_ip=<X> now returns rows for any IP that appears in the unfiltered result list (previously empty).
  • ?profile=registration&method=REGISTER returns REGISTER traffic from hep_proto_1_registration (previously empty).
  • Default (profile omitted) behaves identically to before for call-profile searches.
  • Callid-only search still uses the unbounded call/transaction endpoint when profile=call.

Happy to adjust scope or split into two PRs if you'd prefer the IP fix to land separately from the Type selector.

simllll added 3 commits May 11, 2026 22:55
Two bugs in `/homer` search wired the dashboard against the wrong slice
of Homer 7's schema, making whole categories of search return 0 rows
even when matching data clearly existed in the DB.

1. Source/Destination IP filters always returned 0 rows
   `_build_homer_filters` mapped `source_ip` / `dst_ip` to
   `data_header.src_ip` / `data_header.dst_ip`. Homer 7 stores L3
   addresses under `protocol_header.srcIp` / `protocol_header.dstIp`
   (camelCase), while `data_header` only holds SIP-parsed fields
   (callid, from_user, method, ...). Filtering on the wrong JSONB
   column silently returns no rows. Notably, this file's own result
   rendering elsewhere already reads `srcIp`/`dstIp` — so the same
   module wrote one path and read another. Fixed the field map to
   match where the data actually lives.

2. REGISTER / OPTIONS / MESSAGE etc. were unsearchable
   The search request hard-coded `protocol_profile: "call"`, which
   pins the query to `hep_proto_1_call`. Homer 7 splits SIP into
   three tables by transaction type: `_call` (INVITE/BYE/CANCEL/...),
   `_registration` (REGISTER), and `_default` (OPTIONS/MESSAGE/...).
   `method=REGISTER` against the call table is always empty even
   when REGISTER traffic is being captured fine.
   Added a `Type` dropdown (Call / Registration / Other) plumbed
   through routes → service → Homer payload. Defaults to `call`
   so existing bookmarks behave unchanged. Also skips the unbounded
   call/transaction callid-shortcut for non-call profiles since
   that endpoint is call-table-specific.

Tested by submitting searches with each Type + IP filters against a
Homer 7 deployment ingesting from heplify; rows come back for each
case that previously returned nothing.
PR thinhdanggroup#7 made search work for REGISTER / OPTIONS / MESSAGE traffic, but
clicking a row in the result table still rendered an empty flow
diagram. Same root cause as the search bug, in the *detail* path
this time: `get_call_transaction` hard-coded both the transaction
flags and the search-key prefix to "call", so any callid lookup
queried `hep_proto_1_call` regardless of which table the row
actually lived in.

  payload["param"]["transaction"] = {"call": True, "registration": False, "rest": False}
  payload["param"]["search"]      = {"1_call": ...}

For a REGISTER callid the call table has no messages → Homer returns
zero rows → `_build_call_detail` produces an empty `messages`/`flow_rows`
list → the ladder diagram renders blank.

Plumb the profile through:
  - `get_call_transaction` accepts `profile` (default "call"), maps it
    to the matching transaction-flag triple, and uses `1_{profile}`
    in the search key.
  - `HomerClient.get_call_transaction` accepts profile.
  - `homer_call_detail` / `homer_call_export` routes accept a
    `profile` query param and forward it.
  - Result-row links in `homer/index.html.j2` and the export link in
    `homer/call.html.j2` carry `&profile={{ profile }}` so the detail
    view inherits the search's profile rather than guessing.

Defaults remain "call" so existing call-profile bookmarks and old
links keep working unchanged.
Tab nav hrefs in homer/call.html.j2 rebuilt the query string from
record_id/ts/tab only, so clicking Flow/Messages/Session/Logs/Export
dropped the `profile` param the search-result link had supplied.
The detail route then fell back to the default `call` profile and
queried the wrong transaction table — REGISTERs went back to
rendering as an empty flow diagram on every tab switch.

Include `profile` in all five tab hrefs alongside record_id/ts/tab.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant