Remote-Local CoPy - komunikacja wielu maszyn
Tagi:  •  
RLCP (Remote-Local CoPy) to program służący do kopiowania treści schowka ("clipboard") na inne komputery przy użyciu protokołu TCP/IP.

Działanie wymiany schowka opiera się na komunikacji dwóch programów — klienta i serwera. Serwer powinien stać na każdej maszynie, na której chcesz mieć możliwość wysyłania schowka. Sam schowek natomiast wysyłany przez przez klientów. Przykładowo, jeśli masz komputery W (komputer z Windowsem) oraz L, stawiasz na obu serwery RLCP. Teraz, jeśli chcesz z W przesłać schowek na komputer L (WL), na W uruchamiasz klienta podając numer IP komputera L. Serwer stojący na L odbierze dane i ustawi schowek — proste.

1. Wersja Windows — rlcp32
Odczytywanie schowka z Windows jest proste, szybkie i w sumie przyjemne. Cała filozofia polega na tym, aby wywołać funkcje MSDNOpenClipboard, MSDNGetClipboardContents z argumentem CF_TEXT, a na koniec MSDNCloseClipboard. Ustawianie schowka robione jest podobnie, przez użyciem MSDNSetClipboardData należy jednak wywołać MSDNEmptyClipboard, aby wyczyścić schowek — i i to jest chyba jedyna rzecz, która może powodować dodatkową rekompilację, jeśli tylko nie doczyta jej się w porę z dokumentacji [1] ;).

2. Wersja Linux — rlcp
Na Linuxie jednak sytuacja wygląda nieco inaczej. Przede wszystkim nie ma wsparcia dla czystej konsoli — obsługiwany jest tylko schowek X'ów. Sama komunikacja ze schowkiem odbywa się za pomocą mechanizmów ze standardu ICCCM[2]. Same mechanizmy sprawiają wrażenie nie do końca przemyślanych, lub co najmniej skomplikowanych w użyciu. Znane są przypadki rozstrojeń nerwowych spowodowanych czytaniem dokumentacji [3] (jak to określa Wikipedia, "The ICCCM is notorious for being ambiguous and difficult to correctly implement", hehe); jakoże sam postanowiłem się w to wgłębić, jestem w stanie połączyć się w bólu z autorem tego posta :).

W X są właściwie dwa schowki. Jeden nazywany jest CLIPBOARD i naiwny człowiek mógłby twierdzić, że działa on w taki sam sposób co schowek na Windows: klikając Ctrl+C w jednej aplikacji i wklejając Ctrl+V w drugiej. Dlaczego człowiek naiwny? Ponieważ Linux, jako wytwór zgodny z naturą, w naturalny sposób zdaje się dążyć do coraz większych komplikacji, powodując sytuację, gdzie wszystko to, co z niego korzysta, musi być w równym stopniu skomplikowane, co on sam. Dlatego rzecz, która wygląda na taką samą co na innych systemach, może być na Linuxie zaimplementowana w sposób taki, że do decyzji o sukcesie operacji brany jest pod uwagę stopień zróżnicowania związków chemicznych w kraterach na Marsie.

Xy zaprojektowane są po to, aby np. okna mogły być pokazywane na oddzielnych maszynach (coś co Microsoft wprowadza dopiero w Windows Server 2008), dlatego przy kopiowaniu dużych części danych z jednej aplikacji do serwera, mógłby pojawić się problem nadmiernego obciążenia sieci, lub aplikacji, lub serwera, w zależności od tego które łącze ma słabą przepustowość. Szczerze się przyznam, nie doczytałem z dokumentacji informacji na temat schowka CLIPBOARD jak radzić sobie z takimi problemami, doczytałem jednak że drugi typ schowka, PRIMARY, działa sobie całkiem nieźle, pomijając oczywiście same szczegóły implementacji.

Schowek PRIMARY to ten schowek, którego używasz gdy po prostu zaznaczasz tekst i wklejasz go w inne miejsce za pomocą środkowego przycisku myszy, bez użycia Ctrl+C/Ctrl+V. Nie będę opisywał całego protokołu komunikacji, ponieważ wbrew pozorom można go odczytać z ICCCM[2], powiem tylko tyle, że opiera się na czymś w rodzaju komunikacji międzyprocesowej. Przy zaznaczeniu tekstu, program sygnalizuje Xom, że posiada zaznaczenie — drugi program natomiast, gdy wykryje akcję naciśnięcia środkowego przycisku myszy na swoim obszarze pyta Xy o właściciela zaznaczenia i łączy się z nim za pomocą mechanizmów ICCCM (łączenie się to sformułowanie trochę na wyrost — używane są do tego sygnalizacje we właściwościach okna, tak jak jakieś flagi, i to jest właśnie to niewygodne wyjście). Po połączeniu, program pyta właściciela zaznaczenia o dane, które najcześciej są po prostu zaznaczonym tekstem, a ten z kolei wysyła mu je w podobny sposób jakby to była komunikacja TCP/IP (ale ponownie, operuje na właściwościach okien — XGetWindowProperty).

Takie jest pobieranie schowka. Ustawianie zawartości schowka jest równie ciekawe, ponieważ trzeba napisać coś na wzór serwera pełniącego rolę usługi zaopatrującej dane ze schowka inne aplikacje. Cyrk ;)

3. Cechy wspólne obu klientów
Wspólne cechy to oczywiście protokół, w jaki sposób się komunikują (port 12312). Dane ze schowka przesyłane są przy użyciu kodowania UTF-8, dzięki temu tekst z polskimi znakami skopiowany z Windows (zakodowany CP-1250) będzie zawierał polskie znaki i na Linuxie (który chodzi na np. ISO8859-2). Prawidłowej konwersji poddawane są też znaki końca linii, z Windowsowego \r\n na Unixowy \n, i odwrotnie.

4. Instalacja i użycie — Windows
Instalacja będzie wykorzystywała mechanizmy z których prawdopodobnie wiele osób nigdy nie korzystała, tzn. skrótu klawiaturowe w Windows :).

Krok 1 — budowanie rlcp32.exe

Krok możesz pominąć, jeśli nie chce ci się ściągać pakietu OpenWATCOM [4] i instalacji go na swoim systemie (aktualizacja zmiennych środowiskowych mogą wymagać restartu). Sama instalacja ogranicza się do klikania next, next, next, ale jestem w stanie zrozumieć że nie każdy pragnie mieć pakiet deweloperski na swoim systemie :).

Kompilacja źródeł to przejście do katalogu z plikiem rlcp32.cpp i wydanie polecenia wmake.



Wynik taki jak powyżej będzie swojego rodzaju dowodem, że plik rlcp32.exe został zbudowany poprawnie. Dla pewności możesz jednak wykonać test programu używając opcji probe; ta opcja spróbuje zgadnąć (z różnym skutkiem, ale dla komputerów domowych z jedną kartą sieciową powinno wystarczyć) publiczny numer IP komputera w sieci, do użytku dla opcji listen.



Krok 2 — ustawianie klienta

Skopiuj rlcp32.exe do jakiegoś katalogu, np. C:\rlcp\rlcp32. Następnie zrób nową pozycję w Programach w menu Start, może nazywać się np. "Remote Local Copy", tak jak jest pokazane na następnym screenshocie. Zapisz do niego skrót do programu C:\rlcp\rlcp32\rlcp32.exe i wybierz jego właściwości. Ten krok wydaje się być niepotrzebny, ale z jakiegoś dziwnego powodu nie mogłem zmusić do działania skrótów klawiaturowych dla skrótów nie znajdujących się na pulpicie ani w pasku Start. Pulpit jest zbyt cennym miejscem na skróty do programów, stąd też wybór paska Start wydaje się być oczywisty :).



Kolejny krok to uzupełnienie informacji skrótu. W polu Target do linii poleceń wpisz numer IP komputera, do którego chcesz wysyłać informacje, a Shortcut Key wypełnij interesującym cię skrótem klawiaturowym. Uwaga: zmiana nazwy skrótu wydaje się deaktywować jego zdolności skrótów klawiaturowych, nie mam pojęcia dlaczego, dlatego lepiej zostawić nazwę taką jaka już jest (tzn. w angielskich Windowsach — z prefiksem "Shortcut to", lub w polskich "Skrót do").



Krok 3 — ustawianie serwera

Cała filozofia polega na dodaniu linii rlcp32.exe listen do autostartu, czyli np. przez dodanie odpowiedniego wpisu do klucza HKCU\Software\Microsoft\Windows\CurrentVersion\Run, zgodnie ze screenem:



Po restarcie, lub manualnym uruchomieniu linii poleceń, program rlcp32.exe powinien pojawić się na liście procesów.

Zdarzyć się może też sytuacja, gdy komputer posiada dwa numery IP, natomiast rlcp32.exe nasłuchuje nie na tym co trzeba. W takim przypadku do linii poleceń rlcp32.exe listen należy dodać jeszcze numer IP, na którym powinien nasłuchiwać program, tzn. np.: rlcp32.exe listen 160.84.150.14.

Po przejściu wszystkich kroków ten system Windows powinien być poprawnie skonfigurowany do współpracy z rlcp :).

Jeśli masz już komputer Linuxowy, na którym skonfigurowany jest serwer rlcp, spróbuj napisać jakiś tekst, skopiować go do schowka (Ctrl+C) i nacisnąć wybranego hotkeya (np. Ctrl+Shift+C). Na komputerze z Linuxem będziesz po tym mógł go wkleić środkowym przyciskiem myszy. Problem może pojawić się, gdy korzystasz z programów które nazywają się "managerami schowków" (clipboard manager), np. Klipper, Glipper, xclipboard. Jeśli tak jest, przejmą one to co zrobi klient rlcp i aby dostać się do tego tekstu, musisz kliknąc na taką ikonkę Klippera i wybrać otrzymane zaznaczenie. Po tej akcji będzie ono dostępne w schowku CLIPBOARD, a więc będziesz mógł je wkleić za pomocą Ctrl+V.

5. Instalacja i użycie — Linux
Na Linuxach sytuacja jest inna, ponieważ jest wiele różnych konfiguracji jeśli chodzi o skrypty startowe, dostępne środowiska, etc. Do hotkeyów klawiszowych możesz wykorzystać możliwości które oferuje KDE, Gnome, Fluxbox, albo posłużyć się bardziej uniwersalnym programem, np. xbindkeys[5].

Kompilowanie źródła sprowadza się do użycia make. Wynikowy program możesz skopiować tam gdzie ci najwygodniej, np. do /usr/local/bin/rlcp. Możesz przetestować czy działa jak powinien wydając polecenie rlcp probe.

Użycie programu jest identyczne jak na Windows — rlcp listen stawia serwer nasłuchiwania (następny argument to numer IP na którym program ma nasłuchiwać, brak tego argumentu oznacza sytuację w której program sam sobie ten numer zgaduje), natomiast rlcp numerip wysyła pod IP numerip schowek z lokalnego komputera.

Jeśli korzystasz z xbindkeys, do pliku ~/.xbindkeysrc dopisz taką linijkę (za 192.168.0.100 oczywiście wstaw numer IP komputera z którym chcesz się komunikować — w moim przypadku będzie to numer IP komputera z Windowsem z poprzedniego kroku, a więc takim na którym poprawnie został skonfigurowany serwer rlcp).

  1. 68 "rlcp 192.168.0.100"
  2. 69     m:0x5 + c:54
  3. 70     Control+Shift + c


Uruchom demona xbindkeys, i np. zaznacz ten tekst:

Zażółć gęślą jaźń ;)

Po czym naciśnij Ctrl+Shift+C. Teraz powinieneś móc odpalić np. notepad.exe na Windowsie i po prostu wkleić ten tekst za pomocą Ctrl+V.

6. Możliwe problemy
Program nie jest pisany z bezpieczeństwem na myśli, dlatego może okazać się, że łatwo można zawiesić serwer rlcp, lub spowolnić działanie komputera, dlatego nie korzystaj z tego programu w żadnych wrogich środowiskach. Zawiesić serwer można wysyłając magicznego DWORDa, następnie ilość bajtów do przesłania, jednak nie przesyłając tych bajtów. Można też zadeklarować kosmiczną wartość bajtów do przesłania, jak zachowa się system zależy już od jego mechanizmów alokacji pamięci.

7. Download
Na koniec źródła — Windows (w tej paczce siedzi też plik rlcp32.exe, więc nie musisz kompilować źródeł) i Linux. Kod na Linuxa dodatkowo zawiera przykład w jaki sposób poprawnie enumerować listę interfejsów sieciowych w systemie ("poprawnie", czyli nie korzystając z popen("ifconfig") ;>), pobierać ich numery IP i odczytywać flagi takie jak: interfejs aktywny, numer ip przypisany, itp.

Referencje:

1. Charakterystyka funkcji dotyczących schowka w Windows — http://msdn.microsoft.com/en-us/library/ms674551(VS.85).aspx
2. Inter-Client Communication Conventions Manual, Version 2.0, X Consortium Standard — http://tronche.com/gui/x/icccm/
3. Re: [SLUG] Ximian / Gnome and Xalf — http://lists.slug.org.au/archives/slug-chat/2001/July/msg00054.html
4. OpenWATCOM — zestaw kompilatorów Win32/Linux — http://www.openwatcom.org
5. XBindKeys — demon hotkeyów klawiaturowych dla X — http://hocwp.free.fr/xbindkeys/xbindkeys.html