From a73fc9d7ade304780e80dd8eaf82e3f6af96e05c Mon Sep 17 00:00:00 2001 From: Irina Peshinskaya Date: Mon, 6 Feb 2017 03:21:20 +0200 Subject: [PATCH] TT#9212 Grandstream provisioning draft Change-Id: Ie8cece3dcd200b9714401f1444c1a3f97db1fd0c --- debian/control | 1 + lib/NGCP/Panel/Utils/DeviceBootstrap.pm | 4 +- .../Utils/DeviceBootstrap/Grandstream.pm | 105 +++++++++++++++--- .../Panel/Utils/DeviceBootstrap/VendorRPC.pm | 9 +- 4 files changed, 100 insertions(+), 19 deletions(-) diff --git a/debian/control b/debian/control index 0c7dcc072e..1deb2c501a 100644 --- a/debian/control +++ b/debian/control @@ -57,6 +57,7 @@ Depends: gettext, libhttp-message-perl, libio-compress-lzma-perl, libio-socket-ip-perl, + libipc-run3-perl, libipc-system-simple-perl, libjson-multivalueordered-perl, libjson-perl, diff --git a/lib/NGCP/Panel/Utils/DeviceBootstrap.pm b/lib/NGCP/Panel/Utils/DeviceBootstrap.pm index 76536cd228..8cb745dc34 100644 --- a/lib/NGCP/Panel/Utils/DeviceBootstrap.pm +++ b/lib/NGCP/Panel/Utils/DeviceBootstrap.pm @@ -143,8 +143,8 @@ sub devmod_sync_credentials_store{ $credentials->{device_id} = $devmod->id; $schema->resultset('autoprov_redirect_credentials')->create($credentials); }else{ - delete $credentials->{device_id}; - $credentials_rs->update($credentials); + delete $credentials->{device_id}; + $credentials_rs->update($credentials); } } diff --git a/lib/NGCP/Panel/Utils/DeviceBootstrap/Grandstream.pm b/lib/NGCP/Panel/Utils/DeviceBootstrap/Grandstream.pm index 6b174b93e7..e8632e6fff 100644 --- a/lib/NGCP/Panel/Utils/DeviceBootstrap/Grandstream.pm +++ b/lib/NGCP/Panel/Utils/DeviceBootstrap/Grandstream.pm @@ -3,38 +3,115 @@ package NGCP::Panel::Utils::DeviceBootstrap::Grandstream; use strict; use Moose; use Data::Dumper; + +use JSON; +use LWP::UserAgent; +use HTTP::Request::Common; +use IPC::Run3; + extends 'NGCP::Panel::Utils::DeviceBootstrap::VendorRPC'; sub rpc_server_params{ my $self = shift; my $cfg = { - proto => 'https', - host => '', - port => '', - path => '', + proto => 'https', + host => 'fm.grandstream.com', + port => '443', + path => '/api/provision', + content_type => 'application/json', + query_string => '', + #query_string => $self->{rpc_server_params}->{query_string} // '', }; - $cfg->{headers} = { %{$self->get_basic_authorization($self->params->{credentials})} }; - $self->{rpc_server_params} = $cfg; + $cfg->{headers} = {}; + #don't rewrite server params - every time we will set query_string + $self->{rpc_server_params} //= $cfg; return $self->{rpc_server_params}; } -override 'redirect_server_call' => sub { - my($self,$action) = @_; - return 1; -}; - sub register_content { my $self = shift; - $self->{register_content} = ""; + #TODO: remove actual cid here + $self->{register_content} = + '{"cid":"'.$self->params->{cid} + .'","method":"redirectDefault","params":{"macs":["' + .$self->content_params->{mac}.'"]}}'; + + my ($sign,$time) = $self->get_request_sign($self->{register_content}); + $self->{rpc_server_params}->{query_string} = '?sig='.$sign.'&time='.$time; return $self->{register_content}; } -sub unregister_content { +sub unregister_content { my $self = shift; - $self->{unregister_content} = ""; + $self->{unregister_content} = + '{"cid":"'.$self->params->{cid} + .'","method":"unDeviceProvision","params":{"macs":["' + .$self->content_params->{mac}.'"]}}'; + + my ($sign,$time) = $self->get_request_sign($self->{unregister_content}); + $self->{rpc_server_params}->{query_string} = '?sig='.$sign.'&time='.$time; return $self->{unregister_content}; } +override 'parse_rpc_response_page' => sub { + my($self, $page) = @_; + my $res = JSON::from_json($page); + return $res; +}; + +override 'parse_rpc_response' => sub { + my($self,$rpc_response) = @_; + return $rpc_response; +}; + +#Todo: unify it with snome and vendor version somehow and move to VendorRPC.pm +override 'extract_response_description' => sub { + my($self,$rpc_value) = @_; + my $res = ''; + + if(ref $rpc_value eq 'HASH'){ + #0 - success; > 0 - different errors. See p. 16 of the GAPS_API_Guide.pdf + if($rpc_value->{code} eq '0'){ + $res = '';#clear the error + }elsif($rpc_value->{code} > 0){ + return $rpc_value->{desc}; + }else{ + $res = $self->unknown_error; + } + }else{ + $res = $self->unknown_error; + } + return $res; +}; + + +sub get_server_time { + my $self = shift; + my $ua = LWP::UserAgent->new; + my $req = HTTP::Request->new('GET', + $self->rpc_server_params->{proto} + .'://'.$self->rpc_server_params->{host} + .$self->rpc_server_params->{path}); + + my $time_response = $ua->request($req); + my $time_content = JSON::from_json($time_response->decoded_content); + return $time_content->{time}; +} + +sub get_request_sign{ + my $self = shift; + my ($request,$time) = @_; + my $key = $self->params->{key}; + $time //= $self->get_server_time(); + my $str2sign = $request.$time; + my ($sign,$sign_error); + my $cmd = "openssl sha1 -hmac '$key' -binary|xxd -p"; + #sig=$(echo -n $str2sign | openssl sha1 -hmac $key -binary|xxd -p) + #run3 \@cmd, \$in, \$out, \$err; + run3 $cmd, \$str2sign, \$sign, \$sign_error; + $sign=~s/\n//g; + return ($sign, $time); +} 1; =head1 NAME diff --git a/lib/NGCP/Panel/Utils/DeviceBootstrap/VendorRPC.pm b/lib/NGCP/Panel/Utils/DeviceBootstrap/VendorRPC.pm index 3f5473bebe..168ea129d7 100644 --- a/lib/NGCP/Panel/Utils/DeviceBootstrap/VendorRPC.pm +++ b/lib/NGCP/Panel/Utils/DeviceBootstrap/VendorRPC.pm @@ -55,7 +55,7 @@ sub rpc_https_call{ my($self, $content, $cfg) = @_; $cfg //= $self->rpc_server_params; my $c = $self->params->{c}; - $c->log->debug( "rpc_https_call: host=$cfg->{host}; port=$cfg->{port}; path=$cfg->{path}; content=$content;" ); + $c->log->debug( "rpc_https_call: host=$cfg->{host}; port=$cfg->{port}; path=$cfg->{path}; query_string=$cfg->{query_string}; content=$content;" ); #$c->log->debug( Dumper($cfg->{headers}) ); my( $page, $response_code, %reply_headers, $response_value ); eval { @@ -64,9 +64,9 @@ sub rpc_https_call{ ( $page, $response_code, %reply_headers ) = https_post({ 'host' => $cfg->{host}, 'port' => $cfg->{port}, - 'path' => $cfg->{path}, + 'path' => $cfg->{path}.($cfg->{query_string}//''), 'headers' => $cfg->{headers}, - 'Content-Type' => 'text/xml', + 'Content-Type' => $cfg->{content_type} // 'text/xml', 'content' => $content, },); alarm(0); @@ -91,6 +91,7 @@ sub parse_rpc_response_page{ my $parser = RPC::XML::ParserFactory->new(); return $parser->parse($page); } + sub parse_rpc_response{ my($self,$rpc_response) = @_; return $rpc_response->value->value; @@ -99,6 +100,7 @@ sub parse_rpc_response{ sub extract_response_description{ my($self,$response_value) = @_; + #polyycom version if(('HASH' eq ref $response_value) && $response_value->{faultString}){ return $response_value->{faultString}; } else { @@ -129,6 +131,7 @@ sub get_basic_authorization{ $authorization =~s/[ \s]//gis; return { 'Authorization' => 'Basic '.$authorization }; } + sub get_bootstrap_uri{ my ($self) = @_; my $uri = $self->params->{redirect_uri};