summaryrefslogtreecommitdiff
path: root/src/debug/jdwp/tcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/debug/jdwp/tcp.c')
-rw-r--r--src/debug/jdwp/tcp.c328
1 files changed, 328 insertions, 0 deletions
diff --git a/src/debug/jdwp/tcp.c b/src/debug/jdwp/tcp.c
new file mode 100644
index 0000000..38acd29
--- /dev/null
+++ b/src/debug/jdwp/tcp.c
@@ -0,0 +1,328 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * tcp.c - gestion des connexions TCP aux serveurs JDWP.
+ *
+ * Copyright (C) 2010 Cyrille Bagard
+ *
+ * This file is part of OpenIDA.
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "tcp.h"
+
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+
+#include "packet.h"
+#include "misc/header.h"
+#include "sets/list.h"
+#include "../stream-int.h"
+#include "../../common/net.h"
+
+
+
+/* Flux de communication TCP avec un serveur JDWP (instance) */
+struct _GJdwpTcpClient
+{
+ GDebugStream parent; /* A laisser en premier */
+
+ char *server; /* Serveur à contacter */
+ char *port; /* Port de connexion */
+ int fd; /* Flux ouvert en L./E. */
+
+};
+
+
+/* Flux de communication TCP avec un serveur JDWP (classe) */
+struct _GJdwpTcpClientClass
+{
+ GDebugStreamClass parent; /* A laisser en premier */
+
+};
+
+
+/* Initialise la classe des flux de communication JDWP over TCP. */
+static void g_jdwp_tcp_client_class_init(GJdwpTcpClientClass *);
+
+/* Initialise une instance de flux de communication avec JDWP. */
+static void g_jdwp_tcp_client_init(GJdwpTcpClient *);
+
+/* Etablit de façon effective une connexion à la cible. */
+static bool g_jdwp_tcp_client_connect(GJdwpTcpClient *);
+
+/* Attend le signalement de données à traiter. */
+static bool g_jdwp_tcp_client_poll(GJdwpTcpClient *);
+
+/* Envoie un paquet de données à un serveur de débogage. */
+static bool g_jdwp_tcp_client_send_packet(GJdwpTcpClient *, const GJdwpPacket *);
+
+/* Réceptionne un paquet de données d'un serveur de débogage. */
+static bool g_jdwp_tcp_client_recv_packet(GJdwpTcpClient *, GJdwpPacket *);
+
+
+
+/* Indique le type défini pour un flux de communication TCP avec un serveur JDWP. */
+G_DEFINE_TYPE(GJdwpTcpClient, g_jdwp_tcp_client, G_TYPE_DEBUG_STREAM);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des flux de communication JVDP over TCP.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_jdwp_tcp_client_class_init(GJdwpTcpClientClass *klass)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : client = instance à initialiser. *
+* *
+* Description : Initialise une instance de flux de communication avec JDWP. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_jdwp_tcp_client_init(GJdwpTcpClient *client)
+{
+ GDebugStream *stream; /* Version parente */
+
+ stream = G_DEBUG_STREAM(client);
+
+ stream->connect = (debug_connect_fc)g_jdwp_tcp_client_connect;
+
+ stream->poll = (debug_poll_fc)g_jdwp_tcp_client_poll;
+ stream->send_packet = (debug_pkt_op_fc)g_jdwp_tcp_client_send_packet;
+ stream->recv_packet = (debug_pkt_op_fc)g_jdwp_tcp_client_recv_packet;
+
+ stream->pkt_type = G_TYPE_JDWP_PACKET;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : server = nom ou adresse du serveur à contacter. *
+* port = port de connexion. *
+* *
+* Description : Crée une nouvelle connexion TCP à un serveur JDWP. *
+* *
+* Retour : Adresse de la structure mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GDebugStream *g_jdwp_tcp_client_new(const char *server, const char *port)
+{
+ GJdwpTcpClient *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_JDWP_TCP_CLIENT, NULL);
+
+ result->server = strdup(server);
+ result->port = strdup(port);
+ result->fd = -1;
+
+ return G_DEBUG_STREAM(result);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : client = paramètres de connexion au serveur JDWP. *
+* *
+* Description : Etablit de façon effective une connexion à la cible. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_jdwp_tcp_client_connect(GJdwpTcpClient *client)
+{
+ struct sockaddr_in addr; /* Infos de connexion distante */
+ int sock; /* Flux ouvert à construire */
+ char handshake[15]; /* Poignée de main chaleureuse */
+
+ sock = connect_via_tcp(client->server, client->port, &addr);
+ if (sock == -1)
+ {
+ printf("Echec de connexion au serveur JDWP sur %s:%s\n",
+ client->server, client->port);
+ return false;
+ }
+
+ printf("Connecté à %s:%hd\n", client->server, ntohs(addr.sin_port));
+
+ if (send(sock, "JDWP-Handshake", 14, 0) != 14)
+ goto gjtcc_error;
+
+ if (recv(sock, handshake, 14, 0) != 14)
+ goto gjtcc_error;
+
+ if (strncmp(handshake, "JDWP-Handshake", 14) != 0)
+ goto gjtcc_error;
+
+ client->fd = sock;
+
+ return true;
+
+ gjtcc_error:
+
+ printf("Echec des premiers échanges !\n");
+
+ close(sock);
+
+ return false;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : client = paramètres de connexion au serveur JDWP. *
+* *
+* Description : Attend le signalement de données à traiter. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_jdwp_tcp_client_poll(GJdwpTcpClient *client)
+{
+ bool result; /* Statut à faire remonter */
+ fd_set rfds; /* Liste des flux à surveiller */
+ int ret; /* Bilan d'un appel */
+
+ result = false;
+
+ FD_ZERO(&rfds);
+ FD_SET(client->fd, &rfds);
+
+ ret = select(client->fd + 1, &rfds, NULL, NULL, NULL);
+
+ switch (ret)
+ {
+ case -1:
+ perror("select()");
+ break;
+
+ case 0:
+ /* ?! */
+ break;
+
+ default:
+ result = true;
+ break;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : client = flux ouvert en écriture à utiliser. *
+* packet = zone mémoire à parcourir. *
+* *
+* Description : Envoie un paquet de données à un serveur de débogage. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_jdwp_tcp_client_send_packet(GJdwpTcpClient *client, const GJdwpPacket *packet)
+{
+ struct iovec iov[UIO_MAXIOV]; /* Table de vecteurs à écrire */
+ int iovcnt; /* Quantité de champs valides */
+ int i; /* Boucle de parcours */
+
+ g_debug_packet_vectorize(G_DEBUG_PACKET(packet), iov, &iovcnt);
+
+ for (i = 0; i < iovcnt; i++)
+ if (send(client->fd, iov[i].iov_base, iov[i].iov_len, 0) != iov[i].iov_len)
+ return false;
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : client = flux ouvert en lecture à utiliser. *
+* packet = zone mémoire à remplir. [OUT] *
+* *
+* Description : Réceptionne un paquet de données d'un serveur de débogage. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_jdwp_tcp_client_recv_packet(GJdwpTcpClient *client, GJdwpPacket *packet)
+{
+ bin_t *hblob; /* Contenu encodé en B.E. */
+ jdwp_header *header; /* En-tête à reconstituer */
+ uint32_t length; /* Taille de la charge utile */
+ bin_t *pblob; /* Contenu encodé en B.E. */
+
+ hblob = g_jdwp_packet_get_hblob(packet);
+
+ if (recv(client->fd, hblob, sizeof(jdwp_header), 0) != sizeof(jdwp_header))
+ return false;
+
+ if (!g_jdwp_packet_parse_header(packet))
+ return false;
+
+ header = g_jdwp_packet_get_header(packet);
+ length = header->length - sizeof(jdwp_header);
+
+ pblob = g_jdwp_packet_get_pblob(packet);
+
+ if (recv(client->fd, pblob, length, 0) != length)
+ return false;
+
+ return true;
+
+}