Advertisement
dtorkin

Untitled

Feb 25th, 2025 (edited)
501
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 14.24 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <arpa/inet.h>
  6. #include <netinet/in.h>
  7. #include <pthread.h> // Для работы с потоками
  8. #include <time.h>    // Для работы с таймерами
  9. #include <errno.h>
  10. #include <signal.h>   // Добавлено для signal.h
  11. #include "common.h"
  12.  
  13. #define PORT 8080         // Общий порт для УВМ и СВ-М
  14.  
  15. // Глобальные переменные для счетчика BCB и мьютекса
  16. uint32_t bcb_counter = 0;
  17. pthread_mutex_t bcb_mutex;
  18.  
  19. void timer_handler(union sigval sv) {
  20.     pthread_mutex_lock(&bcb_mutex);
  21.     bcb_counter++;
  22.     pthread_mutex_unlock(&bcb_mutex);
  23. }
  24.  
  25.  
  26. int main() {
  27.     int sockfd, newsockfd;
  28.     struct sockaddr_in serv_addr, cli_addr;
  29.     socklen_t clilen;
  30.     Message received_message;
  31.     uint16_t message_counter = 0;
  32.  
  33.     // Инициализация счетчиков (имитация)
  34.     uint16_t linkup_changes = 0; // Счетчик изменений состояния LinkUp
  35.     uint32_t linkup_low_time = 0; //Счётчик времени LinkUP в 0.
  36.     uint16_t signdet_changes = 0; // Счетчик изменений состояния SignDet
  37.  
  38.     // Состояние СВ-М
  39.     SVMState svm_state = STATE_NOT_INITIALIZED;
  40.  
  41.     // Создаем сокет
  42.     if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  43.         perror("socket creation failed");
  44.         exit(EXIT_FAILURE);
  45.     }
  46.  
  47.     // Заполняем структуру адреса сервера (СВ-М)
  48.     memset(&serv_addr, 0, sizeof(serv_addr));
  49.     serv_addr.sin_family = AF_INET;
  50.     serv_addr.sin_addr.s_addr = INADDR_ANY; // Слушаем на всех интерфейсах
  51.     serv_addr.sin_port = htons(PORT);
  52.  
  53.     // Привязываем сокет к адресу
  54.     if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
  55.         perror("bind failed");
  56.         exit(EXIT_FAILURE);
  57.     }
  58.  
  59.     // Начинаем слушать входящие соединения
  60.     if (listen(sockfd, 5) < 0) { // 5 - максимальная длина очереди ожидающих соединений
  61.         perror("listen failed");
  62.         exit(EXIT_FAILURE);
  63.     }
  64.  
  65.     printf("SVM listening on port %d\n", PORT);
  66.  
  67.     // Инициализация мьютекса и запуск таймера BCB
  68.     pthread_mutex_init(&bcb_mutex, NULL);
  69.  
  70.     struct sigevent sev;
  71.     struct itimerspec its;
  72.     timer_t timerid;
  73.  
  74.     sev.sigev_notify = SIGEV_THREAD;
  75.     sev.sigev_notify_function = timer_handler;
  76.     sev.sigev_notify_attributes = NULL;
  77.     sev.sigev_value.sival_ptr = &timerid;
  78.  
  79.     timer_create(CLOCK_MONOTONIC, &sev, &timerid);
  80.  
  81.     its.it_value.tv_sec = 1;
  82.     its.it_value.tv_nsec = 0;
  83.     its.it_interval = its.it_value;
  84.  
  85.     timer_settime(timerid, 0, &its, NULL);
  86.  
  87.  
  88.     clilen = sizeof(cli_addr);
  89.     // Принимаем входящее соединение (блокирующий вызов)
  90.     if ((newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen)) < 0) {
  91.         perror("accept failed");
  92.         exit(EXIT_FAILURE);
  93.     }
  94.  
  95.     printf("SVM accepted connection from UVM\n");
  96.  
  97.     // Главный цикл обработки сообщений
  98.     while (1)
  99.     {
  100.         // Принимаем сообщение
  101.         memset(&received_message, 0, sizeof(Message)); // Важно обнулять перед приемом!
  102.  
  103.         ssize_t bytes_received = recv(newsockfd, &received_message, sizeof(Message), 0);
  104.         if (bytes_received < 0) {
  105.             perror("recv failed");
  106.             exit(EXIT_FAILURE);
  107.         }
  108.         else if (bytes_received == 0)
  109.         {
  110.             printf("Connection closed by UVM.\n");
  111.             close(newsockfd);
  112.             close(sockfd);
  113.             exit(EXIT_SUCCESS);
  114.         }
  115.         else if (bytes_received < sizeof(MessageHeader)) //Проверка приёма всего заголовка
  116.         {
  117.             printf("Received incomplete message header.\n");
  118.             close(newsockfd);
  119.             close(sockfd);
  120.             exit(EXIT_FAILURE);
  121.  
  122.         }
  123.  
  124.         message_to_host_byte_order(&received_message); //После приёма
  125.  
  126.         // --- ОБРАБОТКА СООБЩЕНИЙ ---
  127.         if (svm_state == STATE_NOT_INITIALIZED) {
  128.             // Если СВ-М не инициализирован, обрабатываем только "Инициализацию канала"
  129.             if (received_message.header.message_type == MESSAGE_TYPE_INIT_CHANNEL) {
  130.                 printf("Received Init Channel message\n");
  131.                 // Обработка полученного сообщения (пример)
  132.                 uint16_t received_message_number = get_full_message_number(&received_message.header);
  133.                 printf("Received message number: %u\n", received_message_number);
  134.                 InitChannelBody *body = (InitChannelBody *)received_message.body;
  135.                 printf("Received Init Channel message from UVM: LAUVM=0x%02X, LAK=0x%02X\n", body->LAUVM, body->LAK);
  136.  
  137.                 // --- ОБРАБОТКА СООБЩЕНИЯ "ИНИЦИАЛИЗАЦИЯ КАНАЛА" (3.3.3) ---
  138.                 // 1. Отключение излучения лазера (имитация)
  139.                 printf("SVM: Emulating laser shutdown in unused channel...\n");
  140.  
  141.                 // 2. Запуск счетчиков (имитация)
  142.                 // bcb_counter++;  // Увеличение счетчика времени работы - ТЕПЕРЬ ДЕЛАЕТ ТАЙМЕР!
  143.                 linkup_changes++; // Имитируем изменение состояния LinkUp
  144.  
  145.                 // 3. Формируем ответ
  146.                 uint8_t slp = 0x03; // Оба канала LinkUp в состоянии 1 (включены)
  147.                 uint8_t vdr = 0x01;  // Версия прошивки (пример)
  148.                 uint8_t vor1 = 0x02; // Версия прошивки (пример)
  149.                 uint8_t vor2 = 0x03; // Версия прошивки (пример)
  150.  
  151.                 // Создаем сообщение "Подтверждение инициализации канала"
  152.                 pthread_mutex_lock(&bcb_mutex);
  153.                 Message confirm_message = create_confirm_init_message(LOGICAL_ADDRESS_SVM_PB_BZ_CHANNEL_1, slp, vdr, vor1, vor2, bcb_counter, message_counter++);
  154.                 pthread_mutex_unlock(&bcb_mutex);
  155.  
  156.  
  157.                 message_to_network_byte_order(&confirm_message); //Перед отправкой
  158.                 // Отправляем сообщение "Подтверждение инициализации канала"
  159.                 if (send(newsockfd, &confirm_message, sizeof(MessageHeader) + ntohs(confirm_message.header.body_length), 0) < 0)
  160.                 {
  161.                     perror("Send confirmation init error");
  162.                     exit(EXIT_FAILURE);
  163.                 }
  164.                 printf("Sent Confirm Init message\n");
  165.                 //-----------------
  166.  
  167.                 svm_state = STATE_INITIALIZED; // Переходим в состояние "инициализирован"
  168.             }
  169.             else
  170.             {
  171.                 printf("SVM: Ignoring message (not initialized). Type: %u\n", received_message.header.message_type);
  172.             }
  173.         }
  174.         else if(svm_state == STATE_INITIALIZED)
  175.         {
  176.             // Добавлена обработка "Провести контроль"
  177.             if (received_message.header.message_type == MESSAGE_TYPE_PROVESTI_KONTROL) {
  178.                 printf("Received Provesti Kontrol message\n");
  179.  
  180.                 // Имитация самоконтроля
  181.                 printf("SVM: Emulating self-test...\n");
  182.                 // bcb_counter++; // Увеличиваем счетчик (имитация времени) - ТЕПЕРЬ ДЕЛАЕТ ТАЙМЕР
  183.  
  184.                 // Отправляем "Подтверждение контроля"
  185.                 ProvestiKontrolBody *received_body = (ProvestiKontrolBody *)received_message.body; // Получаем тело принятого сообщения
  186.                 pthread_mutex_lock(&bcb_mutex);
  187.                 Message confirm_message = create_podtverzhdenie_kontrolya_message(LOGICAL_ADDRESS_SVM_PB_BZ_CHANNEL_1, received_body->TK, bcb_counter, message_counter++);
  188.                 pthread_mutex_unlock(&bcb_mutex);
  189.  
  190.                 message_to_network_byte_order(&confirm_message);
  191.                  if (send(newsockfd, &confirm_message, sizeof(MessageHeader) + ntohs(confirm_message.header.body_length), 0) < 0) {
  192.                     perror("send podtverzhdenie_kontrolya failed");
  193.                     exit(EXIT_FAILURE);
  194.                 }
  195.                 printf("Sent Podtverzhdenie Kontrolya message\n");
  196.             }
  197.             // Добавлена обработка "Выдать результаты контроля"
  198.             else if (received_message.header.message_type == MESSAGE_TYPE_VYDAT_RESULTATY_KONTROLYA) {
  199.                 printf("Received Vydat Rezultaty Kontrolya message\n");
  200.  
  201.                 // Имитация получения результатов контроля (пока константы)
  202.                 uint8_t rsk = 0x01; // Типа "успешно"
  203.                 uint16_t bck = 100;  // Типа 100 мс
  204.                 // Отправляем "Результаты контроля"
  205.                  pthread_mutex_lock(&bcb_mutex);
  206.                 Message results_message = create_rezultaty_kontrolya_message(LOGICAL_ADDRESS_SVM_PB_BZ_CHANNEL_1, rsk, bck, bcb_counter, message_counter++);
  207.                 pthread_mutex_unlock(&bcb_mutex);
  208.  
  209.                 message_to_network_byte_order(&results_message);
  210.                 if (send(newsockfd, &results_message, sizeof(MessageHeader) + ntohs(results_message.header.body_length), 0) < 0) {
  211.                     perror("send rezultaty_kontrolya failed");
  212.                     exit(EXIT_FAILURE);
  213.                 }
  214.                 printf("Sent Rezultaty Kontrolya message\n");
  215.             }
  216.              // Добавлена обработка "Выдать состояние линии"
  217.             else if (received_message.header.message_type == MESSAGE_TYPE_VYDAT_SOSTOYANIE_LINII) {
  218.                 printf("Received Vydat Sostoyanie Linii message\n");
  219.  
  220.                 // Имитация получения состояния линий (пока константы)
  221.                 uint16_t kla = 0x0001; // Типа 1 изменение LinkUp
  222.                 uint32_t sla = 0x00000000; // Типа LinkUp всегда в высоком состоянии
  223.                 uint16_t ksa = 0x0000;     // Типа SignDet всегда 1 (сигнал есть)
  224.  
  225.                 // Отправляем "Состояние линии"
  226.                  pthread_mutex_lock(&bcb_mutex);
  227.                 Message sostoyanie_message = create_sostoyanie_linii_message(LOGICAL_ADDRESS_SVM_PB_BZ_CHANNEL_1,
  228.                                                                          kla, sla, ksa, bcb_counter, message_counter++);
  229.                 pthread_mutex_unlock(&bcb_mutex);
  230.                 message_to_network_byte_order(&sostoyanie_message);
  231.                 if (send(newsockfd, &sostoyanie_message, sizeof(MessageHeader) + ntohs(sostoyanie_message.header.body_length), 0) < 0) {
  232.                     perror("send sostoyanie_linii failed");
  233.                     exit(EXIT_FAILURE);
  234.                 }
  235.                 printf("Sent Sostoyanie Linii message\n");
  236.             }
  237.  
  238.              else if (received_message.header.message_type == MESSAGE_TYPE_PRINYAT_PARAMETRY_CO)
  239.             {
  240.                 printf("Received Prinyat Parametry CO message\n");
  241.                 // Тут нужно сохранить полученные параметры в структуре данных СВ-М (пока не реализовано)
  242.                 PrinyatParametryCOBody *body = (PrinyatParametryCOBody *)received_message.body;
  243.                 printf("Received Prinyat Parametry CO from UVM: PP=0x%02X, BRL=0x%02X, Qo=0x%02X, Q=0x%04X, ARU=0x%02X, SIGMAYBM=0x%04X\n",
  244.                        body->PP, body->BRL, body->Qo, ntohs(body->Q), body->ARU, ntohs(body->SIGMAYBM));  //Добавили ntohs
  245.  
  246.                  // bcb_counter++; // Временно - ТЕПЕРЬ ДЕЛАЕТ ТАЙМЕР
  247.                  message_counter++;
  248.             }
  249.             else if (received_message.header.message_type == MESSAGE_TYPE_PRINYAT_TIME_REF_RANGE) {
  250.                 printf("Received Prinyat Time Ref Range message\n");
  251.                 // Временный вывод для отладки (пока не сохраняем данные)
  252.                 PrinyatTimeRefRangeBody *body = (PrinyatTimeRefRangeBody *)received_message.body;
  253.                  printf("Received Time Ref Range from UVM: First element: real=%d, imag=%d\n",
  254.                        body->time_ref_range[0].real, body->time_ref_range[0].imag);
  255.  
  256.                 // bcb_counter++; // Временно - ТЕПЕРЬ ДЕЛАЕТ ТАЙМЕР
  257.                 message_counter++;
  258.             }
  259.             // Добавлено: обработка "Принять Reper"
  260.             else if (received_message.header.message_type == MESSAGE_TYPE_PRINYAT_REPER) {
  261.                 printf("Received Prinyat Reper message\n");
  262.                 PrinyatReperBody *body = (PrinyatReperBody *)received_message.body;
  263.                 printf("Received Reper Data from UVM: reperR1=0x%04X, reperA1=0x%04X\n",
  264.                 ntohs(body->reperR1), ntohs(body->reperA1)); // не забываем
  265.                 // bcb_counter++; //временно - ТЕПЕРЬ ДЕЛАЕТ ТАЙМЕР
  266.                 message_counter++;
  267.              }
  268.  
  269.  
  270.             else{
  271.                 printf("SVM: Ignoring message after initialization. Type: %u\n", received_message.header.message_type);
  272.             }
  273.  
  274.         }
  275.     }
  276.     // Закрываем соединение и сокет. Тут не должно быть, но пока оставим
  277.     close(newsockfd);
  278.     close(sockfd);
  279.     pthread_mutex_destroy(&bcb_mutex); // Уничтожение мьютекса
  280.  
  281.     return 0;
  282. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement