DBGCTcp.cpp revision ad27e1d5e48ca41245120c331cc88b50464813ce
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/* $Id$ */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/** @file
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * DBGC - Debugger Console, TCP backend.
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/*
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Copyright (C) 2006-2010 Oracle Corporation
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync *
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * available from http://www.virtualbox.org. This file is free software;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * you can redistribute it and/or modify it under the terms of the GNU
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * General Public License (GPL) as published by the Free Software
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/*******************************************************************************
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync* Header Files *
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync*******************************************************************************/
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#include <VBox/dbg.h>
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync#include <VBox/cfgm.h>
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#include <VBox/err.h>
7b9f0c34e9ea328981c99e97054bdf8684d9d620vboxsync
9e7e0b61d29309a0ed7af9472c8d6d865f9e8a2dvboxsync#include <iprt/thread.h>
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#include <iprt/tcp.h>
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#include <VBox/log.h>
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#include <iprt/assert.h>
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync#include <string.h>
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
b1cc3e87518139898395f96974ecff9e6bf228fbvboxsync/*******************************************************************************
b1cc3e87518139898395f96974ecff9e6bf228fbvboxsync* Structures and Typedefs *
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync*******************************************************************************/
7862f4bd000f1eb6c86289f5ac2849e9cf943ca9vboxsync/**
388b6b190a5407548753b7fde12fa58134ec3563vboxsync * Debug console TCP backend instance data.
7862f4bd000f1eb6c86289f5ac2849e9cf943ca9vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsynctypedef struct DBGCTCP
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync{
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync /** The I/O backend for the console. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync DBGCBACK Back;
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync /** The socket of the connection. */
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync RTSOCKET Sock;
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync /** Connection status. */
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync bool fAlive;
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync} DBGCTCP;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/** Pointer to the instance data of the console TCP backend. */
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsynctypedef DBGCTCP *PDBGCTCP;
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync/** Converts a pointer to DBGCTCP::Back to a pointer to DBGCTCP. */
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync#define DBGCTCP_BACK2DBGCTCP(pBack) ( (PDBGCTCP)((char *)pBack - RT_OFFSETOF(DBGCTCP, Back)) )
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync/*******************************************************************************
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync* Internal Functions *
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync*******************************************************************************/
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsyncstatic int dbgcTcpConnection(RTSOCKET Sock, void *pvUser);
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync/**
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync * Checks if there is input.
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync *
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync * @returns true if there is input ready.
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync * @returns false if there not input ready.
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync * @param pBack Pointer to the backend structure supplied by
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync * the backend. The backend can use this to find
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync * it's instance data.
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync * @param cMillies Number of milliseconds to wait on input data.
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync */
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsyncstatic DECLCALLBACK(bool) dbgcTcpBackInput(PDBGCBACK pBack, uint32_t cMillies)
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync{
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync PDBGCTCP pDbgcTcp = DBGCTCP_BACK2DBGCTCP(pBack);
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync if (!pDbgcTcp->fAlive)
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync return false;
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync int rc = RTTcpSelectOne(pDbgcTcp->Sock, cMillies);
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync if (RT_FAILURE(rc) && rc != VERR_TIMEOUT)
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync pDbgcTcp->fAlive = false;
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync return rc != VERR_TIMEOUT;
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync}
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync/**
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * Read input.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync *
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * @returns VBox status code.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * @param pBack Pointer to the backend structure supplied by
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * the backend. The backend can use this to find
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * it's instance data.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * @param pvBuf Where to put the bytes we read.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * @param cbBuf Maximum nymber of bytes to read.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * @param pcbRead Where to store the number of bytes actually read.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * If NULL the entire buffer must be filled for a
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * successful return.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync */
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsyncstatic DECLCALLBACK(int) dbgcTcpBackRead(PDBGCBACK pBack, void *pvBuf, size_t cbBuf, size_t *pcbRead)
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync{
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync PDBGCTCP pDbgcTcp = DBGCTCP_BACK2DBGCTCP(pBack);
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync if (!pDbgcTcp->fAlive)
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync return VERR_INVALID_HANDLE;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync int rc = RTTcpRead(pDbgcTcp->Sock, pvBuf, cbBuf, pcbRead);
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync if (RT_FAILURE(rc))
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync pDbgcTcp->fAlive = false;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync return rc;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync}
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync/**
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * Write (output).
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync *
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * @returns VBox status code.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * @param pBack Pointer to the backend structure supplied by
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * the backend. The backend can use this to find
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * it's instance data.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * @param pvBuf What to write.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * @param cbBuf Number of bytes to write.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * @param pcbWritten Where to store the number of bytes actually written.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * If NULL the entire buffer must be successfully written.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync */
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsyncstatic DECLCALLBACK(int) dbgcTcpBackWrite(PDBGCBACK pBack, const void *pvBuf, size_t cbBuf, size_t *pcbWritten)
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync{
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync PDBGCTCP pDbgcTcp = DBGCTCP_BACK2DBGCTCP(pBack);
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync if (!pDbgcTcp->fAlive)
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync return VERR_INVALID_HANDLE;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync /*
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * convert '\n' to '\r\n' while writing.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync */
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync int rc = 0;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync size_t cbLeft = cbBuf;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync while (cbLeft)
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync {
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync size_t cb = cbLeft;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync /* write newlines */
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync if (*(const char *)pvBuf == '\n')
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync {
581f0625e43a928987623d7cf59e1b1ab61ca6c8vboxsync rc = RTTcpWrite(pDbgcTcp->Sock, "\n\r", 2);
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync cb = 1;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync }
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* write till next newline */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync else
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync {
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync const char *pszNL = (const char *)memchr(pvBuf, '\n', cbLeft);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync if (pszNL)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync cb = (uintptr_t)pszNL - (uintptr_t)pvBuf;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync rc = RTTcpWrite(pDbgcTcp->Sock, pvBuf, cb);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync }
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync if (RT_FAILURE(rc))
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync {
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync pDbgcTcp->fAlive = false;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync break;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync }
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* advance */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync cbLeft -= cb;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync pvBuf = (const char *)pvBuf + cb;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync }
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /*
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Set returned value and return.
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync */
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync if (pcbWritten)
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync *pcbWritten = cbBuf - cbLeft;
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync return rc;
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync}
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync/** @copydoc FNDBGCBACKSETREADY */
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsyncstatic DECLCALLBACK(void) dbgcTcpBackSetReady(PDBGCBACK pBack, bool fBusy)
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync{
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* stub */
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync NOREF(pBack);
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync NOREF(fBusy);
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync}
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync/**
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Serve a TCP Server connection.
fb41ad77bcfbdb3aaa1fc9503a37ee6a70dc6461vboxsync *
fb41ad77bcfbdb3aaa1fc9503a37ee6a70dc6461vboxsync * @returns VBox status.
fb41ad77bcfbdb3aaa1fc9503a37ee6a70dc6461vboxsync * @returns VERR_TCP_SERVER_STOP to terminate the server loop forcing
fb41ad77bcfbdb3aaa1fc9503a37ee6a70dc6461vboxsync * the RTTcpCreateServer() call to return.
fb41ad77bcfbdb3aaa1fc9503a37ee6a70dc6461vboxsync * @param Sock The socket which the client is connected to.
fb41ad77bcfbdb3aaa1fc9503a37ee6a70dc6461vboxsync * The call will close this socket.
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync * @param pvUser The VM handle.
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync */
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsyncstatic int dbgcTcpConnection(RTSOCKET Sock, void *pvUser)
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync{
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync LogFlow(("dbgcTcpConnection: connection! Sock=%d pvUser=%p\n", Sock, pvUser));
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync /*
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync * Start the console.
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync DBGCTCP DbgcTcp;
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync DbgcTcp.Back.pfnInput = dbgcTcpBackInput;
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync DbgcTcp.Back.pfnRead = dbgcTcpBackRead;
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync DbgcTcp.Back.pfnWrite = dbgcTcpBackWrite;
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync DbgcTcp.Back.pfnSetReady = dbgcTcpBackSetReady;
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync DbgcTcp.fAlive = true;
fb41ad77bcfbdb3aaa1fc9503a37ee6a70dc6461vboxsync DbgcTcp.Sock = Sock;
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync int rc = DBGCCreate((PVM)pvUser, &DbgcTcp.Back, 0);
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync LogFlow(("dbgcTcpConnection: disconnect rc=%Rrc\n", rc));
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync return rc;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync}
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync/**
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync * Spawns a new thread with a TCP based debugging console service.
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync *
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync * @returns VBox status.
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync * @param pVM VM handle.
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync * @param ppvData Where to store a pointer to the instance data.
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync */
cd5df721f068659172f3bf95de8fedeb465f057dvboxsyncDBGDECL(int) DBGCTcpCreate(PVM pVM, void **ppvData)
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync{
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync /*
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync * Check what the configuration says.
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync */
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync PCFGMNODE pKey = CFGMR3GetChild(CFGMR3GetRoot(pVM), "DBGC");
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync bool fEnabled;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync int rc = CFGMR3QueryBoolDef(pKey, "Enabled", &fEnabled,
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync#if defined(VBOX_WITH_DEBUGGER) && defined(VBOX_WITH_DEBUGGER_TCP_BY_DEFAULT) && !defined(__L4ENV__) && !defined(DEBUG_dmik)
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync true
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync#else
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync false
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync#endif
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync );
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync if (RT_FAILURE(rc))
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync return VM_SET_ERROR(pVM, rc, "Configuration error: Failed querying \"DBGC/Enabled\"");
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync if (!fEnabled)
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync {
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync LogFlow(("DBGCTcpCreate: returns VINF_SUCCESS (Disabled)\n"));
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync return VINF_SUCCESS;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync }
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync /*
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * Get the port configuration.
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync */
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync uint32_t u32Port;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync rc = CFGMR3QueryU32Def(pKey, "Port", &u32Port, 5000);
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync if (RT_FAILURE(rc))
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync return VM_SET_ERROR(pVM, rc, "Configuration error: Failed querying \"DBGC/Port\"");
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync /*
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * Get the address configuration.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync */
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync char szAddress[512];
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync rc = CFGMR3QueryStringDef(pKey, "Address", szAddress, sizeof(szAddress), "");
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync if (RT_FAILURE(rc))
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync return VM_SET_ERROR(pVM, rc, "Configuration error: Failed querying \"DBGC/Address\"");
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync /*
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * Create the server (separate thread).
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync */
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync PRTTCPSERVER pServer;
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync rc = RTTcpServerCreate(szAddress, u32Port, RTTHREADTYPE_DEBUGGER, "DBGC", dbgcTcpConnection, pVM, &pServer);
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync if (RT_SUCCESS(rc))
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync {
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync LogFlow(("DBGCTcpCreate: Created server on port %d %s\n", u32Port, szAddress));
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync *ppvData = pServer;
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync return rc;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync }
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync LogFlow(("DBGCTcpCreate: returns %Rrc\n", rc));
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync return VM_SET_ERROR(pVM, rc, "Cannot start TCP-based debugging console service");
fb41ad77bcfbdb3aaa1fc9503a37ee6a70dc6461vboxsync}
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/**
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Terminates any running TCP base debugger console service.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync *
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * @returns VBox status.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * @param pVM VM handle.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsyncDBGDECL(int) DBGCTcpTerminate(PVM pVM, void *pvData)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync{
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /*
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Destroy the server instance if any.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync if (pvData)
9523921c89c66f4bececdbd5ac95aed0039eda1bvboxsync {
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync int rc = RTTcpServerDestroy((PRTTCPSERVER)pvData);
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync AssertRC(rc);
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync }
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync return VINF_SUCCESS;
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync}
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync
9523921c89c66f4bececdbd5ac95aed0039eda1bvboxsync