/* Chrysalide - Outil d'analyse de fichiers binaires * stream.c - gestion des connexions aux serveurs de débogage. * * Copyright (C) 2010-2013 Cyrille Bagard * * This file is part of Chrysalide. * * OpenIDA is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * OpenIDA is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Foobar. If not, see . */ #include "stream.h" #include #include #include #include "stream-int.h" #include "../common/dllist.h" /* FIXME : remme ! */ /* Initialise la classe des flux de communication de débogage. */ static void g_debug_stream_class_init(GDebugStreamClass *); /* Initialise une instance de flux de communication de débogage. */ static void g_debug_stream_init(GDebugStream *); /* Ecoute une connexion à un serveur de débogage. */ static void *debug_stream_thread(GDebugStream *); /* Réceptionne un paquet d'un serveur de débogage. */ static bool g_debug_stream_read_packet(GDebugStream *, GDebugPacket *); /* Indique le type défini pour un flux de communication avec un serveur de débogage. */ G_DEFINE_TYPE(GDebugStream, g_debug_stream, G_TYPE_OBJECT); /****************************************************************************** * * * Paramètres : klass = classe à initialiser. * * * * Description : Initialise la classe des flux de communication de débogage. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_debug_stream_class_init(GDebugStreamClass *klass) { } /****************************************************************************** * * * Paramètres : stream = instance à initialiser. * * * * Description : Initialise une instance de flux de communication de débogage.* * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_debug_stream_init(GDebugStream *stream) { g_mutex_init(&stream->free_mutex); g_cond_init(&stream->recv_cond); g_mutex_init(&stream->recv_mutex); } /****************************************************************************** * * * Paramètres : stream = paramètres de connexion distante. * * * * Description : Etablit de façon effective une connexion à la cible. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool g_debug_stream_connect(GDebugStream *stream) { if (stream->connect == NULL || !stream->connect(stream)) return false; if (!g_thread_new("chrysalide_stream", (GThreadFunc)debug_stream_thread, stream)) { /* TODO : disconnect ! */ return false; } return true; } /****************************************************************************** * * * Paramètres : stream = encadrement associée à l'opération. * * * * Description : Ecoute une connexion à un serveur de débogage. * * * * Retour : ??? * * * * Remarques : - * * * ******************************************************************************/ static void *debug_stream_thread(GDebugStream *stream) { bool status; /* Bilan d'évolution */ GDebugPacket *packet; /* Nouveau paquet reçu */ while (1) { status = stream->poll(stream); if (!status) break; packet = g_debug_stream_get_free_packet(stream); if (stream->recv_packet(stream, packet)) { g_mutex_lock(&stream->recv_mutex); g_debug_packet_push(&stream->recv_packets, packet); g_mutex_unlock(&stream->recv_mutex); g_cond_signal(&stream->recv_cond); } else g_debug_stream_mark_packet_as_free(stream, packet); } return NULL; } /****************************************************************************** * * * Paramètres : stream = flux de communication de débogage à consulter. * * * * Description : Fournit un paquet prêt à emploi. * * * * Retour : Paquet prêt à emploi. * * * * Remarques : - * * * ******************************************************************************/ GDebugPacket *g_debug_stream_get_free_packet(GDebugStream *stream) { GDebugPacket *result; /* Paquet à retourner */ g_mutex_lock(&stream->free_mutex); if (dl_list_empty(stream->free_packets)) result = g_object_new(stream->pkt_type, NULL); else result = g_debug_packet_pop(&stream->free_packets); g_mutex_unlock(&stream->free_mutex); return result; } /****************************************************************************** * * * Paramètres : stream = flux de communication de débogage à mettre à jour. * * packet = paquet à considérer comme disponible. * * * * Description : Place un paquet en attente d'une future utilisation. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_debug_stream_mark_packet_as_free(GDebugStream *stream, GDebugPacket *packet) { stream->free_packet(stream, packet); g_mutex_lock(&stream->free_mutex); g_debug_packet_push(&stream->free_packets, packet); g_mutex_unlock(&stream->free_mutex); } /****************************************************************************** * * * Paramètres : stream = flux ouvert en écriture à mettre à jour. * * packet = données à transmettre. * * * * Description : Envoie un paquet à un serveur de débogage. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool g_debug_stream_send_packet(GDebugStream *stream, GDebugPacket *packet) { bool result; /* Bilan à retourner */ result = stream->send_packet(stream, packet); return result; } /****************************************************************************** * * * Paramètres : stream = flux de communication de débogage à consulter. * * filter = éventuelle fonction de sélection du paquet. * * data = éventuelle donnée à associer au filtrage. * * * * Description : Fournit un paquet reçu d'un serveur de débogage. * * * * Retour : Paquet de débogage. * * * * Remarques : - * * * ******************************************************************************/ GDebugPacket *g_debug_stream_recv_packet(GDebugStream *stream, filter_packet_fc filter, void *data) { GDebugPacket *result; /* Paquet à retourner */ g_mutex_lock(&stream->recv_mutex); if (filter != NULL) { gdsrp_try_again: for (result = stream->recv_packets; result != NULL; result = g_debug_packet_get_next_iter(stream->recv_packets, result)) { if (filter(result, data)) { g_debug_packet_extract(&stream->recv_packets, result); break; } } if (result == NULL) { g_cond_wait(&stream->recv_cond, &stream->recv_mutex); goto gdsrp_try_again; } } else { if (dl_list_empty(stream->recv_packets)) g_cond_wait(&stream->recv_cond, &stream->recv_mutex); result = g_debug_packet_pop(&stream->recv_packets); } g_mutex_unlock(&stream->recv_mutex); return result; }