Ошибки, баги, вопросы - страница 2706

 
Slava:

Ошибка открытия файла dip.ex5

Покажите полный лог, а не кусок скриншота

см. вложение

Файлы:
20200415.zip  5 kb
 

Кто-нибудь может подсказать, как подружить TLS-сокеты с эхо-сервером? Взял исходник из примера, допилил заголовки. На порту 80 делает апгрейд, а на 443 - коннектится, получает сертификат, но потом ничего не может прочитать из заголовков. Если выполнять под отладчиком, видно что SocketIsReadable возвращает похожее на правду число, типа 245, но SocketTlsRead по таймауту отваливается, ничего не возвращая. Видимо, требуются сакральные знания от MQ.

Файлы:
 

Баг МЕ (build 2380) некорректная сигнатура шаблонного параметра функции в Error Description и Parameter info.

template<typename T>
class A{};

class B{
public:  
   template<typename T>
   static void test(A<T> &, A<int>* = NULL){
      int x = 1 / 0;                       //'0' - division by zero |  in template 'void B::test(B::A<T>&,A<int>*)' specified with [T=long]
   }
};

void OnStart(){
   A<long> a;
   B::test(a);                             // Parameter info: void test([unknown] &, [unknown] *=NULL)
}
 
Stanislav Korotky:

Кто-нибудь может подсказать, как подружить TLS-сокеты с эхо-сервером? Взял исходник из примера, допилил заголовки. На порту 80 делает апгрейд, а на 443 - коннектится, получает сертификат, но потом ничего не может прочитать из заголовков. Если выполнять под отладчиком, видно что SocketIsReadable возвращает похожее на правду число, типа 245, но SocketTlsRead по таймауту отваливается, ничего не возвращая. Видимо, требуются сакральные знания от MQ.

У меня тоже не получилось получить байтовый массив ответа с помощью HTTPRecv, для дальнейшего разбора протокола.
Отваливается по таймауту, потому что не организован ping pong, но чтоб его организовать нужно сперва получить байтовый ответ от сервера, да и сама функция HTTPRecv  содержит таймаут.
Но почему то HTTPRecv не парсит этот байтовый ответ. 

 
Roman:

У меня тоже не получилось получить байтовый массив ответа с помощью HTTPRecv, для дальнейшего разбора протокола.
Отваливается по таймауту, потому что не организован ping pong, но чтоб его организовать нужно сперва получить байтовый ответ от сервера, да и сама функция HTTPRecv  содержит таймаут.
Но почему то HTTPRecv не парсит этот байтовый ответ. 

Это только самое подключение. Там еще нет никакого пин-понга - он может случиться потом в протоколе вебсокетов. Затык происходит на ответном заголовке сервера, когда он должен подтвердить апгрейд. Когда не используется TLS, подключается нормально. Но и с TLS, суда по всему заголовок в терминал приходит, но не возвращается из SocketTlsRead.

 
Stanislav Korotky:

Это только самое подключение. Там еще нет никакого пин-понга - он может случиться потом в протоколе вебсокетов. Затык происходит на ответном заголовке сервера, когда он должен подтвердить апгрейд. Когда не используется TLS, подключается нормально. Но и с TLS, суда по всему заголовок в терминал приходит, но не возвращается из SocketTlsRead.

Ага, понял о чём речь.
Да действительно в вашем коде, на 80 порт заголовок возвращается, на 443 нет.
Пересмотрел ваш код ещё раз, и не увидел там функцию SocketTlsHandshake.
Ваш код не производит рукопожатия. Возможно в этом дело.
Хотя в справке к этой функции говорится, что она не обязательна, если коннект идёт на 443 порт.
Странно в общем.

UPD:
Как не составлял заголовок запроса, всё равно приходит ошибка

ERR_NETSOCKET_IO_ERROR 5273 Ошибка отправки/получения данных из сокета

 или

HTTP/1.1 400 Bad Request

Может разработчик запретил получение апгрейда на TLS?


UPD:
С вашим заголовком ошибок нет, но и заголовка ответа нет.
В функции HTTPRecv поставил принт, чтоб посмотреть что вообще приходит

result += CharArrayToString(rsp, 0, rsp_len, CP_UTF8);
Print(result);

Принтует только один символ H
По символу можно предположить, что это первая буква заголовка ответа,
остальное содержимое заголовка почему то не выводит. 

Уважаемые разработчики, подскажите как быть?
Это намеренное ограничение, или всё таки ошибка в TLS ?
Просто тоже давно бьюсь с этой проблемой, и безуспешно.

 
Sergey Dzyublik:

Прошу разработчиков (@Ilyas) обратить внимание на обнаруженный дефект.
Баг МТ5 (build 2377) при выборе подходящей перегруженной функции для аргумента типа указатель более приоритетной становится функция с приведением типа в указатель на родительский класс вместо базового.
Так же отсутствие compile time error, когда указатель на базовый класс присваивается указателю на родительский класс. 

Возможно связанный с данным багом дефект: https://www.mql5.com/ru/forum/1111/page2682#comment_15591437

class A{};
class B : public A{};
class C : public B{};


struct T{
   static void test(A*){
      printf("A*");
   }
   static void test(C*){
      printf("C*");
   }
};

struct TT{
   static void test(B*){
      printf("B*");
   }
};

void OnStart(){
   B b;
   T::test(&b);            // Runtime Error: Incorrect casting of pointers.  Expected result: printf("A*");
   
   A a;
   TT::test(&a);           // Runtime Error: Incorrect casting of pointers.  Expected result: Compilation Error
   B* ptr = &a;            // Runtime Error: Incorrect casting of pointers.  Expected result: Compilation Error
}

Спасибо за сообщение.

Исправлено

Runtime Error: Incorrect casting of pointers.  Expected result: printf("A*");


Остаётся как есть - этот код может получиться в результате специализации шаблона (в части, которая работать не будет, но на компиляцию повлияет).

Runtime Error: Incorrect casting of pointers.  Expected result: Compilation Error
Runtime Error: Incorrect casting of pointers.  Expected result: Compilation Error
 
Roman:

Да действительно в вашем коде, на 80 порт заголовок возвращается, на 443 нет.
Пересмотрел ваш код ещё раз, и не увидел там функцию SocketTlsHandshake.
Ваш код не производит рукопожатия. Возможно в этом дело.
Хотя в справке к этой функции говорится, что она не обязательна, если коннект идёт на 443 порт.

Вот именно, что это не мой код, а из примера разработчиков (у сокетов от MQ - некоторые неинтуитивные особенности, которые выясняются иногда на форуме, поэтому обратился к стандартному примеру). SocketTlsHandshake я пробовал - он у меня всегда во всех условиях возвращает false и не оказывает никакого влияния на решение проблем. Поскольку возвращаются данные сертификата, рукопожатие проходит. Даже заголовок судя по длине приходит, но просто не возвращается в MQL-код. Код ошибки слишком общий, и сам факт ошибки сомнителен. Нужен взгляд изнутри.
 
Stanislav Korotky:
Вот именно, что это не мой код, а из примера разработчиков (у сокетов от MQ - некоторые неинтуитивные особенности, которые выясняются иногда на форуме, поэтому обратился к стандартному примеру). SocketTlsHandshake я пробовал - он у меня всегда во всех условиях возвращает false и не оказывает никакого влияния на решение проблем. Поскольку возвращаются данные сертификата, рукопожатие проходит. Даже заголовок судя по длине приходит, но просто не возвращается в MQL-код. Код ошибки слишком общий, и сам факт ошибки сомнителен. Нужен взгляд изнутри.

Не нужно использовать функцию SocketTlsHandshake, если соединение изначально защищённое ("https://" или порт 443 или 465)

Функция используется в специальных случаях / протоколах

 
Ilyas:

Не нужно использовать функцию SocketTlsHandshake, если соединение изначально защищённое ("https://" или порт 443 или 465)

Функция используется в специальных случаях / протоколах

Я её и не использую. Код для воспроизведения проблемы приложен.