VirtualBox

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

Last change on this file since 94993 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

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