VirtualBox

source: vbox/trunk/src/VBox/Debugger/DBGCIoProvUdp.cpp@ 96931

Last change on this file since 96931 was 96865, checked in by vboxsync, 2 years ago

Debugger: Some changes floating around, added a UDP I/O provider to be used for GDB and the WinDbg/Kd backend, bugref:1098

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.4 KB
Line 
1/* $Id: DBGCIoProvUdp.cpp 96865 2022-09-26 14:45:32Z vboxsync $ */
2/** @file
3 * DBGC - Debugger Console, UDP I/O provider.
4 */
5
6/*
7 * Copyright (C) 2022 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#include <VBox/dbg.h>
33#include <VBox/err.h>
34#include <VBox/log.h>
35
36#include <iprt/mem.h>
37#include <iprt/udp.h>
38#include <iprt/assert.h>
39
40#include "DBGCIoProvInternal.h"
41
42
43/*********************************************************************************************************************************
44* Structures and Typedefs *
45*********************************************************************************************************************************/
46/**
47 * Debug console UDP connection data.
48 */
49typedef struct DBGCUDPSRV
50{
51 /** The I/O callback table for the console. */
52 DBGCIO Io;
53 /** The socket of the connection. */
54 RTSOCKET hSock;
55 /** The address of the peer. */
56 RTNETADDR NetAddrPeer;
57 /** Flag whether the peer address was set. */
58 bool fPeerSet;
59 /** Connection status. */
60 bool fAlive;
61} DBGCUDPSRV;
62/** Pointer to the instance data of the console UDP backend. */
63typedef DBGCUDPSRV *PDBGCUDPSRV;
64
65
66/*********************************************************************************************************************************
67* Internal Functions *
68*********************************************************************************************************************************/
69
70/**
71 * @interface_method_impl{DBGCIO,pfnDestroy}
72 */
73static DECLCALLBACK(void) dbgcIoProvUdpIoDestroy(PCDBGCIO pIo)
74{
75 RT_NOREF(pIo);
76}
77
78
79/**
80 * @interface_method_impl{DBGCIO,pfnInput}
81 */
82static DECLCALLBACK(bool) dbgcIoProvUdpIoInput(PCDBGCIO pIo, uint32_t cMillies)
83{
84 PDBGCUDPSRV pUdpSrv = RT_FROM_MEMBER(pIo, DBGCUDPSRV, Io);
85 if (!pUdpSrv->fAlive)
86 return false;
87 int rc = RTSocketSelectOne(pUdpSrv->hSock, cMillies);
88 if (RT_FAILURE(rc) && rc != VERR_TIMEOUT)
89 pUdpSrv->fAlive = false;
90 return rc != VERR_TIMEOUT;
91}
92
93
94/**
95 * @interface_method_impl{DBGCIO,pfnRead}
96 */
97static DECLCALLBACK(int) dbgcIoProvUdpIoRead(PCDBGCIO pIo, void *pvBuf, size_t cbBuf, size_t *pcbRead)
98{
99 PDBGCUDPSRV pUdpSrv = RT_FROM_MEMBER(pIo, DBGCUDPSRV, Io);
100 if (!pUdpSrv->fAlive)
101 return VERR_INVALID_HANDLE;
102 int rc = RTSocketReadFrom(pUdpSrv->hSock, pvBuf, cbBuf, pcbRead, &pUdpSrv->NetAddrPeer);
103 if (RT_SUCCESS(rc) && pcbRead != NULL && *pcbRead == 0)
104 rc = VERR_NET_SHUTDOWN;
105 if (RT_FAILURE(rc))
106 pUdpSrv->fAlive = false;
107 pUdpSrv->fPeerSet = true;
108 return rc;
109}
110
111
112/**
113 * @interface_method_impl{DBGCIO,pfnWrite}
114 */
115static DECLCALLBACK(int) dbgcIoProvUdpIoWrite(PCDBGCIO pIo, const void *pvBuf, size_t cbBuf, size_t *pcbWritten)
116{
117 PDBGCUDPSRV pUdpSrv = RT_FROM_MEMBER(pIo, DBGCUDPSRV, Io);
118 if ( !pUdpSrv->fAlive
119 || !pUdpSrv->fPeerSet)
120 return VERR_INVALID_HANDLE;
121
122 int rc = RTSocketWriteTo(pUdpSrv->hSock, pvBuf, cbBuf, &pUdpSrv->NetAddrPeer);
123 if (RT_FAILURE(rc))
124 pUdpSrv->fAlive = false;
125
126 if (pcbWritten)
127 *pcbWritten = cbBuf;
128
129 return rc;
130}
131
132
133/**
134 * @interface_method_impl{DBGCIO,pfnSetReady}
135 */
136static DECLCALLBACK(void) dbgcIoProvUdpIoSetReady(PCDBGCIO pIo, bool fReady)
137{
138 /* stub */
139 NOREF(pIo);
140 NOREF(fReady);
141}
142
143
144/**
145 * @interface_method_impl{DBGCIOPROVREG,pfnCreate}
146 */
147static DECLCALLBACK(int) dbgcIoProvUdpCreate(PDBGCIOPROV phDbgcIoProv, PCFGMNODE pCfg)
148{
149 /*
150 * Get the port configuration.
151 */
152 uint32_t u32Port;
153 int rc = CFGMR3QueryU32Def(pCfg, "Port", &u32Port, 5000);
154 if (RT_FAILURE(rc))
155 {
156 LogRel(("Configuration error: Failed querying \"Port\" -> rc=%Rc\n", rc));
157 return rc;
158 }
159
160 /*
161 * Get the address configuration.
162 */
163 char szAddress[512];
164 rc = CFGMR3QueryStringDef(pCfg, "Address", szAddress, sizeof(szAddress), "");
165 if (RT_FAILURE(rc))
166 {
167 LogRel(("Configuration error: Failed querying \"Address\" -> rc=%Rc\n", rc));
168 return rc;
169 }
170
171 PDBGCUDPSRV pUdpSrv = (PDBGCUDPSRV)RTMemAllocZ(sizeof(*pUdpSrv));
172 if (RT_LIKELY(pUdpSrv))
173 {
174 pUdpSrv->Io.pfnDestroy = dbgcIoProvUdpIoDestroy;
175 pUdpSrv->Io.pfnInput = dbgcIoProvUdpIoInput;
176 pUdpSrv->Io.pfnRead = dbgcIoProvUdpIoRead;
177 pUdpSrv->Io.pfnWrite = dbgcIoProvUdpIoWrite;
178 pUdpSrv->Io.pfnPktBegin = NULL;
179 pUdpSrv->Io.pfnPktEnd = NULL;
180 pUdpSrv->Io.pfnSetReady = dbgcIoProvUdpIoSetReady;
181 pUdpSrv->fPeerSet = false;
182 pUdpSrv->fAlive = true;
183
184 /*
185 * Create the server.
186 */
187 rc = RTUdpCreateServerSocket(szAddress, u32Port, &pUdpSrv->hSock);
188 if (RT_SUCCESS(rc))
189 {
190 LogFlow(("dbgcIoProvUdpCreate: Created server on port %d %s\n", u32Port, szAddress));
191 *phDbgcIoProv = (DBGCIOPROV)pUdpSrv;
192 return rc;
193 }
194 }
195 else
196 rc = VERR_NO_MEMORY;
197
198 return rc;
199}
200
201
202/**
203 * @interface_method_impl{DBGCIOPROVREG,pfnDestroy}
204 */
205static DECLCALLBACK(void) dbgcIoProvUdpDestroy(DBGCIOPROV hDbgcIoProv)
206{
207 PDBGCUDPSRV pUdpSrv = (PDBGCUDPSRV)hDbgcIoProv;
208
209 RTSocketRelease(pUdpSrv->hSock);
210 pUdpSrv->fAlive = false;
211 RTMemFree(pUdpSrv);
212}
213
214
215/**
216 * @interface_method_impl{DBGCIOPROVREG,pfnWaitForConnect}
217 */
218static DECLCALLBACK(int) dbgcIoProvUdpWaitForConnect(DBGCIOPROV hDbgcIoProv, RTMSINTERVAL cMsTimeout, PCDBGCIO *ppDbgcIo)
219{
220 PDBGCUDPSRV pUdpSrv = (PDBGCUDPSRV)hDbgcIoProv;
221
222 /* Wait for the first datagram. */
223 int rc = RTSocketSelectOne(pUdpSrv->hSock, cMsTimeout);
224 if (RT_SUCCESS(rc))
225 *ppDbgcIo = &pUdpSrv->Io;
226 return rc;
227}
228
229
230/**
231 * @interface_method_impl{DBGCIOPROVREG,pfnWaitInterrupt}
232 */
233static DECLCALLBACK(int) dbgcIoProvUdpWaitInterrupt(DBGCIOPROV hDbgcIoProv)
234{
235 RT_NOREF(hDbgcIoProv);
236 /** @todo */
237 return VINF_SUCCESS;
238}
239
240
241/**
242 * UDP I/O provider registration record.
243 */
244const DBGCIOPROVREG g_DbgcIoProvUdp =
245{
246 /** pszName */
247 "udp",
248 /** pszDesc */
249 "UDP I/O provider.",
250 /** pfnCreate */
251 dbgcIoProvUdpCreate,
252 /** pfnDestroy */
253 dbgcIoProvUdpDestroy,
254 /** pfnWaitForConnect */
255 dbgcIoProvUdpWaitForConnect,
256 /** pfnWaitInterrupt */
257 dbgcIoProvUdpWaitInterrupt
258};
259
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette