VirtualBox

source: vbox/trunk/src/VBox/Devices/GIMDev/DrvUDP.cpp

Last change on this file was 106061, checked in by vboxsync, 3 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.0 KB
Line 
1/* $Id: DrvUDP.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * UDP socket stream driver.
4 */
5
6/*
7 * Copyright (C) 2015-2024 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#define LOG_GROUP LOG_GROUP_DRV_UDP
33#include <VBox/log.h>
34#include <VBox/vmm/pdmdrv.h>
35
36#include "VBoxDD.h"
37
38#include <iprt/socket.h>
39#include <iprt/udp.h>
40#include <iprt/uuid.h>
41
42
43/*********************************************************************************************************************************
44* Defined Constants And Macros *
45*********************************************************************************************************************************/
46/** Converts a pointer to DRVUDP::IStream to a PDRVUDP. */
47#define PDMISTREAM_2_DRVUDP(pInterface) ( (PDRVUDP)((uintptr_t)pInterface - RT_UOFFSETOF(DRVUDP, IStream)) )
48
49
50/*********************************************************************************************************************************
51* Structures and Typedefs *
52*********************************************************************************************************************************/
53/**
54 * UDP driver instance data.
55 *
56 * @implements PDMISTREAM
57 */
58typedef struct DRVUDP
59{
60 /** The stream interface. */
61 PDMISTREAM IStream;
62 /** Pointer to the driver instance. */
63 PPDMDRVINS pDrvIns;
64 /** The server port. */
65 uint16_t uServerPort;
66 /** The server address. */
67 char *pszServerAddress;
68 /** The resolved server address struct. */
69 RTNETADDR ServerAddr;
70 /** The UDP socket. */
71 RTSOCKET hSocket;
72} DRVUDP, *PDRVUDP;
73
74
75/*********************************************************************************************************************************
76* Internal Functions *
77*********************************************************************************************************************************/
78
79
80/** @interface_method_impl{PDMISTREAM,pfnRead} */
81static DECLCALLBACK(int) drvUDPRead(PPDMISTREAM pInterface, void *pvBuf, size_t *pcbRead)
82{
83 int rc = VINF_SUCCESS;
84 PDRVUDP pThis = PDMISTREAM_2_DRVUDP(pInterface);
85 LogFlowFunc(("pvBuf=%p *pcbRead=%#x (%s:%u)\n", pvBuf, *pcbRead, pThis->pszServerAddress, pThis->uServerPort));
86
87 Assert(pvBuf);
88 Assert(pcbRead);
89 if (pThis->hSocket != NIL_RTSOCKET)
90 {
91 size_t cbReallyRead = 0;
92 rc = RTSocketRead(pThis->hSocket, pvBuf, *pcbRead, &cbReallyRead);
93 if (RT_SUCCESS(rc))
94 *pcbRead = cbReallyRead;
95 }
96 else
97 rc = VERR_NET_NOT_SOCKET;
98
99 LogFlowFunc(("*pcbRead=%zu returns %Rrc\n", *pcbRead, rc));
100 return rc;
101}
102
103
104/** @interface_method_impl{PDMISTREAM,pfnWrite} */
105static DECLCALLBACK(int) drvUDPWrite(PPDMISTREAM pInterface, const void *pvBuf, size_t *pcbWrite)
106{
107 int rc = VINF_SUCCESS;
108 PDRVUDP pThis = PDMISTREAM_2_DRVUDP(pInterface);
109 LogFlowFunc(("pvBuf=%p *pcbWrite=%#x (%s:%u)\n", pvBuf, *pcbWrite, pThis->pszServerAddress, pThis->uServerPort));
110
111 Assert(pvBuf);
112 Assert(pcbWrite);
113 if (pThis->hSocket != NIL_RTSOCKET)
114 {
115 size_t cbBuf = *pcbWrite;
116 rc = RTSocketWriteTo(pThis->hSocket, pvBuf, cbBuf, NULL /*pDstAddr*/);
117 if (RT_SUCCESS(rc))
118 *pcbWrite = cbBuf;
119 }
120 else
121 rc = VERR_NET_NOT_SOCKET;
122
123 LogFlowFunc(("*pcbWrite=%zu returns %Rrc\n", *pcbWrite, rc));
124 return rc;
125}
126
127
128/**
129 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
130 */
131static DECLCALLBACK(void *) drvUDPQueryInterface(PPDMIBASE pInterface, const char *pszIID)
132{
133 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
134 PDRVUDP pThis = PDMINS_2_DATA(pDrvIns, PDRVUDP);
135 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
136 PDMIBASE_RETURN_INTERFACE(pszIID, PDMISTREAM, &pThis->IStream);
137 return NULL;
138}
139
140
141/* -=-=-=-=- PDMDRVREG -=-=-=-=- */
142
143/**
144 * Destruct a UDP socket stream driver instance.
145 *
146 * Most VM resources are freed by the VM. This callback is provided so that
147 * any non-VM resources can be freed correctly.
148 *
149 * @param pDrvIns The driver instance data.
150 */
151static DECLCALLBACK(void) drvUDPDestruct(PPDMDRVINS pDrvIns)
152{
153 PDRVUDP pThis = PDMINS_2_DATA(pDrvIns, PDRVUDP);
154 LogFlowFunc(("\n"));
155 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
156
157 if (pThis->hSocket != NIL_RTSOCKET)
158 {
159 /*
160 * We shutdown the socket here to poke out any blocking socket reads. The caller
161 * on the other thread/s need to ensure that they do -not- invoke drvUDPRead()
162 * or drvUDPWrite() after this.
163 */
164 RTSocketRetain(pThis->hSocket);
165 RTSocketShutdown(pThis->hSocket, true, true);
166 RTSocketClose(pThis->hSocket);
167 pThis->hSocket = NIL_RTSOCKET;
168 LogRel(("DrvUDP#%u: Closed socket to %s:%u\n", pThis->pDrvIns->iInstance, pThis->pszServerAddress, pThis->uServerPort));
169 }
170
171 PDMDrvHlpMMHeapFree(pDrvIns, pThis->pszServerAddress);
172 pThis->pszServerAddress = NULL;
173}
174
175
176/**
177 * Construct a UDP socket stream driver instance.
178 *
179 * @copydoc FNPDMDRVCONSTRUCT
180 */
181static DECLCALLBACK(int) drvUDPConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
182{
183 RT_NOREF1(fFlags);
184 PDRVUDP pThis = PDMINS_2_DATA(pDrvIns, PDRVUDP);
185 PCPDMDRVHLPR3 pHlp = pDrvIns->pHlpR3;
186
187 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
188
189 /*
190 * Init the static parts.
191 */
192 pThis->pDrvIns = pDrvIns;
193 /* IBase */
194 pDrvIns->IBase.pfnQueryInterface = drvUDPQueryInterface;
195 /* IStream */
196 pThis->IStream.pfnRead = drvUDPRead;
197 pThis->IStream.pfnWrite = drvUDPWrite;
198
199 /*
200 * Validate and read the configuration.
201 */
202 PDMDRV_VALIDATE_CONFIG_RETURN(pDrvIns, "ServerAddress|ServerPort", "");
203
204 int rc = pHlp->pfnCFGMQueryStringAlloc(pCfg, "ServerAddress", &pThis->pszServerAddress);
205 if (RT_FAILURE(rc))
206 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
207 N_("Configuration error: querying \"ServerAddress\" resulted in %Rrc"), rc);
208 rc = pHlp->pfnCFGMQueryU16(pCfg, "ServerPort", &pThis->uServerPort);
209 if (RT_FAILURE(rc))
210 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
211 N_("Configuration error: querying \"ServerPort\" resulted in %Rrc"), rc);
212
213 /*
214 * Create the socket and connect.
215 */
216 rc = RTUdpCreateClientSocket(pThis->pszServerAddress, pThis->uServerPort, NULL, &pThis->hSocket);
217 if (RT_SUCCESS(rc))
218 LogRel(("DrvUDP#%u: Connected socket to %s:%u\n",
219 pThis->pDrvIns->iInstance, pThis->pszServerAddress, pThis->uServerPort));
220 else
221 LogRel(("DrvUDP#%u: Failed to create/connect socket to %s:%u rc=%Rrc\n",
222 pThis->pDrvIns->iInstance, pThis->pszServerAddress, pThis->uServerPort, rc));
223 return VINF_SUCCESS;
224}
225
226
227/**
228 * UDP socket driver registration record.
229 */
230const PDMDRVREG g_DrvUDP =
231{
232 /* u32Version */
233 PDM_DRVREG_VERSION,
234 /* szName */
235 "UDP",
236 /* szRCMod */
237 "",
238 /* szR0Mod */
239 "",
240 /* pszDescription */
241 "UDP socket stream driver.",
242 /* fFlags */
243 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
244 /* fClass. */
245 PDM_DRVREG_CLASS_STREAM,
246 /* cMaxInstances */
247 ~0U,
248 /* cbInstance */
249 sizeof(DRVUDP),
250 /* pfnConstruct */
251 drvUDPConstruct,
252 /* pfnDestruct */
253 drvUDPDestruct,
254 /* pfnRelocate */
255 NULL,
256 /* pfnIOCtl */
257 NULL,
258 /* pfnPowerOn */
259 NULL,
260 /* pfnReset */
261 NULL,
262 /* pfnSuspend */
263 NULL,
264 /* pfnResume */
265 NULL,
266 /* pfnAttach */
267 NULL,
268 /* pfnDetach */
269 NULL,
270 /* pfnPowerOff */
271 NULL,
272 /* pfnSoftReset */
273 NULL,
274 /* u32EndVersion */
275 PDM_DRVREG_VERSION
276};
277
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