Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M Новый топик    Ответить
 WebSocket и read  [new]
ZitRo
Member

Откуда:
Сообщений: 11
Здравствуйте, коллеги. Такая вот история.

Уже несколько дней не может решится одна из тормозящих задачу мелочь, на первый взгляд. Суть ее заключается в следующем.

В работе по протоколу WebSocket (%CSP.WebSocket), где обмен данными идет меж браузером и сервером, тщетно идут попытки устроить удалённое исполнение кода на сервере. Среди буков исходника за принятие "команды" клиента отвечает нечто такое:
+ принимаем данные
set data = ..Read(,.status) // извлекли данные из пакета
do ..ExecuteCommand(data) // отправили данные на выполнение в свой метод

В методе ExecuteCommand перед непосредственно выполнением устанавливаем флажки T и Q, чтобы вывод (write) с этого произвольного кода летел напрямую к браузеру, и ввод (read) обрывался по терминаторам:
+ помимо всяких локальных настроек
use $Principal:(::"+T+Q")

xecute CODE // выполняем произвольный код

С выводом все хорошо - сценарий типа for i=0:1:10 { write i hang 0.1 } выполняется как следует. Но если выполнять что-то похожее на read ^a write ^a (клиент отдает данные с терминатором в конце), окажется, что в ^a находится несколько лишних байтов перед непосредственно данными, чего и следовало бы ожидать, т.к. ..Read() класса %CSP.WebSocket делает тот же простой read, но извлекает первые пять символов (тело пакета).

Вопрос стоит в отбрасывании этих "мусорных" байтов прилетевшего пакета, не затрагивая код, ведь он может быть произвольным, или вообще содержать вызов программы с read'ами. Есть несколько идей реализации, но только идей, и они наверняка не совершенны.

Буду благодарен за любой совет, пример, критику, подсказку или способ. Заранее спасибо.
26 июл 13, 17:05    [14623623]     Ответить | Цитировать Сообщить модератору
 Re: WebSocket и read  [new]
servit
Member

Откуда: г. Кишинёв, Республика Молдова
Сообщений: 3094
Блог
ZitRo
чтобы вывод (write) с этого произвольного кода летел напрямую к браузеру
То есть, Вы отдаёте данные в обход рекомендованного ..Write()?
Это не очень хорошо вклинивать свои команды read/write внутри сервера websocket, тем самым увеличивая вероятность нарушения обработки протокола RFC6455.
В новой версии код ..Read()/..Write() существенно дополнен с учётом автоматической конвертации входных/выходных данных в UTF8 и поддержки SharedConnection=1, поэтому могут быть проблемы с совместимостью в будущих версиях.
26 июл 13, 20:21    [14624621]     Ответить | Цитировать Сообщить модератору
 Re: WebSocket и read  [new]
ZitRo
Member

Откуда:
Сообщений: 11
Servit, спасибо за совет.

С COS'ом я работаю совсем недавно, и применимо к задаче меня посещали идеи реализовать что-то наподобие такого:
Картинка с другого сайта.
В теории, мне кажется, это возможно, но попытки его реализовать, а особенно, грамотно, не увенчались успехом - проблемы с коммуникацией между WS server и processor. Может, существуют и более простые пути, о которых я пока не догадываюсь.
27 июл 13, 14:25    [14626388]     Ответить | Цитировать Сообщить модератору
 Re: WebSocket и read  [new]
ZitRo
Member

Откуда:
Сообщений: 11
В двух словах, пишу реализацию web-терминала овер WebSockets. Исполняемый код, поступающий на удалённый сервер абсолютно произвольный. Вышеописанным (в шапке) методом все работает, за исключением разных утилит, использующих read. В xecut'e выполняется чтение всего пакета, а не данных, которые он содержит, вот.
Есть ли способ это поправить - для меня пока загадка, в чем и вопрос.
28 июл 13, 14:01    [14628675]     Ответить | Цитировать Сообщить модератору
 Re: WebSocket и read  [new]
servit
Member

Откуда: г. Кишинёв, Республика Молдова
Сообщений: 3094
Блог
ZitRo
Есть ли способ это поправить - для меня пока загадка, в чем и вопрос.
Не уверен, что такое возможно.
Но попробуйте задать Ваш вопрос в WRC.
29 июл 13, 15:59    [14632873]     Ответить | Цитировать Сообщить модератору
 Re: WebSocket и read  [new]
Alexey Maslov
Member

Откуда: СПб
Сообщений: 1509
Есть такая штука - i/o redirection. М.б., поможет. Прилагаю материал по ней.

К сообщению приложен файл (io_redir.html - 2Kb) cкачать
29 июл 13, 16:43    [14633157]     Ответить | Цитировать Сообщить модератору
 Re: WebSocket и read  [new]
servit
Member

Откуда: г. Кишинёв, Республика Молдова
Сообщений: 3094
Блог
ZitRo,

Приведу пример кода использования i/o redirection, предложенной Alexey Maslov.
+ Код класса
Class demo.test Abstract ]
{

/// Публичные точки входа, использующиеся при перенаправлении ввода/вывода
ClassMethod 
redirects() [ InternalPrivateProcedureBlock = 0 ]
{
wstr(s) pStream.Write(sq
wchr(c) pStream.Write($c(c)) q
wnl pStream.Write($c(13,10)) q
wff pStream.Write($c(12)) q
wtab(s) pStream.Write($j("",s-$x)) q

rstr(len,timeout) "test"
rchr(timeout) "-"

  /*
  // этот код нужно менять под Ваши нужды  
rstr(len,timeout)
  n rd,vr,rt
  s vr="rt"
  s rd=##class(%Device).ReDirectIO($$$NO)
  s:$d(len) vr=vr_"#"_len s:$d(timeout) vr=vr_":"_timeout
  r @vr
  s rd=##class(%Device).ReDirectIO(rd)
  s rd=$zu(96,4,$t)
  q rt
  */
}

/// Перенаправляем вывод с терминала в поток, используя публичные точки входа
ClassMethod 
Write2Stream(Output pStream As %Stream.Object) [ ProcedureBlock = 0 ]
{
  
io
  
  
pStream=##class(%Stream.TmpBinary).%New()

  
io $io
  u 
io::("^"_$zn)
  
##class(%Device).ReDirectIO($$$YES)
  
  
..MyPackage()
  
  
##class(%Device).ReDirectIO($$$NO)
  
io
  
  
pStream.Rewind() ##; идём в начало потока
}

/// наш пакет команд
ClassMethod 
MyPackage()
{
  
str="1+2"
  
"Привет!",!
  
str,"=",@str,!
  
a,!
  
*a,!
}

ClassMethod Test()
{
  
..Write2Stream(.stream)
  
  
##; выводим размер потока и его содержимое
  
  
stream.Size,!,stream.Read()
}

}
Результат:

USER>d ##class(demo.test).Test()
25
Привет!
1+2=3
test
-
29 июл 13, 19:00    [14633945]     Ответить | Цитировать Сообщить модератору
 Re: WebSocket и read  [new]
ZitRo
Member

Откуда:
Сообщений: 11
Servit, Alexey Maslov, спасибо большое, по-моему это то, что надо. Завтра будем продолжать, о результатах отпишусь.
29 июл 13, 19:00    [14633946]     Ответить | Цитировать Сообщить модератору
 Re: WebSocket и read  [new]
Alexey Maslov
Member

Откуда: СПб
Сообщений: 1509
servit,
Документация по i/o redirect
Inside io redir handler use idiom S io=$io U 0 Command arg U io. The command is not redirected in this case
поэтому команды отключения/включения redirect внутри закомментированной rstr() - лишние.
30 июл 13, 09:08    [14635480]     Ответить | Цитировать Сообщить модератору
 Re: WebSocket и read  [new]
servit
Member

Откуда: г. Кишинёв, Республика Молдова
Сообщений: 3094
Блог
Alexey Maslov
поэтому команды отключения/включения redirect внутри закомментированной rstr() - лишние.
В исходниках самой InterSystems они везде во встречающихся rstr временно отключают i/o redirect.
30 июл 13, 09:32    [14635593]     Ответить | Цитировать Сообщить модератору
 Re: WebSocket и read  [new]
Alexey Maslov
Member

Откуда: СПб
Сообщений: 1509
servit,

мне приходилось использовать i/o redirect, так что знаю, о чём пишу.
30 июл 13, 09:34    [14635601]     Ответить | Цитировать Сообщить модератору
 Re: WebSocket и read  [new]
ZitRo
Member

Откуда:
Сообщений: 11
Отлично, кажись, все получилось, чрезмерно благодарен за помощь! Команды включения/отключения redirect внутри переопределённого r/w таки оказались нужными.
30 июл 13, 18:54    [14639304]     Ответить | Цитировать Сообщить модератору
 Re: WebSocket и read  [new]
Alexey Maslov
Member

Откуда: СПб
Сообщений: 1509
Как видно, это связано с тем, что использовался редирект текущего устройства. У меня была несколько иная схема, в ней внутреннее переключение redirect было не нужно. Могу набросать, если кому-то интересно.
30 июл 13, 20:20    [14639548]     Ответить | Цитировать Сообщить модератору
Все форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M Ответить