This commit is contained in:
crusader 2018-03-18 20:53:34 +09:00
parent fe9e3cd8f3
commit 272284e425
30 changed files with 373 additions and 92 deletions

View File

@ -63,6 +63,7 @@
"protractor": "~5.1.2", "protractor": "~5.1.2",
"ts-node": "~4.1.0", "ts-node": "~4.1.0",
"tslint": "~5.9.1", "tslint": "~5.9.1",
"typescript": "~2.5.3" "typescript": "~2.5.3",
"typescript-string-enums": "^0.3.5"
} }
} }

View File

@ -12,20 +12,15 @@ import { combineReducers, ActionReducer, ActionReducerMap, MetaReducer } from '@
import { SimpleRouterStateSerializer } from './commons/util/ngrx/router-store/serializer/simple-router-state-serializer'; import { SimpleRouterStateSerializer } from './commons/util/ngrx/router-store/serializer/simple-router-state-serializer';
import { environment } from '../environments/environment'; import { environment } from '../environments/environment';
import { EFFECTS } from './commons/store'; import * as AppStore from './commons/store';
export interface AppState {
}
export const reducers: ActionReducerMap<AppState> = {
};
@NgModule({ @NgModule({
exports: [ exports: [
StoreModule, StoreModule,
], ],
imports: [ imports: [
StoreModule.forRoot(reducers), StoreModule.forRoot(AppStore.REDUCERS),
/** /**
* @ngrx/router-store keeps router state up-to-date in the store. * @ngrx/router-store keeps router state up-to-date in the store.
*/ */
@ -51,7 +46,7 @@ export const reducers: ActionReducerMap<AppState> = {
maxAge: 50, maxAge: 50,
logOnly: environment.production, logOnly: environment.production,
}), }),
EffectsModule.forRoot(EFFECTS), EffectsModule.forRoot(AppStore.EFFECTS),
], ],
providers: [ providers: [
/** /**

View File

@ -30,6 +30,8 @@ import { AppComponent } from './app.component';
import { environment } from '../environments/environment'; import { environment } from '../environments/environment';
import { RPCService } from './commons/service/rpc.service'; import { RPCService } from './commons/service/rpc.service';
import { RESTService } from './commons/service/rest.service'; import { RESTService } from './commons/service/rest.service';
import { AuthGuard } from './commons/guard/auth.guard'; import { AuthGuard } from './commons/guard/auth.guard';
@ -60,6 +62,7 @@ import { AuthGuard } from './commons/guard/auth.guard';
{ {
provide: RPCClient, useClass: RPCService provide: RPCClient, useClass: RPCService
}, },
CookieService, CookieService,
AuthGuard, AuthGuard,
], ],

View File

@ -1,4 +1,5 @@
import { Injectable, Inject } from '@angular/core'; import { Injectable, Inject } from '@angular/core';
import { Store, select } from '@ngrx/store';
import { Observable } from 'rxjs/Observable'; import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject'; import { Subject } from 'rxjs/Subject';
@ -6,6 +7,11 @@ import { Subject } from 'rxjs/Subject';
import { RPCClient } from 'packages/core/rpc/client/RPCClient'; import { RPCClient } from 'packages/core/rpc/client/RPCClient';
import { RPCClientCodec } from 'packages/core/rpc/protocol/RPCClientCodec'; import { RPCClientCodec } from 'packages/core/rpc/protocol/RPCClientCodec';
import { RPCClientRWC } from 'packages/core/rpc/client/rwc/RPCClientRWC'; import { RPCClientRWC } from 'packages/core/rpc/client/rwc/RPCClientRWC';
import { RPCClientNotificationCodec } from 'packages/core/rpc/protocol/RPCClientCodec';
import { notificationAction } from 'packages/core/rpc/store/notification';
import * as AppStore from '../store';
@Injectable() @Injectable()
@ -13,7 +19,12 @@ export class RPCService extends RPCClient {
constructor( constructor(
private _rpcClientCodec: RPCClientCodec, private _rpcClientCodec: RPCClientCodec,
private _rpcClientRWC: RPCClientRWC, private _rpcClientRWC: RPCClientRWC,
private store: Store<AppStore.State>,
) { ) {
super(_rpcClientCodec, _rpcClientRWC); super(_rpcClientCodec, _rpcClientRWC);
} }
protected onNotification(notiCodec: RPCClientNotificationCodec): void {
this.store.dispatch(notificationAction(notiCodec.method(), notiCodec.params()));
}
} }

View File

@ -1,5 +1,13 @@
import { ActionReducerMap } from '@ngrx/store';
import * as SigninInitStore from './signin-init'; import * as SigninInitStore from './signin-init';
export interface State {
}
export const REDUCERS: ActionReducerMap<State> = {
};
export const EFFECTS = [ export const EFFECTS = [
SigninInitStore.Effects, SigninInitStore.Effects,
]; ];

View File

@ -2,15 +2,19 @@ import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject'; import { Subject } from 'rxjs/Subject';
import { RPCClientRWC } from './rwc/RPCClientRWC'; import { RPCClientRWC } from './rwc/RPCClientRWC';
import { RPCRegistry } from './../registry/RPCRegistry';
import { RPCClientCodec, RPCClientResponseCodec } from '../protocol/RPCClientCodec'; import {
RPCClientCodec,
RPCClientResponseCodec,
RPCClientNotificationCodec,
} from '../protocol/RPCClientCodec';
export interface RPCRequestState { export interface RPCRequestState {
subject: Subject<any>; subject: Subject<any>;
request: any; request: any;
} }
export class RPCClient { export abstract class RPCClient {
private _requestID: number; private _requestID: number;
private _pendingRequestsCount: number; private _pendingRequestsCount: number;
@ -56,15 +60,15 @@ export class RPCClient {
/** /**
* notify * notify
*/ */
public notify(method: string, ...args: any[]): void { public send(method: string, ...args: any[]): void {
this.send(false, method, args); this.sendInternal(false, method, args);
} }
/** /**
* call * call
*/ */
public call<T>(method: string, ...args: any[]): Observable<T> { public call<T>(method: string, ...args: any[]): Observable<T> {
return this.send<T>(true, method, args); return this.sendInternal<T>(true, method, args);
} }
/** /**
@ -75,7 +79,7 @@ export class RPCClient {
return undefined; return undefined;
} }
private send<T>(hasResponse: boolean, method: string, args?: any[]): Observable<T> | undefined { private sendInternal<T>(hasResponse: boolean, method: string, args?: any[]): Observable<T> | undefined {
let id: number; let id: number;
let resSubject: Subject<T>; let resSubject: Subject<T>;
if (hasResponse) { if (hasResponse) {
@ -95,7 +99,10 @@ export class RPCClient {
private onMessage(message: Object): void { private onMessage(message: Object): void {
const resCodec = this._codec.response(message); const resCodec = this._codec.response(message);
if (undefined !== resCodec.id()) {
if (resCodec.isNotification()) {
this.onNotification(resCodec.notification());
} else {
this.onResponse(resCodec); this.onResponse(resCodec);
} }
} }
@ -116,4 +123,6 @@ export class RPCClient {
resSubject.error(error); resSubject.error(error);
} }
} }
protected abstract onNotification(notiCodec: RPCClientNotificationCodec): void;
} }

View File

@ -9,4 +9,12 @@ export abstract class RPCClientResponseCodec {
abstract id(): number | undefined; abstract id(): number | undefined;
abstract error(): RPCError | undefined; abstract error(): RPCError | undefined;
abstract result(): any | undefined; abstract result(): any | undefined;
abstract isNotification(): boolean;
abstract notification(): RPCClientNotificationCodec | undefined;
}
export abstract class RPCClientNotificationCodec {
public abstract method(): string;
public abstract params(): any | undefined;
} }

View File

@ -1,12 +1,18 @@
import { import {
RPCClientCodec, RPCClientCodec,
RPCClientResponseCodec, RPCClientResponseCodec,
RPCClientNotificationCodec,
} from '../RPCClientCodec'; } from '../RPCClientCodec';
import { import {
RPCError, RPCError,
} from '../../error'; } from '../../error';
export interface ClientNotification {
method: string;
params?: any[];
}
export interface ClientRequest { export interface ClientRequest {
jsonrpc: string; jsonrpc: string;
method: string; method: string;
@ -56,4 +62,35 @@ export class RPCClientJSONResponseCodec extends RPCClientResponseCodec {
public result(): any | undefined { public result(): any | undefined {
return this._res.result; return this._res.result;
} }
public isNotification(): boolean {
if (undefined !== this.id() || undefined === this.result()) {
return false;
}
return true;
}
public notification(): RPCClientNotificationCodec | undefined {
if (undefined !== this.id() || undefined === this.result()) {
return undefined;
}
const _noti: ClientNotification = {
method: this._res.result.method,
params: this._res.result.params,
};
return new RPCClientJSONNotificationCodec(_noti);
}
}
export class RPCClientJSONNotificationCodec extends RPCClientNotificationCodec {
public constructor(private _noti: ClientNotification) {
super();
}
public method(): string {
return this._noti.method;
}
public params(): any[] | undefined {
return this._noti.params;
}
} }

View File

@ -1,17 +0,0 @@
export class RPCInvoker {
/**
* hasMethod
*/
public hasMethod(method: string): boolean {
return false;
}
/**
* invoke
*/
public invoke() {
}
}

View File

@ -1,18 +0,0 @@
import { RPCInvoker } from './RPCInvoker';
export class RPCRegistry extends RPCInvoker {
/**
* registerService
*/
public registerService<T>(receiver: T, name: string) {
}
/**
* getService
*/
public getService<T>(name: string): T {
return undefined;
}
}

View File

@ -0,0 +1 @@
export * from './notification.action';

View File

@ -0,0 +1,18 @@
import { Action } from '@ngrx/store';
export interface NotificationAction extends Action {
payload?: any;
}
export function notificationActionEnum(method: string): string {
return `[@@NOTIFICATION] ${method}`;
}
export function notificationAction(method: string, params: any): Action {
const action: NotificationAction = {
type: notificationActionEnum(method),
payload: params,
};
return action;
}

View File

@ -0,0 +1,10 @@
import { DiscoveryPort } from './DiscoveryPort';
export interface DiscoveryHost {
firstScanRange: string;
lastScanRange: string;
excludeHosts: string[];
includeHosts: string[];
discoveryPort: DiscoveryPort;
}

View File

@ -0,0 +1,11 @@
import { DiscoveryService } from './DiscoveryService';
export interface DiscoveryPort {
firstScanRange: number;
lastScanRange: number;
excludePorts: number[];
includeTCP: boolean;
includeUDP: boolean;
discoveryService: DiscoveryService;
}

View File

@ -0,0 +1,3 @@
export interface DiscoveryService {
includeServices: string[];
}

View File

@ -0,0 +1,7 @@
import { DiscoveryHost } from './DiscoveryHost';
export interface DiscoveryZone {
excludePatterns: string[];
discoveryHost: DiscoveryHost;
}

View File

@ -1,16 +1,13 @@
import Port from './Port'; import { Zone } from './Zone';
import Zone from './Zone'; import { Port } from './Port';
interface Host { export interface Host {
id?: number; id?: number;
ip: number; ip: string;
mac: number; mac: number;
createDate?: Date;
updateDate: Date;
os: string; os: string;
target: boolean; discoveredDate?: Date;
ports?: Port[];
zone?: Zone; zone?: Zone;
}
export default Host; ports: Map<number, Port> | null;
}

View File

@ -1,15 +1,13 @@
import Host from './Host'; import { Host } from './Host';
import Service from './Service'; import { PortType } from './PortType';
import PortType from './PortType'; import { Service } from './Service';
interface Port { export interface Port {
id?: number; id?: number;
host: Host;
portType: PortType; portType: PortType;
portNumber: number; portNumber: number;
services?: Service[]; discoveredDate?: Date;
createDate?: Date; host: Host;
updateDate: Date;
}
export default Port; services: Map<string, Service> | null;
}

View File

@ -5,6 +5,4 @@
// TLS = 3, // TLS = 3,
// } // }
type PortType = 'TCP' | 'UDP' | 'TLS'; export type PortType = 'TCP' | 'UDP' | 'TLS';
export default PortType;

View File

@ -1,14 +1,9 @@
import Port from './Port'; import { Port } from './Port';
import PortType from './PortType';
interface Service { export interface Service {
id: number; id: number;
port: Port; cryptoType: string;
portType: PortType;
serviceName: string; serviceName: string;
createDate: Date; discoveredDate?: Date;
updateDate: Date; port: Port;
target: boolean;
} }
export default Service;

View File

@ -1,4 +1,4 @@
import Host from './Host'; import { Host } from './Host';
export interface Zone { export interface Zone {
id?: number; id?: number;
@ -6,9 +6,7 @@ export interface Zone {
ip?: string; ip?: string;
iface?: string; iface?: string;
mac?: string; mac?: string;
firstScanRange?: number; discoveredDate?: Date;
lastScanRange?: number;
hosts?: Host[];
}
export default Zone; hosts: Map<string, Host> | null;
}

View File

@ -1,3 +1,7 @@
export * from './DiscoveryHost';
export * from './DiscoveryPort';
export * from './DiscoveryService';
export * from './DiscoveryZone';
export * from './DiscoveryStartInfo'; export * from './DiscoveryStartInfo';
export * from './Host'; export * from './Host';
export * from './Port'; export * from './Port';

View File

@ -1,7 +1,17 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable'; import { Observable } from 'rxjs/Observable';
import { RPCClient } from 'packages/core/rpc/client/RPCClient'; import { RPCClient } from 'packages/core/rpc/client/RPCClient';
import { DiscoveryStartInfo } from '../model'; import {
DiscoveryStartInfo,
DiscoveryZone,
DiscoveryHost,
DiscoveryPort,
DiscoveryService as M_DiscoveryService,
Zone,
Host,
Port,
Service,
} from '../model';
@Injectable() @Injectable()
export class DiscoveryService { export class DiscoveryService {
@ -16,4 +26,17 @@ export class DiscoveryService {
return this.rpcClient.call('DiscoveryService.startDiscovery', dsInfo); return this.rpcClient.call('DiscoveryService.startDiscovery', dsInfo);
} }
public discoverZone(probeID: string, discoveryZone: DiscoveryZone): void {
this.rpcClient.send('DiscoveryService.discoverZone', probeID, discoveryZone);
}
public discoverHost(probeID: string, zone: Zone, discoveryHost: DiscoveryHost): void {
this.rpcClient.send('DiscoveryService.discoverHost', probeID, zone, discoveryHost);
}
public discoverPort(probeID: string, host: Host, discoveryPort: DiscoveryPort): void {
this.rpcClient.send('DiscoveryService.discoverPort', probeID, host, discoveryPort);
}
public discoverService(probeID: string, port: Port, discoveryService: M_DiscoveryService): void {
this.rpcClient.send('DiscoveryService.discoverService', probeID, port, discoveryService);
}
} }

View File

@ -1,14 +1,36 @@
import {
createSelector,
createFeatureSelector,
ActionReducerMap,
Selector,
} from '@ngrx/store';
import { StateSelector } from 'packages/core/ngrx/store';
import { MODULE } from '../discovery.constant';
import * as NotificationStore from './notification';
import * as SettingStore from './setting'; import * as SettingStore from './setting';
export interface State { export interface State {
notification: NotificationStore.State;
setting: SettingStore.State; setting: SettingStore.State;
} }
export const REDUCERS = { export const REDUCERS = {
notification: NotificationStore.reducer,
setting: SettingStore.reducer, setting: SettingStore.reducer,
}; };
export const EFFECTS = [ export const EFFECTS = [
SettingStore.Effects, SettingStore.Effects,
]; ];
export const selectDiscoveryState = createFeatureSelector<State>(MODULE.name);
export const NotificationSelector = new StateSelector<NotificationStore.State>(createSelector(
selectDiscoveryState,
(state: State) => state.notification
));

View File

@ -0,0 +1,3 @@
export * from './notification.action';
export * from './notification.reducer';
export * from './notification.state';

View File

@ -0,0 +1,50 @@
import { Action } from '@ngrx/store';
import { Enum } from 'typescript-string-enums';
import { notificationActionEnum } from 'packages/core/rpc/store/notification';
import { RPCError } from 'packages/core/rpc/error';
import {
Zone,
Host,
Port,
Service,
} from '../../model';
export enum ActionType {
DiscoveredZone = '[@@NOTIFICATION] DiscoveryService.discoveredZone',
DiscoveredHost = '[@@NOTIFICATION] DiscoveryService.discoveredHost',
DiscoveredPort = '[@@NOTIFICATION] DiscoveryService.discoveredPort',
DiscoveredService = '[@@NOTIFICATION] DiscoveryService.discoveredService',
}
export class DiscoveredZone implements Action {
readonly type = ActionType.DiscoveredZone;
constructor(public payload: Zone) {}
}
export class DiscoveredHost implements Action {
readonly type = ActionType.DiscoveredHost;
constructor(public payload: Host) {}
}
export class DiscoveredPort implements Action {
readonly type = ActionType.DiscoveredPort;
constructor(public payload: Port) {}
}
export class DiscoveredService implements Action {
readonly type = ActionType.DiscoveredService;
constructor(public payload: Service) {}
}
export type Actions =
| DiscoveredZone
| DiscoveredHost
| DiscoveredPort
| DiscoveredService
;

View File

@ -0,0 +1,86 @@
import { RPCError } from 'packages/core/rpc/error';
import {
Actions,
ActionType,
} from './notification.action';
import {
State,
initialState,
} from './notification.state';
import {
Zone,
Host,
Port,
Service,
} from '../../model';
export function reducer(state = initialState, action: Actions): State {
switch (action.type) {
case ActionType.DiscoveredZone: {
const zone: Zone = <Zone>action.payload;
state.zones.set(zone.network, zone);
return state;
}
case ActionType.DiscoveredHost: {
const host: Host = <Host>action.payload;
const zone = state.zones.get(host.zone.network);
if (undefined === zone) {
console.error(`Discovery.discoveredHost: Zone[${host.zone.network}] is not exist`);
}
if (null === zone.hosts) {
zone.hosts = new Map();
}
zone.hosts.set(host.ip, host);
return state;
}
case ActionType.DiscoveredPort: {
const port: Port = <Port>action.payload;
const zone = state.zones.get(port.host.zone.network);
if (undefined === zone) {
console.error(`Discovery.DiscoveredPort: Zone[${port.host.zone.network}] is not exist`);
}
if (null === zone.hosts || undefined === zone.hosts.get(port.host.ip)) {
console.error(`Discovery.DiscoveredPort: Host[${port.host.ip}] is not exist`);
}
const host: Host = zone.hosts.get(port.host.ip);
if (null === host.ports) {
host.ports = new Map();
}
host.ports.set(port.portNumber, port);
return state;
}
case ActionType.DiscoveredService: {
const service: Service = <Service>action.payload;
const zone = state.zones.get(service.port.host.zone.network);
if (undefined === zone) {
console.error(`Discovery.DiscoveredService: Zone[${service.port.host.zone.network}] is not exist`);
}
if (null === zone.hosts || undefined === zone.hosts.get(service.port.host.ip)) {
console.error(`Discovery.DiscoveredPort: Host[${service.port.host.ip}] is not exist`);
}
const host: Host = zone.hosts.get(service.port.host.ip);
if (null === host.ports || undefined === host.ports.get(service.port.portNumber)) {
console.error(`Discovery.DiscoveredPort: Port[${service.port.portNumber}] is not exist`);
}
const port: Port = host.ports.get(service.port.portNumber);
if (null === port.services) {
port.services = new Map();
}
port.services.set(service.serviceName, service);
return state;
}
default: {
return state;
}
}
}

View File

@ -0,0 +1,15 @@
import { RPCError } from 'packages/core/rpc/error';
import { Zone } from '../../model';
export interface State {
error: RPCError | null;
processing: boolean;
zones: Map<string, Zone> | null;
}
export const initialState: State = {
error: null,
processing: false,
zones: null,
};

View File

@ -2,6 +2,7 @@ import {
createSelector, createSelector,
createFeatureSelector, createFeatureSelector,
ActionReducerMap, ActionReducerMap,
Selector,
} from '@ngrx/store'; } from '@ngrx/store';
import { StateSelector } from 'packages/core/ngrx/store'; import { StateSelector } from 'packages/core/ngrx/store';

View File

@ -7113,6 +7113,10 @@ typedarray@~0.0.5:
version "0.0.6" version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
typescript-string-enums@^0.3.5:
version "0.3.5"
resolved "https://registry.yarnpkg.com/typescript-string-enums/-/typescript-string-enums-0.3.5.tgz#00f5c30422ec5d8061ed49a0fe06610ae99f02a2"
typescript@~2.5.3: typescript@~2.5.3:
version "2.5.3" version "2.5.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.5.3.tgz#df3dcdc38f3beb800d4bc322646b04a3f6ca7f0d" resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.5.3.tgz#df3dcdc38f3beb800d4bc322646b04a3f6ca7f0d"