feat: Add pcap import, file browser, logging, local capture, and stable call ordering
This commit is contained in:
@@ -4,15 +4,27 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"telephony-inspector/internal/logger"
|
||||||
"telephony-inspector/internal/tui"
|
"telephony-inspector/internal/tui"
|
||||||
|
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
// Initialize logger
|
||||||
|
if err := logger.Init(); err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Warning: Could not initialize logger: %v\n", err)
|
||||||
|
}
|
||||||
|
defer logger.Close()
|
||||||
|
|
||||||
|
logger.Info("Starting Telephony Inspector")
|
||||||
|
|
||||||
p := tea.NewProgram(tui.NewModel(), tea.WithAltScreen())
|
p := tea.NewProgram(tui.NewModel(), tea.WithAltScreen())
|
||||||
if _, err := p.Run(); err != nil {
|
if _, err := p.Run(); err != nil {
|
||||||
|
logger.Error("Program error: %v", err)
|
||||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.Info("Telephony Inspector exited normally")
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
data/calls.pcap
Normal file
BIN
data/calls.pcap
Normal file
Binary file not shown.
BIN
data/test.pcapng
Normal file
BIN
data/test.pcapng
Normal file
Binary file not shown.
BIN
data/test2.pcap
Normal file
BIN
data/test2.pcap
Normal file
Binary file not shown.
4
go.mod
4
go.mod
@@ -5,12 +5,15 @@ go 1.24.0
|
|||||||
toolchain go1.24.12
|
toolchain go1.24.12
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/charmbracelet/bubbles v0.21.0
|
||||||
github.com/charmbracelet/bubbletea v1.3.10
|
github.com/charmbracelet/bubbletea v1.3.10
|
||||||
github.com/charmbracelet/lipgloss v1.1.0
|
github.com/charmbracelet/lipgloss v1.1.0
|
||||||
|
github.com/google/gopacket v1.1.19
|
||||||
golang.org/x/crypto v0.47.0
|
golang.org/x/crypto v0.47.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/atotto/clipboard v0.1.4 // indirect
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||||
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
|
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
|
||||||
github.com/charmbracelet/x/ansi v0.10.1 // indirect
|
github.com/charmbracelet/x/ansi v0.10.1 // indirect
|
||||||
@@ -25,6 +28,7 @@ require (
|
|||||||
github.com/muesli/cancelreader v0.2.2 // indirect
|
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||||
github.com/muesli/termenv v0.16.0 // indirect
|
github.com/muesli/termenv v0.16.0 // indirect
|
||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
|
github.com/sahilm/fuzzy v0.1.1 // indirect
|
||||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||||
golang.org/x/sys v0.40.0 // indirect
|
golang.org/x/sys v0.40.0 // indirect
|
||||||
golang.org/x/text v0.33.0 // indirect
|
golang.org/x/text v0.33.0 // indirect
|
||||||
|
|||||||
28
go.sum
28
go.sum
@@ -1,5 +1,11 @@
|
|||||||
|
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
|
||||||
|
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
||||||
|
github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8=
|
||||||
|
github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA=
|
||||||
|
github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u6mfQdFs=
|
||||||
|
github.com/charmbracelet/bubbles v0.21.0/go.mod h1:HF+v6QUR4HkEpz62dx7ym2xc71/KBHg+zKwJtMw+qtg=
|
||||||
github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw=
|
github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw=
|
||||||
github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4=
|
github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4=
|
||||||
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs=
|
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs=
|
||||||
@@ -10,10 +16,16 @@ github.com/charmbracelet/x/ansi v0.10.1 h1:rL3Koar5XvX0pHGfovN03f5cxLbCF2YvLeyz7
|
|||||||
github.com/charmbracelet/x/ansi v0.10.1/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE=
|
github.com/charmbracelet/x/ansi v0.10.1/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE=
|
||||||
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8=
|
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8=
|
||||||
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
|
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
|
||||||
|
github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 h1:payRxjMjKgx2PaCWLZ4p3ro9y97+TVLZNaRZgJwSVDQ=
|
||||||
|
github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
|
||||||
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
|
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
|
||||||
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
|
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
|
||||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
|
||||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
|
||||||
|
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
|
||||||
|
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
|
||||||
|
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||||
|
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
@@ -31,17 +43,33 @@ github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3
|
|||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
|
github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA=
|
||||||
|
github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
|
||||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
||||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
|
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
|
||||||
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
|
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
|
||||||
golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 h1:MDc5xs78ZrZr3HMQugiXOAkSZtfTpbJLDr/lwfgO53E=
|
golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 h1:MDc5xs78ZrZr3HMQugiXOAkSZtfTpbJLDr/lwfgO53E=
|
||||||
golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
|
golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
|
||||||
|
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
|
||||||
|
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
||||||
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY=
|
golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY=
|
||||||
golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww=
|
golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
||||||
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
||||||
|
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
|||||||
BIN
inspector.exe
BIN
inspector.exe
Binary file not shown.
180
internal/capture/local.go
Normal file
180
internal/capture/local.go
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
package capture
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"telephony-inspector/internal/sip"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LocalCapturer handles SIP packet capture locally via tcpdump
|
||||||
|
type LocalCapturer struct {
|
||||||
|
cmd *exec.Cmd
|
||||||
|
cancel context.CancelFunc
|
||||||
|
running bool
|
||||||
|
mu sync.Mutex
|
||||||
|
|
||||||
|
// Callbacks
|
||||||
|
OnPacket func(*sip.Packet)
|
||||||
|
OnError func(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewLocalCapturer creates a new local capturer
|
||||||
|
func NewLocalCapturer() *LocalCapturer {
|
||||||
|
return &LocalCapturer{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start begins capturing SIP traffic locally
|
||||||
|
func (c *LocalCapturer) Start(iface string, port int) error {
|
||||||
|
c.mu.Lock()
|
||||||
|
if c.running {
|
||||||
|
c.mu.Unlock()
|
||||||
|
return fmt.Errorf("capture already running")
|
||||||
|
}
|
||||||
|
c.running = true
|
||||||
|
c.mu.Unlock()
|
||||||
|
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
c.cancel = cancel
|
||||||
|
|
||||||
|
// Build tcpdump command
|
||||||
|
// -l: line buffered
|
||||||
|
// -A: print packet payload in ASCII
|
||||||
|
// -s 0: capture full packets
|
||||||
|
args := []string{"-l", "-A", "-s", "0", "-i", iface, "port", fmt.Sprintf("%d", port)}
|
||||||
|
c.cmd = exec.CommandContext(ctx, "tcpdump", args...)
|
||||||
|
|
||||||
|
stdout, err := c.cmd.StdoutPipe()
|
||||||
|
if err != nil {
|
||||||
|
c.mu.Lock()
|
||||||
|
c.running = false
|
||||||
|
c.mu.Unlock()
|
||||||
|
return fmt.Errorf("failed to get stdout: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
stderr, err := c.cmd.StderrPipe()
|
||||||
|
if err != nil {
|
||||||
|
c.mu.Lock()
|
||||||
|
c.running = false
|
||||||
|
c.mu.Unlock()
|
||||||
|
return fmt.Errorf("failed to get stderr: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.cmd.Start(); err != nil {
|
||||||
|
c.mu.Lock()
|
||||||
|
c.running = false
|
||||||
|
c.mu.Unlock()
|
||||||
|
return fmt.Errorf("failed to start tcpdump: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process stdout in goroutine
|
||||||
|
go c.processStream(stdout)
|
||||||
|
|
||||||
|
// Log stderr
|
||||||
|
go c.processErrors(stderr)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop stops the capture
|
||||||
|
func (c *LocalCapturer) Stop() {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
|
||||||
|
if !c.running {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.running = false
|
||||||
|
|
||||||
|
if c.cancel != nil {
|
||||||
|
c.cancel()
|
||||||
|
c.cancel = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.cmd != nil && c.cmd.Process != nil {
|
||||||
|
c.cmd.Process.Kill()
|
||||||
|
c.cmd.Wait()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRunning returns whether capture is active
|
||||||
|
func (c *LocalCapturer) IsRunning() bool {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
return c.running
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close cleans up resources
|
||||||
|
func (c *LocalCapturer) Close() error {
|
||||||
|
c.Stop()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *LocalCapturer) processStream(r io.Reader) {
|
||||||
|
scanner := bufio.NewScanner(r)
|
||||||
|
var buffer strings.Builder
|
||||||
|
inSIPMessage := false
|
||||||
|
|
||||||
|
for scanner.Scan() {
|
||||||
|
c.mu.Lock()
|
||||||
|
running := c.running
|
||||||
|
c.mu.Unlock()
|
||||||
|
if !running {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
line := scanner.Text()
|
||||||
|
|
||||||
|
// Detect start of SIP message
|
||||||
|
if isSIPStart(line) {
|
||||||
|
// If we were building a message, parse it
|
||||||
|
if buffer.Len() > 0 {
|
||||||
|
c.parseAndEmit(buffer.String())
|
||||||
|
buffer.Reset()
|
||||||
|
}
|
||||||
|
inSIPMessage = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if inSIPMessage {
|
||||||
|
buffer.WriteString(line)
|
||||||
|
buffer.WriteString("\r\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse remaining buffer
|
||||||
|
if buffer.Len() > 0 {
|
||||||
|
c.parseAndEmit(buffer.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *LocalCapturer) processErrors(r io.Reader) {
|
||||||
|
scanner := bufio.NewScanner(r)
|
||||||
|
for scanner.Scan() {
|
||||||
|
text := scanner.Text()
|
||||||
|
// tcpdump prints "listening on..." to stderr, ignore it
|
||||||
|
if strings.Contains(text, "listening on") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if c.OnError != nil {
|
||||||
|
c.OnError(fmt.Errorf("tcpdump: %s", text))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *LocalCapturer) parseAndEmit(raw string) {
|
||||||
|
packet, err := sip.Parse(raw)
|
||||||
|
if err != nil {
|
||||||
|
if c.OnError != nil {
|
||||||
|
c.OnError(err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if packet != nil && c.OnPacket != nil {
|
||||||
|
c.OnPacket(packet)
|
||||||
|
}
|
||||||
|
}
|
||||||
243
internal/capture/pcap_reader.go
Normal file
243
internal/capture/pcap_reader.go
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
package capture
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"telephony-inspector/internal/logger"
|
||||||
|
"telephony-inspector/internal/sip"
|
||||||
|
|
||||||
|
"github.com/google/gopacket"
|
||||||
|
"github.com/google/gopacket/layers"
|
||||||
|
"github.com/google/gopacket/pcap"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PcapReader reads and parses pcap files
|
||||||
|
type PcapReader struct {
|
||||||
|
path string
|
||||||
|
handle *pcap.Handle
|
||||||
|
packets []*sip.Packet
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPcapReader creates a new pcap reader
|
||||||
|
func NewPcapReader(path string) *PcapReader {
|
||||||
|
logger.Info("PcapReader: Creating reader for %s", path)
|
||||||
|
return &PcapReader{
|
||||||
|
path: path,
|
||||||
|
packets: make([]*sip.Packet, 0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadAll reads all SIP packets from the pcap file
|
||||||
|
func (r *PcapReader) ReadAll() ([]*sip.Packet, error) {
|
||||||
|
logger.Info("PcapReader: Opening file %s", r.path)
|
||||||
|
|
||||||
|
// Check if file exists
|
||||||
|
if _, err := os.Stat(r.path); os.IsNotExist(err) {
|
||||||
|
logger.Error("PcapReader: File does not exist: %s", r.path)
|
||||||
|
return nil, fmt.Errorf("file does not exist: %s", r.path)
|
||||||
|
}
|
||||||
|
|
||||||
|
handle, err := pcap.OpenOffline(r.path)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("PcapReader: Failed to open pcap: %v", err)
|
||||||
|
return nil, fmt.Errorf("failed to open pcap: %w", err)
|
||||||
|
}
|
||||||
|
defer handle.Close()
|
||||||
|
|
||||||
|
logger.Info("PcapReader: File opened successfully, link type: %v", handle.LinkType())
|
||||||
|
|
||||||
|
// Try setting BPF filter (optional)
|
||||||
|
if err := handle.SetBPFFilter("port 5060 or port 5061"); err != nil {
|
||||||
|
logger.Warn("PcapReader: Could not set BPF filter: %v (continuing without filter)", err)
|
||||||
|
} else {
|
||||||
|
logger.Debug("PcapReader: BPF filter set for SIP ports")
|
||||||
|
}
|
||||||
|
|
||||||
|
packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
|
||||||
|
|
||||||
|
totalPackets := 0
|
||||||
|
sipPackets := 0
|
||||||
|
|
||||||
|
for packet := range packetSource.Packets() {
|
||||||
|
totalPackets++
|
||||||
|
logger.Debug("PcapReader: Processing packet %d, layers: %v", totalPackets, packet.Layers())
|
||||||
|
|
||||||
|
sipPacket := r.extractSIPPacket(packet, totalPackets)
|
||||||
|
if sipPacket != nil {
|
||||||
|
sipPackets++
|
||||||
|
r.packets = append(r.packets, sipPacket)
|
||||||
|
logger.Info("PcapReader: Found SIP packet %d: %s %s", sipPackets,
|
||||||
|
func() string {
|
||||||
|
if sipPacket.IsRequest {
|
||||||
|
return string(sipPacket.Method)
|
||||||
|
} else {
|
||||||
|
return fmt.Sprintf("%d", sipPacket.StatusCode)
|
||||||
|
}
|
||||||
|
}(),
|
||||||
|
sipPacket.CallID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("PcapReader: Finished reading. Total packets: %d, SIP packets: %d", totalPackets, sipPackets)
|
||||||
|
return r.packets, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// extractSIPPacket extracts SIP data from a gopacket
|
||||||
|
func (r *PcapReader) extractSIPPacket(packet gopacket.Packet, packetNum int) *sip.Packet {
|
||||||
|
// Get network layer for IPs
|
||||||
|
var srcIP, dstIP string
|
||||||
|
var srcPort, dstPort int
|
||||||
|
var payload []byte
|
||||||
|
|
||||||
|
if ipLayer := packet.Layer(layers.LayerTypeIPv4); ipLayer != nil {
|
||||||
|
ip := ipLayer.(*layers.IPv4)
|
||||||
|
srcIP = ip.SrcIP.String()
|
||||||
|
dstIP = ip.DstIP.String()
|
||||||
|
logger.Debug("PcapReader: Packet %d IPv4 %s -> %s", packetNum, srcIP, dstIP)
|
||||||
|
} else if ipLayer := packet.Layer(layers.LayerTypeIPv6); ipLayer != nil {
|
||||||
|
ip := ipLayer.(*layers.IPv6)
|
||||||
|
srcIP = ip.SrcIP.String()
|
||||||
|
dstIP = ip.DstIP.String()
|
||||||
|
logger.Debug("PcapReader: Packet %d IPv6 %s -> %s", packetNum, srcIP, dstIP)
|
||||||
|
} else {
|
||||||
|
logger.Debug("PcapReader: Packet %d has no IP layer", packetNum)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get transport layer for ports AND payload
|
||||||
|
if udpLayer := packet.Layer(layers.LayerTypeUDP); udpLayer != nil {
|
||||||
|
udp := udpLayer.(*layers.UDP)
|
||||||
|
srcPort = int(udp.SrcPort)
|
||||||
|
dstPort = int(udp.DstPort)
|
||||||
|
payload = udp.Payload
|
||||||
|
logger.Debug("PcapReader: Packet %d UDP %d -> %d, payload len: %d", packetNum, srcPort, dstPort, len(payload))
|
||||||
|
} else if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer != nil {
|
||||||
|
tcp := tcpLayer.(*layers.TCP)
|
||||||
|
srcPort = int(tcp.SrcPort)
|
||||||
|
dstPort = int(tcp.DstPort)
|
||||||
|
payload = tcp.Payload
|
||||||
|
logger.Debug("PcapReader: Packet %d TCP %d -> %d, payload len: %d", packetNum, srcPort, dstPort, len(payload))
|
||||||
|
} else {
|
||||||
|
logger.Debug("PcapReader: Packet %d has no TCP/UDP layer", packetNum)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(payload) == 0 {
|
||||||
|
logger.Debug("PcapReader: Packet %d has empty payload", packetNum)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
payloadStr := string(payload)
|
||||||
|
|
||||||
|
// Log first 200 chars to see full SIP headers
|
||||||
|
preview := payloadStr
|
||||||
|
if len(preview) > 200 {
|
||||||
|
preview = preview[:200]
|
||||||
|
}
|
||||||
|
logger.Debug("PcapReader: Packet %d full payload preview: %q", packetNum, preview)
|
||||||
|
|
||||||
|
// Check if it looks like SIP
|
||||||
|
if !isSIPPayload(payloadStr) {
|
||||||
|
logger.Debug("PcapReader: Packet %d is not SIP", packetNum)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Debug("PcapReader: Packet %d detected as SIP, parsing...", packetNum)
|
||||||
|
|
||||||
|
// Parse the SIP message
|
||||||
|
sipPacket, err := sip.Parse(payloadStr)
|
||||||
|
if err != nil {
|
||||||
|
logger.Warn("PcapReader: Packet %d SIP parse error: %v", packetNum, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if sipPacket == nil {
|
||||||
|
logger.Warn("PcapReader: Packet %d SIP parse returned nil", packetNum)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set network info
|
||||||
|
sipPacket.SourceIP = srcIP
|
||||||
|
sipPacket.SourcePort = srcPort
|
||||||
|
sipPacket.DestIP = dstIP
|
||||||
|
sipPacket.DestPort = dstPort
|
||||||
|
|
||||||
|
return sipPacket
|
||||||
|
}
|
||||||
|
|
||||||
|
// isSIPPayload checks if payload looks like a SIP message
|
||||||
|
func isSIPPayload(payload string) bool {
|
||||||
|
if len(payload) < 4 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for SIP request methods
|
||||||
|
methods := []string{"INVITE ", "ACK ", "BYE ", "CANCEL ", "REGISTER ", "OPTIONS ",
|
||||||
|
"PRACK ", "SUBSCRIBE ", "NOTIFY ", "PUBLISH ", "INFO ", "REFER ", "MESSAGE ", "UPDATE "}
|
||||||
|
for _, m := range methods {
|
||||||
|
if len(payload) >= len(m) && payload[:len(m)] == m {
|
||||||
|
logger.Debug("isSIPPayload: Detected SIP method: %s", m[:len(m)-1])
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for SIP response
|
||||||
|
if len(payload) >= 7 && payload[:7] == "SIP/2.0" {
|
||||||
|
logger.Debug("isSIPPayload: Detected SIP response")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this looks like an SDP body (might be reassembled SIP)
|
||||||
|
if len(payload) >= 4 && payload[:4] == "v=0\r" {
|
||||||
|
logger.Debug("isSIPPayload: Detected SDP-only payload (no SIP headers)")
|
||||||
|
// This is SDP without SIP headers - likely a reassembly issue
|
||||||
|
// Log first 50 chars for debugging
|
||||||
|
preview := payload
|
||||||
|
if len(preview) > 50 {
|
||||||
|
preview = preview[:50]
|
||||||
|
}
|
||||||
|
logger.Debug("isSIPPayload: SDP payload: %q", preview)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log what the payload starts with for debugging
|
||||||
|
preview := payload
|
||||||
|
if len(preview) > 20 {
|
||||||
|
preview = preview[:20]
|
||||||
|
}
|
||||||
|
logger.Debug("isSIPPayload: Unrecognized payload start: %q", preview)
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPacketCount returns number of packets read
|
||||||
|
func (r *PcapReader) GetPacketCount() int {
|
||||||
|
return len(r.packets)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the reader
|
||||||
|
func (r *PcapReader) Close() error {
|
||||||
|
if r.handle != nil {
|
||||||
|
r.handle.Close()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListPcapFiles lists .pcap files in a directory
|
||||||
|
func ListPcapFiles(dir string) ([]string, error) {
|
||||||
|
entries, err := os.ReadDir(dir)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var files []string
|
||||||
|
for _, e := range entries {
|
||||||
|
if e.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
name := e.Name()
|
||||||
|
if len(name) > 5 && (name[len(name)-5:] == ".pcap" || name[len(name)-7:] == ".pcapng") {
|
||||||
|
files = append(files, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return files, nil
|
||||||
|
}
|
||||||
72
internal/config/loader.go
Normal file
72
internal/config/loader.go
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LoadNetworkMap loads a network map from a JSON file
|
||||||
|
func LoadNetworkMap(path string) (*NetworkMap, error) {
|
||||||
|
data, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var nm NetworkMap
|
||||||
|
if err := json.Unmarshal(data, &nm); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &nm, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SaveNetworkMap saves a network map to a JSON file
|
||||||
|
func SaveNetworkMap(nm *NetworkMap, path string) error {
|
||||||
|
data, err := json.MarshalIndent(nm, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return os.WriteFile(path, data, 0644)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultNetworkMapPath returns a default path for the network map file
|
||||||
|
func DefaultNetworkMapPath() string {
|
||||||
|
return "network_map.json"
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateSampleNetworkMap creates a sample network map for testing
|
||||||
|
func CreateSampleNetworkMap() *NetworkMap {
|
||||||
|
nm := NewNetworkMap()
|
||||||
|
|
||||||
|
nm.AddNode(NetworkNode{
|
||||||
|
Name: "Asterisk PBX",
|
||||||
|
IP: "192.168.1.10",
|
||||||
|
Type: NodeTypePBX,
|
||||||
|
Description: "Main PBX server",
|
||||||
|
})
|
||||||
|
|
||||||
|
nm.AddNode(NetworkNode{
|
||||||
|
Name: "Kamailio Proxy",
|
||||||
|
IP: "192.168.1.20",
|
||||||
|
Type: NodeTypeProxy,
|
||||||
|
Aliases: []string{"10.0.0.20"},
|
||||||
|
Description: "SIP proxy/load balancer",
|
||||||
|
})
|
||||||
|
|
||||||
|
nm.AddNode(NetworkNode{
|
||||||
|
Name: "RTPEngine",
|
||||||
|
IP: "192.168.1.30",
|
||||||
|
Type: NodeTypeMediaServer,
|
||||||
|
Description: "Media relay server",
|
||||||
|
})
|
||||||
|
|
||||||
|
nm.AddNode(NetworkNode{
|
||||||
|
Name: "PSTN Gateway",
|
||||||
|
IP: "192.168.1.40",
|
||||||
|
Type: NodeTypeGateway,
|
||||||
|
Description: "Gateway to PSTN",
|
||||||
|
})
|
||||||
|
|
||||||
|
return nm
|
||||||
|
}
|
||||||
113
internal/logger/logger.go
Normal file
113
internal/logger/logger.go
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
package logger
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
instance *Logger
|
||||||
|
once sync.Once
|
||||||
|
)
|
||||||
|
|
||||||
|
// Logger handles application logging
|
||||||
|
type Logger struct {
|
||||||
|
file *os.File
|
||||||
|
mu sync.Mutex
|
||||||
|
path string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init initializes the logger with timestamp-based filename
|
||||||
|
func Init() error {
|
||||||
|
var err error
|
||||||
|
once.Do(func() {
|
||||||
|
// Create logs directory
|
||||||
|
logsDir := "logs"
|
||||||
|
if mkErr := os.MkdirAll(logsDir, 0755); mkErr != nil {
|
||||||
|
err = mkErr
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create log file with timestamp
|
||||||
|
timestamp := time.Now().Format("2006-01-02_15-04-05")
|
||||||
|
filename := filepath.Join(logsDir, fmt.Sprintf("%s.log", timestamp))
|
||||||
|
|
||||||
|
f, openErr := os.Create(filename)
|
||||||
|
if openErr != nil {
|
||||||
|
err = openErr
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
instance = &Logger{
|
||||||
|
file: f,
|
||||||
|
path: filename,
|
||||||
|
}
|
||||||
|
|
||||||
|
Info("Logger initialized: %s", filename)
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the logger
|
||||||
|
func Close() {
|
||||||
|
if instance != nil && instance.file != nil {
|
||||||
|
instance.file.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPath returns the log file path
|
||||||
|
func GetPath() string {
|
||||||
|
if instance != nil {
|
||||||
|
return instance.path
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// log writes a log entry
|
||||||
|
func log(level, format string, args ...interface{}) {
|
||||||
|
if instance == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
instance.mu.Lock()
|
||||||
|
defer instance.mu.Unlock()
|
||||||
|
|
||||||
|
timestamp := time.Now().Format("15:04:05.000")
|
||||||
|
msg := fmt.Sprintf(format, args...)
|
||||||
|
line := fmt.Sprintf("[%s] [%s] %s\n", timestamp, level, msg)
|
||||||
|
|
||||||
|
instance.file.WriteString(line)
|
||||||
|
instance.file.Sync()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug logs a debug message
|
||||||
|
func Debug(format string, args ...interface{}) {
|
||||||
|
log("DEBUG", format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Info logs an info message
|
||||||
|
func Info(format string, args ...interface{}) {
|
||||||
|
log("INFO", format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warn logs a warning message
|
||||||
|
func Warn(format string, args ...interface{}) {
|
||||||
|
log("WARN", format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error logs an error message
|
||||||
|
func Error(format string, args ...interface{}) {
|
||||||
|
log("ERROR", format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writer returns an io.Writer that logs to the file
|
||||||
|
func Writer() io.Writer {
|
||||||
|
if instance != nil {
|
||||||
|
return instance.file
|
||||||
|
}
|
||||||
|
return os.Stdout
|
||||||
|
}
|
||||||
199
internal/sip/callflow.go
Normal file
199
internal/sip/callflow.go
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
package sip
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CallFlow represents a SIP call with all its packets
|
||||||
|
type CallFlow struct {
|
||||||
|
CallID string
|
||||||
|
Packets []*Packet
|
||||||
|
StartTime time.Time
|
||||||
|
EndTime time.Time
|
||||||
|
|
||||||
|
// Summary info
|
||||||
|
From string
|
||||||
|
To string
|
||||||
|
State CallState
|
||||||
|
}
|
||||||
|
|
||||||
|
// CallState represents the current state of a call
|
||||||
|
type CallState string
|
||||||
|
|
||||||
|
const (
|
||||||
|
CallStateInitial CallState = "Initial"
|
||||||
|
CallStateRinging CallState = "Ringing"
|
||||||
|
CallStateConnected CallState = "Connected"
|
||||||
|
CallStateTerminated CallState = "Terminated"
|
||||||
|
CallStateFailed CallState = "Failed"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CallFlowStore stores and manages call flows
|
||||||
|
type CallFlowStore struct {
|
||||||
|
mu sync.RWMutex
|
||||||
|
flows map[string]*CallFlow
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCallFlowStore creates a new call flow store
|
||||||
|
func NewCallFlowStore() *CallFlowStore {
|
||||||
|
return &CallFlowStore{
|
||||||
|
flows: make(map[string]*CallFlow),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddPacket adds a packet to the appropriate call flow
|
||||||
|
func (s *CallFlowStore) AddPacket(p *Packet) *CallFlow {
|
||||||
|
s.mu.Lock()
|
||||||
|
defer s.mu.Unlock()
|
||||||
|
|
||||||
|
if p.CallID == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
flow, exists := s.flows[p.CallID]
|
||||||
|
if !exists {
|
||||||
|
flow = &CallFlow{
|
||||||
|
CallID: p.CallID,
|
||||||
|
Packets: make([]*Packet, 0),
|
||||||
|
StartTime: time.Now(),
|
||||||
|
From: p.From,
|
||||||
|
To: p.To,
|
||||||
|
State: CallStateInitial,
|
||||||
|
}
|
||||||
|
s.flows[p.CallID] = flow
|
||||||
|
}
|
||||||
|
|
||||||
|
flow.Packets = append(flow.Packets, p)
|
||||||
|
flow.EndTime = time.Now()
|
||||||
|
|
||||||
|
// Update call state based on packet
|
||||||
|
s.updateState(flow, p)
|
||||||
|
|
||||||
|
return flow
|
||||||
|
}
|
||||||
|
|
||||||
|
// updateState updates the call state based on the packet
|
||||||
|
func (s *CallFlowStore) updateState(flow *CallFlow, p *Packet) {
|
||||||
|
if p.IsRequest {
|
||||||
|
switch p.Method {
|
||||||
|
case MethodINVITE:
|
||||||
|
if flow.State == CallStateInitial {
|
||||||
|
flow.State = CallStateInitial
|
||||||
|
}
|
||||||
|
case MethodBYE, MethodCANCEL:
|
||||||
|
flow.State = CallStateTerminated
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Response
|
||||||
|
switch {
|
||||||
|
case p.StatusCode >= 100 && p.StatusCode < 200:
|
||||||
|
if p.StatusCode == 180 || p.StatusCode == 183 {
|
||||||
|
flow.State = CallStateRinging
|
||||||
|
}
|
||||||
|
case p.StatusCode >= 200 && p.StatusCode < 300:
|
||||||
|
flow.State = CallStateConnected
|
||||||
|
case p.StatusCode >= 400:
|
||||||
|
flow.State = CallStateFailed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFlow returns a call flow by Call-ID
|
||||||
|
func (s *CallFlowStore) GetFlow(callID string) *CallFlow {
|
||||||
|
s.mu.RLock()
|
||||||
|
defer s.mu.RUnlock()
|
||||||
|
return s.flows[callID]
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAllFlows returns all call flows
|
||||||
|
func (s *CallFlowStore) GetAllFlows() []*CallFlow {
|
||||||
|
s.mu.RLock()
|
||||||
|
defer s.mu.RUnlock()
|
||||||
|
|
||||||
|
flows := make([]*CallFlow, 0, len(s.flows))
|
||||||
|
for _, f := range s.flows {
|
||||||
|
flows = append(flows, f)
|
||||||
|
}
|
||||||
|
return flows
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRecentFlows returns the N most recent call flows sorted by StartTime (oldest first)
|
||||||
|
func (s *CallFlowStore) GetRecentFlows(n int) []*CallFlow {
|
||||||
|
flows := s.GetAllFlows()
|
||||||
|
|
||||||
|
// Sort by start time ascending (oldest first), then by CallID for stable order
|
||||||
|
for i := 0; i < len(flows)-1; i++ {
|
||||||
|
for j := i + 1; j < len(flows); j++ {
|
||||||
|
// Compare by StartTime first
|
||||||
|
if flows[i].StartTime.After(flows[j].StartTime) {
|
||||||
|
flows[i], flows[j] = flows[j], flows[i]
|
||||||
|
} else if flows[i].StartTime.Equal(flows[j].StartTime) {
|
||||||
|
// If same time, sort by CallID for stable order
|
||||||
|
if flows[i].CallID > flows[j].CallID {
|
||||||
|
flows[i], flows[j] = flows[j], flows[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(flows) > n {
|
||||||
|
flows = flows[:n]
|
||||||
|
}
|
||||||
|
return flows
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count returns the number of call flows
|
||||||
|
func (s *CallFlowStore) Count() int {
|
||||||
|
s.mu.RLock()
|
||||||
|
defer s.mu.RUnlock()
|
||||||
|
return len(s.flows)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Summary returns a string summary of a packet for display
|
||||||
|
func (p *Packet) Summary() string {
|
||||||
|
if p.IsRequest {
|
||||||
|
return string(p.Method)
|
||||||
|
}
|
||||||
|
return formatStatusCode(p.StatusCode, p.StatusText)
|
||||||
|
}
|
||||||
|
|
||||||
|
func formatStatusCode(code int, text string) string {
|
||||||
|
if text != "" {
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
switch code {
|
||||||
|
case 100:
|
||||||
|
return "100 Trying"
|
||||||
|
case 180:
|
||||||
|
return "180 Ringing"
|
||||||
|
case 183:
|
||||||
|
return "183 Session Progress"
|
||||||
|
case 200:
|
||||||
|
return "200 OK"
|
||||||
|
case 400:
|
||||||
|
return "400 Bad Request"
|
||||||
|
case 401:
|
||||||
|
return "401 Unauthorized"
|
||||||
|
case 403:
|
||||||
|
return "403 Forbidden"
|
||||||
|
case 404:
|
||||||
|
return "404 Not Found"
|
||||||
|
case 408:
|
||||||
|
return "408 Request Timeout"
|
||||||
|
case 480:
|
||||||
|
return "480 Temporarily Unavailable"
|
||||||
|
case 486:
|
||||||
|
return "486 Busy Here"
|
||||||
|
case 487:
|
||||||
|
return "487 Request Terminated"
|
||||||
|
case 488:
|
||||||
|
return "488 Not Acceptable Here"
|
||||||
|
case 500:
|
||||||
|
return "500 Server Internal Error"
|
||||||
|
case 503:
|
||||||
|
return "503 Service Unavailable"
|
||||||
|
default:
|
||||||
|
return string(rune('0'+code/100)) + "xx"
|
||||||
|
}
|
||||||
|
}
|
||||||
256
internal/tui/file_browser.go
Normal file
256
internal/tui/file_browser.go
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
package tui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
|
"github.com/charmbracelet/lipgloss"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FileBrowserModel handles file selection
|
||||||
|
type FileBrowserModel struct {
|
||||||
|
currentDir string
|
||||||
|
entries []os.DirEntry
|
||||||
|
selected int
|
||||||
|
filter string // file extension filter (e.g., ".pcap")
|
||||||
|
height int
|
||||||
|
offset int
|
||||||
|
|
||||||
|
// Results
|
||||||
|
selectedFile string
|
||||||
|
cancelled bool
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFileBrowser creates a new file browser starting at dir
|
||||||
|
func NewFileBrowser(startDir string, filter string) FileBrowserModel {
|
||||||
|
if startDir == "" {
|
||||||
|
startDir, _ = os.Getwd()
|
||||||
|
}
|
||||||
|
|
||||||
|
fb := FileBrowserModel{
|
||||||
|
currentDir: startDir,
|
||||||
|
filter: filter,
|
||||||
|
height: 15,
|
||||||
|
}
|
||||||
|
fb.loadDir()
|
||||||
|
return fb
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *FileBrowserModel) loadDir() {
|
||||||
|
entries, err := os.ReadDir(m.currentDir)
|
||||||
|
if err != nil {
|
||||||
|
m.err = err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter and sort entries
|
||||||
|
var filtered []os.DirEntry
|
||||||
|
for _, e := range entries {
|
||||||
|
if e.IsDir() {
|
||||||
|
filtered = append(filtered, e)
|
||||||
|
} else if m.filter == "" {
|
||||||
|
filtered = append(filtered, e)
|
||||||
|
} else {
|
||||||
|
name := strings.ToLower(e.Name())
|
||||||
|
if strings.HasSuffix(name, m.filter) || strings.HasSuffix(name, ".pcapng") {
|
||||||
|
filtered = append(filtered, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort: directories first, then alphabetically
|
||||||
|
sort.Slice(filtered, func(i, j int) bool {
|
||||||
|
iDir := filtered[i].IsDir()
|
||||||
|
jDir := filtered[j].IsDir()
|
||||||
|
if iDir != jDir {
|
||||||
|
return iDir
|
||||||
|
}
|
||||||
|
return strings.ToLower(filtered[i].Name()) < strings.ToLower(filtered[j].Name())
|
||||||
|
})
|
||||||
|
|
||||||
|
m.entries = filtered
|
||||||
|
m.selected = 0
|
||||||
|
m.offset = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init initializes the model
|
||||||
|
func (m FileBrowserModel) Init() tea.Cmd {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update handles messages
|
||||||
|
func (m FileBrowserModel) Update(msg tea.Msg) (FileBrowserModel, tea.Cmd) {
|
||||||
|
switch msg := msg.(type) {
|
||||||
|
case tea.KeyMsg:
|
||||||
|
switch msg.String() {
|
||||||
|
case "esc", "q":
|
||||||
|
m.cancelled = true
|
||||||
|
return m, nil
|
||||||
|
|
||||||
|
case "up", "k":
|
||||||
|
if m.selected > 0 {
|
||||||
|
m.selected--
|
||||||
|
if m.selected < m.offset {
|
||||||
|
m.offset = m.selected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case "down", "j":
|
||||||
|
if m.selected < len(m.entries)-1 {
|
||||||
|
m.selected++
|
||||||
|
if m.selected >= m.offset+m.height {
|
||||||
|
m.offset = m.selected - m.height + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case "enter":
|
||||||
|
if len(m.entries) == 0 {
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
entry := m.entries[m.selected]
|
||||||
|
fullPath := filepath.Join(m.currentDir, entry.Name())
|
||||||
|
|
||||||
|
if entry.IsDir() {
|
||||||
|
m.currentDir = fullPath
|
||||||
|
m.loadDir()
|
||||||
|
} else {
|
||||||
|
m.selectedFile = fullPath
|
||||||
|
}
|
||||||
|
|
||||||
|
case "backspace", "h":
|
||||||
|
// Go to parent directory
|
||||||
|
parent := filepath.Dir(m.currentDir)
|
||||||
|
if parent != m.currentDir {
|
||||||
|
m.currentDir = parent
|
||||||
|
m.loadDir()
|
||||||
|
}
|
||||||
|
|
||||||
|
case "home":
|
||||||
|
home, err := os.UserHomeDir()
|
||||||
|
if err == nil {
|
||||||
|
m.currentDir = home
|
||||||
|
m.loadDir()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case tea.WindowSizeMsg:
|
||||||
|
m.height = msg.Height - 10
|
||||||
|
if m.height < 5 {
|
||||||
|
m.height = 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// View renders the file browser
|
||||||
|
func (m FileBrowserModel) View() string {
|
||||||
|
titleStyle := lipgloss.NewStyle().
|
||||||
|
Bold(true).
|
||||||
|
Foreground(lipgloss.Color("#7D56F4")).
|
||||||
|
MarginBottom(1)
|
||||||
|
|
||||||
|
pathStyle := lipgloss.NewStyle().
|
||||||
|
Foreground(lipgloss.Color("#AFAFAF")).
|
||||||
|
MarginBottom(1)
|
||||||
|
|
||||||
|
dirStyle := lipgloss.NewStyle().
|
||||||
|
Foreground(lipgloss.Color("#8BE9FD"))
|
||||||
|
|
||||||
|
fileStyle := lipgloss.NewStyle().
|
||||||
|
Foreground(lipgloss.Color("#F8F8F2"))
|
||||||
|
|
||||||
|
selectedStyle := lipgloss.NewStyle().
|
||||||
|
Bold(true).
|
||||||
|
Background(lipgloss.Color("#44475A")).
|
||||||
|
Foreground(lipgloss.Color("#50FA7B"))
|
||||||
|
|
||||||
|
helpStyle := lipgloss.NewStyle().
|
||||||
|
Foreground(lipgloss.Color("#626262")).
|
||||||
|
MarginTop(1)
|
||||||
|
|
||||||
|
var b strings.Builder
|
||||||
|
|
||||||
|
b.WriteString(titleStyle.Render("📁 Select PCAP File"))
|
||||||
|
b.WriteString("\n")
|
||||||
|
b.WriteString(pathStyle.Render(m.currentDir))
|
||||||
|
b.WriteString("\n\n")
|
||||||
|
|
||||||
|
if m.err != nil {
|
||||||
|
b.WriteString(lipgloss.NewStyle().Foreground(lipgloss.Color("#FF5555")).Render("Error: " + m.err.Error()))
|
||||||
|
b.WriteString("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(m.entries) == 0 {
|
||||||
|
b.WriteString("(empty directory)\n")
|
||||||
|
} else {
|
||||||
|
// Show entries with scrolling
|
||||||
|
end := m.offset + m.height
|
||||||
|
if end > len(m.entries) {
|
||||||
|
end = len(m.entries)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := m.offset; i < end; i++ {
|
||||||
|
entry := m.entries[i]
|
||||||
|
name := entry.Name()
|
||||||
|
|
||||||
|
var style lipgloss.Style
|
||||||
|
prefix := " "
|
||||||
|
|
||||||
|
if entry.IsDir() {
|
||||||
|
name = "📂 " + name + "/"
|
||||||
|
style = dirStyle
|
||||||
|
} else {
|
||||||
|
name = "📄 " + name
|
||||||
|
style = fileStyle
|
||||||
|
}
|
||||||
|
|
||||||
|
if i == m.selected {
|
||||||
|
prefix = "▶ "
|
||||||
|
style = selectedStyle
|
||||||
|
}
|
||||||
|
|
||||||
|
b.WriteString(prefix + style.Render(name) + "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show scroll indicator
|
||||||
|
if len(m.entries) > m.height {
|
||||||
|
b.WriteString(pathStyle.Render(
|
||||||
|
strings.Repeat("─", 20) +
|
||||||
|
" " + string(rune('0'+m.offset/10)) + string(rune('0'+m.offset%10)) +
|
||||||
|
"/" + string(rune('0'+len(m.entries)/10)) + string(rune('0'+len(m.entries)%10)) + " " +
|
||||||
|
strings.Repeat("─", 20)))
|
||||||
|
b.WriteString("\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b.WriteString("\n")
|
||||||
|
b.WriteString(helpStyle.Render("↑/↓ navigate • Enter select/open • Backspace parent • Esc cancel"))
|
||||||
|
|
||||||
|
return b.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSelected returns true if a file was selected
|
||||||
|
func (m FileBrowserModel) IsSelected() bool {
|
||||||
|
return m.selectedFile != ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsCancelled returns true if cancelled
|
||||||
|
func (m FileBrowserModel) IsCancelled() bool {
|
||||||
|
return m.cancelled
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSelectedFile returns the selected file path
|
||||||
|
func (m FileBrowserModel) GetSelectedFile() string {
|
||||||
|
return m.selectedFile
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCurrentDir returns current directory
|
||||||
|
func (m FileBrowserModel) GetCurrentDir() string {
|
||||||
|
return m.currentDir
|
||||||
|
}
|
||||||
@@ -2,8 +2,16 @@ package tui
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"telephony-inspector/internal/config"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"telephony-inspector/internal/capture"
|
||||||
|
"telephony-inspector/internal/config"
|
||||||
|
"telephony-inspector/internal/sip"
|
||||||
|
internalSSH "telephony-inspector/internal/ssh"
|
||||||
|
|
||||||
|
"github.com/charmbracelet/bubbles/list"
|
||||||
|
"github.com/charmbracelet/bubbles/textinput"
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
"github.com/charmbracelet/lipgloss"
|
"github.com/charmbracelet/lipgloss"
|
||||||
)
|
)
|
||||||
@@ -18,9 +26,31 @@ const (
|
|||||||
ViewNetworkMap
|
ViewNetworkMap
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SubView for modal states
|
||||||
|
type SubView int
|
||||||
|
|
||||||
|
const (
|
||||||
|
SubViewNone SubView = iota
|
||||||
|
SubViewSSHConfig
|
||||||
|
SubViewAddNode
|
||||||
|
SubViewCallDetail
|
||||||
|
SubViewCaptureMenu
|
||||||
|
SubViewFileBrowser
|
||||||
|
)
|
||||||
|
|
||||||
|
// CaptureMode defines local vs SSH capture
|
||||||
|
type CaptureMode int
|
||||||
|
|
||||||
|
const (
|
||||||
|
CaptureModeNone CaptureMode = iota
|
||||||
|
CaptureModeLocal
|
||||||
|
CaptureModeSSH
|
||||||
|
)
|
||||||
|
|
||||||
// Model holds the application state
|
// Model holds the application state
|
||||||
type Model struct {
|
type Model struct {
|
||||||
currentView View
|
currentView View
|
||||||
|
subView SubView
|
||||||
width int
|
width int
|
||||||
height int
|
height int
|
||||||
|
|
||||||
@@ -28,9 +58,29 @@ type Model struct {
|
|||||||
networkMap *config.NetworkMap
|
networkMap *config.NetworkMap
|
||||||
|
|
||||||
// Capture state
|
// Capture state
|
||||||
|
captureMode CaptureMode
|
||||||
|
sshConfig SSHConfigModel
|
||||||
|
capturer *capture.Capturer
|
||||||
|
localCapturer *capture.LocalCapturer
|
||||||
|
connected bool
|
||||||
capturing bool
|
capturing bool
|
||||||
packetCount int
|
packetCount int
|
||||||
lastPackets []string // Last N packet summaries
|
lastPackets []string
|
||||||
|
captureError string
|
||||||
|
captureIface string
|
||||||
|
|
||||||
|
// Call flow analysis
|
||||||
|
callFlowStore *sip.CallFlowStore
|
||||||
|
selectedFlow int
|
||||||
|
flowList list.Model
|
||||||
|
|
||||||
|
// File browser for pcap import
|
||||||
|
fileBrowser FileBrowserModel
|
||||||
|
loadedPcapPath string
|
||||||
|
|
||||||
|
// Network node input
|
||||||
|
nodeInput []textinput.Model
|
||||||
|
nodeInputFocus int
|
||||||
|
|
||||||
// Style definitions
|
// Style definitions
|
||||||
styles Styles
|
styles Styles
|
||||||
@@ -44,6 +94,11 @@ type Styles struct {
|
|||||||
Inactive lipgloss.Style
|
Inactive lipgloss.Style
|
||||||
Help lipgloss.Style
|
Help lipgloss.Style
|
||||||
StatusBar lipgloss.Style
|
StatusBar lipgloss.Style
|
||||||
|
Error lipgloss.Style
|
||||||
|
Success lipgloss.Style
|
||||||
|
Box lipgloss.Style
|
||||||
|
PacketRow lipgloss.Style
|
||||||
|
CallFlow lipgloss.Style
|
||||||
}
|
}
|
||||||
|
|
||||||
func defaultStyles() Styles {
|
func defaultStyles() Styles {
|
||||||
@@ -66,30 +121,98 @@ func defaultStyles() Styles {
|
|||||||
Background(lipgloss.Color("#7D56F4")).
|
Background(lipgloss.Color("#7D56F4")).
|
||||||
Foreground(lipgloss.Color("#FFFFFF")).
|
Foreground(lipgloss.Color("#FFFFFF")).
|
||||||
Padding(0, 1),
|
Padding(0, 1),
|
||||||
|
Error: lipgloss.NewStyle().
|
||||||
|
Foreground(lipgloss.Color("#FF5555")),
|
||||||
|
Success: lipgloss.NewStyle().
|
||||||
|
Foreground(lipgloss.Color("#50FA7B")),
|
||||||
|
Box: lipgloss.NewStyle().
|
||||||
|
Border(lipgloss.RoundedBorder()).
|
||||||
|
BorderForeground(lipgloss.Color("#7D56F4")).
|
||||||
|
Padding(1, 2),
|
||||||
|
PacketRow: lipgloss.NewStyle().
|
||||||
|
Foreground(lipgloss.Color("#F8F8F2")),
|
||||||
|
CallFlow: lipgloss.NewStyle().
|
||||||
|
Border(lipgloss.NormalBorder()).
|
||||||
|
BorderForeground(lipgloss.Color("#44475A")).
|
||||||
|
Padding(0, 1),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewModel creates a new TUI model with default values
|
// NewModel creates a new TUI model with default values
|
||||||
func NewModel() Model {
|
func NewModel() Model {
|
||||||
|
// Try to load existing network map
|
||||||
|
nm, err := config.LoadNetworkMap(config.DefaultNetworkMapPath())
|
||||||
|
if err != nil {
|
||||||
|
nm = config.NewNetworkMap()
|
||||||
|
}
|
||||||
|
|
||||||
return Model{
|
return Model{
|
||||||
currentView: ViewDashboard,
|
currentView: ViewDashboard,
|
||||||
networkMap: config.NewNetworkMap(),
|
subView: SubViewNone,
|
||||||
lastPackets: make([]string, 0, 20),
|
networkMap: nm,
|
||||||
|
callFlowStore: sip.NewCallFlowStore(),
|
||||||
|
lastPackets: make([]string, 0, 50),
|
||||||
|
sshConfig: NewSSHConfigModel(),
|
||||||
|
nodeInput: createNodeInputs(),
|
||||||
styles: defaultStyles(),
|
styles: defaultStyles(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createNodeInputs() []textinput.Model {
|
||||||
|
inputs := make([]textinput.Model, 4)
|
||||||
|
|
||||||
|
inputs[0] = textinput.New()
|
||||||
|
inputs[0].Placeholder = "Node Name"
|
||||||
|
inputs[0].Prompt = "Name: "
|
||||||
|
inputs[0].CharLimit = 64
|
||||||
|
|
||||||
|
inputs[1] = textinput.New()
|
||||||
|
inputs[1].Placeholder = "192.168.1.x"
|
||||||
|
inputs[1].Prompt = "IP: "
|
||||||
|
inputs[1].CharLimit = 45
|
||||||
|
|
||||||
|
inputs[2] = textinput.New()
|
||||||
|
inputs[2].Placeholder = "PBX/Proxy/MediaServer/Gateway"
|
||||||
|
inputs[2].Prompt = "Type: "
|
||||||
|
inputs[2].CharLimit = 20
|
||||||
|
|
||||||
|
inputs[3] = textinput.New()
|
||||||
|
inputs[3].Placeholder = "Optional description"
|
||||||
|
inputs[3].Prompt = "Desc: "
|
||||||
|
inputs[3].CharLimit = 256
|
||||||
|
|
||||||
|
return inputs
|
||||||
|
}
|
||||||
|
|
||||||
// Init initializes the model
|
// Init initializes the model
|
||||||
func (m Model) Init() tea.Cmd {
|
func (m Model) Init() tea.Cmd {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PacketMsg is sent when a new packet is received
|
||||||
|
type PacketMsg struct {
|
||||||
|
Packet *sip.Packet
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrorMsg is sent when an error occurs
|
||||||
|
type ErrorMsg struct {
|
||||||
|
Error error
|
||||||
|
}
|
||||||
|
|
||||||
// Update handles messages and updates the model
|
// Update handles messages and updates the model
|
||||||
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
|
var cmd tea.Cmd
|
||||||
|
|
||||||
|
// Handle subview updates first
|
||||||
|
if m.subView != SubViewNone {
|
||||||
|
return m.updateSubView(msg)
|
||||||
|
}
|
||||||
|
|
||||||
switch msg := msg.(type) {
|
switch msg := msg.(type) {
|
||||||
case tea.KeyMsg:
|
case tea.KeyMsg:
|
||||||
switch msg.String() {
|
switch msg.String() {
|
||||||
case "q", "ctrl+c":
|
case "q", "ctrl+c":
|
||||||
|
m.cleanup()
|
||||||
return m, tea.Quit
|
return m, tea.Quit
|
||||||
case "1":
|
case "1":
|
||||||
m.currentView = ViewDashboard
|
m.currentView = ViewDashboard
|
||||||
@@ -99,18 +222,336 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
m.currentView = ViewAnalysis
|
m.currentView = ViewAnalysis
|
||||||
case "4":
|
case "4":
|
||||||
m.currentView = ViewNetworkMap
|
m.currentView = ViewNetworkMap
|
||||||
|
default:
|
||||||
|
cmd = m.handleViewKeys(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
case tea.WindowSizeMsg:
|
case tea.WindowSizeMsg:
|
||||||
m.width = msg.Width
|
m.width = msg.Width
|
||||||
m.height = msg.Height
|
m.height = msg.Height
|
||||||
|
|
||||||
|
case PacketMsg:
|
||||||
|
m.packetCount++
|
||||||
|
summary := formatPacketSummary(msg.Packet, m.networkMap)
|
||||||
|
m.lastPackets = append(m.lastPackets, summary)
|
||||||
|
if len(m.lastPackets) > 50 {
|
||||||
|
m.lastPackets = m.lastPackets[1:]
|
||||||
|
}
|
||||||
|
m.callFlowStore.AddPacket(msg.Packet)
|
||||||
|
|
||||||
|
case ErrorMsg:
|
||||||
|
m.captureError = msg.Error.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
return m, cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Model) handleViewKeys(msg tea.KeyMsg) tea.Cmd {
|
||||||
|
switch m.currentView {
|
||||||
|
case ViewCapture:
|
||||||
|
switch msg.String() {
|
||||||
|
case "c":
|
||||||
|
// Show capture mode menu if not capturing
|
||||||
|
if !m.capturing && m.captureMode == CaptureModeNone {
|
||||||
|
m.subView = SubViewCaptureMenu
|
||||||
|
}
|
||||||
|
case "l":
|
||||||
|
// Start local capture directly
|
||||||
|
if !m.capturing {
|
||||||
|
m.captureMode = CaptureModeLocal
|
||||||
|
m.captureIface = "any"
|
||||||
|
return m.startLocalCapture()
|
||||||
|
}
|
||||||
|
case "r":
|
||||||
|
// SSH remote capture
|
||||||
|
if !m.capturing {
|
||||||
|
m.subView = SubViewSSHConfig
|
||||||
|
m.sshConfig = NewSSHConfigModel()
|
||||||
|
return m.sshConfig.Init()
|
||||||
|
}
|
||||||
|
case "s":
|
||||||
|
if m.capturing {
|
||||||
|
m.stopCapture()
|
||||||
|
} else if m.captureMode != CaptureModeNone {
|
||||||
|
if m.captureMode == CaptureModeLocal {
|
||||||
|
return m.startLocalCapture()
|
||||||
|
} else if m.connected {
|
||||||
|
return m.startSSHCapture()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "d":
|
||||||
|
m.disconnect()
|
||||||
|
}
|
||||||
|
|
||||||
|
case ViewAnalysis:
|
||||||
|
switch msg.String() {
|
||||||
|
case "up", "k":
|
||||||
|
if m.selectedFlow > 0 {
|
||||||
|
m.selectedFlow--
|
||||||
|
}
|
||||||
|
case "down", "j":
|
||||||
|
flows := m.callFlowStore.GetRecentFlows(20)
|
||||||
|
if m.selectedFlow < len(flows)-1 {
|
||||||
|
m.selectedFlow++
|
||||||
|
}
|
||||||
|
case "enter":
|
||||||
|
m.subView = SubViewCallDetail
|
||||||
|
}
|
||||||
|
|
||||||
|
case ViewNetworkMap:
|
||||||
|
switch msg.String() {
|
||||||
|
case "a":
|
||||||
|
m.subView = SubViewAddNode
|
||||||
|
m.nodeInput = createNodeInputs()
|
||||||
|
m.nodeInput[0].Focus()
|
||||||
|
m.nodeInputFocus = 0
|
||||||
|
case "l":
|
||||||
|
if nm, err := config.LoadNetworkMap(config.DefaultNetworkMapPath()); err == nil {
|
||||||
|
m.networkMap = nm
|
||||||
|
}
|
||||||
|
case "s":
|
||||||
|
config.SaveNetworkMap(m.networkMap, config.DefaultNetworkMapPath())
|
||||||
|
case "g":
|
||||||
|
m.networkMap = config.CreateSampleNetworkMap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Model) updateSubView(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
|
switch m.subView {
|
||||||
|
case SubViewCaptureMenu:
|
||||||
|
if keyMsg, ok := msg.(tea.KeyMsg); ok {
|
||||||
|
switch keyMsg.String() {
|
||||||
|
case "l", "1":
|
||||||
|
m.captureMode = CaptureModeLocal
|
||||||
|
m.captureIface = "any"
|
||||||
|
m.subView = SubViewNone
|
||||||
|
return m, m.startLocalCapture()
|
||||||
|
case "r", "2":
|
||||||
|
m.subView = SubViewSSHConfig
|
||||||
|
m.sshConfig = NewSSHConfigModel()
|
||||||
|
return m, m.sshConfig.Init()
|
||||||
|
case "p", "3":
|
||||||
|
// Open file browser for pcap
|
||||||
|
m.fileBrowser = NewFileBrowser("", ".pcap")
|
||||||
|
m.subView = SubViewFileBrowser
|
||||||
|
return m, nil
|
||||||
|
case "esc", "q":
|
||||||
|
m.subView = SubViewNone
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m, nil
|
||||||
|
|
||||||
|
case SubViewFileBrowser:
|
||||||
|
var cmd tea.Cmd
|
||||||
|
m.fileBrowser, cmd = m.fileBrowser.Update(msg)
|
||||||
|
|
||||||
|
if m.fileBrowser.IsSelected() {
|
||||||
|
// Load the pcap file
|
||||||
|
pcapPath := m.fileBrowser.GetSelectedFile()
|
||||||
|
m.loadedPcapPath = pcapPath
|
||||||
|
m.subView = SubViewNone
|
||||||
|
|
||||||
|
// Load packets from pcap
|
||||||
|
reader := capture.NewPcapReader(pcapPath)
|
||||||
|
packets, err := reader.ReadAll()
|
||||||
|
if err != nil {
|
||||||
|
m.captureError = err.Error()
|
||||||
|
} else {
|
||||||
|
m.captureError = ""
|
||||||
|
m.packetCount = len(packets)
|
||||||
|
for _, pkt := range packets {
|
||||||
|
m.callFlowStore.AddPacket(pkt)
|
||||||
|
summary := formatPacketSummary(pkt, m.networkMap)
|
||||||
|
m.lastPackets = append(m.lastPackets, summary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m, nil
|
||||||
|
} else if m.fileBrowser.IsCancelled() {
|
||||||
|
m.subView = SubViewNone
|
||||||
|
}
|
||||||
|
return m, cmd
|
||||||
|
|
||||||
|
case SubViewSSHConfig:
|
||||||
|
var cmd tea.Cmd
|
||||||
|
m.sshConfig, cmd = m.sshConfig.Update(msg)
|
||||||
|
|
||||||
|
if m.sshConfig.IsSubmitted() {
|
||||||
|
host, port, user, password := m.sshConfig.GetConfig()
|
||||||
|
portInt, _ := strconv.Atoi(port)
|
||||||
|
if portInt == 0 {
|
||||||
|
portInt = 22
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg := internalSSH.Config{
|
||||||
|
Host: host,
|
||||||
|
Port: portInt,
|
||||||
|
User: user,
|
||||||
|
Password: password,
|
||||||
|
}
|
||||||
|
|
||||||
|
m.capturer = capture.NewCapturer(cfg)
|
||||||
|
if err := m.capturer.Connect(); err != nil {
|
||||||
|
m.captureError = err.Error()
|
||||||
|
} else {
|
||||||
|
m.connected = true
|
||||||
|
m.captureMode = CaptureModeSSH
|
||||||
|
m.captureError = ""
|
||||||
|
}
|
||||||
|
m.subView = SubViewNone
|
||||||
|
} else if m.sshConfig.IsCancelled() {
|
||||||
|
m.subView = SubViewNone
|
||||||
|
}
|
||||||
|
return m, cmd
|
||||||
|
|
||||||
|
case SubViewAddNode:
|
||||||
|
return m.updateNodeInput(msg)
|
||||||
|
|
||||||
|
case SubViewCallDetail:
|
||||||
|
if keyMsg, ok := msg.(tea.KeyMsg); ok {
|
||||||
|
if keyMsg.String() == "esc" || keyMsg.String() == "q" {
|
||||||
|
m.subView = SubViewNone
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Model) updateNodeInput(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
|
if keyMsg, ok := msg.(tea.KeyMsg); ok {
|
||||||
|
switch keyMsg.String() {
|
||||||
|
case "esc":
|
||||||
|
m.subView = SubViewNone
|
||||||
|
return m, nil
|
||||||
|
case "tab", "down":
|
||||||
|
m.nodeInput[m.nodeInputFocus].Blur()
|
||||||
|
m.nodeInputFocus = (m.nodeInputFocus + 1) % len(m.nodeInput)
|
||||||
|
return m, m.nodeInput[m.nodeInputFocus].Focus()
|
||||||
|
case "shift+tab", "up":
|
||||||
|
m.nodeInput[m.nodeInputFocus].Blur()
|
||||||
|
m.nodeInputFocus--
|
||||||
|
if m.nodeInputFocus < 0 {
|
||||||
|
m.nodeInputFocus = len(m.nodeInput) - 1
|
||||||
|
}
|
||||||
|
return m, m.nodeInput[m.nodeInputFocus].Focus()
|
||||||
|
case "enter":
|
||||||
|
if m.nodeInputFocus == len(m.nodeInput)-1 {
|
||||||
|
// Submit
|
||||||
|
name := m.nodeInput[0].Value()
|
||||||
|
ip := m.nodeInput[1].Value()
|
||||||
|
nodeType := m.nodeInput[2].Value()
|
||||||
|
desc := m.nodeInput[3].Value()
|
||||||
|
|
||||||
|
if name != "" && ip != "" {
|
||||||
|
m.networkMap.AddNode(config.NetworkNode{
|
||||||
|
Name: name,
|
||||||
|
IP: ip,
|
||||||
|
Type: config.NodeType(nodeType),
|
||||||
|
Description: desc,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
m.subView = SubViewNone
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
m.nodeInput[m.nodeInputFocus].Blur()
|
||||||
|
m.nodeInputFocus++
|
||||||
|
return m, m.nodeInput[m.nodeInputFocus].Focus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var cmd tea.Cmd
|
||||||
|
m.nodeInput[m.nodeInputFocus], cmd = m.nodeInput[m.nodeInputFocus].Update(msg)
|
||||||
|
return m, cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Model) startLocalCapture() tea.Cmd {
|
||||||
|
m.capturing = true
|
||||||
|
m.captureError = ""
|
||||||
|
m.packetCount = 0
|
||||||
|
m.lastPackets = m.lastPackets[:0]
|
||||||
|
m.captureMode = CaptureModeLocal
|
||||||
|
|
||||||
|
m.localCapturer = capture.NewLocalCapturer()
|
||||||
|
m.localCapturer.OnPacket = func(p *sip.Packet) {
|
||||||
|
// Note: In real implementation, use channel + tea.Cmd
|
||||||
|
}
|
||||||
|
m.localCapturer.OnError = func(err error) {
|
||||||
|
m.captureError = err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
iface := m.captureIface
|
||||||
|
if iface == "" {
|
||||||
|
iface = "any"
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := m.localCapturer.Start(iface, 5060); err != nil {
|
||||||
|
m.captureError = err.Error()
|
||||||
|
m.capturing = false
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Model) startSSHCapture() tea.Cmd {
|
||||||
|
m.capturing = true
|
||||||
|
m.captureError = ""
|
||||||
|
m.packetCount = 0
|
||||||
|
m.lastPackets = m.lastPackets[:0]
|
||||||
|
|
||||||
|
m.capturer.OnPacket = func(p *sip.Packet) {
|
||||||
|
// Note: In real implementation, use channel + tea.Cmd
|
||||||
|
}
|
||||||
|
m.capturer.OnError = func(err error) {
|
||||||
|
m.captureError = err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := m.capturer.Start("any", 5060); err != nil {
|
||||||
|
m.captureError = err.Error()
|
||||||
|
m.capturing = false
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Model) stopCapture() {
|
||||||
|
if m.localCapturer != nil {
|
||||||
|
m.localCapturer.Stop()
|
||||||
|
}
|
||||||
|
if m.capturer != nil {
|
||||||
|
m.capturer.Stop()
|
||||||
|
}
|
||||||
|
m.capturing = false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Model) disconnect() {
|
||||||
|
m.stopCapture()
|
||||||
|
if m.localCapturer != nil {
|
||||||
|
m.localCapturer.Close()
|
||||||
|
m.localCapturer = nil
|
||||||
|
}
|
||||||
|
if m.capturer != nil {
|
||||||
|
m.capturer.Close()
|
||||||
|
m.capturer = nil
|
||||||
|
}
|
||||||
|
m.connected = false
|
||||||
|
m.captureMode = CaptureModeNone
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Model) cleanup() {
|
||||||
|
m.disconnect()
|
||||||
|
}
|
||||||
|
|
||||||
// View renders the TUI
|
// View renders the TUI
|
||||||
func (m Model) View() string {
|
func (m Model) View() string {
|
||||||
|
// Handle subview modals
|
||||||
|
if m.subView != SubViewNone {
|
||||||
|
return m.renderSubView()
|
||||||
|
}
|
||||||
|
|
||||||
var content string
|
var content string
|
||||||
|
|
||||||
switch m.currentView {
|
switch m.currentView {
|
||||||
@@ -124,15 +565,94 @@ func (m Model) View() string {
|
|||||||
content = m.viewNetworkMap()
|
content = m.viewNetworkMap()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Navigation bar
|
|
||||||
nav := m.renderNav()
|
nav := m.renderNav()
|
||||||
|
status := m.renderStatusBar()
|
||||||
// Status bar
|
|
||||||
status := m.styles.StatusBar.Render(" Telephony Inspector v0.1.0 ")
|
|
||||||
|
|
||||||
return lipgloss.JoinVertical(lipgloss.Left, nav, content, status)
|
return lipgloss.JoinVertical(lipgloss.Left, nav, content, status)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m Model) renderSubView() string {
|
||||||
|
switch m.subView {
|
||||||
|
case SubViewCaptureMenu:
|
||||||
|
return m.styles.Box.Render(m.renderCaptureMenu())
|
||||||
|
case SubViewFileBrowser:
|
||||||
|
return m.styles.Box.Render(m.fileBrowser.View())
|
||||||
|
case SubViewSSHConfig:
|
||||||
|
return m.styles.Box.Render(m.sshConfig.View())
|
||||||
|
case SubViewAddNode:
|
||||||
|
return m.styles.Box.Render(m.renderAddNodeForm())
|
||||||
|
case SubViewCallDetail:
|
||||||
|
return m.renderCallDetail()
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m Model) renderCaptureMenu() string {
|
||||||
|
var b strings.Builder
|
||||||
|
b.WriteString(m.styles.Title.Render("📡 Select Capture Mode"))
|
||||||
|
b.WriteString("\n\n")
|
||||||
|
b.WriteString(" [1] [L]ocal - Capture on this machine (requires tcpdump)\n")
|
||||||
|
b.WriteString(" [2] [R]emote - Capture via SSH on remote server\n")
|
||||||
|
b.WriteString(" [3] [P]cap - Import pcap file from disk\n")
|
||||||
|
b.WriteString("\n")
|
||||||
|
b.WriteString(m.styles.Help.Render("Press 1/L, 2/R, or 3/P to select • Esc to cancel"))
|
||||||
|
return b.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m Model) renderAddNodeForm() string {
|
||||||
|
var b strings.Builder
|
||||||
|
b.WriteString(m.styles.Title.Render("➕ Add Network Node"))
|
||||||
|
b.WriteString("\n\n")
|
||||||
|
for _, input := range m.nodeInput {
|
||||||
|
b.WriteString(input.View())
|
||||||
|
b.WriteString("\n")
|
||||||
|
}
|
||||||
|
b.WriteString("\n")
|
||||||
|
b.WriteString(m.styles.Help.Render("Tab navigate • Enter submit • Esc cancel"))
|
||||||
|
return b.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m Model) renderCallDetail() string {
|
||||||
|
flows := m.callFlowStore.GetRecentFlows(20)
|
||||||
|
if m.selectedFlow >= len(flows) || len(flows) == 0 {
|
||||||
|
return m.styles.Box.Render("No call selected\n\nPress Esc to go back")
|
||||||
|
}
|
||||||
|
|
||||||
|
flow := flows[m.selectedFlow]
|
||||||
|
var b strings.Builder
|
||||||
|
|
||||||
|
b.WriteString(m.styles.Title.Render("📞 Call Detail"))
|
||||||
|
b.WriteString("\n\n")
|
||||||
|
b.WriteString(fmt.Sprintf("Call-ID: %s\n", flow.CallID))
|
||||||
|
b.WriteString(fmt.Sprintf("From: %s\n", flow.From))
|
||||||
|
b.WriteString(fmt.Sprintf("To: %s\n", flow.To))
|
||||||
|
b.WriteString(fmt.Sprintf("State: %s\n", flow.State))
|
||||||
|
b.WriteString(fmt.Sprintf("Packets: %d\n\n", len(flow.Packets)))
|
||||||
|
|
||||||
|
b.WriteString("Transaction Flow:\n")
|
||||||
|
for i, pkt := range flow.Packets {
|
||||||
|
arrow := "→"
|
||||||
|
if !pkt.IsRequest {
|
||||||
|
arrow = "←"
|
||||||
|
}
|
||||||
|
b.WriteString(fmt.Sprintf(" %d. %s %s\n", i+1, arrow, pkt.Summary()))
|
||||||
|
|
||||||
|
// Show SDP info if present
|
||||||
|
if pkt.SDP != nil {
|
||||||
|
mediaIP := pkt.SDP.GetSDPMediaIP()
|
||||||
|
if mediaIP != "" {
|
||||||
|
label := m.networkMap.LabelForIP(mediaIP)
|
||||||
|
b.WriteString(fmt.Sprintf(" SDP Media: %s\n", label))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b.WriteString("\n")
|
||||||
|
b.WriteString(m.styles.Help.Render("Press Esc to go back"))
|
||||||
|
|
||||||
|
return m.styles.Box.Render(b.String())
|
||||||
|
}
|
||||||
|
|
||||||
func (m Model) renderNav() string {
|
func (m Model) renderNav() string {
|
||||||
tabs := []string{"[1] Dashboard", "[2] Capture", "[3] Analysis", "[4] Network Map"}
|
tabs := []string{"[1] Dashboard", "[2] Capture", "[3] Analysis", "[4] Network Map"}
|
||||||
var rendered []string
|
var rendered []string
|
||||||
@@ -148,52 +668,163 @@ func (m Model) renderNav() string {
|
|||||||
return lipgloss.JoinHorizontal(lipgloss.Top, rendered...) + "\n"
|
return lipgloss.JoinHorizontal(lipgloss.Top, rendered...) + "\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m Model) renderStatusBar() string {
|
||||||
|
var parts []string
|
||||||
|
parts = append(parts, " Telephony Inspector v0.1.0 ")
|
||||||
|
|
||||||
|
if m.connected {
|
||||||
|
parts = append(parts, m.styles.Success.Render(" SSH: Connected "))
|
||||||
|
}
|
||||||
|
if m.capturing {
|
||||||
|
parts = append(parts, m.styles.Active.Render(fmt.Sprintf(" Capturing: %d pkts ", m.packetCount)))
|
||||||
|
}
|
||||||
|
if m.captureError != "" {
|
||||||
|
parts = append(parts, m.styles.Error.Render(" Error: "+m.captureError+" "))
|
||||||
|
}
|
||||||
|
|
||||||
|
return m.styles.StatusBar.Render(strings.Join(parts, "|"))
|
||||||
|
}
|
||||||
|
|
||||||
func (m Model) viewDashboard() string {
|
func (m Model) viewDashboard() string {
|
||||||
title := m.styles.Title.Render("📞 Dashboard")
|
title := m.styles.Title.Render("📞 Dashboard")
|
||||||
|
|
||||||
info := lipgloss.JoinVertical(lipgloss.Left,
|
var stats []string
|
||||||
m.styles.Subtitle.Render("SIP Telephony Inspector"),
|
stats = append(stats, m.styles.Subtitle.Render("SIP Telephony Inspector"))
|
||||||
"",
|
stats = append(stats, "")
|
||||||
"• Capture SIP traffic via SSH + tcpdump",
|
|
||||||
"• Analyze SIP/SDP packets in real-time",
|
|
||||||
"• Map network topology for better debugging",
|
|
||||||
"",
|
|
||||||
m.styles.Help.Render("Press 1-4 to navigate, q to quit"),
|
|
||||||
)
|
|
||||||
|
|
||||||
return lipgloss.JoinVertical(lipgloss.Left, title, info)
|
if m.connected {
|
||||||
|
stats = append(stats, m.styles.Success.Render("✓ SSH Connected"))
|
||||||
|
} else {
|
||||||
|
stats = append(stats, m.styles.Inactive.Render("○ SSH Disconnected"))
|
||||||
|
}
|
||||||
|
|
||||||
|
stats = append(stats, fmt.Sprintf("Network Nodes: %d", len(m.networkMap.Nodes)))
|
||||||
|
stats = append(stats, fmt.Sprintf("Active Calls: %d", m.callFlowStore.Count()))
|
||||||
|
stats = append(stats, fmt.Sprintf("Packets Captured: %d", m.packetCount))
|
||||||
|
stats = append(stats, "")
|
||||||
|
stats = append(stats, "Quick Start:")
|
||||||
|
stats = append(stats, " 1. Go to [2] Capture → Press 'c' to connect SSH")
|
||||||
|
stats = append(stats, " 2. Press 's' to start capturing SIP traffic")
|
||||||
|
stats = append(stats, " 3. Go to [3] Analysis to view call flows")
|
||||||
|
stats = append(stats, " 4. Go to [4] Network Map to label IPs")
|
||||||
|
stats = append(stats, "")
|
||||||
|
stats = append(stats, m.styles.Help.Render("Press 1-4 to navigate, q to quit"))
|
||||||
|
|
||||||
|
return lipgloss.JoinVertical(lipgloss.Left, title, lipgloss.JoinVertical(lipgloss.Left, stats...))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m Model) viewCapture() string {
|
func (m Model) viewCapture() string {
|
||||||
title := m.styles.Title.Render("🔍 Capture")
|
title := m.styles.Title.Render("🔍 Capture")
|
||||||
|
|
||||||
status := "Status: "
|
var lines []string
|
||||||
if m.capturing {
|
|
||||||
status += m.styles.Active.Render("● Capturing")
|
// Mode indicator
|
||||||
|
switch m.captureMode {
|
||||||
|
case CaptureModeLocal:
|
||||||
|
lines = append(lines, m.styles.Success.Render("● Mode: Local capture"))
|
||||||
|
case CaptureModeSSH:
|
||||||
|
if m.connected {
|
||||||
|
lines = append(lines, m.styles.Success.Render("● Mode: SSH (connected)"))
|
||||||
} else {
|
} else {
|
||||||
status += m.styles.Inactive.Render("○ Stopped")
|
lines = append(lines, m.styles.Inactive.Render("○ Mode: SSH (disconnected)"))
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
lines = append(lines, m.styles.Inactive.Render("○ No capture mode selected"))
|
||||||
}
|
}
|
||||||
|
|
||||||
packetInfo := fmt.Sprintf("Packets captured: %d", m.packetCount)
|
// Capture status
|
||||||
|
if m.capturing {
|
||||||
|
mode := "local"
|
||||||
|
if m.captureMode == CaptureModeSSH {
|
||||||
|
mode = "SSH"
|
||||||
|
}
|
||||||
|
lines = append(lines, m.styles.Active.Render(fmt.Sprintf("● Capturing on port 5060 (%s)", mode)))
|
||||||
|
} else if m.captureMode != CaptureModeNone {
|
||||||
|
lines = append(lines, m.styles.Inactive.Render("○ Capture stopped"))
|
||||||
|
}
|
||||||
|
|
||||||
help := m.styles.Help.Render("[c] Connect SSH [s] Start/Stop Capture [q] Quit")
|
lines = append(lines, fmt.Sprintf("Packets: %d", m.packetCount))
|
||||||
|
lines = append(lines, "")
|
||||||
|
|
||||||
return lipgloss.JoinVertical(lipgloss.Left, title, status, packetInfo, "", help)
|
// Last packets
|
||||||
|
if len(m.lastPackets) > 0 {
|
||||||
|
lines = append(lines, "Recent Packets:")
|
||||||
|
start := 0
|
||||||
|
if len(m.lastPackets) > 15 {
|
||||||
|
start = len(m.lastPackets) - 15
|
||||||
|
}
|
||||||
|
for _, pkt := range m.lastPackets[start:] {
|
||||||
|
lines = append(lines, " "+pkt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lines = append(lines, "")
|
||||||
|
|
||||||
|
// Help
|
||||||
|
var help string
|
||||||
|
if m.captureMode == CaptureModeNone {
|
||||||
|
help = "[c] Choose mode [l] Local [r] Remote SSH [q] Quit"
|
||||||
|
} else if !m.capturing {
|
||||||
|
help = "[s] Start [c] Change mode [d] Disconnect [q] Quit"
|
||||||
|
} else {
|
||||||
|
help = "[s] Stop [d] Disconnect [q] Quit"
|
||||||
|
}
|
||||||
|
lines = append(lines, m.styles.Help.Render(help))
|
||||||
|
|
||||||
|
return lipgloss.JoinVertical(lipgloss.Left, title, lipgloss.JoinVertical(lipgloss.Left, lines...))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m Model) viewAnalysis() string {
|
func (m Model) viewAnalysis() string {
|
||||||
title := m.styles.Title.Render("📊 Analysis")
|
title := m.styles.Title.Render("📊 Analysis")
|
||||||
|
|
||||||
content := lipgloss.JoinVertical(lipgloss.Left,
|
flows := m.callFlowStore.GetRecentFlows(20)
|
||||||
"Call flows will appear here once packets are captured.",
|
|
||||||
"",
|
|
||||||
"Features:",
|
|
||||||
"• Group packets by Call-ID",
|
|
||||||
"• Visualize SIP transaction flow",
|
|
||||||
"• Decode SDP offers/answers",
|
|
||||||
)
|
|
||||||
|
|
||||||
return lipgloss.JoinVertical(lipgloss.Left, title, content)
|
if len(flows) == 0 {
|
||||||
|
return lipgloss.JoinVertical(lipgloss.Left, title,
|
||||||
|
"No calls captured yet.",
|
||||||
|
"",
|
||||||
|
"Start capturing on the Capture tab to see call flows here.",
|
||||||
|
"",
|
||||||
|
m.styles.Help.Render("Press 2 to go to Capture"))
|
||||||
|
}
|
||||||
|
|
||||||
|
var lines []string
|
||||||
|
lines = append(lines, fmt.Sprintf("Calls: %d", len(flows)))
|
||||||
|
lines = append(lines, "")
|
||||||
|
|
||||||
|
for i, flow := range flows {
|
||||||
|
prefix := " "
|
||||||
|
style := m.styles.Inactive
|
||||||
|
if i == m.selectedFlow {
|
||||||
|
prefix = "▶ "
|
||||||
|
style = m.styles.Active
|
||||||
|
}
|
||||||
|
|
||||||
|
stateIcon := "○"
|
||||||
|
switch flow.State {
|
||||||
|
case sip.CallStateRinging:
|
||||||
|
stateIcon = "◐"
|
||||||
|
case sip.CallStateConnected:
|
||||||
|
stateIcon = "●"
|
||||||
|
case sip.CallStateTerminated:
|
||||||
|
stateIcon = "◯"
|
||||||
|
case sip.CallStateFailed:
|
||||||
|
stateIcon = "✕"
|
||||||
|
}
|
||||||
|
|
||||||
|
summary := fmt.Sprintf("%s%s %s → %s [%d pkts]",
|
||||||
|
prefix, stateIcon,
|
||||||
|
truncate(extractUser(flow.From), 15),
|
||||||
|
truncate(extractUser(flow.To), 15),
|
||||||
|
len(flow.Packets))
|
||||||
|
|
||||||
|
lines = append(lines, style.Render(summary))
|
||||||
|
}
|
||||||
|
|
||||||
|
lines = append(lines, "")
|
||||||
|
lines = append(lines, m.styles.Help.Render("↑/↓ select • Enter details • q quit"))
|
||||||
|
|
||||||
|
return lipgloss.JoinVertical(lipgloss.Left, title, lipgloss.JoinVertical(lipgloss.Left, lines...))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m Model) viewNetworkMap() string {
|
func (m Model) viewNetworkMap() string {
|
||||||
@@ -203,14 +834,71 @@ func (m Model) viewNetworkMap() string {
|
|||||||
return lipgloss.JoinVertical(lipgloss.Left, title,
|
return lipgloss.JoinVertical(lipgloss.Left, title,
|
||||||
"No network nodes configured.",
|
"No network nodes configured.",
|
||||||
"",
|
"",
|
||||||
m.styles.Help.Render("[a] Add node [l] Load from file"),
|
"Add nodes to label IPs in your SIP infrastructure.",
|
||||||
)
|
"",
|
||||||
|
m.styles.Help.Render("[a] Add node [l] Load file [g] Generate sample"))
|
||||||
}
|
}
|
||||||
|
|
||||||
var nodes []string
|
var lines []string
|
||||||
for _, node := range m.networkMap.Nodes {
|
for _, node := range m.networkMap.Nodes {
|
||||||
nodes = append(nodes, fmt.Sprintf("• %s (%s): %s", node.Name, node.Type, node.IP))
|
icon := "○"
|
||||||
|
switch node.Type {
|
||||||
|
case config.NodeTypePBX:
|
||||||
|
icon = "☎"
|
||||||
|
case config.NodeTypeProxy:
|
||||||
|
icon = "⇄"
|
||||||
|
case config.NodeTypeMediaServer:
|
||||||
|
icon = "♪"
|
||||||
|
case config.NodeTypeGateway:
|
||||||
|
icon = "⬚"
|
||||||
|
}
|
||||||
|
line := fmt.Sprintf(" %s %s (%s): %s", icon, node.Name, node.Type, node.IP)
|
||||||
|
if node.Description != "" {
|
||||||
|
line += " - " + node.Description
|
||||||
|
}
|
||||||
|
lines = append(lines, line)
|
||||||
}
|
}
|
||||||
|
|
||||||
return lipgloss.JoinVertical(lipgloss.Left, title, lipgloss.JoinVertical(lipgloss.Left, nodes...))
|
lines = append(lines, "")
|
||||||
|
lines = append(lines, m.styles.Help.Render("[a] Add [s] Save [l] Load [g] Sample [q] Quit"))
|
||||||
|
|
||||||
|
return lipgloss.JoinVertical(lipgloss.Left, title, lipgloss.JoinVertical(lipgloss.Left, lines...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper functions
|
||||||
|
|
||||||
|
func formatPacketSummary(p *sip.Packet, nm *config.NetworkMap) string {
|
||||||
|
src := nm.LabelForIP(p.SourceIP)
|
||||||
|
dst := nm.LabelForIP(p.DestIP)
|
||||||
|
|
||||||
|
if p.IsRequest {
|
||||||
|
return fmt.Sprintf("%s → %s: %s", src, dst, p.Method)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s → %s: %d %s", src, dst, p.StatusCode, p.StatusText)
|
||||||
|
}
|
||||||
|
|
||||||
|
func truncate(s string, max int) string {
|
||||||
|
if len(s) <= max {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return s[:max-1] + "…"
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractUser(sipAddr string) string {
|
||||||
|
// Extract user from "Display Name" <sip:user@host>
|
||||||
|
if idx := strings.Index(sipAddr, "<sip:"); idx >= 0 {
|
||||||
|
start := idx + 5
|
||||||
|
end := strings.Index(sipAddr[start:], "@")
|
||||||
|
if end > 0 {
|
||||||
|
return sipAddr[start : start+end]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if idx := strings.Index(sipAddr, "sip:"); idx >= 0 {
|
||||||
|
start := idx + 4
|
||||||
|
end := strings.Index(sipAddr[start:], "@")
|
||||||
|
if end > 0 {
|
||||||
|
return sipAddr[start : start+end]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sipAddr
|
||||||
}
|
}
|
||||||
|
|||||||
180
internal/tui/ssh_config.go
Normal file
180
internal/tui/ssh_config.go
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
package tui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/charmbracelet/bubbles/textinput"
|
||||||
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
|
"github.com/charmbracelet/lipgloss"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SSHConfigModel handles SSH connection input
|
||||||
|
type SSHConfigModel struct {
|
||||||
|
inputs []textinput.Model
|
||||||
|
focusIndex int
|
||||||
|
submitted bool
|
||||||
|
cancelled bool
|
||||||
|
|
||||||
|
// Parsed values
|
||||||
|
Host string
|
||||||
|
Port string
|
||||||
|
User string
|
||||||
|
Password string
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
inputHost = iota
|
||||||
|
inputPort
|
||||||
|
inputUser
|
||||||
|
inputPassword
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewSSHConfigModel creates a new SSH config input model
|
||||||
|
func NewSSHConfigModel() SSHConfigModel {
|
||||||
|
inputs := make([]textinput.Model, 4)
|
||||||
|
|
||||||
|
// Host input
|
||||||
|
inputs[inputHost] = textinput.New()
|
||||||
|
inputs[inputHost].Placeholder = "192.168.1.100"
|
||||||
|
inputs[inputHost].Focus()
|
||||||
|
inputs[inputHost].CharLimit = 256
|
||||||
|
inputs[inputHost].Width = 30
|
||||||
|
inputs[inputHost].Prompt = "Host: "
|
||||||
|
|
||||||
|
// Port input
|
||||||
|
inputs[inputPort] = textinput.New()
|
||||||
|
inputs[inputPort].Placeholder = "22"
|
||||||
|
inputs[inputPort].CharLimit = 5
|
||||||
|
inputs[inputPort].Width = 10
|
||||||
|
inputs[inputPort].Prompt = "Port: "
|
||||||
|
inputs[inputPort].SetValue("22")
|
||||||
|
|
||||||
|
// User input
|
||||||
|
inputs[inputUser] = textinput.New()
|
||||||
|
inputs[inputUser].Placeholder = "root"
|
||||||
|
inputs[inputUser].CharLimit = 64
|
||||||
|
inputs[inputUser].Width = 20
|
||||||
|
inputs[inputUser].Prompt = "User: "
|
||||||
|
|
||||||
|
// Password input
|
||||||
|
inputs[inputPassword] = textinput.New()
|
||||||
|
inputs[inputPassword].Placeholder = "password"
|
||||||
|
inputs[inputPassword].CharLimit = 128
|
||||||
|
inputs[inputPassword].Width = 30
|
||||||
|
inputs[inputPassword].Prompt = "Password: "
|
||||||
|
inputs[inputPassword].EchoMode = textinput.EchoPassword
|
||||||
|
inputs[inputPassword].EchoCharacter = '•'
|
||||||
|
|
||||||
|
return SSHConfigModel{
|
||||||
|
inputs: inputs,
|
||||||
|
focusIndex: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init initializes the model
|
||||||
|
func (m SSHConfigModel) Init() tea.Cmd {
|
||||||
|
return textinput.Blink
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update handles messages
|
||||||
|
func (m SSHConfigModel) Update(msg tea.Msg) (SSHConfigModel, tea.Cmd) {
|
||||||
|
switch msg := msg.(type) {
|
||||||
|
case tea.KeyMsg:
|
||||||
|
switch msg.String() {
|
||||||
|
case "ctrl+c", "esc":
|
||||||
|
m.cancelled = true
|
||||||
|
return m, nil
|
||||||
|
|
||||||
|
case "tab", "down":
|
||||||
|
m.focusIndex++
|
||||||
|
if m.focusIndex >= len(m.inputs) {
|
||||||
|
m.focusIndex = 0
|
||||||
|
}
|
||||||
|
return m, m.updateFocus()
|
||||||
|
|
||||||
|
case "shift+tab", "up":
|
||||||
|
m.focusIndex--
|
||||||
|
if m.focusIndex < 0 {
|
||||||
|
m.focusIndex = len(m.inputs) - 1
|
||||||
|
}
|
||||||
|
return m, m.updateFocus()
|
||||||
|
|
||||||
|
case "enter":
|
||||||
|
if m.focusIndex == len(m.inputs)-1 {
|
||||||
|
// Submit on last field
|
||||||
|
m.submitted = true
|
||||||
|
m.Host = m.inputs[inputHost].Value()
|
||||||
|
m.Port = m.inputs[inputPort].Value()
|
||||||
|
m.User = m.inputs[inputUser].Value()
|
||||||
|
m.Password = m.inputs[inputPassword].Value()
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
// Move to next field
|
||||||
|
m.focusIndex++
|
||||||
|
return m, m.updateFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update focused input
|
||||||
|
cmd := m.updateInputs(msg)
|
||||||
|
return m, cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SSHConfigModel) updateFocus() tea.Cmd {
|
||||||
|
cmds := make([]tea.Cmd, len(m.inputs))
|
||||||
|
for i := range m.inputs {
|
||||||
|
if i == m.focusIndex {
|
||||||
|
cmds[i] = m.inputs[i].Focus()
|
||||||
|
} else {
|
||||||
|
m.inputs[i].Blur()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tea.Batch(cmds...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SSHConfigModel) updateInputs(msg tea.Msg) tea.Cmd {
|
||||||
|
cmds := make([]tea.Cmd, len(m.inputs))
|
||||||
|
for i := range m.inputs {
|
||||||
|
m.inputs[i], cmds[i] = m.inputs[i].Update(msg)
|
||||||
|
}
|
||||||
|
return tea.Batch(cmds...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// View renders the SSH config form
|
||||||
|
func (m SSHConfigModel) View() string {
|
||||||
|
var b strings.Builder
|
||||||
|
|
||||||
|
titleStyle := lipgloss.NewStyle().
|
||||||
|
Bold(true).
|
||||||
|
Foreground(lipgloss.Color("#7D56F4")).
|
||||||
|
MarginBottom(1)
|
||||||
|
|
||||||
|
b.WriteString(titleStyle.Render("🔌 SSH Connection"))
|
||||||
|
b.WriteString("\n\n")
|
||||||
|
|
||||||
|
for i := range m.inputs {
|
||||||
|
b.WriteString(m.inputs[i].View())
|
||||||
|
b.WriteString("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
helpStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("#626262"))
|
||||||
|
b.WriteString("\n")
|
||||||
|
b.WriteString(helpStyle.Render("Tab/↑↓ navigate • Enter submit • Esc cancel"))
|
||||||
|
|
||||||
|
return b.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSubmitted returns true if the form was submitted
|
||||||
|
func (m SSHConfigModel) IsSubmitted() bool {
|
||||||
|
return m.submitted
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsCancelled returns true if the form was cancelled
|
||||||
|
func (m SSHConfigModel) IsCancelled() bool {
|
||||||
|
return m.cancelled
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetConfig returns the SSH config values
|
||||||
|
func (m SSHConfigModel) GetConfig() (host, port, user, password string) {
|
||||||
|
return m.Host, m.Port, m.User, m.Password
|
||||||
|
}
|
||||||
52
logs/2026-01-19_14-18-33.log
Normal file
52
logs/2026-01-19_14-18-33.log
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
[14:18:33.982] [INFO] Logger initialized: logs\2026-01-19_14-18-33.log
|
||||||
|
[14:18:33.986] [INFO] Starting Telephony Inspector
|
||||||
|
[14:18:40.383] [INFO] PcapReader: Creating reader for D:\Proyectos\telephony-inspector\data\test2.pcap
|
||||||
|
[14:18:40.387] [INFO] PcapReader: Opening file D:\Proyectos\telephony-inspector\data\test2.pcap
|
||||||
|
[14:18:40.391] [INFO] PcapReader: File opened successfully, link type: Ethernet
|
||||||
|
[14:18:40.395] [DEBUG] PcapReader: BPF filter set for SIP ports
|
||||||
|
[14:18:40.399] [DEBUG] PcapReader: Processing packet 1, layers: [0xc00022a150 0xc00034a000 0xc000234100 0xc000232090]
|
||||||
|
[14:18:40.402] [DEBUG] PcapReader: Packet 1 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:18:40.407] [DEBUG] PcapReader: Packet 1 UDP 51416 -> 5060
|
||||||
|
[14:18:40.409] [DEBUG] PcapReader: Packet 1 application layer, payload length: 528
|
||||||
|
[14:18:40.411] [DEBUG] PcapReader: Packet 1 payload preview: "v=0\r\no=- 3977820639 3977820639 IN IP4 192.168.0.164\r\ns=pjmedia\r\nb=AS:84\r\nt=0 0\r\na=X-nat:0\r\nm=audio 4"
|
||||||
|
[14:18:40.413] [DEBUG] PcapReader: Packet 1 is not SIP
|
||||||
|
[14:18:40.415] [DEBUG] PcapReader: Processing packet 2, layers: [0xc00022a1c0 0xc00034a0a0 0xc000234180 0xc000232120]
|
||||||
|
[14:18:40.417] [DEBUG] PcapReader: Packet 2 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:18:40.419] [DEBUG] PcapReader: Packet 2 UDP 5060 -> 51416
|
||||||
|
[14:18:40.421] [DEBUG] PcapReader: Packet 2 application layer, payload length: 0
|
||||||
|
[14:18:40.423] [DEBUG] PcapReader: Packet 2 is not SIP
|
||||||
|
[14:18:40.425] [DEBUG] PcapReader: Processing packet 3, layers: [0xc00022a230 0xc00034a140 0xc000234200 0xc0002321b0]
|
||||||
|
[14:18:40.426] [DEBUG] PcapReader: Packet 3 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:18:40.428] [DEBUG] PcapReader: Packet 3 UDP 5060 -> 51416
|
||||||
|
[14:18:40.431] [DEBUG] PcapReader: Packet 3 application layer, payload length: 375
|
||||||
|
[14:18:40.433] [DEBUG] PcapReader: Packet 3 payload preview: "v=0\r\no=- 3977820639 3977820641 IN IP4 192.168.0.162\r\ns=Asterisk\r\nc=IN IP4 192.168.0.162\r\nt=0 0\r\nm=au"
|
||||||
|
[14:18:40.434] [DEBUG] PcapReader: Packet 3 is not SIP
|
||||||
|
[14:18:40.436] [DEBUG] PcapReader: Processing packet 4, layers: [0xc00022a2a0 0xc00034a1e0 0xc000234280 0xc000232240]
|
||||||
|
[14:18:40.439] [DEBUG] PcapReader: Packet 4 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:18:40.441] [DEBUG] PcapReader: Packet 4 UDP 51416 -> 5060
|
||||||
|
[14:18:40.443] [DEBUG] PcapReader: Packet 4 application layer, payload length: 0
|
||||||
|
[14:18:40.444] [DEBUG] PcapReader: Packet 4 is not SIP
|
||||||
|
[14:18:40.446] [DEBUG] PcapReader: Processing packet 5, layers: [0xc00022a310 0xc00034a280 0xc000234300 0xc0002322d0]
|
||||||
|
[14:18:40.448] [DEBUG] PcapReader: Packet 5 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:18:40.450] [DEBUG] PcapReader: Packet 5 UDP 51416 -> 5060
|
||||||
|
[14:18:40.451] [DEBUG] PcapReader: Packet 5 application layer, payload length: 319
|
||||||
|
[14:18:40.454] [DEBUG] PcapReader: Packet 5 payload preview: "v=0\r\no=- 3977820639 3977820640 IN IP4 192.168.0.164\r\ns=pjmedia\r\nb=AS:84\r\nt=0 0\r\na=X-nat:0\r\nm=audio 4"
|
||||||
|
[14:18:40.456] [DEBUG] PcapReader: Packet 5 is not SIP
|
||||||
|
[14:18:40.457] [DEBUG] PcapReader: Processing packet 6, layers: [0xc00022a380 0xc00034a320 0xc000234380 0xc000232360]
|
||||||
|
[14:18:40.459] [DEBUG] PcapReader: Packet 6 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:18:40.461] [DEBUG] PcapReader: Packet 6 UDP 5060 -> 51416
|
||||||
|
[14:18:40.462] [DEBUG] PcapReader: Packet 6 application layer, payload length: 239
|
||||||
|
[14:18:40.465] [DEBUG] PcapReader: Packet 6 payload preview: "v=0\r\no=- 3977820639 3977820642 IN IP4 192.168.0.162\r\ns=Asterisk\r\nc=IN IP4 192.168.0.162\r\nt=0 0\r\nm=au"
|
||||||
|
[14:18:40.467] [DEBUG] PcapReader: Packet 6 is not SIP
|
||||||
|
[14:18:40.468] [DEBUG] PcapReader: Processing packet 7, layers: [0xc00022a3f0 0xc00034a3c0 0xc000234400 0xc0002323f0]
|
||||||
|
[14:18:40.470] [DEBUG] PcapReader: Packet 7 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:18:40.472] [DEBUG] PcapReader: Packet 7 UDP 51416 -> 5060
|
||||||
|
[14:18:40.474] [DEBUG] PcapReader: Packet 7 application layer, payload length: 0
|
||||||
|
[14:18:40.476] [DEBUG] PcapReader: Packet 7 is not SIP
|
||||||
|
[14:18:40.478] [DEBUG] PcapReader: Processing packet 8, layers: [0xc00022a460 0xc00034a460 0xc000234480 0xc000232480]
|
||||||
|
[14:18:40.480] [DEBUG] PcapReader: Packet 8 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:18:40.481] [DEBUG] PcapReader: Packet 8 UDP 5060 -> 51416
|
||||||
|
[14:18:40.483] [DEBUG] PcapReader: Packet 8 application layer, payload length: 0
|
||||||
|
[14:18:40.485] [DEBUG] PcapReader: Packet 8 is not SIP
|
||||||
|
[14:18:40.487] [INFO] PcapReader: Finished reading. Total packets: 8, SIP packets: 0
|
||||||
|
[14:23:18.995] [INFO] Telephony Inspector exited normally
|
||||||
237
logs/2026-01-19_14-23-22.log
Normal file
237
logs/2026-01-19_14-23-22.log
Normal file
@@ -0,0 +1,237 @@
|
|||||||
|
[14:23:22.124] [INFO] Logger initialized: logs\2026-01-19_14-23-22.log
|
||||||
|
[14:23:22.128] [INFO] Starting Telephony Inspector
|
||||||
|
[14:23:26.188] [INFO] PcapReader: Creating reader for D:\Proyectos\telephony-inspector\data\test.pcapng
|
||||||
|
[14:23:26.193] [INFO] PcapReader: Opening file D:\Proyectos\telephony-inspector\data\test.pcapng
|
||||||
|
[14:23:26.197] [INFO] PcapReader: File opened successfully, link type: Ethernet
|
||||||
|
[14:23:26.200] [DEBUG] PcapReader: BPF filter set for SIP ports
|
||||||
|
[14:23:26.204] [DEBUG] PcapReader: Processing packet 1, layers: [0xc00048c0e0 0xc00049c000 0xc000332100 0xc00049e000]
|
||||||
|
[14:23:26.208] [DEBUG] PcapReader: Packet 1 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:23:26.212] [DEBUG] PcapReader: Packet 1 UDP 51416 -> 5060, payload len: 1154
|
||||||
|
[14:23:26.214] [DEBUG] PcapReader: Packet 1 full payload preview: "INVITE sip:145632@192.168.0.162 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPj2b9d528911164b1795466ba22bc7e1e0\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=d158c77860094"
|
||||||
|
[14:23:26.215] [DEBUG] isSIPPayload: Detected SIP method: INVITE
|
||||||
|
[14:23:26.218] [DEBUG] PcapReader: Packet 1 detected as SIP, parsing...
|
||||||
|
[14:23:26.220] [INFO] PcapReader: Found SIP packet 1: INVITE b8060bf9ee0d43cbb60d714e22046659
|
||||||
|
[14:23:26.221] [DEBUG] PcapReader: Processing packet 2, layers: [0xc00048c150 0xc00049c0a0 0xc000332180 0xc00049e090]
|
||||||
|
[14:23:26.223] [DEBUG] PcapReader: Packet 2 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:23:26.225] [DEBUG] PcapReader: Packet 2 UDP 5060 -> 51416, payload len: 382
|
||||||
|
[14:23:26.227] [DEBUG] PcapReader: Packet 2 full payload preview: "SIP/2.0 100 Trying\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPj2b9d528911164b1795466ba22bc7e1e0\r\nCall-ID: b8060bf9ee0d43cbb60d714e22046659\r\nFrom: <sip:1001"
|
||||||
|
[14:23:26.229] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:23:26.231] [DEBUG] PcapReader: Packet 2 detected as SIP, parsing...
|
||||||
|
[14:23:26.233] [INFO] PcapReader: Found SIP packet 2: 100 b8060bf9ee0d43cbb60d714e22046659
|
||||||
|
[14:23:26.234] [DEBUG] PcapReader: Processing packet 3, layers: [0xc00048c1c0 0xc00049c140 0xc000332200 0xc00049e120]
|
||||||
|
[14:23:26.236] [DEBUG] PcapReader: Packet 3 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:23:26.238] [DEBUG] PcapReader: Packet 3 UDP 5060 -> 51416, payload len: 1075
|
||||||
|
[14:23:26.240] [DEBUG] PcapReader: Packet 3 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPj2b9d528911164b1795466ba22bc7e1e0\r\nCall-ID: b8060bf9ee0d43cbb60d714e22046659\r\nFrom: <sip:1001@192"
|
||||||
|
[14:23:26.242] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:23:26.244] [DEBUG] PcapReader: Packet 3 detected as SIP, parsing...
|
||||||
|
[14:23:26.246] [INFO] PcapReader: Found SIP packet 3: 200 b8060bf9ee0d43cbb60d714e22046659
|
||||||
|
[14:23:26.248] [DEBUG] PcapReader: Processing packet 4, layers: [0xc00048c230 0xc00049c1e0 0xc000332280 0xc00049e1b0]
|
||||||
|
[14:23:26.249] [DEBUG] PcapReader: Packet 4 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:23:26.251] [DEBUG] PcapReader: Packet 4 UDP 51416 -> 5060, payload len: 371
|
||||||
|
[14:23:26.253] [DEBUG] PcapReader: Packet 4 full payload preview: "ACK sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPj5a53b67ee71748bf944b029063d2d8b4\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=d158c77860094c3dbd"
|
||||||
|
[14:23:26.255] [DEBUG] isSIPPayload: Detected SIP method: ACK
|
||||||
|
[14:23:26.257] [DEBUG] PcapReader: Packet 4 detected as SIP, parsing...
|
||||||
|
[14:23:26.259] [INFO] PcapReader: Found SIP packet 4: ACK b8060bf9ee0d43cbb60d714e22046659
|
||||||
|
[14:23:26.261] [DEBUG] PcapReader: Processing packet 5, layers: [0xc00048c2a0 0xc00049c280 0xc000332300 0xc00049e240]
|
||||||
|
[14:23:26.263] [DEBUG] PcapReader: Packet 5 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:23:26.264] [DEBUG] PcapReader: Packet 5 UDP 51416 -> 5060, payload len: 871
|
||||||
|
[14:23:26.267] [DEBUG] PcapReader: Packet 5 full payload preview: "UPDATE sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPje6cb582aed174802a817688d4d8b7f0d\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=d158c77860094c3"
|
||||||
|
[14:23:26.269] [DEBUG] isSIPPayload: Detected SIP method: UPDATE
|
||||||
|
[14:23:26.271] [DEBUG] PcapReader: Packet 5 detected as SIP, parsing...
|
||||||
|
[14:23:26.273] [INFO] PcapReader: Found SIP packet 5: UPDATE b8060bf9ee0d43cbb60d714e22046659
|
||||||
|
[14:23:26.275] [DEBUG] PcapReader: Processing packet 6, layers: [0xc00048c310 0xc00049c320 0xc000332380 0xc00049e2d0]
|
||||||
|
[14:23:26.276] [DEBUG] PcapReader: Packet 6 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:23:26.278] [DEBUG] PcapReader: Packet 6 UDP 5060 -> 51416, payload len: 939
|
||||||
|
[14:23:26.280] [DEBUG] PcapReader: Packet 6 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPje6cb582aed174802a817688d4d8b7f0d\r\nCall-ID: b8060bf9ee0d43cbb60d714e22046659\r\nFrom: <sip:1001@192"
|
||||||
|
[14:23:26.282] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:23:26.284] [DEBUG] PcapReader: Packet 6 detected as SIP, parsing...
|
||||||
|
[14:23:26.286] [INFO] PcapReader: Found SIP packet 6: 200 b8060bf9ee0d43cbb60d714e22046659
|
||||||
|
[14:23:26.288] [DEBUG] PcapReader: Processing packet 7, layers: [0xc00048c380 0xc00049c3c0 0xc000332400 0xc00049e360]
|
||||||
|
[14:23:26.289] [DEBUG] PcapReader: Packet 7 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:23:26.291] [DEBUG] PcapReader: Packet 7 UDP 51416 -> 5060, payload len: 400
|
||||||
|
[14:23:26.293] [DEBUG] PcapReader: Packet 7 full payload preview: "BYE sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPj8e548a072435464c8b97c3930df0cbca\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=d158c77860094c3dbd"
|
||||||
|
[14:23:26.295] [DEBUG] isSIPPayload: Detected SIP method: BYE
|
||||||
|
[14:23:26.297] [DEBUG] PcapReader: Packet 7 detected as SIP, parsing...
|
||||||
|
[14:23:26.299] [INFO] PcapReader: Found SIP packet 7: BYE b8060bf9ee0d43cbb60d714e22046659
|
||||||
|
[14:23:26.301] [DEBUG] PcapReader: Processing packet 8, layers: [0xc00048c3f0 0xc00049c460 0xc000332480 0xc00049e3f0]
|
||||||
|
[14:23:26.303] [DEBUG] PcapReader: Packet 8 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:23:26.305] [DEBUG] PcapReader: Packet 8 UDP 5060 -> 51416, payload len: 416
|
||||||
|
[14:23:26.306] [DEBUG] PcapReader: Packet 8 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPj8e548a072435464c8b97c3930df0cbca\r\nCall-ID: b8060bf9ee0d43cbb60d714e22046659\r\nFrom: <sip:1001@192"
|
||||||
|
[14:23:26.308] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:23:26.310] [DEBUG] PcapReader: Packet 8 detected as SIP, parsing...
|
||||||
|
[14:23:26.311] [INFO] PcapReader: Found SIP packet 8: 200 b8060bf9ee0d43cbb60d714e22046659
|
||||||
|
[14:23:26.314] [INFO] PcapReader: Finished reading. Total packets: 8, SIP packets: 8
|
||||||
|
[14:25:08.950] [INFO] PcapReader: Creating reader for D:\Proyectos\telephony-inspector\data\calls.pcap
|
||||||
|
[14:25:08.953] [INFO] PcapReader: Opening file D:\Proyectos\telephony-inspector\data\calls.pcap
|
||||||
|
[14:25:08.955] [INFO] PcapReader: File opened successfully, link type: Ethernet
|
||||||
|
[14:25:08.957] [DEBUG] PcapReader: BPF filter set for SIP ports
|
||||||
|
[14:25:08.959] [DEBUG] PcapReader: Processing packet 1, layers: [0xc0005320e0 0xc0001121e0 0xc000154080 0xc000232090]
|
||||||
|
[14:25:08.961] [DEBUG] PcapReader: Packet 1 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:25:08.963] [DEBUG] PcapReader: Packet 1 UDP 51416 -> 5060, payload len: 1153
|
||||||
|
[14:25:08.965] [DEBUG] PcapReader: Packet 1 full payload preview: "INVITE sip:123456@192.168.0.162 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPjc988f0aca12d47aa900f472ea93fc0d6\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=d715109fcadd4"
|
||||||
|
[14:25:08.967] [DEBUG] isSIPPayload: Detected SIP method: INVITE
|
||||||
|
[14:25:08.969] [DEBUG] PcapReader: Packet 1 detected as SIP, parsing...
|
||||||
|
[14:25:08.971] [INFO] PcapReader: Found SIP packet 1: INVITE e06cb346194a4f9295d3a325b185912f
|
||||||
|
[14:25:08.973] [DEBUG] PcapReader: Processing packet 2, layers: [0xc000532150 0xc000112460 0xc000154100 0xc000232120]
|
||||||
|
[14:25:08.975] [DEBUG] PcapReader: Packet 2 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:25:08.976] [DEBUG] PcapReader: Packet 2 UDP 5060 -> 51416, payload len: 382
|
||||||
|
[14:25:08.978] [DEBUG] PcapReader: Packet 2 full payload preview: "SIP/2.0 100 Trying\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPjc988f0aca12d47aa900f472ea93fc0d6\r\nCall-ID: e06cb346194a4f9295d3a325b185912f\r\nFrom: <sip:1001"
|
||||||
|
[14:25:08.980] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:25:08.981] [DEBUG] PcapReader: Packet 2 detected as SIP, parsing...
|
||||||
|
[14:25:08.984] [INFO] PcapReader: Found SIP packet 2: 100 e06cb346194a4f9295d3a325b185912f
|
||||||
|
[14:25:08.986] [DEBUG] PcapReader: Processing packet 3, layers: [0xc0005321c0 0xc0001125a0 0xc000154180 0xc0002321b0]
|
||||||
|
[14:25:08.988] [DEBUG] PcapReader: Packet 3 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:25:08.990] [DEBUG] PcapReader: Packet 3 UDP 5060 -> 51416, payload len: 1075
|
||||||
|
[14:25:08.991] [DEBUG] PcapReader: Packet 3 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPjc988f0aca12d47aa900f472ea93fc0d6\r\nCall-ID: e06cb346194a4f9295d3a325b185912f\r\nFrom: <sip:1001@192"
|
||||||
|
[14:25:08.993] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:25:08.995] [DEBUG] PcapReader: Packet 3 detected as SIP, parsing...
|
||||||
|
[14:25:08.997] [INFO] PcapReader: Found SIP packet 3: 200 e06cb346194a4f9295d3a325b185912f
|
||||||
|
[14:25:08.998] [DEBUG] PcapReader: Processing packet 4, layers: [0xc000532230 0xc0001126e0 0xc000154200 0xc000232240]
|
||||||
|
[14:25:09.001] [DEBUG] PcapReader: Packet 4 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:25:09.006] [DEBUG] PcapReader: Packet 4 UDP 51416 -> 5060, payload len: 371
|
||||||
|
[14:25:09.008] [DEBUG] PcapReader: Packet 4 full payload preview: "ACK sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPjf0cf112e8b5d4759a3417bc63cd5481e\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=d715109fcadd492b8f"
|
||||||
|
[14:25:09.010] [DEBUG] isSIPPayload: Detected SIP method: ACK
|
||||||
|
[14:25:09.012] [DEBUG] PcapReader: Packet 4 detected as SIP, parsing...
|
||||||
|
[14:25:09.014] [INFO] PcapReader: Found SIP packet 4: ACK e06cb346194a4f9295d3a325b185912f
|
||||||
|
[14:25:09.016] [DEBUG] PcapReader: Processing packet 5, layers: [0xc0005322a0 0xc000112780 0xc000154280 0xc0002322d0]
|
||||||
|
[14:25:09.018] [DEBUG] PcapReader: Packet 5 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:25:09.019] [DEBUG] PcapReader: Packet 5 UDP 51416 -> 5060, payload len: 870
|
||||||
|
[14:25:09.021] [DEBUG] PcapReader: Packet 5 full payload preview: "UPDATE sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPj1453a8f281f04023b1a9d246fb587ca3\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=d715109fcadd492"
|
||||||
|
[14:25:09.023] [DEBUG] isSIPPayload: Detected SIP method: UPDATE
|
||||||
|
[14:25:09.025] [DEBUG] PcapReader: Packet 5 detected as SIP, parsing...
|
||||||
|
[14:25:09.027] [INFO] PcapReader: Found SIP packet 5: UPDATE e06cb346194a4f9295d3a325b185912f
|
||||||
|
[14:25:09.029] [DEBUG] PcapReader: Processing packet 6, layers: [0xc000532310 0xc000112820 0xc000154300 0xc000232360]
|
||||||
|
[14:25:09.031] [DEBUG] PcapReader: Packet 6 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:25:09.032] [DEBUG] PcapReader: Packet 6 UDP 5060 -> 51416, payload len: 939
|
||||||
|
[14:25:09.034] [DEBUG] PcapReader: Packet 6 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPj1453a8f281f04023b1a9d246fb587ca3\r\nCall-ID: e06cb346194a4f9295d3a325b185912f\r\nFrom: <sip:1001@192"
|
||||||
|
[14:25:09.035] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:25:09.038] [DEBUG] PcapReader: Packet 6 detected as SIP, parsing...
|
||||||
|
[14:25:09.040] [INFO] PcapReader: Found SIP packet 6: 200 e06cb346194a4f9295d3a325b185912f
|
||||||
|
[14:25:09.041] [DEBUG] PcapReader: Processing packet 7, layers: [0xc000532380 0xc0001128c0 0xc000154380 0xc0002323f0]
|
||||||
|
[14:25:09.043] [DEBUG] PcapReader: Packet 7 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:25:09.045] [DEBUG] PcapReader: Packet 7 UDP 51416 -> 5060, payload len: 400
|
||||||
|
[14:25:09.047] [DEBUG] PcapReader: Packet 7 full payload preview: "BYE sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPj15f5d8bca6884d6794f27c43437f1201\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=d715109fcadd492b8f"
|
||||||
|
[14:25:09.048] [DEBUG] isSIPPayload: Detected SIP method: BYE
|
||||||
|
[14:25:09.051] [DEBUG] PcapReader: Packet 7 detected as SIP, parsing...
|
||||||
|
[14:25:09.052] [INFO] PcapReader: Found SIP packet 7: BYE e06cb346194a4f9295d3a325b185912f
|
||||||
|
[14:25:09.054] [DEBUG] PcapReader: Processing packet 8, layers: [0xc0005323f0 0xc000112960 0xc000154400 0xc000232480]
|
||||||
|
[14:25:09.056] [DEBUG] PcapReader: Packet 8 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:25:09.058] [DEBUG] PcapReader: Packet 8 UDP 5060 -> 51416, payload len: 416
|
||||||
|
[14:25:09.059] [DEBUG] PcapReader: Packet 8 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPj15f5d8bca6884d6794f27c43437f1201\r\nCall-ID: e06cb346194a4f9295d3a325b185912f\r\nFrom: <sip:1001@192"
|
||||||
|
[14:25:09.061] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:25:09.064] [DEBUG] PcapReader: Packet 8 detected as SIP, parsing...
|
||||||
|
[14:25:09.065] [INFO] PcapReader: Found SIP packet 8: 200 e06cb346194a4f9295d3a325b185912f
|
||||||
|
[14:25:09.067] [DEBUG] PcapReader: Processing packet 9, layers: [0xc000532460 0xc000112a00 0xc000154480 0xc000232510]
|
||||||
|
[14:25:09.069] [DEBUG] PcapReader: Packet 9 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:25:09.071] [DEBUG] PcapReader: Packet 9 UDP 51416 -> 5060, payload len: 1160
|
||||||
|
[14:25:09.073] [DEBUG] PcapReader: Packet 9 full payload preview: "INVITE sip:962791077@192.168.0.162 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPj25f0f67dd6cb411ab3b6d48b1c0f9ca9\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=820adc6fe0"
|
||||||
|
[14:25:09.074] [DEBUG] isSIPPayload: Detected SIP method: INVITE
|
||||||
|
[14:25:09.076] [DEBUG] PcapReader: Packet 9 detected as SIP, parsing...
|
||||||
|
[14:25:09.078] [INFO] PcapReader: Found SIP packet 9: INVITE a15e53524b304ebf9dd16209f9c95d18
|
||||||
|
[14:25:09.080] [DEBUG] PcapReader: Processing packet 10, layers: [0xc0005324d0 0xc000112aa0 0xc000154580 0xc0002325a0]
|
||||||
|
[14:25:09.081] [DEBUG] PcapReader: Packet 10 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:25:09.083] [DEBUG] PcapReader: Packet 10 UDP 5060 -> 51416, payload len: 385
|
||||||
|
[14:25:09.085] [DEBUG] PcapReader: Packet 10 full payload preview: "SIP/2.0 100 Trying\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPj25f0f67dd6cb411ab3b6d48b1c0f9ca9\r\nCall-ID: a15e53524b304ebf9dd16209f9c95d18\r\nFrom: <sip:1001"
|
||||||
|
[14:25:09.087] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:25:09.089] [DEBUG] PcapReader: Packet 10 detected as SIP, parsing...
|
||||||
|
[14:25:09.090] [INFO] PcapReader: Found SIP packet 10: 100 a15e53524b304ebf9dd16209f9c95d18
|
||||||
|
[14:25:09.092] [DEBUG] PcapReader: Processing packet 11, layers: [0xc000532540 0xc000112b40 0xc000154600 0xc000232630]
|
||||||
|
[14:25:09.094] [DEBUG] PcapReader: Packet 11 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:25:09.096] [DEBUG] PcapReader: Packet 11 UDP 5060 -> 51416, payload len: 1078
|
||||||
|
[14:25:09.098] [DEBUG] PcapReader: Packet 11 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPj25f0f67dd6cb411ab3b6d48b1c0f9ca9\r\nCall-ID: a15e53524b304ebf9dd16209f9c95d18\r\nFrom: <sip:1001@192"
|
||||||
|
[14:25:09.100] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:25:09.101] [DEBUG] PcapReader: Packet 11 detected as SIP, parsing...
|
||||||
|
[14:25:09.103] [INFO] PcapReader: Found SIP packet 11: 200 a15e53524b304ebf9dd16209f9c95d18
|
||||||
|
[14:25:09.105] [DEBUG] PcapReader: Processing packet 12, layers: [0xc0005325b0 0xc000112be0 0xc000154680 0xc0002326c0]
|
||||||
|
[14:25:09.107] [DEBUG] PcapReader: Packet 12 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:25:09.108] [DEBUG] PcapReader: Packet 12 UDP 51416 -> 5060, payload len: 374
|
||||||
|
[14:25:09.110] [DEBUG] PcapReader: Packet 12 full payload preview: "ACK sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPj70a4a90d59254a4885b807deca2166fc\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=820adc6fe0694f93bc"
|
||||||
|
[14:25:09.112] [DEBUG] isSIPPayload: Detected SIP method: ACK
|
||||||
|
[14:25:09.114] [DEBUG] PcapReader: Packet 12 detected as SIP, parsing...
|
||||||
|
[14:25:09.116] [INFO] PcapReader: Found SIP packet 12: ACK a15e53524b304ebf9dd16209f9c95d18
|
||||||
|
[14:25:09.118] [DEBUG] PcapReader: Processing packet 13, layers: [0xc000532620 0xc000112c80 0xc000154700 0xc000232750]
|
||||||
|
[14:25:09.120] [DEBUG] PcapReader: Packet 13 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:25:09.121] [DEBUG] PcapReader: Packet 13 UDP 51416 -> 5060, payload len: 874
|
||||||
|
[14:25:09.123] [DEBUG] PcapReader: Packet 13 full payload preview: "UPDATE sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPjda3c200bd4664b39b5d59177c5f53017\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=820adc6fe0694f9"
|
||||||
|
[14:25:09.125] [DEBUG] isSIPPayload: Detected SIP method: UPDATE
|
||||||
|
[14:25:09.127] [DEBUG] PcapReader: Packet 13 detected as SIP, parsing...
|
||||||
|
[14:25:09.129] [INFO] PcapReader: Found SIP packet 13: UPDATE a15e53524b304ebf9dd16209f9c95d18
|
||||||
|
[14:25:09.131] [DEBUG] PcapReader: Processing packet 14, layers: [0xc000532690 0xc000112d20 0xc000154780 0xc0002327e0]
|
||||||
|
[14:25:09.132] [DEBUG] PcapReader: Packet 14 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:25:09.134] [DEBUG] PcapReader: Packet 14 UDP 5060 -> 51416, payload len: 942
|
||||||
|
[14:25:09.136] [DEBUG] PcapReader: Packet 14 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPjda3c200bd4664b39b5d59177c5f53017\r\nCall-ID: a15e53524b304ebf9dd16209f9c95d18\r\nFrom: <sip:1001@192"
|
||||||
|
[14:25:09.138] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:25:09.139] [DEBUG] PcapReader: Packet 14 detected as SIP, parsing...
|
||||||
|
[14:25:09.141] [INFO] PcapReader: Found SIP packet 14: 200 a15e53524b304ebf9dd16209f9c95d18
|
||||||
|
[14:25:09.143] [DEBUG] PcapReader: Processing packet 15, layers: [0xc000532700 0xc000112dc0 0xc000154800 0xc000232870]
|
||||||
|
[14:25:09.145] [DEBUG] PcapReader: Packet 15 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:25:09.147] [DEBUG] PcapReader: Packet 15 UDP 51416 -> 5060, payload len: 403
|
||||||
|
[14:25:09.148] [DEBUG] PcapReader: Packet 15 full payload preview: "BYE sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPjcca874595f7840409818bf98eb6f7629\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=820adc6fe0694f93bc"
|
||||||
|
[14:25:09.150] [DEBUG] isSIPPayload: Detected SIP method: BYE
|
||||||
|
[14:25:09.152] [DEBUG] PcapReader: Packet 15 detected as SIP, parsing...
|
||||||
|
[14:25:09.154] [INFO] PcapReader: Found SIP packet 15: BYE a15e53524b304ebf9dd16209f9c95d18
|
||||||
|
[14:25:09.156] [DEBUG] PcapReader: Processing packet 16, layers: [0xc000532770 0xc000112e60 0xc000154880 0xc000232900]
|
||||||
|
[14:25:09.157] [DEBUG] PcapReader: Packet 16 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:25:09.159] [DEBUG] PcapReader: Packet 16 UDP 5060 -> 51416, payload len: 419
|
||||||
|
[14:25:09.162] [DEBUG] PcapReader: Packet 16 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPjcca874595f7840409818bf98eb6f7629\r\nCall-ID: a15e53524b304ebf9dd16209f9c95d18\r\nFrom: <sip:1001@192"
|
||||||
|
[14:25:09.163] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:25:09.165] [DEBUG] PcapReader: Packet 16 detected as SIP, parsing...
|
||||||
|
[14:25:09.167] [INFO] PcapReader: Found SIP packet 16: 200 a15e53524b304ebf9dd16209f9c95d18
|
||||||
|
[14:25:09.169] [DEBUG] PcapReader: Processing packet 17, layers: [0xc0005327e0 0xc000112f00 0xc000154900 0xc000232990]
|
||||||
|
[14:25:09.171] [DEBUG] PcapReader: Packet 17 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:25:09.173] [DEBUG] PcapReader: Packet 17 UDP 51416 -> 5060, payload len: 1150
|
||||||
|
[14:25:09.175] [DEBUG] PcapReader: Packet 17 full payload preview: "INVITE sip:3333@192.168.0.162 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPjb6b83a62e76f41c58fe9b71e82af61a5\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=c2ffb0450ac24fb"
|
||||||
|
[14:25:09.176] [DEBUG] isSIPPayload: Detected SIP method: INVITE
|
||||||
|
[14:25:09.178] [DEBUG] PcapReader: Packet 17 detected as SIP, parsing...
|
||||||
|
[14:25:09.180] [INFO] PcapReader: Found SIP packet 17: INVITE e9270b7c047542ef9af488d27b82162e
|
||||||
|
[14:25:09.181] [DEBUG] PcapReader: Processing packet 18, layers: [0xc000532850 0xc000112fa0 0xc000154980 0xc000232a20]
|
||||||
|
[14:25:09.184] [DEBUG] PcapReader: Packet 18 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:25:09.186] [DEBUG] PcapReader: Packet 18 UDP 5060 -> 51416, payload len: 380
|
||||||
|
[14:25:09.187] [DEBUG] PcapReader: Packet 18 full payload preview: "SIP/2.0 100 Trying\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPjb6b83a62e76f41c58fe9b71e82af61a5\r\nCall-ID: e9270b7c047542ef9af488d27b82162e\r\nFrom: <sip:1001"
|
||||||
|
[14:25:09.189] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:25:09.191] [DEBUG] PcapReader: Packet 18 detected as SIP, parsing...
|
||||||
|
[14:25:09.193] [INFO] PcapReader: Found SIP packet 18: 100 e9270b7c047542ef9af488d27b82162e
|
||||||
|
[14:25:09.195] [DEBUG] PcapReader: Processing packet 19, layers: [0xc0005328c0 0xc000113040 0xc000154a00 0xc000232ab0]
|
||||||
|
[14:25:09.197] [DEBUG] PcapReader: Packet 19 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:25:09.198] [DEBUG] PcapReader: Packet 19 UDP 5060 -> 51416, payload len: 1073
|
||||||
|
[14:25:09.201] [DEBUG] PcapReader: Packet 19 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPjb6b83a62e76f41c58fe9b71e82af61a5\r\nCall-ID: e9270b7c047542ef9af488d27b82162e\r\nFrom: <sip:1001@192"
|
||||||
|
[14:25:09.202] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:25:09.204] [DEBUG] PcapReader: Packet 19 detected as SIP, parsing...
|
||||||
|
[14:25:09.206] [INFO] PcapReader: Found SIP packet 19: 200 e9270b7c047542ef9af488d27b82162e
|
||||||
|
[14:25:09.208] [DEBUG] PcapReader: Processing packet 20, layers: [0xc000532930 0xc0001130e0 0xc000154a80 0xc000232b40]
|
||||||
|
[14:25:09.209] [DEBUG] PcapReader: Packet 20 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:25:09.212] [DEBUG] PcapReader: Packet 20 UDP 51416 -> 5060, payload len: 369
|
||||||
|
[14:25:09.213] [DEBUG] PcapReader: Packet 20 full payload preview: "ACK sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPj1ec8fc81ae324187a6feecaf02f04ff1\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=c2ffb0450ac24fb098"
|
||||||
|
[14:25:09.215] [DEBUG] isSIPPayload: Detected SIP method: ACK
|
||||||
|
[14:25:09.217] [DEBUG] PcapReader: Packet 20 detected as SIP, parsing...
|
||||||
|
[14:25:09.219] [INFO] PcapReader: Found SIP packet 20: ACK e9270b7c047542ef9af488d27b82162e
|
||||||
|
[14:25:09.221] [DEBUG] PcapReader: Processing packet 21, layers: [0xc0005329a0 0xc000113180 0xc000154b00 0xc000232bd0]
|
||||||
|
[14:25:09.223] [DEBUG] PcapReader: Packet 21 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:25:09.224] [DEBUG] PcapReader: Packet 21 UDP 51416 -> 5060, payload len: 869
|
||||||
|
[14:25:09.226] [DEBUG] PcapReader: Packet 21 full payload preview: "UPDATE sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPja17c7b2ea9da425d85da051e336794c9\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=c2ffb0450ac24fb"
|
||||||
|
[14:25:09.228] [DEBUG] isSIPPayload: Detected SIP method: UPDATE
|
||||||
|
[14:25:09.230] [DEBUG] PcapReader: Packet 21 detected as SIP, parsing...
|
||||||
|
[14:25:09.231] [INFO] PcapReader: Found SIP packet 21: UPDATE e9270b7c047542ef9af488d27b82162e
|
||||||
|
[14:25:09.233] [DEBUG] PcapReader: Processing packet 22, layers: [0xc000532a10 0xc000113220 0xc000154b80 0xc000232c60]
|
||||||
|
[14:25:09.235] [DEBUG] PcapReader: Packet 22 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:25:09.237] [DEBUG] PcapReader: Packet 22 UDP 5060 -> 51416, payload len: 937
|
||||||
|
[14:25:09.239] [DEBUG] PcapReader: Packet 22 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPja17c7b2ea9da425d85da051e336794c9\r\nCall-ID: e9270b7c047542ef9af488d27b82162e\r\nFrom: <sip:1001@192"
|
||||||
|
[14:25:09.241] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:25:09.242] [DEBUG] PcapReader: Packet 22 detected as SIP, parsing...
|
||||||
|
[14:25:09.245] [INFO] PcapReader: Found SIP packet 22: 200 e9270b7c047542ef9af488d27b82162e
|
||||||
|
[14:25:09.246] [DEBUG] PcapReader: Processing packet 23, layers: [0xc000532a80 0xc0001132c0 0xc000154c00 0xc000232cf0]
|
||||||
|
[14:25:09.248] [DEBUG] PcapReader: Packet 23 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:25:09.250] [DEBUG] PcapReader: Packet 23 UDP 51416 -> 5060, payload len: 398
|
||||||
|
[14:25:09.252] [DEBUG] PcapReader: Packet 23 full payload preview: "BYE sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPjc372eee10c754ece9a873f8e36a6a0e2\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=c2ffb0450ac24fb098"
|
||||||
|
[14:25:09.253] [DEBUG] isSIPPayload: Detected SIP method: BYE
|
||||||
|
[14:25:09.255] [DEBUG] PcapReader: Packet 23 detected as SIP, parsing...
|
||||||
|
[14:25:09.257] [INFO] PcapReader: Found SIP packet 23: BYE e9270b7c047542ef9af488d27b82162e
|
||||||
|
[14:25:09.259] [DEBUG] PcapReader: Processing packet 24, layers: [0xc000532af0 0xc000113360 0xc000154c80 0xc000232d80]
|
||||||
|
[14:25:09.261] [DEBUG] PcapReader: Packet 24 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:25:09.263] [DEBUG] PcapReader: Packet 24 UDP 5060 -> 51416, payload len: 414
|
||||||
|
[14:25:09.264] [DEBUG] PcapReader: Packet 24 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPjc372eee10c754ece9a873f8e36a6a0e2\r\nCall-ID: e9270b7c047542ef9af488d27b82162e\r\nFrom: <sip:1001@192"
|
||||||
|
[14:25:09.266] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:25:09.268] [DEBUG] PcapReader: Packet 24 detected as SIP, parsing...
|
||||||
|
[14:25:09.270] [INFO] PcapReader: Found SIP packet 24: 200 e9270b7c047542ef9af488d27b82162e
|
||||||
|
[14:25:09.271] [INFO] PcapReader: Finished reading. Total packets: 24, SIP packets: 24
|
||||||
|
[14:25:29.806] [INFO] Telephony Inspector exited normally
|
||||||
176
logs/2026-01-19_14-25-30.log
Normal file
176
logs/2026-01-19_14-25-30.log
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
[14:25:30.903] [INFO] Logger initialized: logs\2026-01-19_14-25-30.log
|
||||||
|
[14:25:30.906] [INFO] Starting Telephony Inspector
|
||||||
|
[14:25:35.313] [INFO] PcapReader: Creating reader for D:\Proyectos\telephony-inspector\data\calls.pcap
|
||||||
|
[14:25:35.317] [INFO] PcapReader: Opening file D:\Proyectos\telephony-inspector\data\calls.pcap
|
||||||
|
[14:25:35.320] [INFO] PcapReader: File opened successfully, link type: Ethernet
|
||||||
|
[14:25:35.324] [DEBUG] PcapReader: BPF filter set for SIP ports
|
||||||
|
[14:25:35.327] [DEBUG] PcapReader: Processing packet 1, layers: [0xc00043a230 0xc00044e000 0xc00031a280 0xc000450000]
|
||||||
|
[14:25:35.331] [DEBUG] PcapReader: Packet 1 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:25:35.335] [DEBUG] PcapReader: Packet 1 UDP 51416 -> 5060, payload len: 1153
|
||||||
|
[14:25:35.337] [DEBUG] PcapReader: Packet 1 full payload preview: "INVITE sip:123456@192.168.0.162 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPjc988f0aca12d47aa900f472ea93fc0d6\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=d715109fcadd4"
|
||||||
|
[14:25:35.338] [DEBUG] isSIPPayload: Detected SIP method: INVITE
|
||||||
|
[14:25:35.340] [DEBUG] PcapReader: Packet 1 detected as SIP, parsing...
|
||||||
|
[14:25:35.342] [INFO] PcapReader: Found SIP packet 1: INVITE e06cb346194a4f9295d3a325b185912f
|
||||||
|
[14:25:35.344] [DEBUG] PcapReader: Processing packet 2, layers: [0xc00043a2a0 0xc00044e0a0 0xc00031a300 0xc000450090]
|
||||||
|
[14:25:35.346] [DEBUG] PcapReader: Packet 2 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:25:35.348] [DEBUG] PcapReader: Packet 2 UDP 5060 -> 51416, payload len: 382
|
||||||
|
[14:25:35.350] [DEBUG] PcapReader: Packet 2 full payload preview: "SIP/2.0 100 Trying\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPjc988f0aca12d47aa900f472ea93fc0d6\r\nCall-ID: e06cb346194a4f9295d3a325b185912f\r\nFrom: <sip:1001"
|
||||||
|
[14:25:35.351] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:25:35.353] [DEBUG] PcapReader: Packet 2 detected as SIP, parsing...
|
||||||
|
[14:25:35.355] [INFO] PcapReader: Found SIP packet 2: 100 e06cb346194a4f9295d3a325b185912f
|
||||||
|
[14:25:35.357] [DEBUG] PcapReader: Processing packet 3, layers: [0xc00043a310 0xc00044e140 0xc00031a380 0xc000450120]
|
||||||
|
[14:25:35.359] [DEBUG] PcapReader: Packet 3 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:25:35.361] [DEBUG] PcapReader: Packet 3 UDP 5060 -> 51416, payload len: 1075
|
||||||
|
[14:25:35.363] [DEBUG] PcapReader: Packet 3 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPjc988f0aca12d47aa900f472ea93fc0d6\r\nCall-ID: e06cb346194a4f9295d3a325b185912f\r\nFrom: <sip:1001@192"
|
||||||
|
[14:25:35.365] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:25:35.366] [DEBUG] PcapReader: Packet 3 detected as SIP, parsing...
|
||||||
|
[14:25:35.368] [INFO] PcapReader: Found SIP packet 3: 200 e06cb346194a4f9295d3a325b185912f
|
||||||
|
[14:25:35.370] [DEBUG] PcapReader: Processing packet 4, layers: [0xc00043a380 0xc00044e1e0 0xc00031a400 0xc0004501b0]
|
||||||
|
[14:25:35.372] [DEBUG] PcapReader: Packet 4 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:25:35.374] [DEBUG] PcapReader: Packet 4 UDP 51416 -> 5060, payload len: 371
|
||||||
|
[14:25:35.376] [DEBUG] PcapReader: Packet 4 full payload preview: "ACK sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPjf0cf112e8b5d4759a3417bc63cd5481e\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=d715109fcadd492b8f"
|
||||||
|
[14:25:35.378] [DEBUG] isSIPPayload: Detected SIP method: ACK
|
||||||
|
[14:25:35.379] [DEBUG] PcapReader: Packet 4 detected as SIP, parsing...
|
||||||
|
[14:25:35.381] [INFO] PcapReader: Found SIP packet 4: ACK e06cb346194a4f9295d3a325b185912f
|
||||||
|
[14:25:35.383] [DEBUG] PcapReader: Processing packet 5, layers: [0xc00043a3f0 0xc00044e280 0xc00031a480 0xc000450240]
|
||||||
|
[14:25:35.385] [DEBUG] PcapReader: Packet 5 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:25:35.387] [DEBUG] PcapReader: Packet 5 UDP 51416 -> 5060, payload len: 870
|
||||||
|
[14:25:35.389] [DEBUG] PcapReader: Packet 5 full payload preview: "UPDATE sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPj1453a8f281f04023b1a9d246fb587ca3\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=d715109fcadd492"
|
||||||
|
[14:25:35.390] [DEBUG] isSIPPayload: Detected SIP method: UPDATE
|
||||||
|
[14:25:35.392] [DEBUG] PcapReader: Packet 5 detected as SIP, parsing...
|
||||||
|
[14:25:35.394] [INFO] PcapReader: Found SIP packet 5: UPDATE e06cb346194a4f9295d3a325b185912f
|
||||||
|
[14:25:35.396] [DEBUG] PcapReader: Processing packet 6, layers: [0xc00043a460 0xc00044e320 0xc00031a500 0xc0004502d0]
|
||||||
|
[14:25:35.398] [DEBUG] PcapReader: Packet 6 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:25:35.399] [DEBUG] PcapReader: Packet 6 UDP 5060 -> 51416, payload len: 939
|
||||||
|
[14:25:35.401] [DEBUG] PcapReader: Packet 6 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPj1453a8f281f04023b1a9d246fb587ca3\r\nCall-ID: e06cb346194a4f9295d3a325b185912f\r\nFrom: <sip:1001@192"
|
||||||
|
[14:25:35.403] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:25:35.405] [DEBUG] PcapReader: Packet 6 detected as SIP, parsing...
|
||||||
|
[14:25:35.406] [INFO] PcapReader: Found SIP packet 6: 200 e06cb346194a4f9295d3a325b185912f
|
||||||
|
[14:25:35.408] [DEBUG] PcapReader: Processing packet 7, layers: [0xc00043a4d0 0xc00044e3c0 0xc00031a580 0xc000450360]
|
||||||
|
[14:25:35.410] [DEBUG] PcapReader: Packet 7 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:25:35.412] [DEBUG] PcapReader: Packet 7 UDP 51416 -> 5060, payload len: 400
|
||||||
|
[14:25:35.414] [DEBUG] PcapReader: Packet 7 full payload preview: "BYE sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPj15f5d8bca6884d6794f27c43437f1201\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=d715109fcadd492b8f"
|
||||||
|
[14:25:35.415] [DEBUG] isSIPPayload: Detected SIP method: BYE
|
||||||
|
[14:25:35.417] [DEBUG] PcapReader: Packet 7 detected as SIP, parsing...
|
||||||
|
[14:25:35.419] [INFO] PcapReader: Found SIP packet 7: BYE e06cb346194a4f9295d3a325b185912f
|
||||||
|
[14:25:35.421] [DEBUG] PcapReader: Processing packet 8, layers: [0xc00043a540 0xc00044e460 0xc00031a600 0xc0004503f0]
|
||||||
|
[14:25:35.439] [DEBUG] PcapReader: Packet 8 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:25:35.440] [DEBUG] PcapReader: Packet 8 UDP 5060 -> 51416, payload len: 416
|
||||||
|
[14:25:35.442] [DEBUG] PcapReader: Packet 8 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPj15f5d8bca6884d6794f27c43437f1201\r\nCall-ID: e06cb346194a4f9295d3a325b185912f\r\nFrom: <sip:1001@192"
|
||||||
|
[14:25:35.444] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:25:35.446] [DEBUG] PcapReader: Packet 8 detected as SIP, parsing...
|
||||||
|
[14:25:35.448] [INFO] PcapReader: Found SIP packet 8: 200 e06cb346194a4f9295d3a325b185912f
|
||||||
|
[14:25:35.450] [DEBUG] PcapReader: Processing packet 9, layers: [0xc00043a5b0 0xc00044e500 0xc00031a680 0xc000450480]
|
||||||
|
[14:25:35.451] [DEBUG] PcapReader: Packet 9 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:25:35.453] [DEBUG] PcapReader: Packet 9 UDP 51416 -> 5060, payload len: 1160
|
||||||
|
[14:25:35.454] [DEBUG] PcapReader: Packet 9 full payload preview: "INVITE sip:962791077@192.168.0.162 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPj25f0f67dd6cb411ab3b6d48b1c0f9ca9\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=820adc6fe0"
|
||||||
|
[14:25:35.457] [DEBUG] isSIPPayload: Detected SIP method: INVITE
|
||||||
|
[14:25:35.459] [DEBUG] PcapReader: Packet 9 detected as SIP, parsing...
|
||||||
|
[14:25:35.461] [INFO] PcapReader: Found SIP packet 9: INVITE a15e53524b304ebf9dd16209f9c95d18
|
||||||
|
[14:25:35.462] [DEBUG] PcapReader: Processing packet 10, layers: [0xc00043a620 0xc00044e5a0 0xc00031a700 0xc000450510]
|
||||||
|
[14:25:35.465] [DEBUG] PcapReader: Packet 10 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:25:35.467] [DEBUG] PcapReader: Packet 10 UDP 5060 -> 51416, payload len: 385
|
||||||
|
[14:25:35.468] [DEBUG] PcapReader: Packet 10 full payload preview: "SIP/2.0 100 Trying\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPj25f0f67dd6cb411ab3b6d48b1c0f9ca9\r\nCall-ID: a15e53524b304ebf9dd16209f9c95d18\r\nFrom: <sip:1001"
|
||||||
|
[14:25:35.470] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:25:35.472] [DEBUG] PcapReader: Packet 10 detected as SIP, parsing...
|
||||||
|
[14:25:35.474] [INFO] PcapReader: Found SIP packet 10: 100 a15e53524b304ebf9dd16209f9c95d18
|
||||||
|
[14:25:35.476] [DEBUG] PcapReader: Processing packet 11, layers: [0xc00043a690 0xc00044e640 0xc00031a780 0xc0004505a0]
|
||||||
|
[14:25:35.478] [DEBUG] PcapReader: Packet 11 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:25:35.480] [DEBUG] PcapReader: Packet 11 UDP 5060 -> 51416, payload len: 1078
|
||||||
|
[14:25:35.481] [DEBUG] PcapReader: Packet 11 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPj25f0f67dd6cb411ab3b6d48b1c0f9ca9\r\nCall-ID: a15e53524b304ebf9dd16209f9c95d18\r\nFrom: <sip:1001@192"
|
||||||
|
[14:25:35.483] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:25:35.485] [DEBUG] PcapReader: Packet 11 detected as SIP, parsing...
|
||||||
|
[14:25:35.487] [INFO] PcapReader: Found SIP packet 11: 200 a15e53524b304ebf9dd16209f9c95d18
|
||||||
|
[14:25:35.489] [DEBUG] PcapReader: Processing packet 12, layers: [0xc00043a700 0xc00044e6e0 0xc00031a800 0xc000450630]
|
||||||
|
[14:25:35.491] [DEBUG] PcapReader: Packet 12 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:25:35.492] [DEBUG] PcapReader: Packet 12 UDP 51416 -> 5060, payload len: 374
|
||||||
|
[14:25:35.494] [DEBUG] PcapReader: Packet 12 full payload preview: "ACK sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPj70a4a90d59254a4885b807deca2166fc\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=820adc6fe0694f93bc"
|
||||||
|
[14:25:35.496] [DEBUG] isSIPPayload: Detected SIP method: ACK
|
||||||
|
[14:25:35.498] [DEBUG] PcapReader: Packet 12 detected as SIP, parsing...
|
||||||
|
[14:25:35.500] [INFO] PcapReader: Found SIP packet 12: ACK a15e53524b304ebf9dd16209f9c95d18
|
||||||
|
[14:25:35.502] [DEBUG] PcapReader: Processing packet 13, layers: [0xc00043a770 0xc00044e780 0xc00031a880 0xc0004506c0]
|
||||||
|
[14:25:35.504] [DEBUG] PcapReader: Packet 13 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:25:35.505] [DEBUG] PcapReader: Packet 13 UDP 51416 -> 5060, payload len: 874
|
||||||
|
[14:25:35.507] [DEBUG] PcapReader: Packet 13 full payload preview: "UPDATE sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPjda3c200bd4664b39b5d59177c5f53017\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=820adc6fe0694f9"
|
||||||
|
[14:25:35.509] [DEBUG] isSIPPayload: Detected SIP method: UPDATE
|
||||||
|
[14:25:35.511] [DEBUG] PcapReader: Packet 13 detected as SIP, parsing...
|
||||||
|
[14:25:35.513] [INFO] PcapReader: Found SIP packet 13: UPDATE a15e53524b304ebf9dd16209f9c95d18
|
||||||
|
[14:25:35.515] [DEBUG] PcapReader: Processing packet 14, layers: [0xc00043a7e0 0xc00044e820 0xc00031a900 0xc000450750]
|
||||||
|
[14:25:35.517] [DEBUG] PcapReader: Packet 14 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:25:35.519] [DEBUG] PcapReader: Packet 14 UDP 5060 -> 51416, payload len: 942
|
||||||
|
[14:25:35.521] [DEBUG] PcapReader: Packet 14 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPjda3c200bd4664b39b5d59177c5f53017\r\nCall-ID: a15e53524b304ebf9dd16209f9c95d18\r\nFrom: <sip:1001@192"
|
||||||
|
[14:25:35.522] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:25:35.524] [DEBUG] PcapReader: Packet 14 detected as SIP, parsing...
|
||||||
|
[14:25:35.526] [INFO] PcapReader: Found SIP packet 14: 200 a15e53524b304ebf9dd16209f9c95d18
|
||||||
|
[14:25:35.528] [DEBUG] PcapReader: Processing packet 15, layers: [0xc00043a850 0xc00044e8c0 0xc00031a980 0xc0004507e0]
|
||||||
|
[14:25:35.530] [DEBUG] PcapReader: Packet 15 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:25:35.532] [DEBUG] PcapReader: Packet 15 UDP 51416 -> 5060, payload len: 403
|
||||||
|
[14:25:35.534] [DEBUG] PcapReader: Packet 15 full payload preview: "BYE sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPjcca874595f7840409818bf98eb6f7629\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=820adc6fe0694f93bc"
|
||||||
|
[14:25:35.535] [DEBUG] isSIPPayload: Detected SIP method: BYE
|
||||||
|
[14:25:35.537] [DEBUG] PcapReader: Packet 15 detected as SIP, parsing...
|
||||||
|
[14:25:35.539] [INFO] PcapReader: Found SIP packet 15: BYE a15e53524b304ebf9dd16209f9c95d18
|
||||||
|
[14:25:35.541] [DEBUG] PcapReader: Processing packet 16, layers: [0xc00043a8c0 0xc00044e960 0xc00031aa00 0xc000450870]
|
||||||
|
[14:25:35.543] [DEBUG] PcapReader: Packet 16 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:25:35.545] [DEBUG] PcapReader: Packet 16 UDP 5060 -> 51416, payload len: 419
|
||||||
|
[14:25:35.546] [DEBUG] PcapReader: Packet 16 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPjcca874595f7840409818bf98eb6f7629\r\nCall-ID: a15e53524b304ebf9dd16209f9c95d18\r\nFrom: <sip:1001@192"
|
||||||
|
[14:25:35.548] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:25:35.550] [DEBUG] PcapReader: Packet 16 detected as SIP, parsing...
|
||||||
|
[14:25:35.552] [INFO] PcapReader: Found SIP packet 16: 200 a15e53524b304ebf9dd16209f9c95d18
|
||||||
|
[14:25:35.554] [DEBUG] PcapReader: Processing packet 17, layers: [0xc00043a930 0xc00044ea00 0xc00031aa80 0xc000450900]
|
||||||
|
[14:25:35.555] [DEBUG] PcapReader: Packet 17 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:25:35.557] [DEBUG] PcapReader: Packet 17 UDP 51416 -> 5060, payload len: 1150
|
||||||
|
[14:25:35.559] [DEBUG] PcapReader: Packet 17 full payload preview: "INVITE sip:3333@192.168.0.162 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPjb6b83a62e76f41c58fe9b71e82af61a5\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=c2ffb0450ac24fb"
|
||||||
|
[14:25:35.561] [DEBUG] isSIPPayload: Detected SIP method: INVITE
|
||||||
|
[14:25:35.563] [DEBUG] PcapReader: Packet 17 detected as SIP, parsing...
|
||||||
|
[14:25:35.565] [INFO] PcapReader: Found SIP packet 17: INVITE e9270b7c047542ef9af488d27b82162e
|
||||||
|
[14:25:35.567] [DEBUG] PcapReader: Processing packet 18, layers: [0xc00043a9a0 0xc00044eaa0 0xc00031ab00 0xc000450990]
|
||||||
|
[14:25:35.568] [DEBUG] PcapReader: Packet 18 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:25:35.570] [DEBUG] PcapReader: Packet 18 UDP 5060 -> 51416, payload len: 380
|
||||||
|
[14:25:35.572] [DEBUG] PcapReader: Packet 18 full payload preview: "SIP/2.0 100 Trying\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPjb6b83a62e76f41c58fe9b71e82af61a5\r\nCall-ID: e9270b7c047542ef9af488d27b82162e\r\nFrom: <sip:1001"
|
||||||
|
[14:25:35.574] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:25:35.576] [DEBUG] PcapReader: Packet 18 detected as SIP, parsing...
|
||||||
|
[14:25:35.578] [INFO] PcapReader: Found SIP packet 18: 100 e9270b7c047542ef9af488d27b82162e
|
||||||
|
[14:25:35.579] [DEBUG] PcapReader: Processing packet 19, layers: [0xc00043aa10 0xc00044eb40 0xc00031ab80 0xc000450a20]
|
||||||
|
[14:25:35.581] [DEBUG] PcapReader: Packet 19 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:25:35.583] [DEBUG] PcapReader: Packet 19 UDP 5060 -> 51416, payload len: 1073
|
||||||
|
[14:25:35.585] [DEBUG] PcapReader: Packet 19 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPjb6b83a62e76f41c58fe9b71e82af61a5\r\nCall-ID: e9270b7c047542ef9af488d27b82162e\r\nFrom: <sip:1001@192"
|
||||||
|
[14:25:35.587] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:25:35.589] [DEBUG] PcapReader: Packet 19 detected as SIP, parsing...
|
||||||
|
[14:25:35.591] [INFO] PcapReader: Found SIP packet 19: 200 e9270b7c047542ef9af488d27b82162e
|
||||||
|
[14:25:35.592] [DEBUG] PcapReader: Processing packet 20, layers: [0xc00043aa80 0xc00044ebe0 0xc00031ac00 0xc000450ab0]
|
||||||
|
[14:25:35.594] [DEBUG] PcapReader: Packet 20 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:25:35.596] [DEBUG] PcapReader: Packet 20 UDP 51416 -> 5060, payload len: 369
|
||||||
|
[14:25:35.598] [DEBUG] PcapReader: Packet 20 full payload preview: "ACK sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPj1ec8fc81ae324187a6feecaf02f04ff1\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=c2ffb0450ac24fb098"
|
||||||
|
[14:25:35.600] [DEBUG] isSIPPayload: Detected SIP method: ACK
|
||||||
|
[14:25:35.602] [DEBUG] PcapReader: Packet 20 detected as SIP, parsing...
|
||||||
|
[14:25:35.604] [INFO] PcapReader: Found SIP packet 20: ACK e9270b7c047542ef9af488d27b82162e
|
||||||
|
[14:25:35.605] [DEBUG] PcapReader: Processing packet 21, layers: [0xc00043aaf0 0xc00044ec80 0xc00031ac80 0xc000450b40]
|
||||||
|
[14:25:35.607] [DEBUG] PcapReader: Packet 21 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:25:35.609] [DEBUG] PcapReader: Packet 21 UDP 51416 -> 5060, payload len: 869
|
||||||
|
[14:25:35.611] [DEBUG] PcapReader: Packet 21 full payload preview: "UPDATE sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPja17c7b2ea9da425d85da051e336794c9\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=c2ffb0450ac24fb"
|
||||||
|
[14:25:35.613] [DEBUG] isSIPPayload: Detected SIP method: UPDATE
|
||||||
|
[14:25:35.615] [DEBUG] PcapReader: Packet 21 detected as SIP, parsing...
|
||||||
|
[14:25:35.617] [INFO] PcapReader: Found SIP packet 21: UPDATE e9270b7c047542ef9af488d27b82162e
|
||||||
|
[14:25:35.618] [DEBUG] PcapReader: Processing packet 22, layers: [0xc00043ab60 0xc00044ed20 0xc00031ad00 0xc000450bd0]
|
||||||
|
[14:25:35.620] [DEBUG] PcapReader: Packet 22 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:25:35.622] [DEBUG] PcapReader: Packet 22 UDP 5060 -> 51416, payload len: 937
|
||||||
|
[14:25:35.625] [DEBUG] PcapReader: Packet 22 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPja17c7b2ea9da425d85da051e336794c9\r\nCall-ID: e9270b7c047542ef9af488d27b82162e\r\nFrom: <sip:1001@192"
|
||||||
|
[14:25:35.627] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:25:35.629] [DEBUG] PcapReader: Packet 22 detected as SIP, parsing...
|
||||||
|
[14:25:35.630] [INFO] PcapReader: Found SIP packet 22: 200 e9270b7c047542ef9af488d27b82162e
|
||||||
|
[14:25:35.632] [DEBUG] PcapReader: Processing packet 23, layers: [0xc00043abd0 0xc00044edc0 0xc00031ad80 0xc000450c60]
|
||||||
|
[14:25:35.634] [DEBUG] PcapReader: Packet 23 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:25:35.636] [DEBUG] PcapReader: Packet 23 UDP 51416 -> 5060, payload len: 398
|
||||||
|
[14:25:35.638] [DEBUG] PcapReader: Packet 23 full payload preview: "BYE sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPjc372eee10c754ece9a873f8e36a6a0e2\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=c2ffb0450ac24fb098"
|
||||||
|
[14:25:35.640] [DEBUG] isSIPPayload: Detected SIP method: BYE
|
||||||
|
[14:25:35.642] [DEBUG] PcapReader: Packet 23 detected as SIP, parsing...
|
||||||
|
[14:25:35.644] [INFO] PcapReader: Found SIP packet 23: BYE e9270b7c047542ef9af488d27b82162e
|
||||||
|
[14:25:35.645] [DEBUG] PcapReader: Processing packet 24, layers: [0xc00043ac40 0xc00044ee60 0xc00031ae00 0xc000450cf0]
|
||||||
|
[14:25:35.647] [DEBUG] PcapReader: Packet 24 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:25:35.649] [DEBUG] PcapReader: Packet 24 UDP 5060 -> 51416, payload len: 414
|
||||||
|
[14:25:35.651] [DEBUG] PcapReader: Packet 24 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPjc372eee10c754ece9a873f8e36a6a0e2\r\nCall-ID: e9270b7c047542ef9af488d27b82162e\r\nFrom: <sip:1001@192"
|
||||||
|
[14:25:35.652] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:25:35.654] [DEBUG] PcapReader: Packet 24 detected as SIP, parsing...
|
||||||
|
[14:25:35.656] [INFO] PcapReader: Found SIP packet 24: 200 e9270b7c047542ef9af488d27b82162e
|
||||||
|
[14:25:35.658] [INFO] PcapReader: Finished reading. Total packets: 24, SIP packets: 24
|
||||||
|
[14:28:06.938] [INFO] Telephony Inspector exited normally
|
||||||
175
logs/2026-01-19_14-28-08.log
Normal file
175
logs/2026-01-19_14-28-08.log
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
[14:28:08.952] [INFO] Logger initialized: logs\2026-01-19_14-28-08.log
|
||||||
|
[14:28:08.956] [INFO] Starting Telephony Inspector
|
||||||
|
[14:28:12.252] [INFO] PcapReader: Creating reader for D:\Proyectos\telephony-inspector\data\calls.pcap
|
||||||
|
[14:28:12.256] [INFO] PcapReader: Opening file D:\Proyectos\telephony-inspector\data\calls.pcap
|
||||||
|
[14:28:12.260] [INFO] PcapReader: File opened successfully, link type: Ethernet
|
||||||
|
[14:28:12.264] [DEBUG] PcapReader: BPF filter set for SIP ports
|
||||||
|
[14:28:12.267] [DEBUG] PcapReader: Processing packet 1, layers: [0xc0000e3b20 0xc0000b8640 0xc0000e0280 0xc00037e000]
|
||||||
|
[14:28:12.272] [DEBUG] PcapReader: Packet 1 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:28:12.275] [DEBUG] PcapReader: Packet 1 UDP 51416 -> 5060, payload len: 1153
|
||||||
|
[14:28:12.277] [DEBUG] PcapReader: Packet 1 full payload preview: "INVITE sip:123456@192.168.0.162 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPjc988f0aca12d47aa900f472ea93fc0d6\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=d715109fcadd4"
|
||||||
|
[14:28:12.280] [DEBUG] isSIPPayload: Detected SIP method: INVITE
|
||||||
|
[14:28:12.281] [DEBUG] PcapReader: Packet 1 detected as SIP, parsing...
|
||||||
|
[14:28:12.283] [INFO] PcapReader: Found SIP packet 1: INVITE e06cb346194a4f9295d3a325b185912f
|
||||||
|
[14:28:12.285] [DEBUG] PcapReader: Processing packet 2, layers: [0xc0000e3b90 0xc0000b86e0 0xc0000e0300 0xc00037e090]
|
||||||
|
[14:28:12.286] [DEBUG] PcapReader: Packet 2 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:28:12.289] [DEBUG] PcapReader: Packet 2 UDP 5060 -> 51416, payload len: 382
|
||||||
|
[14:28:12.290] [DEBUG] PcapReader: Packet 2 full payload preview: "SIP/2.0 100 Trying\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPjc988f0aca12d47aa900f472ea93fc0d6\r\nCall-ID: e06cb346194a4f9295d3a325b185912f\r\nFrom: <sip:1001"
|
||||||
|
[14:28:12.292] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:28:12.294] [DEBUG] PcapReader: Packet 2 detected as SIP, parsing...
|
||||||
|
[14:28:12.296] [INFO] PcapReader: Found SIP packet 2: 100 e06cb346194a4f9295d3a325b185912f
|
||||||
|
[14:28:12.298] [DEBUG] PcapReader: Processing packet 3, layers: [0xc0000e3c00 0xc0000b8780 0xc0000e0380 0xc00037e120]
|
||||||
|
[14:28:12.300] [DEBUG] PcapReader: Packet 3 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:28:12.302] [DEBUG] PcapReader: Packet 3 UDP 5060 -> 51416, payload len: 1075
|
||||||
|
[14:28:12.304] [DEBUG] PcapReader: Packet 3 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPjc988f0aca12d47aa900f472ea93fc0d6\r\nCall-ID: e06cb346194a4f9295d3a325b185912f\r\nFrom: <sip:1001@192"
|
||||||
|
[14:28:12.306] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:28:12.307] [DEBUG] PcapReader: Packet 3 detected as SIP, parsing...
|
||||||
|
[14:28:12.309] [INFO] PcapReader: Found SIP packet 3: 200 e06cb346194a4f9295d3a325b185912f
|
||||||
|
[14:28:12.311] [DEBUG] PcapReader: Processing packet 4, layers: [0xc0000e3c70 0xc0000b8820 0xc0000e0400 0xc00037e1b0]
|
||||||
|
[14:28:12.313] [DEBUG] PcapReader: Packet 4 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:28:12.315] [DEBUG] PcapReader: Packet 4 UDP 51416 -> 5060, payload len: 371
|
||||||
|
[14:28:12.317] [DEBUG] PcapReader: Packet 4 full payload preview: "ACK sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPjf0cf112e8b5d4759a3417bc63cd5481e\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=d715109fcadd492b8f"
|
||||||
|
[14:28:12.319] [DEBUG] isSIPPayload: Detected SIP method: ACK
|
||||||
|
[14:28:12.320] [DEBUG] PcapReader: Packet 4 detected as SIP, parsing...
|
||||||
|
[14:28:12.322] [INFO] PcapReader: Found SIP packet 4: ACK e06cb346194a4f9295d3a325b185912f
|
||||||
|
[14:28:12.324] [DEBUG] PcapReader: Processing packet 5, layers: [0xc0000e3ce0 0xc0000b88c0 0xc0000e0480 0xc00037e240]
|
||||||
|
[14:28:12.326] [DEBUG] PcapReader: Packet 5 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:28:12.328] [DEBUG] PcapReader: Packet 5 UDP 51416 -> 5060, payload len: 870
|
||||||
|
[14:28:12.330] [DEBUG] PcapReader: Packet 5 full payload preview: "UPDATE sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPj1453a8f281f04023b1a9d246fb587ca3\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=d715109fcadd492"
|
||||||
|
[14:28:12.332] [DEBUG] isSIPPayload: Detected SIP method: UPDATE
|
||||||
|
[14:28:12.334] [DEBUG] PcapReader: Packet 5 detected as SIP, parsing...
|
||||||
|
[14:28:12.335] [INFO] PcapReader: Found SIP packet 5: UPDATE e06cb346194a4f9295d3a325b185912f
|
||||||
|
[14:28:12.337] [DEBUG] PcapReader: Processing packet 6, layers: [0xc0000e3d50 0xc0000b8960 0xc0000e0500 0xc00037e2d0]
|
||||||
|
[14:28:12.339] [DEBUG] PcapReader: Packet 6 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:28:12.341] [DEBUG] PcapReader: Packet 6 UDP 5060 -> 51416, payload len: 939
|
||||||
|
[14:28:12.342] [DEBUG] PcapReader: Packet 6 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPj1453a8f281f04023b1a9d246fb587ca3\r\nCall-ID: e06cb346194a4f9295d3a325b185912f\r\nFrom: <sip:1001@192"
|
||||||
|
[14:28:12.345] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:28:12.346] [DEBUG] PcapReader: Packet 6 detected as SIP, parsing...
|
||||||
|
[14:28:12.348] [INFO] PcapReader: Found SIP packet 6: 200 e06cb346194a4f9295d3a325b185912f
|
||||||
|
[14:28:12.350] [DEBUG] PcapReader: Processing packet 7, layers: [0xc0000e3dc0 0xc0000b8a00 0xc0000e0580 0xc00037e360]
|
||||||
|
[14:28:12.352] [DEBUG] PcapReader: Packet 7 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:28:12.354] [DEBUG] PcapReader: Packet 7 UDP 51416 -> 5060, payload len: 400
|
||||||
|
[14:28:12.356] [DEBUG] PcapReader: Packet 7 full payload preview: "BYE sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPj15f5d8bca6884d6794f27c43437f1201\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=d715109fcadd492b8f"
|
||||||
|
[14:28:12.358] [DEBUG] isSIPPayload: Detected SIP method: BYE
|
||||||
|
[14:28:12.360] [DEBUG] PcapReader: Packet 7 detected as SIP, parsing...
|
||||||
|
[14:28:12.361] [INFO] PcapReader: Found SIP packet 7: BYE e06cb346194a4f9295d3a325b185912f
|
||||||
|
[14:28:12.363] [DEBUG] PcapReader: Processing packet 8, layers: [0xc0000e3e30 0xc0000b8aa0 0xc0000e0600 0xc00037e3f0]
|
||||||
|
[14:28:12.365] [DEBUG] PcapReader: Packet 8 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:28:12.367] [DEBUG] PcapReader: Packet 8 UDP 5060 -> 51416, payload len: 416
|
||||||
|
[14:28:12.369] [DEBUG] PcapReader: Packet 8 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPj15f5d8bca6884d6794f27c43437f1201\r\nCall-ID: e06cb346194a4f9295d3a325b185912f\r\nFrom: <sip:1001@192"
|
||||||
|
[14:28:12.371] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:28:12.373] [DEBUG] PcapReader: Packet 8 detected as SIP, parsing...
|
||||||
|
[14:28:12.374] [INFO] PcapReader: Found SIP packet 8: 200 e06cb346194a4f9295d3a325b185912f
|
||||||
|
[14:28:12.376] [DEBUG] PcapReader: Processing packet 9, layers: [0xc0000e3ea0 0xc0000b8b40 0xc0000e0680 0xc00037e480]
|
||||||
|
[14:28:12.378] [DEBUG] PcapReader: Packet 9 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:28:12.380] [DEBUG] PcapReader: Packet 9 UDP 51416 -> 5060, payload len: 1160
|
||||||
|
[14:28:12.382] [DEBUG] PcapReader: Packet 9 full payload preview: "INVITE sip:962791077@192.168.0.162 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPj25f0f67dd6cb411ab3b6d48b1c0f9ca9\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=820adc6fe0"
|
||||||
|
[14:28:12.384] [DEBUG] isSIPPayload: Detected SIP method: INVITE
|
||||||
|
[14:28:12.386] [DEBUG] PcapReader: Packet 9 detected as SIP, parsing...
|
||||||
|
[14:28:12.388] [INFO] PcapReader: Found SIP packet 9: INVITE a15e53524b304ebf9dd16209f9c95d18
|
||||||
|
[14:28:12.390] [DEBUG] PcapReader: Processing packet 10, layers: [0xc0000e3f10 0xc0000b8be0 0xc0000e0700 0xc00037e510]
|
||||||
|
[14:28:12.391] [DEBUG] PcapReader: Packet 10 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:28:12.394] [DEBUG] PcapReader: Packet 10 UDP 5060 -> 51416, payload len: 385
|
||||||
|
[14:28:12.395] [DEBUG] PcapReader: Packet 10 full payload preview: "SIP/2.0 100 Trying\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPj25f0f67dd6cb411ab3b6d48b1c0f9ca9\r\nCall-ID: a15e53524b304ebf9dd16209f9c95d18\r\nFrom: <sip:1001"
|
||||||
|
[14:28:12.397] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:28:12.399] [DEBUG] PcapReader: Packet 10 detected as SIP, parsing...
|
||||||
|
[14:28:12.401] [INFO] PcapReader: Found SIP packet 10: 100 a15e53524b304ebf9dd16209f9c95d18
|
||||||
|
[14:28:12.403] [DEBUG] PcapReader: Processing packet 11, layers: [0xc000498000 0xc0000b8c80 0xc0000e0780 0xc00037e5a0]
|
||||||
|
[14:28:12.405] [DEBUG] PcapReader: Packet 11 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:28:12.407] [DEBUG] PcapReader: Packet 11 UDP 5060 -> 51416, payload len: 1078
|
||||||
|
[14:28:12.408] [DEBUG] PcapReader: Packet 11 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPj25f0f67dd6cb411ab3b6d48b1c0f9ca9\r\nCall-ID: a15e53524b304ebf9dd16209f9c95d18\r\nFrom: <sip:1001@192"
|
||||||
|
[14:28:12.410] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:28:12.413] [DEBUG] PcapReader: Packet 11 detected as SIP, parsing...
|
||||||
|
[14:28:12.414] [INFO] PcapReader: Found SIP packet 11: 200 a15e53524b304ebf9dd16209f9c95d18
|
||||||
|
[14:28:12.416] [DEBUG] PcapReader: Processing packet 12, layers: [0xc000498070 0xc0000b8d20 0xc0000e0800 0xc00037e630]
|
||||||
|
[14:28:12.418] [DEBUG] PcapReader: Packet 12 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:28:12.419] [DEBUG] PcapReader: Packet 12 UDP 51416 -> 5060, payload len: 374
|
||||||
|
[14:28:12.421] [DEBUG] PcapReader: Packet 12 full payload preview: "ACK sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPj70a4a90d59254a4885b807deca2166fc\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=820adc6fe0694f93bc"
|
||||||
|
[14:28:12.423] [DEBUG] isSIPPayload: Detected SIP method: ACK
|
||||||
|
[14:28:12.425] [DEBUG] PcapReader: Packet 12 detected as SIP, parsing...
|
||||||
|
[14:28:12.427] [INFO] PcapReader: Found SIP packet 12: ACK a15e53524b304ebf9dd16209f9c95d18
|
||||||
|
[14:28:12.429] [DEBUG] PcapReader: Processing packet 13, layers: [0xc0004980e0 0xc0000b8dc0 0xc0000e0880 0xc00037e6c0]
|
||||||
|
[14:28:12.431] [DEBUG] PcapReader: Packet 13 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:28:12.433] [DEBUG] PcapReader: Packet 13 UDP 51416 -> 5060, payload len: 874
|
||||||
|
[14:28:12.434] [DEBUG] PcapReader: Packet 13 full payload preview: "UPDATE sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPjda3c200bd4664b39b5d59177c5f53017\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=820adc6fe0694f9"
|
||||||
|
[14:28:12.436] [DEBUG] isSIPPayload: Detected SIP method: UPDATE
|
||||||
|
[14:28:12.438] [DEBUG] PcapReader: Packet 13 detected as SIP, parsing...
|
||||||
|
[14:28:12.440] [INFO] PcapReader: Found SIP packet 13: UPDATE a15e53524b304ebf9dd16209f9c95d18
|
||||||
|
[14:28:12.442] [DEBUG] PcapReader: Processing packet 14, layers: [0xc000498150 0xc0000b8e60 0xc0000e0900 0xc00037e750]
|
||||||
|
[14:28:12.444] [DEBUG] PcapReader: Packet 14 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:28:12.446] [DEBUG] PcapReader: Packet 14 UDP 5060 -> 51416, payload len: 942
|
||||||
|
[14:28:12.448] [DEBUG] PcapReader: Packet 14 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPjda3c200bd4664b39b5d59177c5f53017\r\nCall-ID: a15e53524b304ebf9dd16209f9c95d18\r\nFrom: <sip:1001@192"
|
||||||
|
[14:28:12.449] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:28:12.451] [DEBUG] PcapReader: Packet 14 detected as SIP, parsing...
|
||||||
|
[14:28:12.453] [INFO] PcapReader: Found SIP packet 14: 200 a15e53524b304ebf9dd16209f9c95d18
|
||||||
|
[14:28:12.455] [DEBUG] PcapReader: Processing packet 15, layers: [0xc0004981c0 0xc0000b8f00 0xc0000e0980 0xc00037e7e0]
|
||||||
|
[14:28:12.457] [DEBUG] PcapReader: Packet 15 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:28:12.459] [DEBUG] PcapReader: Packet 15 UDP 51416 -> 5060, payload len: 403
|
||||||
|
[14:28:12.461] [DEBUG] PcapReader: Packet 15 full payload preview: "BYE sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPjcca874595f7840409818bf98eb6f7629\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=820adc6fe0694f93bc"
|
||||||
|
[14:28:12.462] [DEBUG] isSIPPayload: Detected SIP method: BYE
|
||||||
|
[14:28:12.464] [DEBUG] PcapReader: Packet 15 detected as SIP, parsing...
|
||||||
|
[14:28:12.466] [INFO] PcapReader: Found SIP packet 15: BYE a15e53524b304ebf9dd16209f9c95d18
|
||||||
|
[14:28:12.468] [DEBUG] PcapReader: Processing packet 16, layers: [0xc000498230 0xc0000b8fa0 0xc0000e0a00 0xc00037e870]
|
||||||
|
[14:28:12.470] [DEBUG] PcapReader: Packet 16 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:28:12.472] [DEBUG] PcapReader: Packet 16 UDP 5060 -> 51416, payload len: 419
|
||||||
|
[14:28:12.474] [DEBUG] PcapReader: Packet 16 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPjcca874595f7840409818bf98eb6f7629\r\nCall-ID: a15e53524b304ebf9dd16209f9c95d18\r\nFrom: <sip:1001@192"
|
||||||
|
[14:28:12.476] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:28:12.482] [DEBUG] PcapReader: Packet 16 detected as SIP, parsing...
|
||||||
|
[14:28:12.484] [INFO] PcapReader: Found SIP packet 16: 200 a15e53524b304ebf9dd16209f9c95d18
|
||||||
|
[14:28:12.485] [DEBUG] PcapReader: Processing packet 17, layers: [0xc0004982a0 0xc0000b9040 0xc0000e0a80 0xc00037e900]
|
||||||
|
[14:28:12.487] [DEBUG] PcapReader: Packet 17 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:28:12.489] [DEBUG] PcapReader: Packet 17 UDP 51416 -> 5060, payload len: 1150
|
||||||
|
[14:28:12.492] [DEBUG] PcapReader: Packet 17 full payload preview: "INVITE sip:3333@192.168.0.162 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPjb6b83a62e76f41c58fe9b71e82af61a5\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=c2ffb0450ac24fb"
|
||||||
|
[14:28:12.493] [DEBUG] isSIPPayload: Detected SIP method: INVITE
|
||||||
|
[14:28:12.495] [DEBUG] PcapReader: Packet 17 detected as SIP, parsing...
|
||||||
|
[14:28:12.497] [INFO] PcapReader: Found SIP packet 17: INVITE e9270b7c047542ef9af488d27b82162e
|
||||||
|
[14:28:12.499] [DEBUG] PcapReader: Processing packet 18, layers: [0xc000498310 0xc0000b90e0 0xc0000e0b00 0xc00037e990]
|
||||||
|
[14:28:12.501] [DEBUG] PcapReader: Packet 18 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:28:12.504] [DEBUG] PcapReader: Packet 18 UDP 5060 -> 51416, payload len: 380
|
||||||
|
[14:28:12.505] [DEBUG] PcapReader: Packet 18 full payload preview: "SIP/2.0 100 Trying\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPjb6b83a62e76f41c58fe9b71e82af61a5\r\nCall-ID: e9270b7c047542ef9af488d27b82162e\r\nFrom: <sip:1001"
|
||||||
|
[14:28:12.507] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:28:12.509] [DEBUG] PcapReader: Packet 18 detected as SIP, parsing...
|
||||||
|
[14:28:12.511] [INFO] PcapReader: Found SIP packet 18: 100 e9270b7c047542ef9af488d27b82162e
|
||||||
|
[14:28:12.513] [DEBUG] PcapReader: Processing packet 19, layers: [0xc000498380 0xc0000b9180 0xc0000e0b80 0xc00037ea20]
|
||||||
|
[14:28:12.515] [DEBUG] PcapReader: Packet 19 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:28:12.517] [DEBUG] PcapReader: Packet 19 UDP 5060 -> 51416, payload len: 1073
|
||||||
|
[14:28:12.518] [DEBUG] PcapReader: Packet 19 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPjb6b83a62e76f41c58fe9b71e82af61a5\r\nCall-ID: e9270b7c047542ef9af488d27b82162e\r\nFrom: <sip:1001@192"
|
||||||
|
[14:28:12.521] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:28:12.523] [DEBUG] PcapReader: Packet 19 detected as SIP, parsing...
|
||||||
|
[14:28:12.524] [INFO] PcapReader: Found SIP packet 19: 200 e9270b7c047542ef9af488d27b82162e
|
||||||
|
[14:28:12.526] [DEBUG] PcapReader: Processing packet 20, layers: [0xc0004983f0 0xc0000b9220 0xc0000e0c00 0xc00037eab0]
|
||||||
|
[14:28:12.528] [DEBUG] PcapReader: Packet 20 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:28:12.530] [DEBUG] PcapReader: Packet 20 UDP 51416 -> 5060, payload len: 369
|
||||||
|
[14:28:12.532] [DEBUG] PcapReader: Packet 20 full payload preview: "ACK sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPj1ec8fc81ae324187a6feecaf02f04ff1\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=c2ffb0450ac24fb098"
|
||||||
|
[14:28:12.534] [DEBUG] isSIPPayload: Detected SIP method: ACK
|
||||||
|
[14:28:12.535] [DEBUG] PcapReader: Packet 20 detected as SIP, parsing...
|
||||||
|
[14:28:12.537] [INFO] PcapReader: Found SIP packet 20: ACK e9270b7c047542ef9af488d27b82162e
|
||||||
|
[14:28:12.539] [DEBUG] PcapReader: Processing packet 21, layers: [0xc000498460 0xc0000b92c0 0xc0000e0c80 0xc00037eb40]
|
||||||
|
[14:28:12.541] [DEBUG] PcapReader: Packet 21 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:28:12.543] [DEBUG] PcapReader: Packet 21 UDP 51416 -> 5060, payload len: 869
|
||||||
|
[14:28:12.545] [DEBUG] PcapReader: Packet 21 full payload preview: "UPDATE sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPja17c7b2ea9da425d85da051e336794c9\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=c2ffb0450ac24fb"
|
||||||
|
[14:28:12.547] [DEBUG] isSIPPayload: Detected SIP method: UPDATE
|
||||||
|
[14:28:12.548] [DEBUG] PcapReader: Packet 21 detected as SIP, parsing...
|
||||||
|
[14:28:12.550] [INFO] PcapReader: Found SIP packet 21: UPDATE e9270b7c047542ef9af488d27b82162e
|
||||||
|
[14:28:12.552] [DEBUG] PcapReader: Processing packet 22, layers: [0xc0004984d0 0xc0000b9360 0xc0000e0d00 0xc00037ebd0]
|
||||||
|
[14:28:12.554] [DEBUG] PcapReader: Packet 22 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:28:12.555] [DEBUG] PcapReader: Packet 22 UDP 5060 -> 51416, payload len: 937
|
||||||
|
[14:28:12.558] [DEBUG] PcapReader: Packet 22 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPja17c7b2ea9da425d85da051e336794c9\r\nCall-ID: e9270b7c047542ef9af488d27b82162e\r\nFrom: <sip:1001@192"
|
||||||
|
[14:28:12.559] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:28:12.561] [DEBUG] PcapReader: Packet 22 detected as SIP, parsing...
|
||||||
|
[14:28:12.563] [INFO] PcapReader: Found SIP packet 22: 200 e9270b7c047542ef9af488d27b82162e
|
||||||
|
[14:28:12.565] [DEBUG] PcapReader: Processing packet 23, layers: [0xc000498540 0xc0000b9400 0xc0000e0d80 0xc00037ec60]
|
||||||
|
[14:28:12.566] [DEBUG] PcapReader: Packet 23 IPv4 192.168.0.164 -> 192.168.0.162
|
||||||
|
[14:28:12.568] [DEBUG] PcapReader: Packet 23 UDP 51416 -> 5060, payload len: 398
|
||||||
|
[14:28:12.570] [DEBUG] PcapReader: Packet 23 full payload preview: "BYE sip:192.168.0.162:5060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport;branch=z9hG4bKPjc372eee10c754ece9a873f8e36a6a0e2\r\nMax-Forwards: 70\r\nFrom: <sip:1001@192.168.0.162>;tag=c2ffb0450ac24fb098"
|
||||||
|
[14:28:12.572] [DEBUG] isSIPPayload: Detected SIP method: BYE
|
||||||
|
[14:28:12.574] [DEBUG] PcapReader: Packet 23 detected as SIP, parsing...
|
||||||
|
[14:28:12.576] [INFO] PcapReader: Found SIP packet 23: BYE e9270b7c047542ef9af488d27b82162e
|
||||||
|
[14:28:12.578] [DEBUG] PcapReader: Processing packet 24, layers: [0xc0004985b0 0xc0000b94a0 0xc0000e0e00 0xc00037ecf0]
|
||||||
|
[14:28:12.579] [DEBUG] PcapReader: Packet 24 IPv4 192.168.0.162 -> 192.168.0.164
|
||||||
|
[14:28:12.581] [DEBUG] PcapReader: Packet 24 UDP 5060 -> 51416, payload len: 414
|
||||||
|
[14:28:12.583] [DEBUG] PcapReader: Packet 24 full payload preview: "SIP/2.0 200 OK\r\nVia: SIP/2.0/UDP 192.168.0.164:51416;rport=51416;received=192.168.0.164;branch=z9hG4bKPjc372eee10c754ece9a873f8e36a6a0e2\r\nCall-ID: e9270b7c047542ef9af488d27b82162e\r\nFrom: <sip:1001@192"
|
||||||
|
[14:28:12.585] [DEBUG] isSIPPayload: Detected SIP response
|
||||||
|
[14:28:12.587] [DEBUG] PcapReader: Packet 24 detected as SIP, parsing...
|
||||||
|
[14:28:12.588] [INFO] PcapReader: Found SIP packet 24: 200 e9270b7c047542ef9af488d27b82162e
|
||||||
|
[14:28:12.591] [INFO] PcapReader: Finished reading. Total packets: 24, SIP packets: 24
|
||||||
Reference in New Issue
Block a user