DBGCTcp.cpp revision 677833bc953b6cb418c701facbdcf4aa18d6c44e
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Debugger TCP backend
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Copyright (C) 2006 InnoTek Systemberatung GmbH
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 * 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* Header Files *
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering*******************************************************************************/
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering/*******************************************************************************
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering* Structures and Typedefs *
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering*******************************************************************************/
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Debug console TCP backend instance data.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering /** The I/O backend for the console. */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering /** The socket of the connection. */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering /** Connection status. */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering/** Pointer to the instance data of the console TCP backend. */
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* Internal Functions *
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering*******************************************************************************/
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poetteringstatic int dbgcTcpConnection(RTSOCKET Sock, void *pvUser);
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Checks if there is input.
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 Poetteringstatic DECLCALLBACK(bool) dbgcTcpBackInput(PDBGCBACK pBack, uint32_t cMillies)
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering PDBGCTCP pDbgcTcp = DBGCTCP_BACK2DBGCTCP(pBack);
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering int rc = RTTcpSelectOne(pDbgcTcp->Sock, cMillies);
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering if (VBOX_FAILURE(rc) && rc != VERR_TIMEOUT)
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 Poetteringstatic DECLCALLBACK(int) dbgcTcpBackRead(PDBGCBACK pBack, void *pvBuf, size_t cbBuf, size_t *pcbRead)
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering PDBGCTCP pDbgcTcp = DBGCTCP_BACK2DBGCTCP(pBack);
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering int rc = RTTcpRead(pDbgcTcp->Sock, pvBuf, cbBuf, pcbRead);
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Write (output).
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 Poetteringstatic DECLCALLBACK(int) dbgcTcpBackWrite(PDBGCBACK pBack, const void *pvBuf, size_t cbBuf, size_t *pcbWritten)
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering PDBGCTCP pDbgcTcp = DBGCTCP_BACK2DBGCTCP(pBack);
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * convert '\n' to '\r\n' while writing.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering /* write newlines */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering rc = RTTcpWrite(pDbgcTcp->Sock, "\n\r", 2);
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering /* write till next newline */
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering const char *pszNL = (const char *)memchr(pvBuf, '\n', cbLeft);
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering cb = (uintptr_t)pszNL - (uintptr_t)pvBuf;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering rc = RTTcpWrite(pDbgcTcp->Sock, pvBuf, cb);
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Set returned value and return.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Serve a TCP Server connection.
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 Poetteringstatic int dbgcTcpConnection(RTSOCKET Sock, void *pvUser)
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering LogFlow(("dbgcTcpConnection: connection! Sock=%d pvUser=%p\n", Sock, pvUser));
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Start the console.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering DbgcTcp.Back.pfnInput = dbgcTcpBackInput;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering DbgcTcp.Back.pfnWrite = dbgcTcpBackWrite;
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering int rc = DBGCCreate((PVM)pvUser, &DbgcTcp.Back, 0);
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering LogFlow(("dbgcTcpConnection: disconnect rc=%Vrc\n", rc));
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Spawns a new thread with a TCP based debugging console service.
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 PoetteringDBGDECL(int) DBGCTcpCreate(PVM pVM, void **ppvData)
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Check what the configuration says.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering PCFGMNODE pKey = CFGMR3GetChild(CFGMR3GetRoot(pVM), "DBGC");
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 AssertMsgFailed(("Configuration error: Querying \"Enabled\" -> %Vrc\n", rc));
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering LogFlow(("DBGCTcpCreate: returns VINF_SUCCESS (Disabled)\n"));
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Get the port configuration.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering rc = CFGMR3QueryU32(pKey, "Port", &u32Port);
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering AssertMsgFailed(("Configuration error: Querying \"Port\" -> %Vrc\n", rc));
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Get the address configuration.
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 AssertMsgFailed(("Configuration error: Querying \"Address\" -> %Vrc\n", rc));
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Create the server (separate thread).
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering rc = RTTcpServerCreate(szAddress, u32Port, RTTHREADTYPE_DEBUGGER, "DBGC", dbgcTcpConnection, pVM, &pServer);
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering LogFlow(("DBGCTcpCreate: Created server on port %d %s\n", u32Port, szAddress));
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering LogFlow(("DBGCTcpCreate: returns %Vrc\n", rc));
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Terminates any running TCP base debugger consolse service.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * @returns VBox status.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * @param pVM VM handle.
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart PoetteringDBGDECL(int) DBGCTcpTerminate(PVM pVM, void *pvData)
6b1dc2bd3cdb3bd932b0692be636ddd2879edb92Lennart Poettering * Destroy the server instance if any.