1
0
mirror of https://github.com/Bayselonarrend/OpenIntegrations.git synced 2025-12-01 22:29:52 +02:00

FTP: Доработка компоненты, исключение shutdown_delay для TLS

This commit is contained in:
Anton Titovets
2025-08-04 11:07:21 +03:00
parent 328f936fa8
commit 46dbda706c
13 changed files with 55 additions and 74 deletions

View File

@@ -445,7 +445,6 @@ dependencies = [
"rustls-pemfile",
"serde",
"serde_json",
"socket2",
"socks",
"suppaftp",
"webpki-roots",
@@ -661,16 +660,6 @@ version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "socket2"
version = "0.5.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678"
dependencies = [
"libc",
"windows-sys 0.52.0",
]
[[package]]
name = "socks"
version = "0.3.4"

View File

@@ -23,5 +23,4 @@ base64 = "0.22.1"
chrono = { version = "0.4", features = ["serde"] }
webpki-roots = "1.0.1"
rustls = { version = "0.23.28", features = ["ring"] }
rustls-pemfile = "2.2.0"
socket2 = "0.5.10"
rustls-pemfile = "2.2.0"

View File

@@ -1,9 +1,9 @@
"MAIN ---"
linux-vdso.so.1 (0x00007ffc0467e000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x000070aa97000000)
libc.so.6 => /lib64/libc.so.6 (0x000070aa96c00000)
libdl.so.2 => /lib64/libdl.so.2 (0x000070aa96800000)
/lib64/ld-linux-x86-64.so.2 (0x000070aa97600000)
linux-vdso.so.1 (0x00007ffe4c948000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x0000759ff8e00000)
libc.so.6 => /lib64/libc.so.6 (0x0000759ff8a00000)
libdl.so.2 => /lib64/libdl.so.2 (0x0000759ff8600000)
/lib64/ld-linux-x86-64.so.2 (0x0000759ff9400000)
GLIBC_2.2.5
GLIBC_2.3
GLIBC_2.3.4

View File

@@ -26,5 +26,4 @@ pub struct FtpTlsSettings {
pub use_tls: bool,
pub accept_invalid_certs: bool,
pub ca_cert_path: Option<String>,
pub shutdown_delay: u64,
}

View File

@@ -1,4 +1,4 @@
use std::io::{copy, BufReader, Cursor, Write};
use std::io::{copy, BufReader, Cursor, ErrorKind, Write};
use std::net::{SocketAddr, TcpStream};
use serde_json::json;
use suppaftp::{FtpResult, FtpStream, Mode, RustlsConnector, RustlsFtpStream};
@@ -7,8 +7,7 @@ use std::str::FromStr;
use chrono::{DateTime, Utc};
use serde::Serialize;
use std::string::String;
use std::thread::sleep;
use std::time::Duration;
use std::time::{Duration, Instant};
use crate::component::configuration::{FtpProxySettings, FtpSettings, FtpTlsSettings};
use crate::component::tls_establish;
use crate::component::tcp_establish;
@@ -158,22 +157,22 @@ impl FtpClient {
}
}
pub fn upload_data(&mut self, path: &str, data: &[u8], tls_delay: u64) -> String {
pub fn upload_data(&mut self, path: &str, data: &[u8]) -> String {
let mut cursor = Cursor::new(data);
match self.upload_from_reader(path, &mut cursor, tls_delay) {
match self.upload_from_reader(path, &mut cursor) {
Ok(bytes) => json!({"result": true, "bytes": bytes}).to_string(),
Err(e) => format_json_error(e)
}
}
pub fn upload_file(&mut self, path: &str, filepath: &str, tls_delay: u64) -> String {
pub fn upload_file(&mut self, path: &str, filepath: &str) -> String {
let file = match std::fs::File::open(filepath) {
Ok(f) => f,
Err(e) => return format_json_error(format!("File error: {}", e))
};
let mut buf_reader = BufReader::new(file);
match self.upload_from_reader(path, &mut buf_reader, tls_delay) {
match self.upload_from_reader(path, &mut buf_reader) {
Ok(bytes) => json!({"result": true, "bytes": bytes}).to_string(),
Err(e) => format_json_error(e)
}
@@ -204,8 +203,7 @@ impl FtpClient {
fn upload_from_reader<R: std::io::Read>(
&mut self,
path: &str,
reader: &mut R,
tls_delay: u64
reader: &mut R
) -> Result<u64, String> {
match self {
FtpClient::Secure(stream) => {
@@ -213,11 +211,16 @@ impl FtpClient {
let mut data_stream = stream.put_with_stream(path)
.map_err(|e| format!("Data stream error: {}", e))?;
let bytes = copy(reader, &mut data_stream)
.map_err(|e| format!("Upload error: {}", e))?;
let _ = data_stream.flush();
sleep(Duration::from_millis(tls_delay));
let bytes = match copy(reader, &mut data_stream) {
Ok(b) => {
match wait_for_writable(&mut data_stream, Duration::from_secs(5)){
Ok(_) => {},
Err(e) => return Err(e)
};
b
},
Err(e) => return Err(format!("Upload error: {}", &e.to_string()))
};
stream.finalize_put_stream(data_stream)
.map(|_| bytes)
@@ -301,4 +304,24 @@ fn format_json_error<E: ToString>(error: E) -> String {
"error": error_message,
});
json_obj.to_string()
}
fn wait_for_writable<S>(stream: &mut S, timeout: Duration) -> Result<(), String>
where
S: Write
{
let start = Instant::now();
loop {
match stream.write(&[]) {
Ok(_) => return Ok(()),
Err(e) if e.kind() == ErrorKind::WouldBlock => {
if start.elapsed() > timeout {
return Err("Check error: Write timed out".to_string());
}
std::thread::yield_now();
}
Err(e) => return Err(format!("Check error: {}", e.to_string())),
}
}
}

View File

@@ -43,7 +43,7 @@ pub fn get_params_amount(num: usize) -> usize {
1 => 0,
2 => 1,
3 => 1,
4 => 4,
4 => 3,
5 => 0,
6 => 1,
7 => 1,
@@ -79,9 +79,8 @@ pub fn cal_func(obj: &mut AddIn, num: usize, params: &mut [Variant]) -> Box<dyn
let use_tls = params[0].get_bool().unwrap_or(false);
let accept_invalid_certs = params[1].get_bool().unwrap_or(false);
let ca_cert_path = params[2].get_string().unwrap_or("".to_string());
let shutdown_delay = params[3].get_i32().unwrap_or(0);
Box::new(obj.set_tls(use_tls, accept_invalid_certs, &ca_cert_path, shutdown_delay as u64))
Box::new(obj.set_tls(use_tls, accept_invalid_certs, &ca_cert_path))
},
5 => {
@@ -127,13 +126,8 @@ pub fn cal_func(obj: &mut AddIn, num: usize, params: &mut [Variant]) -> Box<dyn
let path = params[1].get_string().unwrap_or("".to_string());
let tls_delay = match &obj.tls_settings{
Some(s) => s.shutdown_delay,
None => 0
};
Box::new(match &mut obj.get_client(){
Ok(c) => c.upload_data(&path, data, tls_delay),
Ok(c) => c.upload_data(&path, data),
Err(e) => e.to_string()
})
},
@@ -142,13 +136,8 @@ pub fn cal_func(obj: &mut AddIn, num: usize, params: &mut [Variant]) -> Box<dyn
let filepath = params[0].get_string().unwrap_or("".to_string());
let path = params[1].get_string().unwrap_or("".to_string());
let tls_delay = match &obj.tls_settings{
Some(s) => s.shutdown_delay,
None => 0
};
Box::new(match &mut obj.get_client(){
Ok(c) => c.upload_file(&path, &filepath, tls_delay),
Ok(c) => c.upload_file(&path, &filepath),
Err(e) => e.to_string()
})
@@ -304,8 +293,7 @@ impl AddIn {
pub fn set_tls(&mut self
, use_tls: bool
, accept_invalid_certs: bool
, ca_cert_path: &str
, shutdown_delay: u64) -> String {
, ca_cert_path: &str) -> String {
if self.client.is_some(){
return process_error("TLS settings can only be set before the connection is established");
@@ -316,8 +304,7 @@ impl AddIn {
self.tls_settings = Some(FtpTlsSettings{
use_tls,
accept_invalid_certs,
ca_cert_path: ca_path,
shutdown_delay
ca_cert_path: ca_path
});
json!({"result": true}).to_string()

View File

@@ -3,7 +3,6 @@ use std::net::{SocketAddr, TcpStream};
use std::time::Duration;
use socks::{Socks4Stream, Socks5Stream};
use base64::{Engine as _, engine::general_purpose};
use socket2::Socket;
use suppaftp::FtpError;
use crate::component::configuration::{FtpProxySettings, FtpSettings};

Binary file not shown.

Binary file not shown.

View File

@@ -303,18 +303,16 @@
// Примечание:
// Настройки Tls могут быть установлены только в момент создания соединения: явного, при использовании функции `ОткрытьСоединение`^^
// или неявного, при передаче настроек
// `Задержка` может быть увеличена при низкой скорости соединения для избежания проблем с корректным завершением TLS
//
// Параметры:
// ОтключитьПроверкуСертификатов - Булево - Позволяет работать с некорретными сертификатами, в т.ч. самоподписанными - trust
// ПутьКСертификату - Строка - Путь к корневому PEM файлу сертификата, если его нет в системном хранилище - cert
// Задержка - Число - Задержка перед закрытием соединения для корректного завершения TLS (мс) - delay
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура настроек TLS соединения
Функция ПолучитьНастройкиTls(Знач ОтключитьПроверкуСертификатов, Знач ПутьКСертификату = "", Знач Задержка = 250) Экспорт
Функция ПолучитьНастройкиTls(Знач ОтключитьПроверкуСертификатов, Знач ПутьКСертификату = "") Экспорт
Возврат OPI_Компоненты.ПолучитьНастройкиTls(ОтключитьПроверкуСертификатов, ПутьКСертификату, Задержка);
Возврат OPI_Компоненты.ПолучитьНастройкиTls(ОтключитьПроверкуСертификатов, ПутьКСертификату);
КонецФункции

View File

@@ -84,25 +84,15 @@
СообщениеОшибки = "Переданы некорректные настройки Tls!";
OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(Tls, СообщениеОшибки);
ИспользоватьTls = OPI_Инструменты.ПолучитьИли(Tls, "use_tls", Ложь);
ИспользоватьTls = OPI_Инструменты.ПолучитьИли(Tls, "use_tls" , Ложь);
ОтключитьВалидацию = OPI_Инструменты.ПолучитьИли(Tls, "accept_invalid_certs", Ложь);
ПутьКСертификату = OPI_Инструменты.ПолучитьИли(Tls, "ca_cert_path", "");
ПутьКСертификату = OPI_Инструменты.ПолучитьИли(Tls, "ca_cert_path" , "");
OPI_ПреобразованиеТипов.ПолучитьБулево(ИспользоватьTls);
OPI_ПреобразованиеТипов.ПолучитьБулево(ОтключитьВалидацию);
OPI_ПреобразованиеТипов.ПолучитьСтроку(ПутьКСертификату);
Задержка = Неопределено;
Если OPI_Инструменты.ПолеКоллекцииСуществует(Tls, "shutdown_delay", Задержка) Тогда
OPI_ПреобразованиеТипов.ПолучитьЧисло(Задержка);
Результат = Компонета.SetTLS(ИспользоватьTls, ОтключитьВалидацию, ПутьКСертификату, Задержка);
Иначе
Результат = Компонета.SetTLS(ИспользоватьTls, ОтключитьВалидацию, ПутьКСертификату);
КонецЕсли;
Результат = Компонета.SetTLS(ИспользоватьTls, ОтключитьВалидацию, ПутьКСертификату);
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
КонецЕсли;
@@ -111,15 +101,12 @@
КонецФункции
Функция ПолучитьНастройкиTls(Знач ОтключитьПроверкуСертификатов
, Знач ПутьКСертификату = ""
, Знач Задержка = Неопределено) Экспорт
Функция ПолучитьНастройкиTls(Знач ОтключитьПроверкуСертификатов, Знач ПутьКСертификату = "") Экспорт
СтруктураСертификата = Новый Структура;
OPI_Инструменты.ДобавитьПоле("use_tls" , Истина , "Булево", СтруктураСертификата);
OPI_Инструменты.ДобавитьПоле("accept_invalid_certs", ОтключитьПроверкуСертификатов, "Булево", СтруктураСертификата);
OPI_Инструменты.ДобавитьПоле("ca_cert_path" , ПутьКСертификату , "Строка", СтруктураСертификата);
OPI_Инструменты.ДобавитьПоле("shutdown_delay" , Задержка , "Число" , СтруктураСертификата);
Возврат СтруктураСертификата;