about summary refs log tree commit diff
FAt Remoute SHell

Перед сборкой убедиться, что в config-farshd.h выставлен нужный шелл.
Выставить переменные окружения CC, CFLAGS и т.п. и собрать:

	export CFLAGS="-O2"
	make farsh
	make farshd

Ну или вручную:

	cc -O2 -o farsh farsh.c
	cc -O2 -o farshd farshd.c



Приблизительный алгоритм работы программы.

Максимальный размер пакета задаётся MAX_PKT_SZ, это нужно чтоб не возиться с
Path MTU Discovery. Интервал отправки пакетов задаётся в PKT_INT. Эти
значения ограничивают макс. пропускную способность. Значение PKT_INT на
клиенте рекоммендуется выставить меньше чем на сервере.

Бесконечный цикл на клиенте:

1) Если есть данные с терминала, то пишем их в кольцевой буфер
2) Если пришёл пакет, то читаем из него данные и пишем их в stdout
3) Если прошло PKT_INT микросекунд или около того (PKT_INT - MIN_SLEEP), то
   пора сформировать пакет:
    1) если соединение не установлено, то выставляем в пакете бит CONNECT и
       добавляем в него значение перемнной окружения TERM.
    2) Получаем размеры терминала, если они отличаются от тех, что мы раньше
       отправляли на сервер, то выставляем в пакете бит PING и добавляем
       туда новые размеры терминала.
    3) Если в кольцевом буфере есть данные, то добавляем их в пакет, а также
       добавляем состояния потоков: количество принятых от сервера байт
       данных (не просто байт а именно тех что пишем в терминал) и
       количество байт данных которое сервер получил от клиента (клиент
       получает эти данные с сервера). Выставляем бит SSTATE в пакете.
    4) Если данных нет, но состояния потоков разные на сервере и клиенте, то
       выставляем бит SSTATE в пакете и добавляем состояния потоков в пакет.
    5) Если получился не пустой пакет, то отправляем его. Если с момента
       последнего полученного от сервера пакета прошло TIMEOUT_P секунд, то
       добавляем в пакет PING, размеры терминала и шлём.

Клиент перестаёт слать пакеты с битом CONNECT после получения пакета от
сервера с таким битом.

Бесконечный цикл на сервере:

1) Если что-то есть в клиентских псевдотерминалах, то читаем это в
   клиентские колцевые буферы.
2) Если есть пакет от клиента, то пишем данные из пакета в клиентский
   псевдотерминал. Обновляем состояния потоков. Обновляем размеры терминала,
   если они есть в паете.
3) Прошло PKT_INT микросекунд или около того. Пробегаем по всем клиентам и
   формируем пакет если:
     а) был пакет от клиента с битом PING
     б) был пакет от клиента с битом SSTATE
     в) в кольцевом буфере клиента есть данные.

После установки соединения сервер шлёт пакеты с битом CONNECT пока не
получит от клиента подряд NOT_CONNECTED пакетов без бита CONNECT. После
этого сервер перстаёт добавлять CONNECT бит в пакет и если получит пакет с
этим битом от клиента, то отключит его. NOT_CONNECTED пакетов подряд нужно
на случай перестановки пакетов (хоть это и маловероятно из-за большого
интервала между пакетами).



Формат пакета:

Первые два байта это u16 переменная, которая может содержать флаги:
CONNECT, PING, SSTATE.

Вторые 2 байта, это u16 переменная, в которой будет размер данных в пакете
(может быть 0).

Флаг CONNECT озанчает что сразу за первыми 4 байтами пакета идёт буфер
размером CONNECT байт с содержимым клиентской переменной TERM (если пакет от
сервера, то ничего не добавляется).

Флаг PING означает что сразу за первыми 4 байтами (или за первыми 4+CONNECT
байтами) идут две u16 переменных, в которых содержатся размеры терминала.
Сервер должен ответить на этот пакет, и он шлёт те значения которые получил
последние.

Флаг SSTATE означает что в пакет добавлены состояния потоков: две u32
переменные.

Значения флагов выбраны таким образом что образуемая ими u16 переменная
содержит количество данных в пакете помимо данных для терминала (кроме
случая, когда сервер шлёт пакет с битом CONNECT). Так добавив к этой
переменной 4 (первые байты) можно получить смещение данных в пакете.