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