Advertisement
dtorkin

Untitled

Apr 9th, 2025
278
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.69 KB | None | 0 0
  1. // Получает полное протокольное сообщение из интерфейса
  2. int receive_protocol_message(IOInterface *io, int handle, Message *message) {
  3.     if (!io || !io->receive_data || handle < 0 || !message) {
  4.         fprintf(stderr, "receive_protocol_message: Invalid arguments\n");
  5.         return -1;
  6.     }
  7.  
  8.     MessageHeader header_net;
  9.     ssize_t bytesRead;
  10.     size_t totalBytesRead;
  11.  
  12.     // --- Этап 1: Чтение заголовка ---
  13.     totalBytesRead = 0;
  14.     while (totalBytesRead < sizeof(MessageHeader)) {
  15.         bytesRead = io->receive_data(handle, ((char*)&header_net) + totalBytesRead, sizeof(MessageHeader) - totalBytesRead);
  16.  
  17.         if (bytesRead < 0) {
  18.             // -2 означает таймаут/прерывание poll/EINTR read - просто повторяем попытку
  19.             if (bytesRead == -2 || errno == EINTR) {
  20.                  errno = 0; // Сбрасываем errno для EINTR
  21.                  usleep(10000); // Небольшая пауза перед повтором
  22.                  continue;
  23.             }
  24.             // Другая ошибка чтения
  25.             fprintf(stderr, "receive_protocol_message: Ошибка получения заголовка (io->receive_data вернул %zd, errno %d: %s)\n",
  26.                     bytesRead, errno, strerror(errno));
  27.             return -1; // Критическая ошибка
  28.         } else if (bytesRead == 0) {
  29.             // Для TCP это точно закрытие. Для Serial - маловероятно, но тоже обработаем как закрытие.
  30.              printf("receive_protocol_message: Соединение закрыто при чтении заголовка (получено 0 байт).\n");
  31.              return 1; // Соединение закрыто
  32.         }
  33.         // Данные получены
  34.         totalBytesRead += bytesRead;
  35.     }
  36.     // Заголовок прочитан успешно
  37.  
  38.     memcpy(&message->header, &header_net, sizeof(MessageHeader));
  39.  
  40.     // --- Этап 2: Преобразование длины тела и чтение тела ---
  41.     uint16_t bodyLenNet = message->header.body_length;
  42.     uint16_t bodyLenHost = ntohs(bodyLenNet);
  43.  
  44.     if (bodyLenHost > MAX_MESSAGE_BODY_SIZE) {
  45.         fprintf(stderr, "receive_protocol_message: Ошибка: Полученная длина тела (%u) > MAX (%d).\n", bodyLenHost, MAX_MESSAGE_BODY_SIZE);
  46.         return -1;
  47.     }
  48.  
  49.     if (bodyLenHost > 0) {
  50.         totalBytesRead = 0;
  51.         while (totalBytesRead < bodyLenHost) {
  52.              bytesRead = io->receive_data(handle, message->body + totalBytesRead, bodyLenHost - totalBytesRead);
  53.              if (bytesRead < 0) {
  54.                  if (errno == EINTR || bytesRead == -2) {
  55.                      errno = 0;
  56.                      usleep(10000);
  57.                      continue; // Повторить попытку
  58.                  }
  59.                 fprintf(stderr, "receive_protocol_message: Ошибка получения тела сообщения (io->receive_data вернул %zd, errno %d: %s)\n",
  60.                         bytesRead, errno, strerror(errno));
  61.                 return -1; // Критическая ошибка
  62.              } else if (bytesRead == 0) {
  63.                   // Для TCP это закрытие. Для Serial может означать, что просто больше нет данных *сейчас*.
  64.                   // Однако, если мы ожидаем тело определенной длины, а получили 0, это проблема.
  65.                   fprintf(stderr, "receive_protocol_message: Соединение закрыто при чтении тела (получено 0 байт, ожидалось %u).\n", (unsigned int)(bodyLenHost - totalBytesRead));
  66.                   return 1; // Считаем соединение закрытым
  67.              }
  68.             totalBytesRead += bytesRead;
  69.         }
  70.     }
  71.     // Тело прочитано успешно
  72.  
  73.     // --- Этап 3: Преобразование всего сообщения в хост-порядок ---
  74.     message->header.body_length = bodyLenNet;
  75.     message_to_host_byte_order(message);
  76.  
  77.     printf("Получено сообщение через %s: Тип=%u, Номер=%u, Длина тела=%u, Handle=%d\n",
  78.            (io->type == IO_TYPE_ETHERNET) ? "Ethernet" : ((io->type == IO_TYPE_SERIAL) ? "Serial" : "Unknown"),
  79.            message->header.message_type,
  80.            get_full_message_number(&message->header),
  81.            message->header.body_length,
  82.            handle);
  83.  
  84.     return 0; // Успех
  85. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement