Munca mea se face aproape in intregime dintr-un manager de conexiuni. Cel pe care il foloseam de ani de zile, mRemoteNG, exista doar pe Windows. Am scris unul nativ pentru Mac care citeste exact acelasi fisier de configuratie, si l-am publicat sub aceeasi licenta ca originalul. Articolul asta e despre drumul de la nevoie la aplicatie, si despre de ce partea cu „inapoi la comunitate" nu e o formalitate.
Nevoia
Lucrez de pe Mac. Conexiunile stau in confCons.xml — fisierul in care
mRemoteNG isi tine arborele: un arbore mare, cu credentiale mostenite de la foldere
catre conexiuni. Ani de curatenie si conventii proprii stau in fisierul ala.
Variantele erau doua, si amandoua proaste. Ori tin o masina virtuala cu Windows pornita permanent doar ca sa deschid sesiuni RDP si SSH — ceea ce inseamna un strat de virtualizare intre mine si tastatura, pentru o operatiune care ar trebui sa fie instantanee. Ori trec pe un client de Mac si renunt la arbore: il reintroduc de mana, conexiune cu conexiune, sau accept un import aproximativ care pierde structura si mostenirea. Niciuna nu e o solutie, ambele sunt o taxa platita zilnic.
Ideea
Punctul in care s-a decis totul a fost o intrebare simpla: ce anume trebuie
pastrat? Raspunsul nu era interfata, ci datele. Daca aplicatia
citeste si scrie exact acelasi confCons.xml, byte cu byte compatibil,
atunci nu mai exista migrare. Acelasi fisier traieste pe Mac si pe Windows, se poate
sincroniza intre ele, iar daca aplicatia mea dispare maine, fisierul ramane valid
pentru mRemoteNG. Zero blocare, zero conversie, zero drum fara intoarcere.
Asta a insemnat sa reproduc si criptarea, nu doar structura XML: aceeasi derivare de cheie si acelasi mod de cifrare, inclusiv marcajul din radacina prin care mRemoteNG verifica parola master. O parola pusa pe Mac trebuie sa deschida fisierul pe Windows, si invers. Decizia asta a modelat tot ce a urmat — inclusiv lucruri la care as fi vrut sa ma abat si n-am facut-o, pentru ca ar fi rupt compatibilitatea.
Am verificat direct in sursa mRemoteNG: atributele pe care nu le cunoaste sunt aruncate la prima salvare. Deci extensii proprii in
confCons.xmlnu exista ca optiune. Setarile care sunt doar ale aplicatiei de Mac stau in preferintele ei, nu in fisierul comun.
Actiunea
Interfata e SwiftUI. Sub ea, fiecare protocol are motorul lui: RDP prin FreeRDP 3 apelat din C, SSH/Telnet/SFTP prin SwiftTerm, HTTP/HTTPS intr-un WKWebView — toate in tab-uri, in aceeasi fereastra.
Partea interesanta n-a fost scrisul, ci diagnosticarea. Cateva exemple concrete, pentru ca sunt genul de lucruri care nu apar in niciun tutorial:
- Crash la deschiderea mai multor sesiuni RDP odata. Nu era codecul, cum am crezut initial, ci thread pool-ul de decodare al FreeRDP, partajat intre sesiuni. Rezolvat prin decodare pe un singur fir.
- RDP catre masini Windows in afara unui domeniu pica la autentificare, raportat inselator ca eroare de transport. Cauza reala: NTLM calculeaza hash-ul cu MD4, pe care OpenSSL 3 l-a mutat intr-un modul „legacy" separat, neincarcat implicit.
- Un Windows Server 2012 R2 rupea sesiunea la o secunda dupa conectare. Trimiteam un factor de scalare de 200 intr-un camp unde protocolul admite doar 100, 140 sau 180 — pentru ca FreeRDP scrie cele doua valori de scalare inversate cand isi construieste singur definitia de monitor. Windows 10 si 11 ignora; cel vechi nu.
- A saptea conexiune RDP nu se mai deschidea. macOS da unei aplicatii 256 de descriptori de fisier, iar o sesiune RDP e scumpa in ei: fiecare eveniment si canal e un pipe. Sase sesiuni plus cateva terminale stau exact pe plafon, iar a saptea moare adanc in connect, cu o eroare care arata ca un refuz al serverului.
De fiecare data cand raspunsul nu era clar, l-am cautat in sursa mRemoteNG in loc sa-l ghicesc. Asa am aflat cum isi roteste copiile de siguranta — copiaza inainte de fiecare salvare, apoi sterge cele mai vechi peste un numar configurabil — si am facut la fel, cu acelasi implicit de 10. Tot asa am aflat de ce reordonarea tab-urilor prin drag-and-drop e o problema si pe Windows: biblioteca lor de docking nu foloseste API-ul de sistem, ci captureaza mouse-ul direct. Dupa cinci incercari esuate cu API-ul SwiftUI, am ajuns la aceeasi solutie.
Rezultatul
Aplicatia se numeste mRemoteNXT si e in folosinta zilnica, pe arborele real de care depinde munca mea.
| Cifra | Valoare |
|---|---|
| Primul commit public | 24 mai 2026 |
| Versiuni publicate de atunci | 21 |
| Commit-uri | 103 |
| Cod (Swift, C, Objective-C) | ~7.400 de linii in 25 de fisiere |
| Licenta | GPL-2.0-or-later, ca mRemoteNG |
Protocoale: SSH si SFTP, Telnet, RDP, HTTP/HTTPS, plus unelte externe rulate in tab de terminal. Ferestre multiple, fiecare cu fisierul ei de configuratie, pentru cine lucreaza pe doua monitoare. Import din Royal TS. Actualizare automata semnata si notarizata la Apple. VNC urmeaza.
Inapoi la comunitate
Aplicatia asta nu exista fara mRemoteNG. Nu am pornit de la o pagina alba: am pornit de la un format de fisier gandit de altcineva, de la o schema de mostenire care functioneaza, si de la un set de decizii de interfata rafinate in ani de folosire reala. Cand nu stiam cum se face ceva, raspunsul era deja scris in sursa lor.
De aceea licenta e GPL-2.0-or-later, aceeasi cu a lor, si nu una permisiva care mi-ar fi lasat mai multa libertate. Codul e public pe GitHub: cine vrea sa-l foloseasca, sa-l modifice sau sa continue de unde am ramas, poate. Mi se pare singurul raspuns onest cand construiesti pe munca altcuiva.
Multumiri celor care au facut mRemoteNG posibil, asa cum apar chiar in sursa proiectului: Felix Deimel (2007–2009, mRemote-ul original), Riley McArdle (2010–2013) si echipa mRemoteNG de atunci incoace. Un manager de conexiuni open-source folosit de doua decenii in atatea camere de servere nu e un lucru marunt.
Ce am invatat
- Formatul de date e contractul, nu interfata. Alegerea de a
pastra
confCons.xmlneatins a eliminat migrarea, sincronizarea si frica de blocare — dintr-o singura decizie luata la inceput. - Citeste sursa proiectului cu care vrei sa fii compatibil. Fiecare intrebare importanta avea deja raspuns acolo, iar de fiecare data cand am presupus in loc sa citesc, am pierdut timp.
- O corelatie stransa nu e o cauza. Am gasit un tipar care se repeta de trei ori din trei si l-am declarat cauza; era coincidenta, pentru ca ambele evenimente erau ancorate de acelasi moment de start. Testul corect nu e daca simptomul mai apare, ci daca se schimba momentul in care apare.
- Cand log-ul aplicatiei nu mai spune nimic, pune tcpdump. Doua zile de ipoteze au fost inlocuite de treizeci de secunde de captura, care a aratat serverul trimitand un pachet de eroare si un reset la doua microsecunde dupa el.
- Ruleaza clientul oficial in paralel. Aceeasi masina, aceeasi cale, acelasi cont, alt client — raspunsul binar „merge / nu merge" muta investigatia dintr-un loc in altul mai repede decat orice teorie.
mRemoteNXT are pagina lui pe cremenescu.ro, cu capturi si instructiuni de instalare. Cere macOS 14 sau mai nou, e semnat si notarizat, si nu trimite nimic nicaieri.