Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Получает полное протокольное сообщение из интерфейса
- int receive_protocol_message(IOInterface *io, int handle, Message *message) {
- if (!io || !io->receive_data || handle < 0 || !message) {
- fprintf(stderr, "receive_protocol_message: Invalid arguments\n");
- return -1;
- }
- MessageHeader header_net;
- ssize_t bytesRead;
- size_t totalBytesRead;
- // --- Этап 1: Чтение заголовка ---
- totalBytesRead = 0;
- while (totalBytesRead < sizeof(MessageHeader)) {
- bytesRead = io->receive_data(handle, ((char*)&header_net) + totalBytesRead, sizeof(MessageHeader) - totalBytesRead);
- if (bytesRead < 0) {
- // -2 означает таймаут/прерывание poll/EINTR read - просто повторяем попытку
- if (bytesRead == -2 || errno == EINTR) {
- errno = 0; // Сбрасываем errno для EINTR
- usleep(10000); // Небольшая пауза перед повтором
- continue;
- }
- // Другая ошибка чтения
- fprintf(stderr, "receive_protocol_message: Ошибка получения заголовка (io->receive_data вернул %zd, errno %d: %s)\n",
- bytesRead, errno, strerror(errno));
- return -1; // Критическая ошибка
- } else if (bytesRead == 0) {
- // Для TCP это точно закрытие. Для Serial - маловероятно, но тоже обработаем как закрытие.
- printf("receive_protocol_message: Соединение закрыто при чтении заголовка (получено 0 байт).\n");
- return 1; // Соединение закрыто
- }
- // Данные получены
- totalBytesRead += bytesRead;
- }
- // Заголовок прочитан успешно
- memcpy(&message->header, &header_net, sizeof(MessageHeader));
- // --- Этап 2: Преобразование длины тела и чтение тела ---
- uint16_t bodyLenNet = message->header.body_length;
- uint16_t bodyLenHost = ntohs(bodyLenNet);
- if (bodyLenHost > MAX_MESSAGE_BODY_SIZE) {
- fprintf(stderr, "receive_protocol_message: Ошибка: Полученная длина тела (%u) > MAX (%d).\n", bodyLenHost, MAX_MESSAGE_BODY_SIZE);
- return -1;
- }
- if (bodyLenHost > 0) {
- totalBytesRead = 0;
- while (totalBytesRead < bodyLenHost) {
- bytesRead = io->receive_data(handle, message->body + totalBytesRead, bodyLenHost - totalBytesRead);
- if (bytesRead < 0) {
- if (errno == EINTR || bytesRead == -2) {
- errno = 0;
- usleep(10000);
- continue; // Повторить попытку
- }
- fprintf(stderr, "receive_protocol_message: Ошибка получения тела сообщения (io->receive_data вернул %zd, errno %d: %s)\n",
- bytesRead, errno, strerror(errno));
- return -1; // Критическая ошибка
- } else if (bytesRead == 0) {
- // Для TCP это закрытие. Для Serial может означать, что просто больше нет данных *сейчас*.
- // Однако, если мы ожидаем тело определенной длины, а получили 0, это проблема.
- fprintf(stderr, "receive_protocol_message: Соединение закрыто при чтении тела (получено 0 байт, ожидалось %u).\n", (unsigned int)(bodyLenHost - totalBytesRead));
- return 1; // Считаем соединение закрытым
- }
- totalBytesRead += bytesRead;
- }
- }
- // Тело прочитано успешно
- // --- Этап 3: Преобразование всего сообщения в хост-порядок ---
- message->header.body_length = bodyLenNet;
- message_to_host_byte_order(message);
- printf("Получено сообщение через %s: Тип=%u, Номер=%u, Длина тела=%u, Handle=%d\n",
- (io->type == IO_TYPE_ETHERNET) ? "Ethernet" : ((io->type == IO_TYPE_SERIAL) ? "Serial" : "Unknown"),
- message->header.message_type,
- get_full_message_number(&message->header),
- message->header.body_length,
- handle);
- return 0; // Успех
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement