summaryrefslogtreecommitdiffstats
path: root/doc/devel/0300-pvs.tex
blob: 54fedd41e2653d326853d82f7fa03724ba592d24 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
\chapter{Aufbau und Funktionsweise des PVS}
\index{Aufbau} \index{Funktionsweise} \index{Konzept}

Der Pool Video Switch ist als verteilte Netzwerkapplikation angelegt, die sich aus einer speziellen Steuerkonsole und damit gesteuerten Clients zusammensetzt. Diese kommunizieren untereinander einerseits über ein spezielles Message-Protokoll, verwenden andererseits für bestimmte Aufgaben, wie die Übertragung von Bildinhalten oder Dateien weitere Protokolle wie VNC oder Multicast-IP.

\section{Einzelne Komponenten}
\index{Komponenten}
Die Steuerkonsole wird durch das Programm pvsmgr, das Client-Backend durch pvs und das Client-Frontend durch pvsgui repräsentiert.

\subsection{Zuordnung von Konsole und Clients}
\input{devel/0310-service-discovery}

\section{Überblick über Aktivitäten auf Clients}

\subsection{Projektion an Alle}
\index{Projektion}
Eine wichtige Eigenschaft des PVS ist die Verwaltung von Projektionen zwischen mehreren Clients. Eine Projektion ist hierbei das Anzeigen des Bildschirminhalts eines Clients - der sogenannten Source oder Quelle - auf einem oder mehreren anderen Clients - den Targets oder Zielen der Projektion.
Die für die Projektion benötigten Verbindungsdaten wie Passwort und IP werden von jedem Client bei der Anmeldung an der Steuerkonsole übermittelt und in einer Liste von PVSConnection Objekten in der Klasse \textit{PVSConnectionManager} gespeichert. Diese zentrale Verwaltung hat mehrere Vorteile:
\begin{itemize}
  \item Die Quelle einer Projektion muss keine Aktion ausführen und kann passiv bleiben.
  \item Redundanz der Daten wird verhindert, da diese auch in der Steuerkonsole zur Darstellung der Thumbnails benötigt werden.
  \item Das Nachrichtenaufkommen wird reduziert, da lediglich eine Nachricht bei der Anmeldung an der Steuerkonsole übermittelt wird.
\end{itemize}

Bei der Auswahl der Quelle und Ziele ist zu beachten, dass man für jede Projektion jeweils nur eine Quelle jedoch mehrere Ziele auswählen kann.
Quelle und Ziel müssen außerdem verschiedenen Kriterien genügen. 
\begin{itemize}
  \item Eine Quelle darf nicht gleichzeitig Ziel einer Projektion sein.
  \item Ein Ziel einer Projektion darf nicht Ziel einer anderen Projektion sein.
  \item Eine Quelle darf mehrfach als Quelle ausgewählt werden.
\end{itemize}
Diese Einschränkungen werden in der Steuerkonsole durchgesetzt, indem im Zielauswahldialog die Zielmenge eingeschränkt wird.
Siehe hierzu auch \ref{pvs-console-projection} Projektion.

Der Projektionsvorgang an sich besteht aus mehreren Teilen. Wird eine Projektion angefordert, wird überprüft, ob auf der Quelle ein VNC Server gestartet ist. Falls nicht, wird versucht, einen VNC Server zu starten. Ist dies erfolgreich, so sendet die Steuerkonsole das entsprechende Tripel (IP, Passwort und Port der Quelle) an alle ausgewählten Ziele. Clients, welche eine Projektionsaufforderung erhalten, verbinden sich dann mit den Verbindungsdaten zum VNC Server der Quelle. Um die Einstellbarkeit der Qualität einer Projektion zu ermöglichen, kann die Steuerkonsole einen von drei Qualitätswerten an die Zielclients übermitteln. Siehe hierzu auch \ref{pvs-console-quality} Qualitätsoptionen.


\subsection{Projektion eines Clients auf dem Beamer}
\index{Beamer}

Die Projektion eines Clients an den Beamer unterscheidet sich im Wesentlichen nicht von anderen Projektionen. Lediglich ist das Ziel der Projektion hierbei der Dozentenpc bzw. der PC, welcher an den Beamer angeschlossen ist. Eine spezielle Auszeichnung des Beamers erfolgt nicht. Die Anzahl der Ziele wird hierbei nicht beschränkt, da es wünschenswert sein kann, den auf dem Beamer dargestellten Bildschirminhalt auch gleichzeitig auf anderen Clients darzustellen.

\subsection{Chat- und Informationskanal}
\index{Chat}

Es gibt 2 Möglichkeiten um Kontakt mit den Clients aufzunehmen. Die erste ist über den Chat, wo Nachrichten sowohl über den offentlichen Kanal als
auch über einen privaten Kanäle verteilt werden können, und die zweite vom PVSManager aus über den Informationskanal.
Der Informationskanal ermöglich das Versenden von Nachrichten, die dringend zu lesen sind, an die Clients.
Im Gegenteil zum Chat erscheinen solche Nachrichten nicht im Chatfenster sondern in einem Pop-Up-Fenster und werden vom Bildschirm entfernt erst wenn man sie
als gelesen markiert durch das Drucken auf dem Knopf \textit{'OK'}.
\\
\\
\textbf{Behandlung der Nachrichten im Server}
\\
\\
Chat-Nachtichten werden von Server in der Klasse \texttt{PVSConnectionManager} mittels der Methode \texttt{onChat} behandelt. Dort wird aus der Nachrit den Empfänger
und den Absender ausglesen und die Nachricht an beide versendet. So gilt das Empfangen eine eigene Nachricht als Bestätigung, dass die Nachricht ordentlich vom Server
behandelt und versendet wurde. Das Gestalt von solchen Nachrichten sieht folgendermaßen aus

\begin{center}
 PVSMSG
\end{center}
\begin{center}
\begin{tabular}{|l | p{3cm} | p{3cm} | p{3cm}|}
\hline
Type & Ident & Msg & sndID\\
\hline
\texttt{PVSMESSAGE} & \texttt{<Username des Empfängers>} & \texttt{<<Username des Absenders>:<Die eigentliche nachrich>} & \texttt{<<Vom server zugewissene ID des Absenders>}\\
\end{tabular}
\end{center}

Informationsnachrichten werden ausschließlich vom PVSManager versendet.Dies geschiet in der Klasse \texttt{ConnectionList} mittels der Methode \texttt{on\_Message}.

\begin{center}
 PVSMSG
\end{center}
\begin{center}
\begin{tabular}{|l | l | p{6cm} | p{6cm}}
\hline
Type & Ident & Msg\\
\hline
\texttt{PVSMESSAGE} & \texttt{BROADCAST} & \texttt{<Die eigentliche nachrich>} \\
\end{tabular}
\end{center}

Informationnachrichten können außerdem einen oder mehrere Clients sperren, wenn sie den Ident \texttt{LOCKSTATION} enthalten. Sobald ein Client die Nachricht empfängt,
wird diese auf dem Bilschirm angezeigt und 10 Sekunden später wird der Client gesperrt.

Abgesehen von der  Behandlung der Nachrichten muss sich der Server darum kümmern, dass jeder verbunde Client über alle nötige Informationionen verfügt damit er
Nachrichten mit andren Clients austauschen kann. Dies wird folgendermaßen erledigt:
\begin{itemize}
 \item \textbf{Einfügen eines Clients:} um die Verwaltung von Clients kümmert sich die Klasse \texttt{PVSConnectionManager}, in der die Methode \texttt{onClientNew} für das Einfügen
von neuen Clients zuständigt ist. Sowald ein neuer Client in der Client-Liste des Servers eingefügt wird, wird an ihn die Liste aller im Server bereits angemeldete
Clients geschickt. Dazu dient die Methode \texttt{sendEventToClients}.

Bis hier ist der neue Client noch unbekannt für den Rest der Nutzer. Der neuer Client wird erst bekannt gegeben sobald er vom Server einen Benutzername
zugewissen bekommen hat. Da es sein kann, dass den Name, mit dem der neue Client sich beim Server anmelden wollte,
bereits vergeben ist und muss unter Umständen verändert werden. Diese Zuweisung findet in der Methode  \texttt{onLoginUsername} statt,
wo nicht nur alle andere Clients sondern auch der neue Client darüber informiert werden. Auch hier kümmert sich die Methoder \texttt{sendEventToClients}
ums Vesenden der entsprechenden Informationen.

 \item \textbf{Entfernen eines Clients:} das Entfernen von Clients wird von der Methode
\\
\texttt{onClientRemove} erledigt, wo analog wie
Oben alle Clients darüber informiert werden. 
\end{itemize}

Für dei Übermittlung solche Informationen werden Nachrichten mit folgenden Gestal benutzt

\begin{center}
 PVSMSG
\end{center}
\begin{center}
\begin{tabular}{|l | l | p{6cm} |}
\hline
Type & Ident & Msg\\
\hline
\texttt{PVSMESSAGE} & \texttt{<Befehl>} & \texttt{<Benutzername>:<IP-Adresse>} \\
\end{tabular}
\end{center}

Es gibt drei unterschiedliche Befehle, die welche Änderung in der localen Client-Liste der Clients vorgenommen werden soll angeben.
\begin{enumerate}
 \item \texttt{clientToAdd}
\item \texttt{clientToRemove}
\item \texttt{assignedName}
\end{enumerate}

Wie es bei Servern gewöhnt ist, werden alle relevante Ereignisse in Log-Dateien protokolliert. Ereignisse werden im Chat-Log mit folgendem
Befehl eingetragen

\begin{center}
\texttt{ConsoleLog writeChat(<Beschreibung des Ereignisses>)}
\end{center}

\textbf{Chat-Interface der Steuerkonsole}
\\
\\
So wie alle Clients ist der PVSManager auch ein Teilnehmer im Chat. Der PVSManager steht wie alle andere Teilnehmer auch in der Nutzer-Liste
jedes Chat-Fenster und kann ebenfalls über private Nachrichten direkt angesprochen werden. Die Arbeitsweise dieser Chat-Interface ist sehr simple.
Da sie sich im Server befindet, müssen einfach alle Ereignise (Nachrichten senden ist die einzige Ausnahme) von der Klasse \texttt{PVSConnectionManager}
an die Klasse \texttt{MainWindow} weitergegeben werden. Dies kümmert sich darum, alle Informationen zu verarbeiten und diesein der Chat-Fenster der
Steuerkonsole anzuzeigen.

Folgende Methoden der Klasse \texttt{MainWindow} ermöglichen das Anzeigen einer empfangenen Nachricht im Chat-Fenster der Steuerkonsole und Änderungen (Clients einfügen
und entfernen) in der sowohl im Chat-Fenster als auch in der Steuerkonsole angezeigten Client-Liste.
\\
\\
\texttt{receiveChatMsg(<Absender>, <Empfänger>, <Nachricht>)}
\\
\texttt{removeConnection(*pvsClient)}
\\
\texttt{addConnection(*pvsClient)}
\\
\\
Alle diese Methoden werden im Gegensatz von der Methode \texttt{sendChatMsg(PVSMsg myMsg)} von der Klasse \texttt{PVSConnectionManager} aus ausgeführt. Da alle durchs
Netz empfangene Nachrichten müssen an die GUI-Weitergegeben werden. Beim Versenden von Nachrichten funktioniert es genau umgekehrt. Die Nachricht wird
vom Nutzer in der GUI eingegeben und muss an die Klasse \texttt{PVSConnectionManager} weitergeleitet werden, damit diese ins Netz gesendet wird. Darum kümmert
sich die Methode in der Klasse \texttt{MainWindow}.
\\
\\
\texttt{MainWindow::sendChatMsg(PVSMsg myMsg)}
\\
\\
\textbf{Chat-Clients}
\\
\\
So weit haben wir die Funtionsweisen des Servers im Bezug auf dem Chat kennengelernt.
Nun wird erläutert wie die einzelnen Clients die Nachrichten bearbeiten.
\\
\\
Auf der Client-Seite in der Klasse \texttt{PVSConnectionServer} werden alle Nachrichten des PVS-Protokolls empfangen und gefiltert (Siehe Methode \texttt{handleClientMsg}).
Nachrichten mit dem Ident \texttt{PVSMESSAGE} werden durch den Dispatcher direkt an die Klasse \texttt{PVSChatClient} weitergeleitet, wo die Methode \texttt{receive} feststellen wird,
ob es sich dabei um eine Gespräch-Nachricht oder eine Befehl-Nachricht handelt. Um es feststellen zu können, wird aus der empfangenen Nachricht ein PVSChatMsg-Objekt
erzeugt (siehe Konstruktor) und mittels der Methode \texttt{isCommand} erfährt man ob es sich um einen Befehl handelt oder nicht.
Falls ja leitet der Dispatche die Nachricht an die Stelle \texttt{PVS::UpdateChatClients} sonst an die Stelle \texttt{PVS::chat\_receive}, wo die Änderungen in der Client-Liste
vorgenommen werden oder die Gespräch-Nachricht der GUI abgegeben wird.

\subsection{Multicast-Dateiversand}
\index{Dateiversand}\index{Multicast}

Der Multicast-Dateiversand geschieht über die Bibliothek \texttt{OpenPGM}\index{OpenPGM}
(\url{http://code.google.com/p/openpgm/}), die das ,,\textit{Pragmatic General Multicast}''-Protokoll\index{Pragmatic General Multicast}
(PGM)\index{PGM} implementiert.
Darin enthalten ist eine Implementierung der \textit{PGMCC}-Methode zur
Regulierung der Sendebandbreite.
Vorteil der Verwendung einer externen Bibliothek ist, 
dass die ,,schwierigen'' Probleme bei der Implementierung einer verlässlichen Datenstrom-orientierten
Multicast-Übertragung bereits von Netzwerkexperten gelöst wurden.

Die Bibliothek ist in das PVS-System über die interne Bibliothek \texttt{libpvsmcast}\index{libpvsmcast}
eingebunden (der Quellcode findet sich im Verzeichnis \texttt{src/net/mcast}).
Diese stellt mit der Klasse \texttt{McastPGMSocket}\index{Klasse!\texttt{McastPGMSocket}} einen
objektorientierten, ereignisgetriebenen Wrapper zu OpenPGM bereit.
Die Konfigurationsdaten, die zur Einrichtung einer PGM-Verbindung notwendig sind,
sind in der Klasse \texttt{McastConfiguration}\index{Klasse!\texttt{McastConfiguration}} verpackt.

Auf der nächsten Ebene wird der Versand einer Datei von den Klassen \texttt{McastSender}\index{Klasse!\texttt{McastSender}}
und \texttt{McastReceiver}\index{Klasse!\texttt{McastReceiver}} übernommen.
Diese brechen den Bytestrom der Datei in Pakete auf und formatieren diese wie in Tabelle \ref{tab:mcastpacket}
gezeigt.
\begin{table}
\begin{center}
\begin{tabular}{|l|l|l|}
\hline
\textbf{Format} & \textbf{Feld} & \textbf{Erläuterung} \\
\hline
\texttt{quint64} & \texttt{magic\_number} & = 0x0x6d60ad83825fb7f9 \\
\hline
\texttt{quint64} & \texttt{offset} & Position des Datenpaketes in der Datei \\
\hline
\texttt{QByteArray} & \texttt{data} & Daten \\
\hline
\texttt{quint64} & \texttt{checksum} & CRC16-CCITT der vorhergehenden Felder \\
\hline
\end{tabular}
\caption{Paketformat für Multicast-Dateiversand}\label{tab:mcastpacket}\index{Multicast!Paketformat}
\end{center}
\end{table}
Das Paketformat ist mit Hilfe der Qt-eigenen Klasse \texttt{QDataStream} implementiert.
Numerische Felder werden in Netzwerk-Bytereihenfolge übertragen.
Das Ende einer Übertragung wird markiert durch ein Paket, in dessen \texttt{offset}
alle bits gesetzt sind und dessen \texttt{data} die MD5-Prüfsumme der übertragenen Datei
enthält.

Zur Integration dieser -- prinzipiell von PVS unabhängigen -- Funktionalität
dienen die Klassen \texttt{PVSIncomingMulticastTransfer}\index{Klasse!\texttt{PVSIncomingMulticastTransfer}}
und \texttt{PVSOutgoingMulticastTransfer}\index{Klasse!{PVSOutgoingMulticastTransfer}}.
Diese sorgen hauptsächlich für die Konfiguration der Multicast-Funktionalität mit Hilfe der 
PVS-Konfiguration und das Generieren der richtigen Signale einerseits in Bezug auf die Benutzerschnittstelle,
sowie andererseits in Bezug zur Netzwerkkomponente des PVS-Systems.

Ein Client, der eine Datei per Multicast zu versenden wünscht, wählt zufällig einen Port und 
kündigt diesen mit der Nachricht MCASTFTANNOUNCE an.
Falls innerhalb einer festgesetzten Zeit (30 Sekunden) keine MCASTFTRETRY-Nachricht eintrifft,
beginnt die Übertragung.
Die Nachricht MCASTFTCONFIG dient zum Setzen netzwerkweiter Parameter von der Steuerkonsole aus.

\section{Fernsteuerung}

Die Fernsteuerung eines Clients erfolgt durch den clientseitigen Empfang von \texttt{PVSCOMMAND}-Nachrichten
mit dem Ident \texttt{INPUTEVENT}.
Dieser ist die Base64-kodierte Binärdarstellung eines Eingabeereignisses angehängt, das
clientseitig nachvollzogen werden soll.
\begin{table}
 \begin{tabular}{|l|l|p{4cm}|p{4cm}|}
  \hline
  \textbf{\texttt{type}} & \textbf{\texttt{code}} & \textbf{\texttt{value}} & \textbf{Beschreibung} \\
  \hline
  \multirow{2}{*}{\texttt{ET\_KEY}} & 
    \texttt{EC\_PRESS} & 
    \multirow{2}{4cm}{Auslösende Taste und gehaltene Modifikatortasten} & 
    Taste gedrückt \\
  \cline{2-2}\cline{4-4}
  &
    \texttt{EC\_RELEASE} &
    &
    Taste losgelassen\newline \\
  \hline
  \multirow{2}{*}{\texttt{ET\_BUTTON}} &
    \texttt{EC\_PRESS} &
    \multirow{2}{4cm}{Auslösende und
    gedrückte Maustasten} &
    Maustaste gedrückt \\
  \cline{2-2}\cline{4-4}
  &
    \texttt{EC\_RELEASE} &
    &
    Maustaste losgelassen \\
  \hline
  \texttt{ET\_POINTER} &
    --- &
    Absolute Koordinaten &
    Mauszeiger bewegt \\
  \hline
  \multirow{4}{*}{\texttt{ET\_SPECIAL}} &
    \texttt{EC\_REBOOT} &
    --- &
    Systemneustart \\
  \cline{2-4}
  &
    \texttt{EC\_KILL\_X} &
    --- &
    X-Server töten \\
  \cline{2-4}
  &
    \texttt{EC\_SYSRQ} &
    Kommando &
    Magic-SysRq-Taste \\
  \cline{2-4}
  &
    \texttt{EC\_SAY\_HELLO} &
    --- &
    Harmloses Kommando für Funktionstest \\
  \hline
 \end{tabular}
 \caption{Mögliche Eingabeereignisse\label{tab:input-events}\index{Eingabeereignis!\texttt{InputEvent}}}
\end{table}
Tabelle \ref{tab:input-events} zeigt die möglichen Eingabeereignisse.
Eingabeereignisse werden durch die PVS Input Library (libpvsinput) behandelt,
deren Funktion an dieser Stelle dargestellt werden soll.

\subsection{Behandlung eines Eingabeereignisses}
\index{Eingabeereignis!Behandlung}

Ein Eingabeereignis durchläuft die folgenden Stationen:
\begin{enumerate}
 \item Die Steuerkonsole generiert ein Eingabeereignis und übergibt dieses an die Netzwerktransportschicht.
 \item Der PVS-Client empfängt das Eingabeereignis und übergibt die Behandlung einer Instanz der
  Klasse \texttt{InputEventHandlerChain}\index{Klasse!\texttt{InputEventHandlerChain}}.
 \item Die Klasse \texttt{InputEventHandlerChain} arbeitet eine Liste von Instanzen der Klasse 
  \texttt{InputEventHandler}\index{Klasse!\texttt{InputEventHandler}} der Reihe nach ab, um zu sehen, ob eine dieser Instanzen
  das Ereignis bearbeiten kann.
 \item Falls die betrachtete Instanz das Ereignis bearbeiten kann, wird geprüft, ob der dafür
  nötige Sicherheitskontext vorhanden ist.
 \item Falls dies ebenfalls der Fall ist, wird die entsprechende Aktion in einer implementierung
  der abstrakten Methode \texttt{InputEventHandler::handle} ausgeführt und die weitere Bearbeitung
  beendet.
 \item Falls keiner der vorherigen Handler das Ereignis behandelt hat, wird es durch
  die Klasse \texttt{PrivilegedHandlerForwarder}\index{Klasse!\texttt{PrivilegedHandlerForwarder}} an den zusätzlichen Daemon \texttt{pvsprivinputd}
  weitergegeben.
 \item Der \texttt{pvsprivinputd}\index{pvsprivinputd} besitzt ebenfalls eine \texttt{InputEventHandlerChain}, die
  nach dem gleichen Muster bearbeitet wird.
  Falls hierbei kein passender Handler gefunden wird, wird das Ereignis in eine Logdatei geschrieben
  und die Bearbeitung aufgegeben.
\end{enumerate}
Ereignishandler sind implementiert für Maus- und Tastatureingaben unter Linux/X11 (mit Hilfe der XTest-Erweiterung),
sowie zur Simulation von Strg+Alt+Entf, Strg+Alt+Rück und Magic SysRq.

\subsection{Erweiterungen}

Weitere Eingabehandler lassen sich der libpvsinput hinzufügen.
Dazu muss eine Klasse bereitgestellt werden, die von der Template-Klasse
\texttt{InputEventHandler} erbt.
Diese akzeptiert eine variable Anzahl\footnote{%
  Bis zu 16, diese Zahl lässt sich jedoch durch Neugenerierung
  der Datei \texttt{src/input/detail/ typelist\_autogen.h} erhöhen. 
  Ein entsprechendes Programm ist im Quellcode zu finden.}
von Templateparametern, die verschiedene Aspekte der Eingabeereignisbehandlung konfigurieren.

Durch die Angabe eines Templateparameters \texttt{input\_policy::Match<\textit{typ}, \textit{code}, \textit{wert}>}\index{Klasse!\texttt{input\_policy::Match}},
wobei \textit{code} und \textit{wert} weggelassen werden können, wird spezifiziert,
dass der betreffende Handler nur für Eingabeereignisse mit den entsprechenden Feldwerten aufgerufen wird.
Wird kein solcher Parameter angegeben, wird der betreffende Handler niemals aufgerufen.
Mehrere \texttt{Match}-Parameter werden mittels logischem ODER verknüpft.

Ein Templateparameter der Form \texttt{input\_policy::Require<\textit{Merkmal\dots}>}\index{Klasse!\texttt{input\_policy::Require}}
gibt an, dass dieser Handler nur auf einem System lauffähig ist, das die entsprechenden \textit{Merkmale}
aufweist.
Eine Liste von Systemmerkmalen wird in der Datei \texttt{src/input/detail/systemTraits.h}
zentral verwaltet.
Hier lassen sich neue Merkmale mit Hilfe des Makros \texttt{DEFINE\_SYSTEM\_TRAIT} definieren
und mit Hilfe des Präprozessors zwischen den Zeilen \texttt{BEGIN\_SYSTEM\_TRAITS} und
\texttt{END\_SYSTEM\_TRAITS} einfügen.
Diese Vorgehensweise beschränkt die Nutzung des Präprozessors auf eine Datei.
Wird kein \texttt{Require}-Parameter angegeben, so wird der entsprechende Handler als
immer lauffähig eingestuft.
Mehrere \texttt{Require}-Parameter werden mittels logischem ODER verknüpft.

Weiterhin kann ein Templateparameter der Form \texttt{input\_policy::Security<\textit{Richtlinie}>}\index{Klasse!\texttt{input\_policy::Security}}
angegeben werden. Hierbei stehen für \textit{Richtlinie} die Klassen \texttt{input\_policy::AllowLocal\-OrPrivileged}
oder \texttt{input\_policy::AllowEverybody} zur Verfügung.
Hierdurch wird bestimmt, welche Sicherheitsanforderungen zur Ausführung des Handlers erfüllt sein
müssen.
Die Richtlinie \texttt{input\_policy::AllowLocalOrPrivileged} bestimmt, dass nur Benutzer,
deren Sitzung lokal ist, oder solche, die nach der Konfiguration des pvsprivinputd als privilegiert
gelten, die entsprechende Aktion aufrufen dürfen (hierbei geht es um den Benutzer, der den PVS-Client
ausführt, und nicht den Benutzer, der die Steuerkonsole bedient).
Die Richtlinie \texttt{input\_policy::AllowEverybody} erlaubt die Ausführung der Aktion ohne
besonderen Sicherheitskontext.
Neue Sicherheitsrichtlinien der Form \texttt{input\_policy::Security<\textit{T}>} lassen sich
nutzen, indem eine Klasse \textit{T} eingeführt wird, die eine Methode\\
\makebox[1cm]{}\texttt{static bool allow(InputEventContext const*)}\\
besitzt, an die die Entscheidung, ob eine Aktion zuzulassen ist, delegiert wird.

Der zu implementierende Eingabehandler braucht weiterhin eine Implementierung der abstrakten
Methode\\
\makebox[1cm]{}\texttt{virtual void handle(InputEvent const\&, InputEventContext const*)},\\
in der die entsprechende Aktion ausgeführt wird.

Die Aufnahme des neuen Handlers in die Liste der abzuarbeitenden Handle erfolgt,
je nachdem ob erweiterte Berechtigungen zur Bearbeitung notwendig sind,
in einer der Dateien \texttt{privilegedHandlerChain.cpp} oder \texttt{unprivilegedHandler\-Chain.cpp}
in \texttt{src/input}, wo dem Kettenaufruf eine Zeile der Form\\
\makebox[1cm]{}\texttt{.add<\textit{Handler}>()}\\
hinzugefügt wird.
Die Verwendung des Präprozessors zum Ausschluss von Handlern, die auf dem
Zielsystem nicht lauffähig sind, ist an dieser Stelle nicht notwendig und wird durch die
\texttt{Require}-Richtlinie umgesetzt.
Notwendig ist lediglich, die Übersetzung des Handlers auf inkompatiblen Systemen zu verhindern.
Dies kann mit Hilfe des Build-Systems oder durch die Klammerung der gesamten Übersetzungseinheit
in Präprozessorbedingungen geschehen.

Eine API-Referenz zur libpvsinput (Stand: 4.~November~2010) findet sich im Projektwiki
unter \url{http://lab.openslx.org/projects/pvs/wiki/RemoteKeyMouse}.

\section{Prozesse fernsteuern}
\index{Prozesse fernsteuern}

\subsection{Prozesse starten}
\index{Prozesse!starten} \index{starten} 
Das ferngesteuerte Starten von Prozessen funktioniert durch den einfachen Versand eines PVSCOMMAND mit dem dem Ident STARTPROCESS an den Client, der Inhalt des PVSCOMMAND ist in diesem Fall ein durch den Dozenten angegebener Prozess. Der Client versucht diesen Prozess lokal zu starten.\\
Sollte hierbei ein Fehler auftreten schickt der Client dem Manager ein PVSCOMMAND mit Ident PROCESSES, der Inhalt besteht dann aus der Nachricht START ERROR und einer Zahl, die die Art des Fehlers angibt.\\
Die Fehlermeldung wird zusammen mit der Information über die Art des Fehlers (Fehlender Prozess/nicht genug Rechte, Crash, Timeout, Read Error, Write Error, Unbekannter Fehler) im Log angezeigt.\\
Es ist möglich, dass der Dozent sich eine Liste von Prozessen, die er nutzen möchte erstellt und im PVSManager abspeichert, dies geht über den Prozesse starten-Dialog, er zeigt eine Liste an, die die beliebig erweiterbar ist. Einmal getätigte Änderungen werden in der Datei \textit{pvsmgr.conf} abgespeichert. Die Konfigurationsdatei ist nach folgendem Beispiel aufgebaut:
\begin{verbatim}
[RemoteProcessesList]
size=2
1\command=oowriter
1\description=OpenOffice Writer
2\command=oocalc
2\description=OpenOffice Calc
\end{verbatim}
Hier ist zu beachten, dass size mit 1 beginnt.\\ 

\subsection{Prozesse beenden}
\index{Prozesse!beenden} \index{beenden} 
Das ferngesteuerte Beenden von Prozessen funktioniert analog zum Starten durch den Versand eines PVSCOMMAND mit dem dem Ident KILLPROCESS an den Client, hier gibt der Inhalt die lokale PID, des zu beendenden Prozesses an.\\
Auch hier schickt der Client dem Manager bei einem Fehler ein PVSCOMMAND mit Ident PROCESSES, der Inhalt besteht dann aus der Nachricht STOP ERROR und einer Zahl, die die Art des Fehlers angibt.\\
Auch hier wird die Fehlermeldung zusammen mit der Information über die Art des Fehlers (Fehlender Prozess/nicht genug Rechte, Crash, Timeout, Read Error, Write Error, Unbekannter Fehler) im Log angezeigt.

\subsection{Prozesseliste anzeigen}
\index{Prozesse!anzeigen} \index{anzeigen} 
Hier sendet der Manager dem Client ein PVSCOMMAND mit Ident SHOWPROCESSES, der Inhalt der Nachricht gibt Prozesse an die herausgefiltert werden sollen. Das PVSCOMMAND mit Ident SHOW und Inhalt clear lässt den Client seine Prozessliste leeren.\\
Anschließend wird der Inhalt von \textit{/proc/} auf dem Client ausgelesen, ist kein Inhalt vorhanden wird ein PVSCOMMAND mit Ident PROCESSES und Nachricht SHOW ERROR gesendet. Sonst werden sämtliche Ordner in \textit{/proc/}  die nur aus Zahlen bestehen durchlaufen. Es wird die Datei \textit{status}  ausgelesen um den Namen des Prozesses und die UID des Besitzers zu erhalten. Ist die UID nicht identisch mit der UID des Client wird dieser Prozess verworfen, somit ist sichergestellt, dass nur Prozesse angezeigt werden, bei denen auch tatsächlich die Berechtigung vorhanden ist sie zu beenden. Ist dies der Fall wird außerdem noch ein Teil der Datei \textit{cmdline} ausgelesen. Der Client sendet daraufhin ein PVSCOMMAND mit Ident SHOW und Inhalt PID<\#>Name<\#>cmdline und füllt somit seinen Prozessvektor auf. Ist \textit{/proc} komplett abgearbeitet wird ein PVSCOMMAND mit Ident SHOW und Inhalt finished abgesendet, dies löst ein erneuetes lesen der Prozessliste Managerseitig aus:\\
Hier wird zu beginn die Prozessliste des Client gelöscht und der Prozessvektor des Clients gelesen. Für jeden Eintrag der Art PID<\#>Name<\#>cmdline wird eine neue Zeile in der Prozessliste geschrieben und PID, Name und cmdline in die jeweiligen Zellen geschrieben.\\
Prozesse die aus der Liste herausgefiltert werden werden auch in der Datei \textit{pvsmgr.conf} abgespeichert. Eine mögliche Konfigurationsdatei sieht etwa so aus:
\begin{verbatim}
[RemoteProcessesList]
filter=pvs pvsgui pvsmgr
\end{verbatim}

\section{Netzwerkkommunikation}
\index{Netzwerkkommunikation}

\subsection{PVS-Protokoll}
\index{Protokoll!PVS} \index{Protokoll} 
Im Zuge der Entwicklung des PVS wurde ein sehr einfaches Messagingprotokoll entwickelt.
Die Nachrichten bzw. Messages bestehen dabei aus Header, Nachrichtentyp, Ident und dem eigentlichen Nachrichtentext. Die einzelnen Nachrichtenteile, welche bis auf den Header selbst definiert werden können, werden verknüpft und versendet. Es sind schon Nachrichtentypen vordefiniert, welche sich nur durch unterschiedliche Dispatcher unterscheiden.
Bereits vorhandene Typen sind COMMAND, LOGIN, MESSAGE und UNKNOWN. Die Dispatcher (\_commandDispatcher, \_loginDispatcher und \_chatDispatcher) befinden sich im Client in der Klasse \texttt{ServerConnection}, in der Steuerkonsole in der Klasse \texttt{ClientConnection} bzw. \texttt{ListenServer}. Ein Ident wie z.B. Username, Befehl oder Beschreibung des Nachrichteninhalts dient zur Unterscheidung verschiedener Nachrichten mit demselben Nachrichtentyp, wobei die Nachricht dann den dem Ident entsprechenden Nachrichtentext enthält.
Um eine Funktion zur Behandlung einer bestimmten Nachricht zu definieren, wird diese Funktion als Handler mit dem entsprechenden Dispatcher verknüpft. Im PVS-Client beispielsweise befindet sich der Dispatcher für Nachrichten vom Typ Command in der Klasse \texttt{pvsServerConnection}, daher wird in der Klasse \texttt{pvs} die Funktion \texttt{void PVS::onCommand(PVSMsg cmdMessage)} wie folgt als Handler registriert: 
\texttt{\_pvsServerConnection->addCommandHandler("*", this, \&PVS::onCommand)}. Erhält nun der Client eine Nachricht vom Typ COMMAND, so wird die Funktion onCommand mit dem entsprechenden Nachrichtenobjekt aufgerufen. Auf die eigentliche Nachricht kann dann über die Methoden \texttt{getIdent()} und \texttt{getMessage()} des Objektes zugegriffen werden. 

\subsection{PVS-Messages}
\index{Message!PVS} \index{Message}
In Tabelle \ref{tab:messagelist} sind die Messages, die zwischen den einzelnen PVS Komponenenten ausgetauscht werden, aufgelistet.
Der Nachrichtentyp gibt dabei an, welcher Dispatcher die Nachricht behandelt. 
Der Ident einer Nachricht wird zur Verarbeitung einer empfangenen Nachricht in der aufzurufenden Funktion benötigt (Unterscheidung von anderen Nachrichten gleichen Typs).

\begin{table}
\begin{center}
\begin{tabular}{l | l | p{2cm} | p{4cm}}
\label{pvs-msg-liste}
Nachrichtentyp & Nachrichten Ident & Inhalt & Beschreibung \\
\hline
PVSCOMMAND & PROJECT & hostname port password quality & Hostname, Port, Passwort und Qualität des VNC Servers zu dem verbunden werden soll (durch Space getrennt) \\
PVSCOMMAND & UNPROJECT &  & \\
PVSCOMMAND & LOCKSTATION &  & \\
PVSCOMMAND & LOCKSTATION & Message & Client mit Nachricht sperren \\
PVSCOMMAND & UNLOCKSTATION &  & \\
PVSCOMMAND & STARTPROCESS & process & gibt Prozessnamen an der auf Client gestartet werden soll\\
PVSCOMMAND & KILLPROCESS & PID & gibt ProzessID an von Prozess der auf Client beendet werden soll\\
PVSCOMMAND & SHOWPROCESSES & filter & weist den Client an seine Prozesse auszulesen und den Prozessvektor zu füllen, filter ist eine Nachricht der Art 'Prozess1 Prozess2 Prozess3', wobei die Prozesse Prozess1, Prozess2 und Prozess3 aus der Liste der laufenden Prozesse ausgeblendet werden\\
PVSLOGIN & USERNAME & username & Client Benutzername \\
PVSLOGIN & PASSWORD & password & Serverpasswort \\
PVSLOGIN & ID & id & \\
PVSLOGIN & FAILED & "`Wrong Password"' & Wird bei falschem Passwort gesendet \\ 
PVSCOMMAND & PORT & port & \\
PVSCOMMAND & PASSWORD & password & VNC Passwort\\
PVSCOMMAND & RWPASSWORD & rwpassword & Passwort für den Zugriff auf die Tastatur und Maus \\
PVSCOMMAND & VNC & YES &  Erlaube Zugriff \\
PVSCOMMAND & VNC & NO & Verbiete Zugriff \\
PVSCOMMAND & PING &  & \\
PVSCOMMAND & VNCREQUEST &  & \\
PVSCOMMAND & VNCSRVRESULT & result code & Der Rückgabewert des pvs-vncsrv Skripts \\
\end{tabular}
\end{center}
\caption{Liste der PVS Messages}
\label{tab:messagelist}
\end{table} 

\begin{table}
\begin{center}
\begin{tabular}{l | l | p{2cm} | p{4cm}}
\label{pvs-msg-liste}
Nachrichtentyp & Nachrichten Ident & Inhalt & Beschreibung \\
\hline
PVSCOMMAND & MCASTFTANNOUNCE & sender transferID basename size port & Ankündigung eines Multicast-Transfer \\
PVSCOMMAND & MCASTFTRETRY & sender transferID & Rückmeldung: Konfiguration des Multicast-Empfängers fehlgeschlagen, bitte auf anderem Port noch einmal versuchen \\
PVSCOMMAND & MCASTFTCONFIG & blob & Multicast-Konfiguration aus dem angehängten Binärblob neu laden \\
PVSCOMMAND & INPUTEVENT & Base64-kodierte InputEvent-Struktur & Fernsteuerung \\
PVSCOMMAND & PROCESSES & START ERROR errorlevel & errorlevel gibt an, welcher Fehler beim Starten eines Prozesses aufgetreten ist \\
PVSCOMMAND & PROCESSES & STOP ERROR errorlevel & errorlevel gibt an, welcher Fehler beim Beenden eines Prozesses aufgetreten ist \\
PVSCOMMAND & PROCESSES & SHOW ERROR & gibt an, dass beim Anzeigen der Prozessliste ein Fehler aufgetreten ist \\
PVSCOMMAND & PROCESSES & SHOW clear & weist Client an den Prozessvektor zu leeren \\
PVSCOMMAND & PROCESSES & SHOW finished & weist Manager an, Prozessliste neu zu füllen \\
PVSMESSAGE & BROADCAST & MESSAGE &\\
PVSMESSAGE & clientToAdd & & Client hinzufügen (Chat)\\
PVSMESSAGE & clientToRemove & & Client entfernen (Chat)\\
PVSMESSAGE & assignedName & & Festgelegter Name (Chat)\\
\end{tabular}
\end{center}
\caption{Liste der PVS Messages (Fortsetzung}
\label{tab:messagelist}
\end{table}