diff --git a/src/addins/tcp_server/Cargo.lock b/src/addins/tcp_server/Cargo.lock index a3d46e2970..05c19b812b 100644 --- a/src/addins/tcp_server/Cargo.lock +++ b/src/addins/tcp_server/Cargo.lock @@ -98,6 +98,7 @@ dependencies = [ "dashmap", "once_cell", "serde_json", + "widestring", ] [[package]] @@ -213,6 +214,12 @@ version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14706d2a800ee8ff38c1d3edb873cd616971ea59eb7c0d046bb44ef59b06a1ae" +[[package]] +name = "widestring" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" + [[package]] name = "windows-targets" version = "0.52.6" diff --git a/src/addins/tcp_server/Cargo.toml b/src/addins/tcp_server/Cargo.toml index 2ee4cceb42..db311c868f 100644 --- a/src/addins/tcp_server/Cargo.toml +++ b/src/addins/tcp_server/Cargo.toml @@ -16,4 +16,5 @@ strip = true # Automatically strip symbols from the binary. addin1c = "0.5.0" serde_json = "1.0.137" dashmap = "6.1.0" -once_cell = "1.20.2" \ No newline at end of file +once_cell = "1.20.2" +widestring = "1.1.0" \ No newline at end of file diff --git a/src/addins/tcp_server/src/handler/component/mod.rs b/src/addins/tcp_server/src/handler/component/mod.rs index 5ccfbd03b8..4eefbd8da0 100644 --- a/src/addins/tcp_server/src/handler/component/mod.rs +++ b/src/addins/tcp_server/src/handler/component/mod.rs @@ -28,14 +28,14 @@ pub fn cal_func(_obj: &mut AddIn, num: usize, params: &mut [Variant]) -> Box { + 0 => { let connection_id = params[0].get_string().unwrap_or("".to_string()); let max_size = params[1].get_i32().unwrap_or(0); commons::receive_data(connection_id, max_size as usize) }, - 2 => { + 1 => { let connection_id = params[0].get_string().unwrap_or("".to_string()); let data = params[1].get_blob().unwrap_or(&[]).to_vec(); @@ -43,7 +43,7 @@ pub fn cal_func(_obj: &mut AddIn, num: usize, params: &mut [Variant]) -> Box { + 2 => { let connection_id = params[0].get_string().unwrap_or("".to_string()); Box::new(commons::close_connection(connection_id)) } diff --git a/src/addins/tcp_server/src/lib.rs b/src/addins/tcp_server/src/lib.rs index 3320115b7e..52a5c9afdc 100644 --- a/src/addins/tcp_server/src/lib.rs +++ b/src/addins/tcp_server/src/lib.rs @@ -7,6 +7,8 @@ use std::{ ffi::{c_int, c_long, c_void}, sync::atomic::{AtomicI32, Ordering}, }; +use widestring::U16CStr; + use addin1c::{create_component, destroy_component, name, AttachType}; @@ -16,17 +18,22 @@ pub static mut PLATFORM_CAPABILITIES: AtomicI32 = AtomicI32::new(-1); #[no_mangle] pub unsafe extern "C" fn GetClassObject(name: *const u16, component: *mut *mut c_void) -> c_long { - match *name as u8 { - b'1' => { + let u16_name = U16CStr::from_ptr_str(name); + let rust_name = u16_name.to_string().expect("Invalid UTF-16 string"); + + + match rust_name.as_str() { + "Server" => { let addin = server::AddIn::new(); create_component(component, addin) - } - b'2' => { + }, + "Handler" => { let addin = handler::AddIn::new(); create_component(component, addin) - } + }, _ => 0, } + } #[allow(non_snake_case)] diff --git a/src/en/OInt/addins/OPI_TCPServer.zip b/src/en/OInt/addins/OPI_TCPServer.zip index 0919771b78..ae81c0c243 100644 Binary files a/src/en/OInt/addins/OPI_TCPServer.zip and b/src/en/OInt/addins/OPI_TCPServer.zip differ diff --git a/src/en/OPI/src/CommonTemplates/OPI_TCPServer/Template.addin b/src/en/OPI/src/CommonTemplates/OPI_TCPServer/Template.addin index 0919771b78..ae81c0c243 100644 Binary files a/src/en/OPI/src/CommonTemplates/OPI_TCPServer/Template.addin and b/src/en/OPI/src/CommonTemplates/OPI_TCPServer/Template.addin differ diff --git a/src/ru/OInt/addins/OPI_TCPServer.zip b/src/ru/OInt/addins/OPI_TCPServer.zip index 0919771b78..ae81c0c243 100644 Binary files a/src/ru/OInt/addins/OPI_TCPServer.zip and b/src/ru/OInt/addins/OPI_TCPServer.zip differ diff --git a/src/ru/OPI/src/CommonModules/OPI_TCP/Module.bsl b/src/ru/OPI/src/CommonModules/OPI_TCP/Module.bsl index b9e43bfdd3..f0014b233b 100644 --- a/src/ru/OPI/src/CommonModules/OPI_TCP/Module.bsl +++ b/src/ru/OPI/src/CommonModules/OPI_TCP/Module.bsl @@ -293,31 +293,6 @@ КонецФункции -// Ожидать подключение !NOCLI -// Блокирует выполнение программы до появления нового подключения -// -// Параметры: -// TCPСервер - Произвольный - TCP сервер. См. СоздатьСервер - srv -// Таймаут - Число - Максимальное время ожидания подключений. 0 > бесконечно - timeout -// -// Возвращаемое значение: -// Структура Из КлючИЗначение - Структура с идентификатором нового подключения или ошибкой -Функция ОжидатьПодключение(Знач TCPСервер, Знач Таймаут = 0) Экспорт - - Если Не ЭтоСервер(TCPСервер) Тогда - ВызватьИсключение "Переданное значение не является TCP-сервером!"; - КонецЕсли; - - OPI_ПреобразованиеТипов.ПолучитьЧисло(Таймаут); - - Результат = TCPСервер.Wait(Таймаут); - - ОбработатьРезультат(Результат); - - Возврат Результат; - -КонецФункции - // Отключить сервер !NOCLI // Останавливает запущенный сервер // @@ -341,6 +316,31 @@ КонецФункции +// Ожидать входящие соединения !NOCLI +// Блокирует выполнение программы до появления нового подключения +// +// Параметры: +// TCPСервер - Произвольный - TCP сервер. См. СоздатьСервер - srv +// Таймаут - Число - Максимальное время ожидания подключений. 0 > бесконечно - timeout +// +// Возвращаемое значение: +// Структура Из КлючИЗначение - Структура с идентификатором нового подключения или ошибкой +Функция ОжидатьВходящиеСоединения(Знач TCPСервер, Знач Таймаут = 0) Экспорт + + Если Не ЭтоСервер(TCPСервер) Тогда + ВызватьИсключение "Переданное значение не является TCP-сервером!"; + КонецЕсли; + + OPI_ПреобразованиеТипов.ПолучитьЧисло(Таймаут); + + Результат = TCPСервер.Wait(Таймаут); + + ОбработатьРезультат(Результат); + + Возврат Результат; + +КонецФункции + // Получить входящие соединения !NOCLI // Получает список соединений в пуле // @@ -368,7 +368,7 @@ КонецФункции -// Актуализировать входящие соединения +// Актуализировать входящие соединения !NOCLI // Удаляет неактивные соединения из пула // // Параметры: @@ -391,27 +391,42 @@ КонецФункции -// Получить данные !NOCLI +// Это сервер !NOCLI +// Определяет, является ли переданное значение объектом TCP сервера +// +// Параметры: +// Значение - Произвольный - произвольное значение для проверки - value +// +// Возвращаемое значение: +// Булево - Это сервер +Функция ЭтоСервер(Знач Значение) Экспорт + + Возврат Строка(ТипЗнч(Значение)) = "AddIn.OPI_TCPServer.Server"; + +КонецФункции + +#КонецОбласти + +#Область МетодыОбработкиСоединений + +// Получить запрос !NOCLI // Получает данные из потока существующего соединения // // Параметры: -// TCPОбработчик - Произвольный - TCP сервер или идентификатор подключения - hnd -// IDПодключения - Строка, Число - ID активного подключения. См. ОжидатьПодключение - conn -// МаксимальныйРазмер - Число - Максимальный размер данных. 0 > до конца потока - maxsize +// IDПодключения - Строка, Число - ID активного подключения. См. ОжидатьПодключение - conn +// МаксимальныйРазмер - Число - Максимальный размер данных. 0 > до конца потока - maxsize +// TCPОбработчик - Произвольный - TCP сервер или пустое значение при обособленной обоработке - hnd // // Возвращаемое значение: // Структура Из КлючИЗначение, ДвоичныеДанные - Двоичные данные при успехе или структура с описанием ошибки -Функция ПолучитьДанные(Знач TCPОбработчик, Знач IDПодключения, Знач МаксимальныйРазмер = 0) Экспорт - - Если Не ЭтоСервер(TCPОбработчик) Тогда - - OPI_ПреобразованиеТипов.ПолучитьСтроку(TCPОбработчик); - TCPОбработчик = ПодключитьКомпонентуНаСервере("OPI_TCPServer", "Handler"); - - КонецЕсли; +Функция ПолучитьЗапрос(Знач IDПодключения, Знач МаксимальныйРазмер = 0, Знач TCPОбработчик = "") Экспорт OPI_ПреобразованиеТипов.ПолучитьСтроку(IDПодключения); OPI_ПреобразованиеТипов.ПолучитьЧисло(МаксимальныйРазмер); + + Если Не ЭтоСерверИлиОбработчик(TCPОбработчик) Тогда + TCPОбработчик = ПодключитьКомпонентуНаСервере("OPI_TCPServer", "Handler"); + КонецЕсли; Данные = TCPОбработчик.Receive(IDПодключения, МаксимальныйРазмер); @@ -431,27 +446,24 @@ КонецФункции -// Отправить данные !NOCLI +// Отправить ответ !NOCLI // Отправляет данные клиенту по идентификатору подключения // // Параметры: -// TCPОбработчик - Произвольный - TCP сервер или идентификатор подключения - hnd -// IDПодключения - Строка, Число - ID активного подключения. См. ОжидатьПодключение - conn -// Данные - ДвоичныеДанные - Данные для отправки - data +// IDПодключения - Строка, Число - ID активного подключения. См. ОжидатьПодключение - conn +// Данные - ДвоичныеДанные - Данные для отправки - data +// TCPОбработчик - Произвольный - TCP сервер или пустое значение при обособленной обоработке - hnd // // Возвращаемое значение: // Структура Из КлючИЗначение - Информация о выполнении -Функция ОтправитьДанные(Знач TCPОбработчик, Знач IDПодключения, Знач Данные) Экспорт +Функция ОтправитьОтвет(Знач IDПодключения, Знач Данные, Знач TCPОбработчик = "") Экспорт - Если Не ЭтоСервер(TCPОбработчик) Тогда - - OPI_ПреобразованиеТипов.ПолучитьСтроку(TCPОбработчик); - TCPОбработчик = ПодключитьКомпонентуНаСервере("OPI_TCPServer", "Handler"); - - КонецЕсли; - OPI_ПреобразованиеТипов.ПолучитьСтроку(IDПодключения); OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(Данные); + + Если Не ЭтоСерверИлиОбработчик(TCPОбработчик) Тогда + TCPОбработчик = ПодключитьКомпонентуНаСервере("OPI_TCPServer", "Handler"); + КонецЕсли; Результат = TCPОбработчик.Send(IDПодключения, Данные); @@ -466,21 +478,18 @@ // Закрывает существующее соединение по идентификатору // // Параметры: -// TCPОбработчик - Произвольный - TCP сервер или идентификатор подключения - hnd -// IDПодключения - Строка, Число - ID активного подключения. См. ОжидатьПодключение - conn +// IDПодключения - Строка, Число - ID активного подключения. См. ОжидатьПодключение - conn +// TCPОбработчик - Произвольный - TCP сервер или пустое значение при обособленной обоработке - hnd // // Возвращаемое значение: // Структура Из КлючИЗначение - Информация о выполнении -Функция ЗакрытьВходящееСоединение(Знач TCPОбработчик, Знач IDПодключения) Экспорт - - Если Не ЭтоСервер(TCPОбработчик) Тогда - - OPI_ПреобразованиеТипов.ПолучитьСтроку(TCPОбработчик); - TCPОбработчик = ПодключитьКомпонентуНаСервере("OPI_TCPServer", "Handler"); - - КонецЕсли; +Функция ЗакрытьВходящееСоединение(Знач IDПодключения, Знач TCPОбработчик = "") Экспорт OPI_ПреобразованиеТипов.ПолучитьСтроку(IDПодключения); + + Если Не ЭтоСерверИлиОбработчик(TCPОбработчик) Тогда + TCPОбработчик = ПодключитьКомпонентуНаСервере("OPI_TCPServer", "Handler"); + КонецЕсли; Результат = TCPОбработчик.Close(IDПодключения); @@ -491,21 +500,6 @@ КонецФункции - -// Это сервер !NOCLI -// Определяет, является ли переданное значение объектом TCP сервера -// -// Параметры: -// Значение - Произвольный - произвольное значение для проверки - value -// -// Возвращаемое значение: -// Булево - Это сервер -Функция ЭтоСервер(Знач Значение) Экспорт - - Возврат Строка(ТипЗнч(Значение)) = "AddIn.OPI_TCPServer.Main"; - -КонецФункции - #КонецОбласти #КонецОбласти @@ -527,6 +521,13 @@ КонецФункции +Функция ЭтоСерверИлиОбработчик(Знач Значение) + + Возврат Строка(ТипЗнч(Значение)) = "AddIn.OPI_TCPServer.Server" + Или Строка(ТипЗнч(Значение)) = "AddIn.OPI_TCPServer.Handler"; + +КонецФункции + Процедура ОбработатьРезультат(Результат) Попытка diff --git a/src/ru/OPI/src/CommonModules/OPI_Тесты/Module.bsl b/src/ru/OPI/src/CommonModules/OPI_Тесты/Module.bsl index e028882080..1167cbfa79 100644 --- a/src/ru/OPI/src/CommonModules/OPI_Тесты/Module.bsl +++ b/src/ru/OPI/src/CommonModules/OPI_Тесты/Module.bsl @@ -16474,55 +16474,73 @@ TCPСервер = OPI_TCP.СоздатьСервер(7788, Истина); - НовоеПодключение = OPI_TCP.ОжидатьПодключение(TCPСервер, 20); + НовоеПодключение = OPI_TCP.ОжидатьВходящиеСоединения(TCPСервер, 20); Если НовоеПодключение["result"] Тогда Подключение = НовоеПодключение["connection"]["id"]; - Адрес = НовоеПодключение.connection.addr; - ЗапросДвочиные = OPI_TCP.ПолучитьДанные(TCPСервер, Подключение); - ЗапросТекст = ПолучитьСтрокуИзДвоичныхДанных(ЗапросДвочиные); + МассивПараметровОбработки = Новый Массив; + МассивПараметровОбработки.Добавить(Подключение); // Строка: "1:7788" + + ФоновоеОбработки = ФоновыеЗадания.Выполнить("OPI_Тесты.TCP_ОбработатьПодключение", МассивПараметровОбработки); + + TCP_ОбработатьПодключение(Подключение); - ОтправкаОтвета = OPI_TCP.ОтправитьДанные(TCPСервер, Подключение, ПолучитьДвоичныеДанныеИзСтроки("Yo")); - ЗакрытиеПодключения = OPI_TCP.ЗакрытьВходящееСоединение(TCPСервер, Подключение); - КонецЕсли; Отключение = OPI_TCP.ОтключитьСервер(TCPСервер); - - ЗаданиеКлиента = ФоновоеКлиента.ОжидатьЗавершенияВыполнения(); - + // END - OPI_ПолучениеДанныхТестов.ЗаписатьЛог(TCPСервер, "ОжидатьПодключение (сервер)", "TCP"); - OPI_ПолучениеДанныхТестов.Проверка_Компонента(TCPСервер, "AddIn.OPI_TCPServer.Main"); + ЗаданиеКлиента = ФоновоеКлиента.ОжидатьЗавершенияВыполнения(); + ЗаданиеОбработки = ФоновоеОбработки.ОжидатьЗавершенияВыполнения(); - OPI_ПолучениеДанныхТестов.ЗаписатьЛог(TCPСервер, "ОжидатьПодключение", "TCP"); + + OPI_ПолучениеДанныхТестов.ЗаписатьЛог(TCPСервер, "ОжидатьПодключение (сервер)", "TCP"); + OPI_ПолучениеДанныхТестов.Проверка_Компонента(TCPСервер, "AddIn.OPI_TCPServer.Server"); + + OPI_ПолучениеДанныхТестов.ЗаписатьЛог(НовоеПодключение, "ОжидатьПодключение", "TCP"); OPI_ПолучениеДанныхТестов.Проверка_РезультатИстина(НовоеПодключение); - OPI_ПолучениеДанныхТестов.ЗаписатьЛог(TCPСервер, "ОжидатьПодключение (подключение)", "TCP"); - OPI_ПолучениеДанныхТестов.Проверка_Строка(Подключение, "1"); + OPI_ПолучениеДанныхТестов.ЗаписатьЛог(Подключение, "ОжидатьПодключение (подключение)", "TCP"); + OPI_ПолучениеДанныхТестов.Проверка_Строка(Подключение, "7788:1"); - OPI_ПолучениеДанныхТестов.ЗаписатьЛог(TCPСервер, "ОжидатьПодключение (сообщение)", "TCP"); - OPI_ПолучениеДанныхТестов.Проверка_Строка(ЗапросТекст, Сообщение); - - OPI_ПолучениеДанныхТестов.ЗаписатьЛог(TCPСервер, "ОжидатьПодключение (ответ)", "TCP"); - OPI_ПолучениеДанныхТестов.Проверка_РезультатИстина(ОтправкаОтвета); - - OPI_ПолучениеДанныхТестов.ЗаписатьЛог(TCPСервер, "ОжидатьПодключение (закрытие)", "TCP"); - OPI_ПолучениеДанныхТестов.Проверка_РезультатИстина(ЗакрытиеПодключения); - - OPI_ПолучениеДанныхТестов.ЗаписатьЛог(TCPСервер, "ОжидатьПодключение (отвключение)", "TCP"); + OPI_ПолучениеДанныхТестов.ЗаписатьЛог(Отключение, "ОжидатьПодключение (отвключение)", "TCP"); OPI_ПолучениеДанныхТестов.Проверка_РезультатИстина(Отключение); Состояние = Строка(ЗаданиеКлиента.Состояние); - OPI_ПолучениеДанныхТестов.ЗаписатьЛог(TCPСервер, "ОжидатьПодключение (фоновое)", "TCP"); + OPI_ПолучениеДанныхТестов.ЗаписатьЛог(Состояние, "ОжидатьПодключение (фоновое)", "TCP"); OPI_ПолучениеДанныхТестов.Проверка_Строка(Состояние, "Задание выполнено"); КонецПроцедуры +Процедура TCP_ОбработатьПодключение(Подключение) Экспорт + + // Подключение - Строка: "1:7788" + + ЗапросДвочиные = OPI_TCP.ПолучитьЗапрос(Подключение); + ЗапросТекст = ПолучитьСтрокуИзДвоичныхДанных(ЗапросДвочиные); + + ОтправкаОтвета = OPI_TCP.ОтправитьОтвет(Подключение, ПолучитьДвоичныеДанныеИзСтроки("Yo")); + ЗакрытиеПодключения = OPI_TCP.ЗакрытьВходящееСоединение(Подключение); + + // END + + Сообщение = "Тестовая отправка данных на сервер"; + + OPI_ПолучениеДанныхТестов.ЗаписатьЛог(Сообщение, "ОжидатьПодключение (сообщение)", "TCP"); + OPI_ПолучениеДанныхТестов.Проверка_Строка(ЗапросТекст, Сообщение); + + OPI_ПолучениеДанныхТестов.ЗаписатьЛог(ОтправкаОтвета, "ОжидатьПодключение (ответ)", "TCP"); + OPI_ПолучениеДанныхТестов.Проверка_РезультатИстина(ОтправкаОтвета); + + OPI_ПолучениеДанныхТестов.ЗаписатьЛог(ЗакрытиеПодключения, "ОжидатьПодключение (закрытие)", "TCP"); + OPI_ПолучениеДанныхТестов.Проверка_РезультатИстина(ЗакрытиеПодключения); + +КонецПроцедуры + #КонецОбласти #Область SQLite diff --git a/src/ru/OPI/src/CommonTemplates/OPI_TCPServer/Template.addin b/src/ru/OPI/src/CommonTemplates/OPI_TCPServer/Template.addin index 0919771b78..ae81c0c243 100644 Binary files a/src/ru/OPI/src/CommonTemplates/OPI_TCPServer/Template.addin and b/src/ru/OPI/src/CommonTemplates/OPI_TCPServer/Template.addin differ