内容简介:组里的网络测试仪整个框架是用perl+extjs实现的。项目很大,看了好久了解了整体框架结构。perl+extjs的实现主要有以下几个好处:入口程序为业务逻辑代码靠 GuiServer.pm 承载,并返回内容,主要函数如下:
组里的网络测试仪整个框架是用perl+extjs实现的。项目很大,看了好久了解了整体框架结构。perl+extjs的实现主要有以下几个好处:
- 轻量级,web服务端与业务逻辑紧耦合,无需web服务器去承载应用
- 调用外部命令行程序方便
- 采用ajax技术,省去了频繁的页面跳转
- extjs封装了大量的组件,界面效果风格一致,省去了前端页面开发工作
入口程序为 server.pl
, 启动web服务,监听端口,轮训请求,两个主要函数如下:
sub ServerInit { my $group = shift; my $server_sock = undef; if($group eq "GUI") { $server_sock = &guiServerInit($ServerParams->{CONFIG}); GuiServer->removeShm(); } elsif($group eq "PKTGEN") {$server_sock = &pktgenInit($ServerParams->{CONFIG});} elsif($group eq "CLUSTER_TEST") {$server_sock = &clusterMasterInit($ServerParams->{CONFIG});} elsif($group eq "ATTACKENGINE") {$server_sock = AttackEngineServer::init($ServerParams->{CONFIG});} if( defined($server_sock) ) {$ServerParams->{"$group"}->{"socket"} = $server_sock;} else { printf("Can not setup $group socket at--[%s, %s]\n", __FILE__, __LINE__); return 0; } $ServerParams->{"SELECT"}->add($ServerParams->{"$group"}->{"socket"}); return 1; } sub mainLoop { my @ready; my $sock; my $sel = $ServerParams->{"SELECT"}; my $GUIConnections = $ServerParams->{"GUI"}->{"connections"}; my $PKTGENConnections = $ServerParams->{"PKTGEN"}->{"connections"}; my $ATTACKENGINEConnections = $ServerParams->{"ATTACKENGINE"}->{"connections"}; my $CLUSTERConnections = $ServerParams->{"CLUSTER_TEST"}->{"connections"}; my $STATConnections = $ServerParams->{"PKTGEN"}->{"connections"}; my $tmpSock; my $tid; #starts looping while(1) { #select: BLOCK, selection loop may be interrupted by signals. @ready = $sel->can_read(); foreach my $fh (@ready) { if($fh == $ServerParams->{"GUI"}->{"socket"}) { #accept the connection $sock = $fh->accept(); #setup buffer for this connection $GUIConnections->{"$sock"} = { "buffer" => "" }; #add this socket into selection loop $sel->add($sock); } #Connection from PKTGEN elsif($fh == $ServerParams->{"PKTGEN"}->{"socket"}) { $sock = $fh->accept(); $PKTGENConnections->{"$sock"} = { "tid" => "-1", "buffer" => "" }; $sel->add($sock); } elsif($fh == $ServerParams->{"ATTACKENGINE"}->{"socket"}) { $sock = $fh->accept(); $sel->add($sock); $ATTACKENGINEConnections->{"$sock"} = {}; } elsif($fh == $ServerParams->{"CLUSTER_TEST"}->{"socket"}) { # connection request from cluster master $sock = $fh->accept(); $sel->add($sock); $CLUSTERConnections->{"$sock"} = { status => "CONNECTED", buffer => "", 'length' => 0, DFA => "AUTH" }; } elsif(&WhichConnection($fh, "GUI")) #for GUI requests { if(! &processGUIRequest_keepalive($fh, $GUIConnections)) { $sel->remove($fh); close($fh); delete $GUIConnections->{"$fh"}; } } elsif(&WhichConnection($fh, "CLUSTER_TEST")) { if(! &processClusterMasterRequest($fh, $CLUSTERConnections)) { $sel->remove($fh); close($fh); } } #stat. from pkt-gens elsif(&WhichConnection($fh, "PKTGEN")) #for PKTGEN running statistics { if(! &processPKTGENMsg_keepalive($fh, $PKTGENConnections)) { $sel->remove($fh); close($fh); delete $PKTGENConnections->{"$fh"}; } } elsif(&WhichConnection($fh, "ATTACKENGINE")) { if(! AttackEngineServer::processAttackEngineResponse($fh, $ATTACKENGINEConnections->{"$fh"})) { $sel->remove($fh); close($fh); delete $ATTACKENGINEConnections->{"$fh"}; } } else { #TODO: error print("Isolated connection!!!!!!!Never should be here. Need debugging."); #throw this connection away $sel->remove($fh); close($fh); } } # can write } }
业务逻辑代码靠 GuiServer.pm 承载,并返回内容,主要函数如下:
sub guiServerInit { my $config = shift; $config_defs->{config} = $config; $config_defs->{path} = $config->{database}->{xmlDatabasePath}; $config_defs->{maxHistory} = $config->{web}->{maxHistory}; $config_defs->{webRoot} = $config->{web}->{webRoot}; $config_defs->{cacheEnabled} = $config->{web}->{cacheEnabled}; $config_defs->{sessionExpires} = $config->{web}->{sessionExpires}; $config_defs->{port} = $config->{web}->{port}; $config_defs->{protocolTemplates} = $config->{msgCompiler}->{protocolTemplates}; $config_defs->{webVersion} = $config->{web}->{version} ? $config->{web}->{version} : "0.1"; $config_defs->{msgCompilerVersion} = $config->{msgCompiler}->{version} ? $config->{msgCompiler}->{version} : "0.1"; $config_defs->{pktgenVersion} = $config->{pktgenVersion}->{version} ? $config->{pktgenVersion}->{version} : "0.1"; $config_defs->{protocolScripts} = $config->{msgCompiler}->{protocolScripts}; $config_defs->{attackScripts} = $config->{msgCompiler}->{attackScripts}; $config_defs->{database} = Database->getDatabaseConnection() or return undef; $config_defs->{totParser} = ToTParser->new($config_defs->{protocolTemplates}, $config_defs->{protocolScripts}); #$config_defs->{"physicalPortManager"} = PhysicalPortManager->new("$config_defs->{path}/System/physicalPortManagement.config","$config_defs->{path}/System/ui_physicalPortMapping.config"); $config_defs->{"physicalPortManager"} = PhysicalPortManager->new("$config_defs->{path}"); #$config_defs->{"physicalPortManager"} = shared_clone(PhysicalPortManager->new("$config_defs->{path}")); #$config_defs->{"ManagementIPConfig"} = ManagementIPConfig->new($MANAGEMENTPORT); $config_defs->{"ManagementIPConfig"} = ManagementIPConfig->new($config_defs->{path}); # set session time $config_defs->{sessions} = Session->new($config_defs->{sessionExpires}); $config_defs->{preferences} = Preference->new($config_defs->{path}); $config_defs->{packetGenerator}={}; $config_defs->{packetGenerator}->{port} = $config->{packetGenerator}->{port}; $config_defs->{DocGenerator} = $config->{DocGenerator}; $config_defs->{PcapBuffer} = $config->{PcapBuffer}; # printf("INIT GUI LOG FILE: $config->{web}->{logFile}\n"); if($config->{web}->{logFile} ne "") { open($config_defs->{GUILOGFILE}, ">$config->{web}->{logFile}") || die "failed to open gui log file!\n"; guiLog("GUI LOG FILE\n"); } #print(Dumper($config_defs)); return IO::Socket::INET->new(LocalPort=> $config_defs->{port}, Reuse => 1, Listen => SOMAXCONN); } sub parseGUIRequest_keepalive { my ($sock, $request, $cleanSockFun) = @_; my ($ret, $params, $file); while(length($request->{"buffer"}) > 0) { if(! defined($request->{"state"})) {$request->{"state"} = "WAIT_FOR_HEADER";} if($request->{"state"} eq "WAIT_FOR_HEADER") { # whether http header is ready $ret = index($request->{"buffer"}, "\r\n\r\n"); if($ret <= 0) # negative {return "MORE_DATA";} # cut request header $request->{"header"} = substr($request->{"buffer"}, 0, $ret + 4); guiLog(Dumper($request->{"header"})); substr($request->{"buffer"}, 0, $ret + 4) = ""; if($request->{"header"} =~ m/^.*Accept-Language: ([^\r\n]+)\r\n/s) { #Accept-Language: zh-CN,zh;q=0.8 @{$request->{languages}} = split(/ *, */, $1); } # parse header $request->{"header"} =~ m/^.*(GET|get|POST|post)\s+(\S+).*/s; $request->{"method"} = uc($1); $request->{"uri"} = $2; $request->{"header"} =~ m/^.*Connection: (\S+)\r\n.*/s; $request->{"connection"} = $1; # parse cookie if($request->{"header"} =~ m/^.*Cookie: ([^\r\n]+)\r\n/s) {$request->{"cookies"} = $1;} # check Modifed-Since if($request->{"header"} =~ m/^.*If-None-Match/s) { print("TODO: return 304 not modifed\n"); print(Dumper($request->{header})); } $request->{"uri"} =~ /^([^?]+)(\?(.+))?/; $request->{"path"} = $1; if($3){ %{$params} = split(/&|=/, $3); } foreach my $pp (keys(%{$params})) {$request->{"params"}->{$pp} = &urlDecode($params->{$pp});} $request->{"state"} = "HEADER_READY"; } if($request->{"state"} eq "HEADER_READY") { if($request->{"method"} eq "GET") {$request->{"state"} = "REQUEST_READY";} else { if($request->{"header"} =~ m/^.*Content-Length:\s+(\d+).*/s) {$request->{"length"} = $1;} if($request->{"length"} < 0) # wrong http post request, ignore it. {return "END";} else { if($request->{"path"} =~ /^\/upload\//i || $request->{"path"} =~ /^\/import\//i) {$request->{"state"} = "FILE_UPLOADING";} elsif(length($request->{"buffer"}) >= $request->{"length"}) { $request->{"data"} = substr($request->{"buffer"}, 0, $request->{"length"}); substr($request->{"buffer"}, 0, $request->{"length"}) = ""; $param = {}; %{$params} = split(/&|=/, $request->{"data"}); foreach my $pp (keys(%{$params})) { my $tmpParam=&urlDecode($params->{$pp}); $tmpParam =~ s/^\s+|\s+$//g;#remove head and tail backspeace,equal to string trim $request->{"params"}->{$pp} = $tmpParam; } $request->{"state"} = "REQUEST_READY"; } else {return "MORE_DATA";} } } } # http request is ready if($request->{"state"} eq "REQUEST_READY") { #print("\n++++++++++\n".$request->{"path"}."\n+++++++++++\n"); # forward to ajax, if($request->{"path"} =~ /^\/ajax\//) {$ret = &ajaxRequest($sock, $request);} elsif($request->{"path"} =~ /^\/attackQuery\//) {$ret = &attackQuery($sock, $request);} elsif($request->{"path"} =~ /^\/testsQuery\//) {$ret = &testsQueryProc($sock, $request);} elsif($request->{"path"} =~ /^\/login\//) {$ret = &loginProc($sock, $request);} elsif($request->{"path"} =~ /^\/logout\//) {$ret = &logoutProc($sock, $request);} elsif($request->{"path"} =~ /^\/session.js$/) {$ret = &sessionJSProc($sock, $request);} elsif($request->{"path"} =~ /^\/command\//) {$ret = &commandProc($sock, $request);} elsif($request->{"path"} =~ /^\/export\//) {$ret = &exportProc($sock, $request);} elsif($request->{"path"} =~ /^\/testReportsDoc\//) {$ret = &testReportsDocProc($sock, $request, $cleanSockFun);} elsif($request->{"path"} =~ /^\/monitor\//) {$ret = &monitorProc($sock, $request);} elsif($request->{"path"} =~ /^\/util\//) {$ret = &utilProc($sock, $request);} elsif($request->{"path"} =~ /^\/exportPcap\//) {$ret = &exportPcapProc($sock, $request, $cleanSockFun);} elsif($request->{"path"} =~ /^\/onlineHelp\//) {$ret = &onlineHelpProc($sock, $request);} elsif($request->{"path"} =~ /^\/loadresourcefile\//) {$ret = &loadResourceFileProc($sock, $request);} elsif($request->{"path"} =~ /^\/license\//) {$ret = &licenseProc($sock, $request);} else {$ret = &staticFileProc($sock, $request);} if(! defined($ret)) {printf("connection closed!\n"); return undef;} foreach my $e (keys(%{$request})) { if($e eq "state" || $e eq "buffer") {next;} delete $request->{$e}; } # waiting for next round $request->{"state"} = "WAIT_FOR_HEADER"; } if($request->{"state"} eq "FILE_UPLOADING") { if(&fileUploadProc($sock, $request)) { foreach my $e (keys(%{$request})) { if($e eq "state" || $e eq "buffer") {next;} delete $request->{$e}; } $request->{"state"} = "WAIT_FOR_HEADER"; } } if(defined($request->{"connection"})){ if($request->{"connection"} =~ /close/i) {printf("Connection to be closed!\n"); return "END";} } } return "MORE_DATA"; }
extjs 在前端通过ajax发起请求,与后端进行交互,示例代码如下:
// 左侧导航历史结果列表数据 var historyresultStore = new Ext.data.JsonStore({ // store configs autoDestroy : true, storeId : 'historyresultStore', proxy : { type : 'ajax', url : '/loadresultlist/', reader : { type : 'json', root : 'history', idProperty : 'id' } }, fields : ['name', 'time', 'url'] }); // 左侧导航历史结果列表数据的容器 var historychart = Ext.create('Ext.grid.Panel', { title : '历史结果', id : 'historychart', store : Ext.data.StoreManager.lookup('historyresultStore'), columns : [{ header:'', xtype:'rownumberer', align:'center' },{ text : '名称', dataIndex : 'name', align:'center' },{ text : '时间', dataIndex : 'time', align:'center' }], width : "100%", forceFit : true, listeners : { 'itemcontextmenu' : function(view, record, item, index, e, eOpts) { // 禁用浏览器的右键相应事件 e.preventDefault(); e.stopEvent(); // var nodename = record.raw.name; delete_menu.showAt(e.getXY()); } }, viewConfig : { listeners : { scope : this, itemdblclick : function(view, record, item, index, e) { var filename = record.data.url; Ext.Ajax.request({ url : "/getrunlog/", method : 'get', params : { name : filename }, success : function(response, opts) { // 清空tabs内容 Ext.getCmp('tabs').removeAll(); if(Ext.getCmp('Onlynavigationpanel')!=undefined){Ext.getCmp('Onlynavigationpanel').destroy();} var testreport = Ext.create('Mytestreport'); Ext.getCmp('tabs').add(testreport); Ext.getCmp('tabs').doLayout(true); Ext.getCmp('testreport').body .update('<iframe scrolling="auto" frameborder="0" width="100%" height="100%" src="../../testResult/' + filename + '/index.html"></iframe>'); // runlog.collapse(); testreport.expand(); // Ext.getCmp('runlog').body.update(response["responseText"]); }, failure : function(response, opts) { Ext.MessageBox.alert({ title : '提示信息', msg : "运行日志获取失败!", buttons : Ext.Msg.OK }); } }); } } } }); // console.log(historyresultStore); historyresultStore.load();
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 利用Helm简化Kubernetes应用部署
- [应用安全]之ActiveMQ漏洞利用方法总结
- 利用obfuscar对.NET应用进行混淆
- 利用React 16.6新特性优化应用性能
- APP漏洞利用组合拳——应用克隆案例分析
- Win10利用应用商店WSReset.exe进行bypassuac
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
数值方法和MATLAB实现与应用
拉克唐瓦尔德 / 机械工业出版社 / 2004-9 / 59.00元
本书是关于数值方法和MATLAB的介绍,是针对高等院校理工科专业学生编写的教材。数值方法可以用来生成其他方法无法求解的问题的近似解。本书的主要目的是为应用计算打下坚实的基础,由简单到复杂讲述了标准数值方法在实际问题中的实现和应用。本书通篇使用良好的编程习惯向读者展示了如何清楚地表达计算思想及编制文档。书中通过给读者提供大量的可直接运行的代码库以及讲解MARLAB工具箱中内置函数使用的数量方法,帮助......一起来看看 《数值方法和MATLAB实现与应用》 这本书的介绍吧!
HTML 压缩/解压工具
在线压缩/解压 HTML 代码
SHA 加密
SHA 加密工具