# # Copyright (C) 2026 GNS3 Technologies Inc. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import List, Optional from pydantic import BaseModel, ConfigDict, Field class ReplaySource(BaseModel): """ A capture source (one marker pcap) of a replay tag. """ node_id: str link_id: str marker: str data_link_type: str count: int = Field(..., description="Total frames in the capture, unaffected by filters") class ReplayFrame(BaseModel): """ One frame of the merged replay timeline. """ ts: str = Field(..., description="Timestamp string to send back unchanged") len: int = Field(..., description="Captured length in bytes") node_id: str link_id: str marker: str frame_number: int = Field(..., description="1-based frame number in the source pcap") src: Optional[str] = None dst: Optional[str] = None proto: Optional[str] = None info: Optional[str] = None bg: Optional[str] = Field(None, description="Wireshark coloring rule background") fg: Optional[str] = Field(None, description="Wireshark coloring rule foreground") class ReplayTimeline(BaseModel): """ Replay timeline of a tag. """ tag: int start: Optional[str] = Field(None, description="Timestamp of the first matching frame") end: Optional[str] = Field(None, description="Timestamp of the last matching frame") frame_count: int sources: List[ReplaySource] frames: List[ReplayFrame] class ReplayFrames(BaseModel): """ Frames of a replay time window. """ frames: List[ReplayFrame] class ReplayFrameSource(BaseModel): """ The source pcap and frame a decoded frame comes from. """ node_id: str link_id: str marker: str frame_number: int class ReplayTreeNode(BaseModel): """ A node of the decoded protocol tree. Keys sharkd adds in the future are passed through unchanged. """ model_config = ConfigDict(extra="allow") element: Optional[str] = Field(None, description="Node type") label: Optional[str] = Field(None, description="Display text") name: Optional[str] = Field(None, description="Field name, e.g. 'ip.ttl'") filter_expr: Optional[str] = Field(None, description="Display filter with the value baked in") pos: Optional[int] = Field(None, description="Byte offset for hex highlighting") size: Optional[int] = Field(None, description="Byte length for hex highlighting") expert: Optional[str] = Field(None, description="Expert severity") generated: Optional[bool] = Field(None, description="Generated by Wireshark") children: Optional[List["ReplayTreeNode"]] = Field(None, description="Nested fields") class ReplayFrameDetail(BaseModel): """ One decoded frame. """ ts: str source: ReplayFrameSource field_count: int hex: str = Field(..., description="Raw frame bytes as hex") tree: List[ReplayTreeNode]