DBGCTcp.cpp revision 677833bc953b6cb418c701facbdcf4aa18d6c44e
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering/** @file
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering *
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Debugger TCP backend
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering/*
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Copyright (C) 2006 InnoTek Systemberatung GmbH
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering *
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * This file is part of VirtualBox Open Source Edition (OSE), as
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * available from http://www.virtualbox.org. This file is free software;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * you can redistribute it and/or modify it under the terms of the GNU
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * General Public License as published by the Free Software Foundation,
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * distribution. VirtualBox OSE is distributed in the hope that it will
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * be useful, but WITHOUT ANY WARRANTY of any kind.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering *
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * If you received this file as part of a commercial VirtualBox
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * distribution, then only the terms of your commercial VirtualBox
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * license agreement apply instead of the previous paragraph.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering/*******************************************************************************
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering* Header Files *
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering*******************************************************************************/
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering#include <VBox/dbg.h>
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering#include <VBox/cfgm.h>
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering#include <VBox/err.h>
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering#include <iprt/thread.h>
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering#include <iprt/tcp.h>
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering#include <VBox/log.h>
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering#include <iprt/assert.h>
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering#include <string.h>
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering/*******************************************************************************
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering* Structures and Typedefs *
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering*******************************************************************************/
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering/**
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Debug console TCP backend instance data.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poetteringtypedef struct DBGCTCP
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering{
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering /** The I/O backend for the console. */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering DBGCBACK Back;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering /** The socket of the connection. */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering RTSOCKET Sock;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering /** Connection status. */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering bool fAlive;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering} DBGCTCP;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering/** Pointer to the instance data of the console TCP backend. */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poetteringtypedef DBGCTCP *PDBGCTCP;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering/** Converts a pointer to DBGCTCP::Back to a pointer to DBGCTCP. */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering#define DBGCTCP_BACK2DBGCTCP(pBack) ( (PDBGCTCP)((char *)pBack - RT_OFFSETOF(DBGCTCP, Back)) )
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering/*******************************************************************************
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering* Internal Functions *
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering*******************************************************************************/
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poetteringstatic int dbgcTcpConnection(RTSOCKET Sock, void *pvUser);
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering/**
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Checks if there is input.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering *
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * @returns true if there is input ready.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * @returns false if there not input ready.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * @param pBack Pointer to the backend structure supplied by
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * the backend. The backend can use this to find
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * it's instance data.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * @param cMillies Number of milliseconds to wait on input data.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poetteringstatic DECLCALLBACK(bool) dbgcTcpBackInput(PDBGCBACK pBack, uint32_t cMillies)
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering{
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering PDBGCTCP pDbgcTcp = DBGCTCP_BACK2DBGCTCP(pBack);
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering if (!pDbgcTcp->fAlive)
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering return false;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering int rc = RTTcpSelectOne(pDbgcTcp->Sock, cMillies);
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering if (VBOX_FAILURE(rc) && rc != VERR_TIMEOUT)
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering pDbgcTcp->fAlive = false;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering return rc != VERR_TIMEOUT;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering}
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering/**
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Read input.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering *
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * @returns VBox status code.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * @param pBack Pointer to the backend structure supplied by
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * the backend. The backend can use this to find
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * it's instance data.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * @param pvBuf Where to put the bytes we read.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * @param cbBuf Maximum nymber of bytes to read.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * @param pcbRead Where to store the number of bytes actually read.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * If NULL the entire buffer must be filled for a
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * successful return.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poetteringstatic DECLCALLBACK(int) dbgcTcpBackRead(PDBGCBACK pBack, void *pvBuf, size_t cbBuf, size_t *pcbRead)
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering{
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering PDBGCTCP pDbgcTcp = DBGCTCP_BACK2DBGCTCP(pBack);
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering if (!pDbgcTcp->fAlive)
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering return VERR_INVALID_HANDLE;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering int rc = RTTcpRead(pDbgcTcp->Sock, pvBuf, cbBuf, pcbRead);
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering if (VBOX_FAILURE(rc))
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering pDbgcTcp->fAlive = false;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering return rc;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering}
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering/**
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Write (output).
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering *
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * @returns VBox status code.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * @param pBack Pointer to the backend structure supplied by
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * the backend. The backend can use this to find
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * it's instance data.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * @param pvBuf What to write.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * @param cbBuf Number of bytes to write.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * @param pcbWritten Where to store the number of bytes actually written.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * If NULL the entire buffer must be successfully written.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poetteringstatic DECLCALLBACK(int) dbgcTcpBackWrite(PDBGCBACK pBack, const void *pvBuf, size_t cbBuf, size_t *pcbWritten)
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering{
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering PDBGCTCP pDbgcTcp = DBGCTCP_BACK2DBGCTCP(pBack);
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering if (!pDbgcTcp->fAlive)
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering return VERR_INVALID_HANDLE;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering /*
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * convert '\n' to '\r\n' while writing.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering int rc = 0;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering size_t cbLeft = cbBuf;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering while (cbLeft)
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering {
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering size_t cb = cbLeft;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering /* write newlines */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering if (*(const char *)pvBuf == '\n')
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering {
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering rc = RTTcpWrite(pDbgcTcp->Sock, "\n\r", 2);
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering cb = 1;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering }
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering /* write till next newline */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering else
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering {
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering const char *pszNL = (const char *)memchr(pvBuf, '\n', cbLeft);
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering if (pszNL)
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering cb = (uintptr_t)pszNL - (uintptr_t)pvBuf;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering rc = RTTcpWrite(pDbgcTcp->Sock, pvBuf, cb);
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering }
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering if (VBOX_FAILURE(rc))
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering {
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering pDbgcTcp->fAlive = false;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering break;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering }
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering /* advance */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering cbLeft -= cb;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering pvBuf = (const char *)pvBuf + cb;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering }
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering /*
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Set returned value and return.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering if (pcbWritten)
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering *pcbWritten = cbBuf - cbLeft;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering return rc;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering}
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering/**
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Serve a TCP Server connection.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering *
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * @returns VBox status.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * @returns VERR_TCP_SERVER_STOP to terminate the server loop forcing
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * the RTTcpCreateServer() call to return.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * @param Sock The socket which the client is connected to.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * The call will close this socket.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * @param pvUser The VM handle.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poetteringstatic int dbgcTcpConnection(RTSOCKET Sock, void *pvUser)
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering{
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering LogFlow(("dbgcTcpConnection: connection! Sock=%d pvUser=%p\n", Sock, pvUser));
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering /*
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Start the console.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering DBGCTCP DbgcTcp;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering DbgcTcp.Back.pfnInput = dbgcTcpBackInput;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering DbgcTcp.Back.pfnRead = dbgcTcpBackRead;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering DbgcTcp.Back.pfnWrite = dbgcTcpBackWrite;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering DbgcTcp.fAlive = true;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering DbgcTcp.Sock = Sock;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering int rc = DBGCCreate((PVM)pvUser, &DbgcTcp.Back, 0);
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering LogFlow(("dbgcTcpConnection: disconnect rc=%Vrc\n", rc));
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering return rc;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering}
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering/**
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Spawns a new thread with a TCP based debugging console service.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering *
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * @returns VBox status.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * @param pVM VM handle.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * @param ppvData Where to store a pointer to the instance data.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart PoetteringDBGDECL(int) DBGCTcpCreate(PVM pVM, void **ppvData)
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering{
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering /*
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Check what the configuration says.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering PCFGMNODE pKey = CFGMR3GetChild(CFGMR3GetRoot(pVM), "DBGC");
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering bool fEnabled;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering int rc = CFGMR3QueryBool(pKey, "Enabled", &fEnabled);
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering#if defined(DEBUG) && !defined(__L4ENV__) && !defined(DEBUG_dmik)
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering fEnabled = true;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering#else
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering fEnabled = false;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering#endif
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering else if (VBOX_FAILURE(rc))
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering {
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering AssertMsgFailed(("Configuration error: Querying \"Enabled\" -> %Vrc\n", rc));
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering return rc;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering }
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering if (!fEnabled)
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering {
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering LogFlow(("DBGCTcpCreate: returns VINF_SUCCESS (Disabled)\n"));
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering return VINF_SUCCESS;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering }
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering /*
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Get the port configuration.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering uint32_t u32Port;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering rc = CFGMR3QueryU32(pKey, "Port", &u32Port);
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering u32Port = 5000;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering else if (VBOX_FAILURE(rc))
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering {
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering AssertMsgFailed(("Configuration error: Querying \"Port\" -> %Vrc\n", rc));
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering return rc;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering }
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering /*
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Get the address configuration.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering char szAddress[512];
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering rc = CFGMR3QueryString(pKey, "Address", szAddress, sizeof(szAddress));
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering szAddress[0] = '\0';
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering else if (VBOX_FAILURE(rc))
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering {
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering AssertMsgFailed(("Configuration error: Querying \"Address\" -> %Vrc\n", rc));
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering return rc;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering }
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering /*
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Create the server (separate thread).
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering PRTTCPSERVER pServer;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering rc = RTTcpServerCreate(szAddress, u32Port, RTTHREADTYPE_DEBUGGER, "DBGC", dbgcTcpConnection, pVM, &pServer);
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering if (VBOX_SUCCESS(rc))
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering {
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering LogFlow(("DBGCTcpCreate: Created server on port %d %s\n", u32Port, szAddress));
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering *ppvData = pServer;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering }
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering LogFlow(("DBGCTcpCreate: returns %Vrc\n", rc));
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering return rc;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering}
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering/**
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Terminates any running TCP base debugger consolse service.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering *
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * @returns VBox status.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * @param pVM VM handle.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart PoetteringDBGDECL(int) DBGCTcpTerminate(PVM pVM, void *pvData)
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering{
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering /*
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Destroy the server instance if any.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering if (pvData)
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering {
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering int rc = RTTcpServerDestroy((PRTTCPSERVER)pvData);
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering AssertRC(rc);
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering }
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering return VINF_SUCCESS;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering}
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering