Adding RemoteDesktop client. It wraps a port forwarding ssh call to provide
security and compression for the session. This allows to keep these layers separate from the actual protocol. This needs to be run from the command line, as it will request ssh auth there. After connecting it will export the needed env variable and run the specified shell (Terminal by default) on the remote host to make it connect to the local client app. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33418 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
68667bf48a
commit
b3901807e8
@ -42,6 +42,7 @@ HaikuSubInclude poorman ;
|
||||
HaikuSubInclude powerstatus ;
|
||||
HaikuSubInclude processcontroller ;
|
||||
HaikuSubInclude pulse ;
|
||||
HaikuSubInclude remotedesktop ;
|
||||
HaikuSubInclude resedit ;
|
||||
HaikuSubInclude screenshot ;
|
||||
HaikuSubInclude showimage ;
|
||||
|
25
src/apps/remotedesktop/Jamfile
Normal file
25
src/apps/remotedesktop/Jamfile
Normal file
@ -0,0 +1,25 @@
|
||||
SubDir HAIKU_TOP src apps remotedesktop ;
|
||||
|
||||
local defines = [ FDefines CLIENT_COMPILE ] ;
|
||||
local serverDir = [ FDirName $(HAIKU_TOP) src servers app drawing remote ] ;
|
||||
|
||||
SubDirC++Flags $(defines) ;
|
||||
|
||||
UsePrivateHeaders shared ;
|
||||
UseHeaders $(serverDir) ;
|
||||
|
||||
Application RemoteDesktop :
|
||||
RemoteDesktop.cpp
|
||||
RemoteMessage.cpp
|
||||
RemoteView.cpp
|
||||
|
||||
NetReceiver.cpp
|
||||
NetSender.cpp
|
||||
StreamingRingBuffer.cpp
|
||||
|
||||
: be bnetapi $(TARGET_LIBSUPC++)
|
||||
: RemoteDesktop.rdef
|
||||
;
|
||||
|
||||
SEARCH on [ FGristFiles NetReceiver.cpp NetSender.cpp RemoteMessage.cpp
|
||||
StreamingRingBuffer.cpp ] = $(serverDir) ;
|
176
src/apps/remotedesktop/RemoteDesktop.cpp
Normal file
176
src/apps/remotedesktop/RemoteDesktop.cpp
Normal file
@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright 2009, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <mmlr@mlotz.ch>
|
||||
*/
|
||||
|
||||
#include <Application.h>
|
||||
#include <Screen.h>
|
||||
#include <Window.h>
|
||||
|
||||
#include "RemoteView.h"
|
||||
|
||||
#include <new>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
void
|
||||
print_usage(const char *app)
|
||||
{
|
||||
printf("usage:\t%s --listenOnly [-p <listenPort>]\n", app);
|
||||
printf("\t%s <user@host> [-p <listenPort>] [-s <sshPort>] [-c <command>]\n",
|
||||
app);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 2) {
|
||||
print_usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool listenOnly = false;
|
||||
uint32 listenPort = 10900;
|
||||
uint32 sshPort = 22;
|
||||
const char *command = "/system/apps/Terminal";
|
||||
|
||||
for (int32 i = 2; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-p") == 0) {
|
||||
if (argc < i + 1 || sscanf(argv[i + 1], "%lu", &listenPort) != 1) {
|
||||
print_usage(argv[0]);
|
||||
return 2;
|
||||
}
|
||||
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(argv[i], "-s") == 0) {
|
||||
if (argc < i + 1 || sscanf(argv[i + 1], "%lu", &sshPort) != 1) {
|
||||
print_usage(argv[0]);
|
||||
return 2;
|
||||
}
|
||||
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(argv[i], "-c") == 0) {
|
||||
if (argc < i + 1) {
|
||||
print_usage(argv[0]);
|
||||
return 2;
|
||||
}
|
||||
|
||||
i++;
|
||||
command = argv[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(argv[i], "--listenOnly") == 0) {
|
||||
listenOnly = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
print_usage(argv[0]);
|
||||
return 2;
|
||||
}
|
||||
|
||||
pid_t sshPID = -1;
|
||||
if (!listenOnly) {
|
||||
char shellCommand[4096];
|
||||
snprintf(shellCommand, sizeof(shellCommand),
|
||||
"echo connected; export TARGET_SCREEN=localhost:%lu; %s\n",
|
||||
listenPort, command);
|
||||
|
||||
int pipes[4];
|
||||
if (pipe(&pipes[0]) != 0 || pipe(&pipes[2]) != 0) {
|
||||
printf("failed to create redirection pipes\n");
|
||||
return 3;
|
||||
}
|
||||
|
||||
sshPID = fork();
|
||||
if (sshPID < 0) {
|
||||
printf("failed to fork ssh process\n");
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (sshPID == 0) {
|
||||
// child code, redirect std* and execute ssh
|
||||
close(STDOUT_FILENO);
|
||||
close(STDIN_FILENO);
|
||||
dup2(pipes[1], STDOUT_FILENO);
|
||||
dup2(pipes[1], STDERR_FILENO);
|
||||
dup2(pipes[2], STDIN_FILENO);
|
||||
for (int32 i = 0; i < 4; i++)
|
||||
close(pipes[i]);
|
||||
|
||||
char localRedirect[50];
|
||||
sprintf(localRedirect, "localhost:%lu:localhost:%lu",
|
||||
listenPort + 1, listenPort + 1);
|
||||
|
||||
char remoteRedirect[50];
|
||||
sprintf(remoteRedirect, "localhost:%lu:localhost:%lu",
|
||||
listenPort, listenPort);
|
||||
|
||||
char portNumber[10];
|
||||
sprintf(portNumber, "%lu", sshPort);
|
||||
|
||||
int result = execl("ssh", "-C", "-L", localRedirect,
|
||||
"-R", remoteRedirect, "-p", portNumber, argv[1],
|
||||
shellCommand, NULL);
|
||||
|
||||
// we don't get here unless there was an error in executing
|
||||
printf("failed to execute ssh process in child\n");
|
||||
return result;
|
||||
} else {
|
||||
close(pipes[1]);
|
||||
close(pipes[2]);
|
||||
|
||||
char buffer[10];
|
||||
read(pipes[0], buffer, sizeof(buffer));
|
||||
// block until connected/error message from ssh
|
||||
}
|
||||
}
|
||||
|
||||
BApplication app("application/x-vnd.Haiku-RemoteDesktop");
|
||||
BScreen screen;
|
||||
BWindow *window = new(std::nothrow) BWindow(screen.Frame(), "RemoteDesktop",
|
||||
B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE);
|
||||
|
||||
if (window == NULL) {
|
||||
printf("no memory to allocate window\n");
|
||||
return 4;
|
||||
}
|
||||
|
||||
RemoteView *view = new(std::nothrow) RemoteView(window->Bounds(),
|
||||
listenPort);
|
||||
if (view == NULL) {
|
||||
printf("no memory to allocate remote view\n");
|
||||
return 4;
|
||||
}
|
||||
|
||||
status_t init = view->InitCheck();
|
||||
if (init != B_OK) {
|
||||
printf("initialization of remote view failed: %s\n", strerror(init));
|
||||
delete view;
|
||||
return 5;
|
||||
}
|
||||
|
||||
window->AddChild(view);
|
||||
view->MakeFocus();
|
||||
window->Show();
|
||||
app.Run();
|
||||
|
||||
if (sshPID >= 0)
|
||||
kill(sshPID, SIGINT);
|
||||
|
||||
return 0;
|
||||
}
|
15
src/apps/remotedesktop/RemoteDesktop.rdef
Normal file
15
src/apps/remotedesktop/RemoteDesktop.rdef
Normal file
@ -0,0 +1,15 @@
|
||||
resource app_signature "application/x-vnd.Haiku-RemoteDesktop";
|
||||
|
||||
resource app_version {
|
||||
major = 0,
|
||||
middle = 1,
|
||||
minor = 0,
|
||||
|
||||
variety = B_APPV_ALPHA,
|
||||
internal = 0,
|
||||
|
||||
short_info = "RemoteDesktop",
|
||||
long_info = "RemoteDesktop ©2009 Haiku, Inc."
|
||||
};
|
||||
|
||||
resource app_flags B_MULTIPLE_LAUNCH;
|
1249
src/apps/remotedesktop/RemoteView.cpp
Normal file
1249
src/apps/remotedesktop/RemoteView.cpp
Normal file
File diff suppressed because it is too large
Load Diff
86
src/apps/remotedesktop/RemoteView.h
Normal file
86
src/apps/remotedesktop/RemoteView.h
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2009, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <mmlr@mlotz.ch>
|
||||
*/
|
||||
#ifndef REMOTE_VIEW_H
|
||||
#define REMOTE_VIEW_H
|
||||
|
||||
#include <Cursor.h>
|
||||
#include <NetEndpoint.h>
|
||||
#include <ObjectList.h>
|
||||
#include <View.h>
|
||||
|
||||
class BBitmap;
|
||||
class NetReceiver;
|
||||
class NetSender;
|
||||
class StreamingRingBuffer;
|
||||
|
||||
struct engine_state;
|
||||
|
||||
class RemoteView : public BView {
|
||||
public:
|
||||
RemoteView(BRect frame, uint16 listenPort);
|
||||
virtual ~RemoteView();
|
||||
|
||||
status_t InitCheck();
|
||||
|
||||
virtual void AttachedToWindow();
|
||||
|
||||
virtual void Draw(BRect updateRect);
|
||||
|
||||
virtual void MouseMoved(BPoint where, uint32 code,
|
||||
const BMessage *dragMessage);
|
||||
virtual void MouseDown(BPoint where);
|
||||
virtual void MouseUp(BPoint where);
|
||||
|
||||
virtual void KeyDown(const char *bytes, int32 numBytes);
|
||||
virtual void KeyUp(const char *bytes, int32 numBytes);
|
||||
|
||||
virtual void MessageReceived(BMessage *message);
|
||||
|
||||
private:
|
||||
void _SendMouseMessage(uint16 code,
|
||||
BPoint where);
|
||||
void _SendKeyMessage(uint16 code,
|
||||
const char *bytes, int32 numBytes);
|
||||
|
||||
static int _StateCompareByKey(const uint32 *key,
|
||||
const engine_state *state);
|
||||
void _CreateState(uint32 token);
|
||||
void _DeleteState(uint32 token);
|
||||
engine_state * _FindState(uint32 token);
|
||||
|
||||
static int32 _DrawEntry(void *data);
|
||||
void _DrawThread();
|
||||
|
||||
BRect _BuildInvalidateRect(BPoint *points,
|
||||
int32 pointCount);
|
||||
|
||||
status_t fInitStatus;
|
||||
bool fIsConnected;
|
||||
|
||||
StreamingRingBuffer * fReceiveBuffer;
|
||||
StreamingRingBuffer * fSendBuffer;
|
||||
BNetEndpoint * fReceiveEndpoint;
|
||||
BNetEndpoint * fSendEndpoint;
|
||||
NetReceiver * fReceiver;
|
||||
NetSender * fSender;
|
||||
|
||||
bool fStopThread;
|
||||
thread_id fDrawThread;
|
||||
|
||||
BBitmap * fOffscreenBitmap;
|
||||
BView * fOffscreen;
|
||||
|
||||
BCursor fViewCursor;
|
||||
BBitmap * fCursorBitmap;
|
||||
BRect fCursorFrame;
|
||||
bool fCursorVisible;
|
||||
|
||||
BObjectList<engine_state> fStates;
|
||||
};
|
||||
|
||||
#endif // REMOTE_VIEW_H
|
Loading…
x
Reference in New Issue
Block a user