/** * Phantom Client - Простой клиент для работы с Phantom сетью * * Эта утилита позволяет обычным пользователям легко подключаться * к Phantom сети и использовать её для анонимной передачи данных. * * Примеры использования: * ./phantom-client --connect # Подключение к сети * ./phantom-client --send "Hello" node123 # Отправка сообщения * ./phantom-client --proxy 8080 # SOCKS5 прокси на порту 8080 * ./phantom-client --tunnel 22 remote.phantom # SSH туннель * * Автор: Phantom Protocol Team 2025 * Версия: 1.0.0 */ #include #include #include #include #include #include #include #include #include #include #include #include // Включение основных модулей Phantom #include "../src/config.h" #include "../src/kademlia.h" #include "../src/path.h" #include "../src/server.h" #define PHANTOM_CLIENT_VERSION "1.0.0" #define MAX_MESSAGE_SIZE 4096 #define MAX_NODES 100 #define DEFAULT_PHANTOM_PORT 8050 // Структура клиента Phantom typedef struct { bool is_connected; bool is_running; char local_node_id[64]; char phantom_address[64]; uint16_t phantom_port; // Сетевые настройки int phantom_socket; struct sockaddr_in phantom_addr; // Прокси настройки bool proxy_enabled; uint16_t proxy_port; int proxy_socket; pthread_t proxy_thread; // Туннель настройки bool tunnel_enabled; uint16_t local_port; char remote_host[256]; uint16_t remote_port; pthread_t tunnel_thread; // Статистика uint64_t bytes_sent; uint64_t bytes_received; uint32_t connections_count; time_t start_time; } phantom_client_t; // Глобальная переменная клиента static phantom_client_t *g_client = NULL; // Прототипы функций phantom_client_t* phantom_client_create(void); int phantom_client_connect(phantom_client_t *client, const char *address, uint16_t port); int phantom_client_disconnect(phantom_client_t *client); int phantom_client_send_message(phantom_client_t *client, const char *message, const char *target); int phantom_client_start_proxy(phantom_client_t *client, uint16_t port); int phantom_client_start_tunnel(phantom_client_t *client, uint16_t local_port, const char *remote_host, uint16_t remote_port); void phantom_client_show_status(phantom_client_t *client); void phantom_client_show_help(void); void phantom_client_signal_handler(int signal); void phantom_client_destroy(phantom_client_t *client); /** * Создание клиента Phantom */ phantom_client_t* phantom_client_create(void) { phantom_client_t *client = calloc(1, sizeof(phantom_client_t)); if (!client) { fprintf(stderr, "Не удалось выделить память для клиента\n"); return NULL; } // Инициализация значений по умолчанию client->is_connected = false; client->is_running = false; client->phantom_port = DEFAULT_PHANTOM_PORT; strcpy(client->phantom_address, "127.0.0.1"); client->phantom_socket = -1; client->proxy_socket = -1; // Генерация уникального ID клиента snprintf(client->local_node_id, sizeof(client->local_node_id), "client-%ld-%d", time(NULL), getpid()); client->start_time = time(NULL); printf("Phantom Client создан (ID: %s)\n", client->local_node_id); return client; } /** * Подключение к Phantom сети */ int phantom_client_connect(phantom_client_t *client, const char *address, uint16_t port) { if (!client) { return -1; } if (client->is_connected) { printf("Клиент уже подключен к сети\n"); return 0; } printf("Подключение к Phantom сети %s:%d...\n", address, port); // Сохранение параметров подключения strncpy(client->phantom_address, address, sizeof(client->phantom_address) - 1); client->phantom_port = port; // Создание сокета client->phantom_socket = socket(AF_INET, SOCK_STREAM, 0); if (client->phantom_socket < 0) { perror("socket"); return -1; } // Настройка адреса сервера memset(&client->phantom_addr, 0, sizeof(client->phantom_addr)); client->phantom_addr.sin_family = AF_INET; client->phantom_addr.sin_port = htons(port); if (inet_pton(AF_INET, address, &client->phantom_addr.sin_addr) <= 0) { fprintf(stderr, "Неверный IP адрес: %s\n", address); close(client->phantom_socket); client->phantom_socket = -1; return -1; } // Подключение к серверу if (connect(client->phantom_socket, (struct sockaddr*)&client->phantom_addr, sizeof(client->phantom_addr)) < 0) { perror("connect"); close(client->phantom_socket); client->phantom_socket = -1; return -1; } // Отправка приветственного сообщения char hello_msg[256]; snprintf(hello_msg, sizeof(hello_msg), "PHANTOM_HELLO %s CLIENT %s", client->local_node_id, PHANTOM_CLIENT_VERSION); if (send(client->phantom_socket, hello_msg, strlen(hello_msg), 0) < 0) { perror("send hello"); close(client->phantom_socket); client->phantom_socket = -1; return -1; } // Ожидание ответа char response[256]; ssize_t received = recv(client->phantom_socket, response, sizeof(response) - 1, 0); if (received <= 0) { fprintf(stderr, "Не получен ответ от сервера\n"); close(client->phantom_socket); client->phantom_socket = -1; return -1; } response[received] = '\0'; if (strncmp(response, "PHANTOM_WELCOME", 15) != 0) { fprintf(stderr, "Неожиданный ответ сервера: %s\n", response); close(client->phantom_socket); client->phantom_socket = -1; return -1; } client->is_connected = true; client->is_running = true; printf("✅ Успешно подключен к Phantom сети!\n"); printf(" Узел ID: %s\n", client->local_node_id); printf(" Сервер: %s:%d\n", address, port); return 0; } /** * Отключение от Phantom сети */ int phantom_client_disconnect(phantom_client_t *client) { if (!client || !client->is_connected) { return 0; } printf("Отключение от Phantom сети...\n"); client->is_running = false; // Остановка прокси if (client->proxy_enabled) { client->proxy_enabled = false; if (client->proxy_socket >= 0) { close(client->proxy_socket); client->proxy_socket = -1; } pthread_cancel(client->proxy_thread); } // Остановка туннеля if (client->tunnel_enabled) { client->tunnel_enabled = false; pthread_cancel(client->tunnel_thread); } // Отправка сообщения об отключении if (client->phantom_socket >= 0) { char goodbye_msg[128]; snprintf(goodbye_msg, sizeof(goodbye_msg), "PHANTOM_GOODBYE %s", client->local_node_id); send(client->phantom_socket, goodbye_msg, strlen(goodbye_msg), 0); close(client->phantom_socket); client->phantom_socket = -1; } client->is_connected = false; printf("✅ Отключен от Phantom сети\n"); return 0; } /** * Отправка сообщения через Phantom сеть */ int phantom_client_send_message(phantom_client_t *client, const char *message, const char *target) { if (!client || !client->is_connected || !message || !target) { return -1; } printf("Отправка сообщения '%s' узлу %s...\n", message, target); // Формирование пакета сообщения char packet[MAX_MESSAGE_SIZE]; snprintf(packet, sizeof(packet), "PHANTOM_MESSAGE %s %s %zu %s", client->local_node_id, target, strlen(message), message); // Отправка через Phantom сеть ssize_t sent = send(client->phantom_socket, packet, strlen(packet), 0); if (sent < 0) { perror("send message"); return -1; } client->bytes_sent += sent; // Ожидание подтверждения char response[256]; ssize_t received = recv(client->phantom_socket, response, sizeof(response) - 1, 0); if (received > 0) { response[received] = '\0'; client->bytes_received += received; if (strncmp(response, "PHANTOM_ACK", 11) == 0) { printf("✅ Сообщение доставлено\n"); return 0; } else if (strncmp(response, "PHANTOM_ERROR", 13) == 0) { printf("❌ Ошибка доставки: %s\n", response + 14); return -1; } } printf("⚠️ Статус доставки неизвестен\n"); return 0; } /** * Запуск SOCKS5 прокси */ int phantom_client_start_proxy(phantom_client_t *client, uint16_t port) { if (!client || !client->is_connected) { fprintf(stderr, "Клиент не подключен к сети\n"); return -1; } if (client->proxy_enabled) { printf("Прокси уже запущен на порту %d\n", client->proxy_port); return 0; } printf("Запуск SOCKS5 прокси на порту %d...\n", port); // Создание серверного сокета client->proxy_socket = socket(AF_INET, SOCK_STREAM, 0); if (client->proxy_socket < 0) { perror("socket"); return -1; } // Разрешение повторного использования адреса int opt = 1; setsockopt(client->proxy_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); // Настройка адреса прокси struct sockaddr_in proxy_addr; memset(&proxy_addr, 0, sizeof(proxy_addr)); proxy_addr.sin_family = AF_INET; proxy_addr.sin_addr.s_addr = INADDR_ANY; proxy_addr.sin_port = htons(port); // Привязка сокета if (bind(client->proxy_socket, (struct sockaddr*)&proxy_addr, sizeof(proxy_addr)) < 0) { perror("bind"); close(client->proxy_socket); client->proxy_socket = -1; return -1; } // Прослушивание подключений if (listen(client->proxy_socket, 10) < 0) { perror("listen"); close(client->proxy_socket); client->proxy_socket = -1; return -1; } client->proxy_port = port; client->proxy_enabled = true; // Запуск потока прокси if (pthread_create(&client->proxy_thread, NULL, phantom_proxy_thread, client) != 0) { perror("pthread_create"); close(client->proxy_socket); client->proxy_socket = -1; client->proxy_enabled = false; return -1; } printf("✅ SOCKS5 прокси запущен на порту %d\n", port); printf(" Настройте браузер: 127.0.0.1:%d\n", port); return 0; } /** * Поток SOCKS5 прокси */ void* phantom_proxy_thread(void *arg) { phantom_client_t *client = (phantom_client_t*)arg; printf("Поток SOCKS5 прокси запущен\n"); while (client->proxy_enabled && client->is_running) { struct sockaddr_in client_addr; socklen_t client_len = sizeof(client_addr); // Принятие подключения int client_sock = accept(client->proxy_socket, (struct sockaddr*)&client_addr, &client_len); if (client_sock < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { usleep(100000); // 100ms continue; } perror("accept"); continue; } client->connections_count++; // Обработка SOCKS5 подключения в отдельном потоке pthread_t connection_thread; phantom_proxy_connection_t *conn_data = malloc(sizeof(phantom_proxy_connection_t)); if (conn_data) { conn_data->client = client; conn_data->client_socket = client_sock; if (pthread_create(&connection_thread, NULL, phantom_proxy_connection_thread, conn_data) == 0) { pthread_detach(connection_thread); } else { close(client_sock); free(conn_data); } } else { close(client_sock); } } printf("Поток SOCKS5 прокси завершен\n"); return NULL; } /** * Структура данных подключения прокси */ typedef struct { phantom_client_t *client; int client_socket; } phantom_proxy_connection_t; /** * Поток обработки подключения прокси */ void* phantom_proxy_connection_thread(void *arg) { phantom_proxy_connection_t *conn = (phantom_proxy_connection_t*)arg; // Простая реализация SOCKS5 char buffer[4096]; // Чтение запроса аутентификации SOCKS5 ssize_t received = recv(conn->client_socket, buffer, sizeof(buffer), 0); if (received < 3) { close(conn->client_socket); free(conn); return NULL; } // Проверка версии SOCKS if (buffer[0] != 0x05) { close(conn->client_socket); free(conn); return NULL; } // Ответ: без аутентификации char auth_response[2] = {0x05, 0x00}; send(conn->client_socket, auth_response, 2, 0); // Чтение запроса подключения received = recv(conn->client_socket, buffer, sizeof(buffer), 0); if (received < 10) { close(conn->client_socket); free(conn); return NULL; } // Извлечение целевого адреса char target_host[256]; uint16_t target_port; if (buffer[3] == 0x01) { // IPv4 struct in_addr addr; memcpy(&addr, buffer + 4, 4); inet_ntop(AF_INET, &addr, target_host, sizeof(target_host)); memcpy(&target_port, buffer + 8, 2); target_port = ntohs(target_port); } else if (buffer[3] == 0x03) { // Доменное имя uint8_t domain_len = buffer[4]; memcpy(target_host, buffer + 5, domain_len); target_host[domain_len] = '\0'; memcpy(&target_port, buffer + 5 + domain_len, 2); target_port = ntohs(target_port); } else { // Неподдерживаемый тип адреса char error_response[10] = {0x05, 0x08, 0x00, 0x01, 0, 0, 0, 0, 0, 0}; send(conn->client_socket, error_response, 10, 0); close(conn->client_socket); free(conn); return NULL; } printf("SOCKS5: Подключение к %s:%d через Phantom\n", target_host, target_port); // Создание туннеля через Phantom сеть char tunnel_request[512]; snprintf(tunnel_request, sizeof(tunnel_request), "PHANTOM_TUNNEL %s %s %d", conn->client->local_node_id, target_host, target_port); if (send(conn->client->phantom_socket, tunnel_request, strlen(tunnel_request), 0) < 0) { // Ошибка подключения char error_response[10] = {0x05, 0x01, 0x00, 0x01, 0, 0, 0, 0, 0, 0}; send(conn->client_socket, error_response, 10, 0); close(conn->client_socket); free(conn); return NULL; } // Успешное подключение char success_response[10] = {0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0, 0}; send(conn->client_socket, success_response, 10, 0); // Проксирование данных между клиентом и Phantom сетью phantom_proxy_relay_data(conn); close(conn->client_socket); free(conn); return NULL; } /** * Проксирование данных */ void phantom_proxy_relay_data(phantom_proxy_connection_t *conn) { fd_set read_fds; int max_fd = (conn->client_socket > conn->client->phantom_socket) ? conn->client_socket : conn->client->phantom_socket; char buffer[4096]; while (conn->client->is_running) { FD_ZERO(&read_fds); FD_SET(conn->client_socket, &read_fds); FD_SET(conn->client->phantom_socket, &read_fds); struct timeval timeout = {1, 0}; // 1 секунда int activity = select(max_fd + 1, &read_fds, NULL, NULL, &timeout); if (activity < 0) { break; } if (activity == 0) { continue; // Таймаут } // Данные от клиента к Phantom if (FD_ISSET(conn->client_socket, &read_fds)) { ssize_t received = recv(conn->client_socket, buffer, sizeof(buffer), 0); if (received <= 0) { break; } if (send(conn->client->phantom_socket, buffer, received, 0) <= 0) { break; } conn->client->bytes_sent += received; } // Данные от Phantom к клиенту if (FD_ISSET(conn->client->phantom_socket, &read_fds)) { ssize_t received = recv(conn->client->phantom_socket, buffer, sizeof(buffer), 0); if (received <= 0) { break; } if (send(conn->client_socket, buffer, received, 0) <= 0) { break; } conn->client->bytes_received += received; } } } /** * Запуск туннеля */ int phantom_client_start_tunnel(phantom_client_t *client, uint16_t local_port, const char *remote_host, uint16_t remote_port) { if (!client || !client->is_connected || !remote_host) { return -1; } if (client->tunnel_enabled) { printf("Туннель уже активен\n"); return 0; } printf("Создание туннеля %d -> %s:%d через Phantom...\n", local_port, remote_host, remote_port); client->local_port = local_port; strncpy(client->remote_host, remote_host, sizeof(client->remote_host) - 1); client->remote_port = remote_port; client->tunnel_enabled = true; // Запуск потока туннеля if (pthread_create(&client->tunnel_thread, NULL, phantom_tunnel_thread, client) != 0) { perror("pthread_create"); client->tunnel_enabled = false; return -1; } printf("✅ Туннель создан: localhost:%d -> %s:%d\n", local_port, remote_host, remote_port); return 0; } /** * Поток туннеля */ void* phantom_tunnel_thread(void *arg) { phantom_client_t *client = (phantom_client_t*)arg; printf("Поток туннеля запущен\n"); // Создание серверного сокета для туннеля int tunnel_socket = socket(AF_INET, SOCK_STREAM, 0); if (tunnel_socket < 0) { perror("socket"); return NULL; } int opt = 1; setsockopt(tunnel_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); struct sockaddr_in tunnel_addr; memset(&tunnel_addr, 0, sizeof(tunnel_addr)); tunnel_addr.sin_family = AF_INET; tunnel_addr.sin_addr.s_addr = INADDR_ANY; tunnel_addr.sin_port = htons(client->local_port); if (bind(tunnel_socket, (struct sockaddr*)&tunnel_addr, sizeof(tunnel_addr)) < 0) { perror("bind"); close(tunnel_socket); return NULL; } if (listen(tunnel_socket, 5) < 0) { perror("listen"); close(tunnel_socket); return NULL; } while (client->tunnel_enabled && client->is_running) { struct sockaddr_in client_addr; socklen_t client_len = sizeof(client_addr); int client_sock = accept(tunnel_socket, (struct sockaddr*)&client_addr, &client_len); if (client_sock < 0) { continue; } // Создание туннеля через Phantom для этого подключения phantom_handle_tunnel_connection(client, client_sock); } close(tunnel_socket); printf("Поток туннеля завершен\n"); return NULL; } /** * Обработка подключения туннеля */ void phantom_handle_tunnel_connection(phantom_client_t *client, int client_sock) { printf("Новое подключение к туннелю\n"); // Отправка запроса на создание туннеля через Phantom char tunnel_request[512]; snprintf(tunnel_request, sizeof(tunnel_request), "PHANTOM_TUNNEL %s %s %d", client->local_node_id, client->remote_host, client->remote_port); if (send(client->phantom_socket, tunnel_request, strlen(tunnel_request), 0) < 0) { close(client_sock); return; } // Простое проксирование данных char buffer[4096]; fd_set read_fds; int max_fd = (client_sock > client->phantom_socket) ? client_sock : client->phantom_socket; while (client->is_running) { FD_ZERO(&read_fds); FD_SET(client_sock, &read_fds); FD_SET(client->phantom_socket, &read_fds); struct timeval timeout = {1, 0}; int activity = select(max_fd + 1, &read_fds, NULL, NULL, &timeout); if (activity <= 0) { break; } if (FD_ISSET(client_sock, &read_fds)) { ssize_t received = recv(client_sock, buffer, sizeof(buffer), 0); if (received <= 0) break; if (send(client->phantom_socket, buffer, received, 0) <= 0) break; client->bytes_sent += received; } if (FD_ISSET(client->phantom_socket, &read_fds)) { ssize_t received = recv(client->phantom_socket, buffer, sizeof(buffer), 0); if (received <= 0) break; if (send(client_sock, buffer, received, 0) <= 0) break; client->bytes_received += received; } } close(client_sock); } /** * Показ статуса клиента */ void phantom_client_show_status(phantom_client_t *client) { if (!client) { return; } printf("\n=== Статус Phantom Client ===\n"); printf("Версия: %s\n", PHANTOM_CLIENT_VERSION); printf("ID узла: %s\n", client->local_node_id); printf("Состояние: %s\n", client->is_connected ? "Подключен" : "Отключен"); if (client->is_connected) { printf("Сервер: %s:%d\n", client->phantom_address, client->phantom_port); time_t uptime = time(NULL) - client->start_time; printf("Время работы: %ld сек\n", uptime); printf("Отправлено: %llu байт\n", client->bytes_sent); printf("Получено: %llu байт\n", client->bytes_received); printf("Подключений: %u\n", client->connections_count); if (client->proxy_enabled) { printf("SOCKS5 прокси: активен на порту %d\n", client->proxy_port); } if (client->tunnel_enabled) { printf("Туннель: %d -> %s:%d\n", client->local_port, client->remote_host, client->remote_port); } } printf("=============================\n\n"); } /** * Показ справки */ void phantom_client_show_help(void) { printf("Phantom Client v%s - Клиент для работы с Phantom сетью\n\n", PHANTOM_CLIENT_VERSION); printf("Использование:\n"); printf(" phantom-client [ОПЦИИ]\n\n"); printf("Опции:\n"); printf(" -c, --connect [АДРЕС:ПОРТ] Подключиться к Phantom сети\n"); printf(" -d, --disconnect Отключиться от сети\n"); printf(" -s, --send СООБЩЕНИЕ УЗЕЛ Отправить сообщение узлу\n"); printf(" -p, --proxy ПОРТ Запустить SOCKS5 прокси\n"); printf(" -t, --tunnel ПОРТ:ХОСТ:ПОРТ Создать туннель\n"); printf(" -S, --status Показать статус\n"); printf(" -i, --interactive Интерактивный режим\n"); printf(" -h, --help Показать эту справку\n\n"); printf("Примеры:\n"); printf(" phantom-client --connect # Подключение к локальному серверу\n"); printf(" phantom-client --connect 192.168.1.100:8050 # Подключение к удаленному серверу\n"); printf(" phantom-client --proxy 8080 # SOCKS5 прокси на порту 8080\n"); printf(" phantom-client --tunnel 2222:remote.phantom:22 # SSH туннель\n"); printf(" phantom-client --send \"Hello\" node123 # Отправка сообщения\n\n"); } /** * Обработчик сигналов */ void phantom_client_signal_handler(int signal) { printf("\nПолучен сигнал %d, завершение работы...\n", signal); if (g_client) { phantom_client_disconnect(g_client); } exit(0); } /** * Уничтожение клиента */ void phantom_client_destroy(phantom_client_t *client) { if (!client) { return; } phantom_client_disconnect(client); free(client); } /** * Интерактивный режим */ void phantom_client_interactive_mode(phantom_client_t *client) { char input[512]; char command[64], arg1[256], arg2[256]; printf("\n=== Интерактивный режим Phantom Client ===\n"); printf("Введите 'help' для списка команд\n\n"); while (client->is_running) { printf("phantom> "); fflush(stdout); if (!fgets(input, sizeof(input), stdin)) { break; } // Удаление символа новой строки input[strcspn(input, "\n")] = 0; // Парсинг команды int args = sscanf(input, "%s %s %s", command, arg1, arg2); if (args == 0) { continue; } if (strcmp(command, "help") == 0) { printf("Доступные команды:\n"); printf(" connect [адрес:порт] - Подключиться к сети\n"); printf(" disconnect - Отключиться от сети\n"); printf(" send <сообщение> <узел> - Отправить сообщение\n"); printf(" proxy <порт> - Запустить SOCKS5 прокси\n"); printf(" tunnel <порт:хост:порт> - Создать туннель\n"); printf(" status - Показать статус\n"); printf(" quit - Выйти\n"); } else if (strcmp(command, "connect") == 0) { char *address = "127.0.0.1"; uint16_t port = DEFAULT_PHANTOM_PORT; if (args > 1) { char *colon = strchr(arg1, ':'); if (colon) { *colon = '\0'; address = arg1; port = atoi(colon + 1); } else { address = arg1; } } phantom_client_connect(client, address, port); } else if (strcmp(command, "disconnect") == 0) { phantom_client_disconnect(client); } else if (strcmp(command, "send") == 0) { if (args >= 3) { phantom_client_send_message(client, arg1, arg2); } else { printf("Использование: send <сообщение> <узел>\n"); } } else if (strcmp(command, "proxy") == 0) { if (args >= 2) { uint16_t port = atoi(arg1); phantom_client_start_proxy(client, port); } else { printf("Использование: proxy <порт>\n"); } } else if (strcmp(command, "tunnel") == 0) { if (args >= 2) { // Парсинг формата порт:хост:порт char *first_colon = strchr(arg1, ':'); if (first_colon) { *first_colon = '\0'; char *second_colon = strchr(first_colon + 1, ':'); if (second_colon) { *second_colon = '\0'; uint16_t local_port = atoi(arg1); char *remote_host = first_colon + 1; uint16_t remote_port = atoi(second_colon + 1); phantom_client_start_tunnel(client, local_port, remote_host, remote_port); } else { printf("Неверный формат. Используйте: tunnel <локальный_порт:удаленный_хост:удаленный_порт>\n"); } } else { printf("Неверный формат. Используйте: tunnel <локальный_порт:удаленный_хост:удаленный_порт>\n"); } } else { printf("Использование: tunnel <локальный_порт:удаленный_хост:удаленный_порт>\n"); } } else if (strcmp(command, "status") == 0) { phantom_client_show_status(client); } else if (strcmp(command, "quit") == 0 || strcmp(command, "exit") == 0) { break; } else { printf("Неизвестная команда: %s\n", command); } } } /** * Главная функция */ int main(int argc, char *argv[]) { printf("Phantom Client v%s\n", PHANTOM_CLIENT_VERSION); printf("Простой клиент для работы с Phantom сетью\n\n"); // Создание клиента g_client = phantom_client_create(); if (!g_client) { return 1; } // Установка обработчиков сигналов signal(SIGINT, phantom_client_signal_handler); signal(SIGTERM, phantom_client_signal_handler); // Парсинг аргументов командной строки static struct option long_options[] = { {"connect", optional_argument, 0, 'c'}, {"disconnect", no_argument, 0, 'd'}, {"send", required_argument, 0, 's'}, {"proxy", required_argument, 0, 'p'}, {"tunnel", required_argument, 0, 't'}, {"status", no_argument, 0, 'S'}, {"interactive", no_argument, 0, 'i'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; int option_index = 0; int c; bool interactive_mode = false; while ((c = getopt_long(argc, argv, "c::ds:p:t:Sih", long_options, &option_index)) != -1) { switch (c) { case 'c': { char *address = "127.0.0.1"; uint16_t port = DEFAULT_PHANTOM_PORT; if (optarg) { char *colon = strchr(optarg, ':'); if (colon) { *colon = '\0'; address = optarg; port = atoi(colon + 1); } else { address = optarg; } } phantom_client_connect(g_client, address, port); break; } case 'd': phantom_client_disconnect(g_client); break; case 's': if (optind < argc) { phantom_client_send_message(g_client, optarg, argv[optind]); optind++; } else { fprintf(stderr, "Не указан получатель сообщения\n"); } break; case 'p': { uint16_t port = atoi(optarg); phantom_client_start_proxy(g_client, port); break; } case 't': { // Парсинг формата порт:хост:порт char *arg_copy = strdup(optarg); char *first_colon = strchr(arg_copy, ':'); if (first_colon) { *first_colon = '\0'; char *second_colon = strchr(first_colon + 1, ':'); if (second_colon) { *second_colon = '\0'; uint16_t local_port = atoi(arg_copy); char *remote_host = first_colon + 1; uint16_t remote_port = atoi(second_colon + 1); phantom_client_start_tunnel(g_client, local_port, remote_host, remote_port); } else { fprintf(stderr, "Неверный формат туннеля. Используйте: порт:хост:порт\n"); } } else { fprintf(stderr, "Неверный формат туннеля. Используйте: порт:хост:порт\n"); } free(arg_copy); break; } case 'S': phantom_client_show_status(g_client); break; case 'i': interactive_mode = true; break; case 'h': phantom_client_show_help(); phantom_client_destroy(g_client); return 0; default: phantom_client_show_help(); phantom_client_destroy(g_client); return 1; } } // Интерактивный режим if (interactive_mode) { phantom_client_interactive_mode(g_client); } else if (argc == 1) { // Если нет аргументов, показать справку phantom_client_show_help(); } else { // Ожидание завершения работы while (g_client->is_running) { sleep(1); } } // Очистка phantom_client_destroy(g_client); printf("Phantom Client завершен\n"); return 0; }