aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bin/telekinesis-client131
-rw-r--r--lib/Arctica/Telekinesis/Client.pm329
2 files changed, 460 insertions, 0 deletions
diff --git a/bin/telekinesis-client b/bin/telekinesis-client
new file mode 100644
index 0000000..4a65b9c
--- /dev/null
+++ b/bin/telekinesis-client
@@ -0,0 +1,131 @@
+#!/usr/bin/perl -T
+################################################################################
+# _____ _
+# |_ _| |_ ___
+# | | | ' \/ -_)
+# |_| |_||_\___|
+# _ _ ____ _ _
+# / \ _ __ ___| |_(_) ___ __ _ | _ \ _ __ ___ (_) ___ ___| |_
+# / _ \ | '__/ __| __| |/ __/ _` | | |_) | '__/ _ \| |/ _ \/ __| __|
+# / ___ \| | | (__| |_| | (_| (_| | | __/| | | (_) | | __/ (__| |_
+# /_/ \_\_| \___|\__|_|\___\__,_| |_| |_| \___// |\___|\___|\__|
+# |__/
+# The Arctica Modular Remote Computing Framework
+#
+################################################################################
+#
+# Copyright (C) 2015-2016 The Arctica Project
+# http://arctica-project.org/
+#
+# This code is dual licensed: strictly GPL-2 or AGPL-3+
+#
+# GPL-2
+# -----
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the
+# Free Software Foundation, Inc.,
+#
+# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# AGPL-3+
+# -------
+# This programm is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This programm is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# Copyright (C) 2015-2016 Guangzhou Nianguan Electronics Technology Co.Ltd.
+# <opensource@gznianguan.com>
+# Copyright (C) 2015-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>
+#
+################################################################################
+use strict;
+use Data::Dumper;
+use Arctica::Core::eventInit qw(genARandom BugOUT);
+use Arctica::Core::JABus::Socket;
+use Arctica::Telekinesis::Client;
+#use POSIX;daemonize();
+
+my $ACO = Arctica::Core::eventInit->new({
+ app_name=>'telekinesis-client',
+ app_class =>'telekinesis-core',
+ app_version=>'0.0.1.1'});
+
+my $TeKiClient = Arctica::Telekinesis::Core::Client->new($ACO);
+my $server_sock_id = $TeKiClient->get_tmp_servers_socket_id;
+
+
+$TeKiClient->{'socks'}{'local'} = Arctica::Core::JABus::Socket->new($ACO,{
+ type => "unix",
+ destination => "local",
+ is_server => 1,
+ handle_in_dispatch => {
+# csappreg => sub {$TeKiClient->csapp_reg(@_)},
+ appcom => \&my_Own_Sub2,
+ treg => sub {$TeKiClient->target_reg($_[0],$_[1]);},
+ qvdcmd => \&my_Own_Sub2,
+ },
+});
+
+$TeKiClient->{'socks'}{'remote'} = Arctica::Core::JABus::Socket->new($ACO,{
+ type => "unix",
+ destination => "local", # FIX ME (change to remote!!!)
+ is_client => 1,
+ connect_to => $server_sock_id,
+ handle_in_dispatch => {
+ csappreg => sub {$TeKiClient->csapp_reg(@_)},
+ srvcneg => sub {$TeKiClient->c2s_service_neg(@_)},
+ appctrl => \&teki_client2s_appctrl,
+ },
+ hooks => {
+ on_ready => sub {$TeKiClient->init_c2s_service_neg;},
+ on_client_errhup => sub {print "\tLOST CONN!\n"},
+ },
+
+});
+
+
+sub teki_client2s_appctrl {
+ my $app_id = $_[0]->{'appid'};
+ my $ctrldata = $_[0]->{'ctrldata'};
+# print "APPCTRL: $app_id",Dumper($ctrldata);
+ if ($ctrldata->{'action'} eq "app_init") {
+# print "YAY APPARAPPARAPPAPA INIT LA!\n";
+ $TeKiClient->app_init_win_and_targets($app_id,$ctrldata);
+ } elsif ($ctrldata->{'action'} eq "state_change") {
+ $TeKiClient->target_state_change($app_id,$ctrldata);
+ }else {
+ warn("Unknown 'action': '$ctrldata->{'action'}'");
+ }
+}
+
+$ACO->{'Glib'}{'MainLoop'}->run;
+
+
+
+sub my_Own_Sub1 {
+
+}
+
+sub my_Own_Sub2 {
+
+}
diff --git a/lib/Arctica/Telekinesis/Client.pm b/lib/Arctica/Telekinesis/Client.pm
new file mode 100644
index 0000000..5d7cc04
--- /dev/null
+++ b/lib/Arctica/Telekinesis/Client.pm
@@ -0,0 +1,329 @@
+################################################################################
+# _____ _
+# |_ _| |_ ___
+# | | | ' \/ -_)
+# |_| |_||_\___|
+# _ _ ____ _ _
+# / \ _ __ ___| |_(_) ___ __ _ | _ \ _ __ ___ (_) ___ ___| |_
+# / _ \ | '__/ __| __| |/ __/ _` | | |_) | '__/ _ \| |/ _ \/ __| __|
+# / ___ \| | | (__| |_| | (_| (_| | | __/| | | (_) | | __/ (__| |_
+# /_/ \_\_| \___|\__|_|\___\__,_| |_| |_| \___// |\___|\___|\__|
+# |__/
+# The Arctica Modular Remote Computing Framework
+#
+################################################################################
+#
+# Copyright (C) 2015-2016 The Arctica Project
+# http://arctica-project.org/
+#
+# This code is dual licensed: strictly GPL-2 or AGPL-3+
+#
+# GPL-2
+# -----
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the
+# Free Software Foundation, Inc.,
+#
+# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# AGPL-3+
+# -------
+# This programm is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This programm is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# Copyright (C) 2015-2016 Guangzhou Nianguan Electronics Technology Co.Ltd.
+# <opensource@gznianguan.com>
+# Copyright (C) 2015-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>
+#
+################################################################################
+package Arctica::Telekinesis::Client;
+use strict;
+use Exporter qw(import);
+use Data::Dumper;
+use Arctica::Core::eventInit qw( genARandom BugOUT );
+# Be very selective about what (if any) gets exported by default:
+our @EXPORT = qw();
+# And be mindfull of what we lett the caller request here too:
+our @EXPORT_OK = qw();
+
+my $arctica_core_object;
+
+sub new {
+ BugOUT(9,"TeKi Client new->ENTER");
+ my $class_name = $_[0];# Be EXPLICIT!! DON'T SHIFT OR "@_";
+ $arctica_core_object = $_[1];
+ my $the_tmpdir = $arctica_core_object->{'a_dirs'}{'tmp_adir'};
+ my $teki_tmpdir = "$the_tmpdir/teki";
+ unless (-d $teki_tmpdir) {
+ mkdir($teki_tmpdir) or die("TeKi Client unable to create TMP dir $teki_tmpdir ($!)");
+ }
+ my $self = {
+ tmpdir => $teki_tmpdir,
+ isArctica => 1, # Declare that this is a Arctica "something"
+ aobject_name => "Telekinesis_Client",
+ available_services => {
+ multimedia => 1,
+ },
+ };
+# $self->{'session_id'} = genARandom('id');
+ $self->{'state'}{'active'} = 0;
+ bless($self, $class_name);
+ $arctica_core_object->{'aobj'}{'Telekinesis_Client'} = \$self;
+
+ BugOUT(9,"TeKi Client new->DONE");
+ return $self;
+}
+
+sub csapp_reg {
+ my $self = $_[0];
+ print "CSAPPREG:\t$_[1]\n",Dumper(@_),"\n";
+ my $app_id = $_[1];
+ $self->{'running_apps'}{$app_id}{'state'} = 1;
+ $self->{'socks'}{'remote'}->client_send('appinit',$app_id)
+}
+
+sub app_init_win_and_targets {
+ my $self = $_[0];
+ my $app_id = $_[1];
+ my $init_data = $_[2];
+ if ($self->{'running_apps'}{$app_id}) {
+# print "DUMP YOUR RUMP:\t$app_id\t\n",Dumper($init_data);
+ if ($init_data->{'windows'}) {
+ foreach my $wid (sort keys $init_data->{'windows'}) {
+ print "WINDOW:\t$wid\t\n",#
+ $self->{'running_apps'}{$app_id}{'windows'}{$wid} = $init_data->{'windows'}{$wid};
+ }
+ }
+ if ($init_data->{'targets'}) {
+ foreach my $ttid (sort keys $init_data->{'targets'}) {
+ print "TARGETS:\t$ttid\t\n",Dumper($init_data->{'targets'}{$ttid});
+ $self->{'running_apps'}{$app_id}{'targets'}{$ttid} = $init_data->{'targets'}{$ttid};
+ if ($self->{'running_apps'}{$app_id}{'targets'}{$ttid}{'window'}) {
+ if ($self->{'running_apps'}{$app_id}{'windows'}{$self->{'running_apps'}{$app_id}{'targets'}{$ttid}{'window'}}) {
+ $self->{'running_apps'}{$app_id}{'windows'}{$self->{'running_apps'}{$app_id}{'targets'}{$ttid}{'window'}}{'targets'}{$ttid} = 1;
+ }
+ }
+ $self->target_spawn($app_id,$ttid);
+ }
+ }
+ }
+}
+
+
+
+sub target_spawn {
+ my $self = $_[0];
+ my $app_id = $_[1];
+ my $ttid = $_[2];
+ if ($app_id =~ /^([a-zA-Z0-9\_\-]*)$/) {
+ $app_id = $1;
+ } else {
+ die("!!!");
+ }
+ if ($ttid =~ /^([a-zA-Z0-9\_\-]*)$/) {
+ $ttid = $1;
+ } else {
+ die("!!!");
+ }
+
+ print "Spawning target:\t$app_id\n$ttid\n";
+ if ($self->{'running_apps'}{$app_id}{'targets'}{$ttid}{'service'} eq 'multimedia') {
+# obviously want to do this in a more elegant and generic fashion! (but Mother::Forker is a bit overkill here since we're going to chitchat on the j.buz)
+#print "<<<<<<<<<<<<<SPAWN>>>>>>>>>>>>>>>>\n";
+# my $pid = open(my $fh,"|-",'./forkedmmoverlay.pl',$app_id,$ttid,$self->{'socks'}{'local'}{'_socket_id'});
+ system("forkedmmoverlay.pl $app_id $ttid $self->{'socks'}{'local'}{'_socket_id'} &");
+ } else {
+ warn("Unknown service $self->{'running_apps'}{$app_id}{'targets'}{$ttid}{'service'}");
+ }
+}
+
+
+sub target_reg {
+ my $self = $_[0];
+ my $sclient_id = $_[2];
+ my $data = $_[1];
+ if ($data->{'app_id'} and $data->{'ttid'}) {
+ warn "HELLO $sclient_id";
+ if ($self->{'running_apps'}{$data->{'app_id'}}{'targets'}{$data->{'ttid'}}) {
+ $self->{'running_apps'}{$data->{'app_id'}}{'targets'}{$data->{'ttid'}}{'scli_id'} = $sclient_id;
+ }
+ } else {
+ die("WTF");
+ }
+}
+
+sub target_state_change {
+ my $self = $_[0];
+ my $app_id = $_[1];
+ my $data = $_[2];
+ my %ch_targets;
+
+ if ($self->{'running_apps'}{$app_id}) {
+ if ($data->{'data'}{'w'}) {
+ print "DATA/W:\n";
+ foreach my $wid (keys $data->{'data'}{'w'}) {
+ print "\t$wid\n";
+ if ($data->{'data'}{'w'}{$wid} and $self->{'running_apps'}{$app_id}{'windows'}{$wid}) {
+ print "\t\tDEEPER 1\n";
+ foreach my $key (keys $data->{'data'}{'w'}{$wid}) {
+ print "\t\t\tDEEPER 2:\t$key\n";
+ if ($data->{'data'}{'w'}{$wid}{$key} ne $self->{'running_apps'}{$app_id}{'windows'}{$wid}{'state'}{$key}) {
+ print "\t\t\t\tD3:\t[$data->{'data'}{'w'}{$wid}{$key}]\t[$self->{'running_apps'}{$app_id}{'windows'}{$wid}{'state'}{$key}]\n";
+ $self->{'running_apps'}{$app_id}{'windows'}{$wid}{'state'}{$key} = $data->{'data'}{'w'}{$wid}{$key};
+ }
+ }
+# $self->{'running_apps'}{$app_id}{'windows'}{$wid}{'targets'}
+ if ($self->{'running_apps'}{$app_id}{'windows'}{$wid}{'targets'}) {
+ foreach my $ttid (keys $self->{'running_apps'}{$app_id}{'windows'}{$wid}{'targets'}) {
+ $ch_targets{$ttid} = 1;
+ print "\t\t\t\t\tWCHT:$ttid\n";
+ }
+ }
+ }
+ }
+ }
+
+ if ($data->{'data'}{'t'}) {
+ print "DATA/T:\n";
+ foreach my $ttid (keys $data->{'data'}{'t'}) {
+ print "\t$ttid\n";
+ if ($data->{'data'}{'t'}{$ttid} and $self->{'running_apps'}{$app_id}{'targets'}{$ttid}) {
+ print "\t\tDEEPER 1\n";
+ foreach my $key (keys $data->{'data'}{'t'}{$ttid}) {
+ print "\t\t\tDEEPER 2:\t$key\n";
+ if ($data->{'data'}{'t'}{$ttid}{$key} ne $self->{'running_apps'}{$app_id}{'targets'}{$ttid}{'state'}{$key}) {
+ print "\t\t\t\tD3:\t[$data->{'data'}{'t'}{$ttid}{$key}]\t[$self->{'running_apps'}{$app_id}{'targets'}{$ttid}{'state'}{$key}]\n";
+ $self->{'running_apps'}{$app_id}{'targets'}{$ttid}{'state'}{$key} = $data->{'data'}{'t'}{$ttid}{$key};
+ }
+ $ch_targets{$ttid} = 1;
+ print "\t\t\t\t\tTCHT:$ttid\n";
+ }
+ }
+ }
+ }
+ }
+
+ foreach my $ttid (keys %ch_targets) {
+ $self->target_send_state_changes($app_id,$ttid);
+ }
+# print "STATE CHANGE!!!!\n",Dumper(%ch_targets);
+}
+
+sub target_send_state_changes {
+ my $self = $_[0];
+ my $app_id = $_[1];
+ my $ttid = $_[2];
+ if ($self->{'running_apps'}{$app_id}{'windows'}{$self->{'running_apps'}{$app_id}{'targets'}{$ttid}{'window'}}{'state'} and
+ $self->{'running_apps'}{$app_id}{'targets'}{$ttid}{'state'})
+ {
+ print "WHAT THE!!:\n",Dumper($self->{'running_apps'}{$app_id}{'windows'}{$self->{'running_apps'}{$app_id}{'targets'}{$ttid}{'window'}}{'state'});
+# my %ws = $self->{'running_apps'}{$app_id}{'windows'}{$self->{'running_apps'}{$app_id}{'targets'}{$ttid}{'window'}}{'state'};
+# my $ts = $self->{'running_apps'}{$app_id}{'targets'}{$ttid}{'state'};
+
+ my $apx = ($self->{'running_apps'}{$app_id}{'windows'}{$self->{'running_apps'}{$app_id}{'targets'}{$ttid}{'window'}}{'state'}{'of_x'}
+ + $self->{'running_apps'}{$app_id}{'windows'}{$self->{'running_apps'}{$app_id}{'targets'}{$ttid}{'window'}}{'state'}{'x'}
+ + $self->{'running_apps'}{$app_id}{'targets'}{$ttid}{'state'}{'x'});
+ my $apy = ($self->{'running_apps'}{$app_id}{'windows'}{$self->{'running_apps'}{$app_id}{'targets'}{$ttid}{'window'}}{'state'}{'of_y'}
+ + $self->{'running_apps'}{$app_id}{'windows'}{$self->{'running_apps'}{$app_id}{'targets'}{$ttid}{'window'}}{'state'}{'y'}
+ + $self->{'running_apps'}{$app_id}{'targets'}{$ttid}{'state'}{'y'});
+
+ my $visible = 0;
+ if (($self->{'running_apps'}{$app_id}{'targets'}{$ttid}{'state'}{'viz'} eq 1) and ($self->{'running_apps'}{$app_id}{'windows'}{$self->{'running_apps'}{$app_id}{'targets'}{$ttid}{'window'}}{'state'}{'map'} eq 1)) {
+ $visible = 1;
+ }
+# my $apy = 100;#($ws->{'of_y'}+$ws->{'os_y'}+$ts->{'y'});
+# print "SEND\n\tX:\t$ws->{'of_x'}+$ws->{'os_x'}+$ts->{'x'} ($apx)\n\tY:$ws->{'of_y'}+$ws->{'os_y'}+$ts->{'y'} $apy\n";
+ if ($self->{'running_apps'}{$app_id}{'targets'}{$ttid}{'scli_id'}) {
+ $self->{'socks'}{'local'}->server_send($self->{'running_apps'}{$app_id}{'targets'}{$ttid}{'scli_id'},'chtstate',{
+ visible => $visible,
+ apy => $apy,apx => $apx,
+ h => $self->{'running_apps'}{$app_id}{'targets'}{$ttid}{'state'}{'h'},
+ w => $self->{'running_apps'}{$app_id}{'targets'}{$ttid}{'state'}{'w'},
+ });
+ }
+ }
+}
+
+################################################################################
+# Stuff that will eventually be replaced:
+
+
+sub init_c2s_service_neg {
+ my $self = $_[0];
+################################################################################
+# This is just a "dummy" place holder for the real negotiation function
+################################################################################
+# In step one we tell the server what services we have....
+# probably with some more info like... versions etc....
+ BugOUT(9,"Service Negotiation Step 0");
+ $self->{'socks'}{'remote'}->client_send('srvcneg',{
+ step => 1,
+ services => {
+ multimedia => 1,
+ }
+ })
+}
+
+
+sub c2s_service_neg {
+ my $self = $_[0];
+################################################################################
+# This is just a "dummy" place holder for the real negotiation function
+################################################################################
+ my $jdata = $_[1];
+ print "SRVCNEG:\t",Dumper($jdata),"\n";
+ if ($jdata->{'step'} eq 2) {
+# Ok so here we're beign told what the server have and if we are newer version than server
+# we need to check compatibility...
+# Send server a final list of services we'll be able to provide.
+ BugOUT(9,"Service Negotiation Step 2");
+ $self->{'socks'}{'remote'}->client_send('srvcneg',{
+ step => 3,
+ services => {
+ multimedia => 1,
+ }
+ })
+ }
+}
+
+
+sub get_tmp_servers_socket_id {
+ my $self = $_[0];
+ if (-f "$self->{'tmpdir'}/server_sockets.info") {
+ open(SIF,"$self->{'tmpdir'}/server_sockets.info");
+ my (undef,$remote_line) = <SIF>;
+ close(SIF);
+ $remote_line =~ s/[\n\s]//g;
+ if ($remote_line =~ /^remote\:([0-9a-zA-Z]*)$/) {
+ my $sock_id = $1;
+ return $sock_id;
+ } else {
+ die("TOTAL FAILURE! BUHUHUHHUUUUUUUUUUU!");
+ }
+ } else {
+ die("TOTAL FAILURE! BUHUHUHHUUUUUUUUUUU!");
+ }
+}
+
+1;