Capturing packets visible on map

This commit is contained in:
Piotr Pekala
2019-03-18 06:40:06 -07:00
parent e507e26cda
commit 2997d1ff66
21 changed files with 167 additions and 38 deletions

View File

@ -169,10 +169,14 @@ import { DateFilter } from './filters/dateFilter.pipe';
import { NameFilter } from './filters/nameFilter.pipe'; import { NameFilter } from './filters/nameFilter.pipe';
import { CustomAdaptersComponent } from './components/preferences/common/custom-adapters/custom-adapters.component'; import { CustomAdaptersComponent } from './components/preferences/common/custom-adapters/custom-adapters.component';
import { NodesMenuComponent } from './components/project-map/nodes-menu/nodes-menu.component'; import { NodesMenuComponent } from './components/project-map/nodes-menu/nodes-menu.component';
import { PacketFiltersActionComponent } from './components/project-map/context-menu/actions/packet-filters-action/packet-filters-action.component';
import { PacketFiltersDialogComponent } from './components/project-map/packet-capturing/packet-filters/packet-filters.component'; import { PacketFiltersDialogComponent } from './components/project-map/packet-capturing/packet-filters/packet-filters.component';
import { HelpDialogComponent } from './components/project-map/help-dialog/help-dialog.component'; import { HelpDialogComponent } from './components/project-map/help-dialog/help-dialog.component';
import { StartCaptureActionComponent } from './components/project-map/context-menu/actions/start-capture/start-capture-action.component'; import { StartCaptureActionComponent } from './components/project-map/context-menu/actions/start-capture/start-capture-action.component';
import { StartCaptureDialogComponent } from './components/project-map/packet-capturing/start-capture/start-capture.component'; import { StartCaptureDialogComponent } from './components/project-map/packet-capturing/start-capture/start-capture.component';
import { SuspendLinkActionComponent } from './components/project-map/context-menu/actions/suspend-link/suspend-link-action.component';
import { ResumeLinkActionComponent } from './components/project-map/context-menu/actions/resume-link-action/resume-link-action.component';
import { StopCaptureActionComponent } from './components/project-map/context-menu/actions/stop-capture/stop-capture-action.component';
if (environment.production) { if (environment.production) {
Raven.config('https://b2b1cfd9b043491eb6b566fd8acee358@sentry.io/842726', { Raven.config('https://b2b1cfd9b043491eb6b566fd8acee358@sentry.io/842726', {
@ -209,6 +213,9 @@ if (environment.production) {
DeleteActionComponent, DeleteActionComponent,
PacketFiltersActionComponent, PacketFiltersActionComponent,
StartCaptureActionComponent, StartCaptureActionComponent,
StopCaptureActionComponent,
ResumeLinkActionComponent,
SuspendLinkActionComponent,
ProjectMapShortcutsComponent, ProjectMapShortcutsComponent,
SettingsComponent, SettingsComponent,
PreferencesComponent, PreferencesComponent,

View File

@ -19,6 +19,7 @@ export class LinkToMapLinkConverter implements Converter<Link, MapLink> {
mapLink.linkType = link.link_type; mapLink.linkType = link.link_type;
mapLink.nodes = link.nodes.map(linkNode => this.linkNodeToMapLinkNode.convert(linkNode, { link_id: link.link_id })); mapLink.nodes = link.nodes.map(linkNode => this.linkNodeToMapLinkNode.convert(linkNode, { link_id: link.link_id }));
mapLink.projectId = link.project_id; mapLink.projectId = link.project_id;
mapLink.suspend = link.suspend;
return mapLink; return mapLink;
} }
} }

View File

@ -19,6 +19,7 @@ export class MapLinkToLinkConverter implements Converter<MapLink, Link> {
link.link_type = mapLink.linkType; link.link_type = mapLink.linkType;
link.nodes = mapLink.nodes.map(mapLinkNode => this.mapLinkNodeToMapLinkNode.convert(mapLinkNode)); link.nodes = mapLink.nodes.map(mapLinkNode => this.mapLinkNodeToMapLinkNode.convert(mapLinkNode));
link.project_id = mapLink.projectId; link.project_id = mapLink.projectId;
link.suspend = mapLink.suspend;
return link; return link;
} }
} }

View File

@ -12,6 +12,7 @@ export class MapLink implements Indexed {
linkType: string; linkType: string;
nodes: MapLinkNode[]; nodes: MapLinkNode[];
projectId: string; projectId: string;
suspend: boolean;
distance: number; // this is not from server distance: number; // this is not from server
length: number; // this is not from server length: number; // this is not from server

View File

@ -32,12 +32,12 @@ export class LinkWidget implements Widget {
return `translate (${translation.dx}, ${translation.dy})`; return `translate (${translation.dx}, ${translation.dy})`;
}); });
link_body.select('.svg-icon').remove(); link_body.select('.capture-icon').remove();
link_body link_body
.filter(l => { return l.filters.frequency_drop }) .filter(l => { return l.capturing })
.append<SVGGElement>('g') .append<SVGGElement>('g')
.attr('class', 'svg-icon') .attr('class', 'capture-icon')
.attr('transform', link => { .attr('transform', link => {
return `translate (${(link.source.x + link.target.x)/2}, ${(link.source.y + link.target.y)/2})` return `translate (${(link.source.x + link.target.x)/2}, ${(link.source.y + link.target.y)/2})`
}) })

View File

@ -0,0 +1,4 @@
<button mat-menu-item *ngIf="link.suspend" (click)="resumeLink()">
<mat-icon>play_arrow</mat-icon>
<span>Resume</span>
</button>

View File

@ -0,0 +1,22 @@
import { Component, Input } from '@angular/core';
import { Server } from '../../../../../models/server';
import { Link } from '../../../../../models/link';
import { LinkService } from '../../../../../services/link.service';
@Component({
selector: 'app-resume-link-action',
templateUrl: './resume-link-action.component.html'
})
export class ResumeLinkActionComponent {
@Input() server: Server;
@Input() link: Link;
constructor(
private linkService: LinkService
) {}
resumeLink() {
this.link.suspend = false;
this.linkService.updateLink(this.server, this.link).subscribe(() => {});
}
}

View File

@ -0,0 +1,4 @@
<button mat-menu-item *ngIf="link.capturing" (click)="stopCapture()">
<mat-icon>pause_circle_filled</mat-icon>
<span>Stop capture</span>
</button>

View File

@ -0,0 +1,21 @@
import { Component, Input } from '@angular/core';
import { Server } from '../../../../../models/server';
import { Link } from '../../../../../models/link';
import { LinkService } from '../../../../../services/link.service';
@Component({
selector: 'app-stop-capture-action',
templateUrl: './stop-capture-action.component.html'
})
export class StopCaptureActionComponent {
@Input() server: Server;
@Input() link: Link;
constructor(
private linkService: LinkService
) {}
stopCapture() {
this.linkService.stopCaptureOnLink(this.server, this.link).subscribe(() => {});
}
}

View File

@ -0,0 +1,4 @@
<button mat-menu-item *ngIf="!link.suspend" (click)="suspendLink()">
<mat-icon>pause</mat-icon>
<span>Suspend</span>
</button>

View File

@ -0,0 +1,22 @@
import { Component, Input } from '@angular/core';
import { Server } from '../../../../../models/server';
import { Link } from '../../../../../models/link';
import { LinkService } from '../../../../../services/link.service';
@Component({
selector: 'app-suspend-link-action',
templateUrl: './suspend-link-action.component.html'
})
export class SuspendLinkActionComponent {
@Input() server: Server;
@Input() link: Link;
constructor(
private linkService: LinkService
) {}
suspendLink() {
this.link.suspend = true;
this.linkService.updateLink(this.server, this.link).subscribe(() => {});
}
}

View File

@ -31,12 +31,27 @@
[server]="server" [server]="server"
[link]="links[0]" [link]="links[0]"
></app-start-capture-action> ></app-start-capture-action>
<app-stop-capture-action
*ngIf="!projectService.isReadOnly(project) && drawings.length===0 && nodes.length===0 && links.length===1"
[server]="server"
[link]="links[0]"
></app-stop-capture-action>
<app-packet-filters-action <app-packet-filters-action
*ngIf="!projectService.isReadOnly(project) && drawings.length===0 && nodes.length===0 && links.length===1" *ngIf="!projectService.isReadOnly(project) && drawings.length===0 && nodes.length===0 && links.length===1"
[server]="server" [server]="server"
[project]="project" [project]="project"
[link]="links[0]" [link]="links[0]"
></app-packet-filters-action> ></app-packet-filters-action>
<app-resume-link-action
*ngIf="!projectService.isReadOnly(project) && drawings.length===0 && nodes.length===0 && links.length===1"
[server]="server"
[link]="links[0]"
></app-resume-link-action>
<app-suspend-link-action
*ngIf="!projectService.isReadOnly(project) && drawings.length===0 && nodes.length===0 && links.length===1"
[server]="server"
[link]="links[0]"
></app-suspend-link-action>
<app-delete-action <app-delete-action
*ngIf="!projectService.isReadOnly(project)" *ngIf="!projectService.isReadOnly(project)"
[server]="server" [server]="server"

View File

@ -1,6 +1,6 @@
<h1 mat-dialog-title>Packet filters</h1> <h1 mat-dialog-title>Packet filters</h1>
<div class="modal-form-container"> <div class="modal-form-container" class="content">
<mat-tab-group *ngIf="this.filters"> <mat-tab-group *ngIf="this.filters">
<mat-tab label="Frequency drop"> <mat-tab label="Frequency drop">
<mat-form-field class="input-field"> <mat-form-field class="input-field">
@ -32,11 +32,13 @@
</mat-tab> </mat-tab>
</mat-tab-group> </mat-tab-group>
</div> </div>
<div class="bottom-bar">
<div mat-dialog-actions> <div class="spacer"></div>
<div mat-dialog-actions layout="row" class="dialog-actions">
<button mat-button (click)="onNoClick()" color="accent">Cancel</button> <button mat-button (click)="onNoClick()" color="accent">Cancel</button>
<button mat-button (click)="onResetClick()" color="accent">Reset</button> <button mat-button (click)="onResetClick()" color="accent">Reset</button>
<button mat-button (click)="onYesClick()" tabindex="2" mat-raised-button color="primary">Apply</button> <button mat-button (click)="onYesClick()" tabindex="2" mat-raised-button color="primary">Apply</button>
<div class="divider"></div> <div class="divider"></div>
<button mat-button (click)="onHelpClick()" color="accent">Help</button> <button mat-button (click)="onHelpClick()" color="accent">Help</button>
</div> </div>
</div>

View File

@ -1,3 +1,11 @@
.spacer {
flex-grow: 1;
}
.content {
height: 260px;
}
.item { .item {
height: 25px; height: 25px;
font-size: 10pt; font-size: 10pt;

View File

@ -1,10 +1,11 @@
<h1 mat-dialog-title>Packet capture</h1> <h1 mat-dialog-title>Packet capture</h1>
<div class="modal-form-container"> <div class="modal-form-container">
<form [formGroup]="inputForm">
<mat-form-field class="input-field"> <mat-form-field class="input-field">
<mat-select <mat-select
placeholder="Link type" placeholder="Link type"
[(ngModel)]="linkType"> formControlName="linkType">
<mat-option *ngFor="let type of linkTypes" [value]="type[1]"> <mat-option *ngFor="let type of linkTypes" [value]="type[1]">
{{type[0]}} {{type[0]}}
</mat-option> </mat-option>
@ -13,9 +14,10 @@
<mat-form-field class="input-field"> <mat-form-field class="input-field">
<input <input
placeholder="File name" placeholder="File name"
matInput type="text" formControlName="fileName"
[(ngModel)]="filename" > matInput type="text">
</mat-form-field> </mat-form-field>
</form>
</div> </div>
<div mat-dialog-actions> <div mat-dialog-actions>

View File

@ -0,0 +1,3 @@
.input-field {
width: 100%;
}

View File

@ -5,6 +5,8 @@ import { MatDialogRef } from '@angular/material';
import { PacketFiltersDialogComponent } from '../packet-filters/packet-filters.component'; import { PacketFiltersDialogComponent } from '../packet-filters/packet-filters.component';
import { LinkService } from '../../../../services/link.service'; import { LinkService } from '../../../../services/link.service';
import { CapturingSettings } from '../../../../models/capturingSettings'; import { CapturingSettings } from '../../../../models/capturingSettings';
import { FormBuilder, FormGroup, FormControl, Validators } from '@angular/forms';
import { ToasterService } from '../../../../services/toaster.service';
@Component({ @Component({
selector: 'app-start-capture', selector: 'app-start-capture',
@ -15,14 +17,19 @@ export class StartCaptureDialogComponent implements OnInit {
server: Server; server: Server;
link: Link; link: Link;
linkTypes = []; linkTypes = [];
inputForm: FormGroup;
linkType: string;
fileName: string;
constructor( constructor(
private dialogRef: MatDialogRef<PacketFiltersDialogComponent>, private dialogRef: MatDialogRef<PacketFiltersDialogComponent>,
private linkService: LinkService private linkService: LinkService,
) {} private formBuilder: FormBuilder,
private toasterService: ToasterService
) {
this.inputForm = this.formBuilder.group({
linkType: new FormControl('', Validators.required),
fileName: new FormControl('', Validators.required)
});
}
ngOnInit() { ngOnInit() {
if (this.link.link_type === 'ethernet') { if (this.link.link_type === 'ethernet') {
@ -40,15 +47,19 @@ export class StartCaptureDialogComponent implements OnInit {
} }
onYesClick() { onYesClick() {
if (this.inputForm.invalid) {
this.toasterService.error(`Fill all required fields`);
} else {
let captureSettings: CapturingSettings = { let captureSettings: CapturingSettings = {
capture_file_name: this.fileName, capture_file_name: this.inputForm.get('fileName').value,
data_link_type: this.linkType data_link_type: this.inputForm.get('linkType').value
}; };
this.linkService.startCaptureOnLink(this.server, this.link, captureSettings).subscribe(() => { this.linkService.startCaptureOnLink(this.server, this.link, captureSettings).subscribe(() => {
this.dialogRef.close(); this.dialogRef.close();
}); });
} }
}
onNoClick() { onNoClick() {
this.dialogRef.close(); this.dialogRef.close();

View File

@ -11,6 +11,7 @@ export class Link {
link_type: string; link_type: string;
nodes: LinkNode[]; nodes: LinkNode[];
project_id: string; project_id: string;
suspend: boolean;
distance: number; // this is not from server distance: number; // this is not from server
length: number; // this is not from server length: number; // this is not from server