VirtualBox

source: vbox/trunk/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.cpp@ 54647

Last change on this file since 54647 was 53502, checked in by vboxsync, 10 years ago

NetworkServices: no need to poll here

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.2 KB
Line 
1/* $Id: VBoxNetBaseService.cpp 53502 2014-12-10 17:02:39Z vboxsync $ */
2/** @file
3 * VBoxNetDHCP - DHCP Service for connecting to IntNet.
4 */
5/** @todo r=bird: Cut&Past rules... Please fix DHCP refs! */
6
7/*
8 * Copyright (C) 2009-2011 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define LOG_GROUP LOG_GROUP_NET_SERVICE
23
24#include <VBox/com/com.h>
25#include <VBox/com/listeners.h>
26#include <VBox/com/string.h>
27#include <VBox/com/Guid.h>
28#include <VBox/com/array.h>
29#include <VBox/com/ErrorInfo.h>
30#include <VBox/com/errorprint.h>
31#include <VBox/com/VirtualBox.h>
32#include <VBox/com/NativeEventQueue.h>
33
34#include <iprt/alloca.h>
35#include <iprt/buildconfig.h>
36#include <iprt/err.h>
37#include <iprt/net.h> /* must come before getopt.h. */
38#include <iprt/getopt.h>
39#include <iprt/initterm.h>
40#include <iprt/param.h>
41#include <iprt/path.h>
42#include <iprt/process.h>
43#include <iprt/stream.h>
44#include <iprt/string.h>
45#include <iprt/time.h>
46#include <iprt/thread.h>
47#include <iprt/mem.h>
48#include <iprt/message.h>
49
50#include <VBox/sup.h>
51#include <VBox/intnet.h>
52#include <VBox/intnetinline.h>
53#include <VBox/vmm/vmm.h>
54#include <VBox/version.h>
55
56#include <vector>
57#include <string>
58
59#include <VBox/err.h>
60#include <VBox/log.h>
61
62#include "VBoxNetLib.h"
63#include "VBoxNetBaseService.h"
64
65#ifdef RT_OS_WINDOWS /* WinMain */
66# include <Windows.h>
67# include <stdlib.h>
68#endif
69
70
71/*******************************************************************************
72* Structures and Typedefs *
73*******************************************************************************/
74struct VBoxNetBaseService::Data
75{
76 Data(const std::string& aName, const std::string& aNetworkName):
77 m_Name(aName),
78 m_Network(aNetworkName),
79 m_enmTrunkType(kIntNetTrunkType_WhateverNone),
80 m_pSession(NIL_RTR0PTR),
81 m_cbSendBuf(128 * _1K),
82 m_cbRecvBuf(256 * _1K),
83 m_hIf(INTNET_HANDLE_INVALID),
84 m_pIfBuf(NULL),
85 m_cVerbosity(0),
86 m_fNeedMain(false),
87 m_EventQ(NULL),
88 m_hThrRecv(NIL_RTTHREAD),
89 fShutdown(false)
90 {
91 int rc = RTCritSectInit(&m_csThis);
92 AssertRC(rc);
93 };
94
95 std::string m_Name;
96 std::string m_Network;
97 std::string m_TrunkName;
98 INTNETTRUNKTYPE m_enmTrunkType;
99
100 RTMAC m_MacAddress;
101 RTNETADDRIPV4 m_Ipv4Address;
102 RTNETADDRIPV4 m_Ipv4Netmask;
103
104 PSUPDRVSESSION m_pSession;
105 uint32_t m_cbSendBuf;
106 uint32_t m_cbRecvBuf;
107 INTNETIFHANDLE m_hIf; /**< The handle to the network interface. */
108 PINTNETBUF m_pIfBuf; /**< Interface buffer. */
109
110 std::vector<PRTGETOPTDEF> m_vecOptionDefs;
111
112 int32_t m_cVerbosity;
113
114 /* cs for syncing */
115 RTCRITSECT m_csThis;
116
117 /* Controls whether service will connect SVC for runtime needs */
118 bool m_fNeedMain;
119 /* Event Queue */
120 com::NativeEventQueue *m_EventQ;
121
122 /** receiving thread, used only if main is used */
123 RTTHREAD m_hThrRecv;
124
125 bool fShutdown;
126 static int recvLoop(RTTHREAD, void *);
127};
128
129/*******************************************************************************
130* Global Variables *
131*******************************************************************************/
132/* Commonly used options for network configuration */
133static RTGETOPTDEF g_aGetOptDef[] =
134{
135 { "--name", 'N', RTGETOPT_REQ_STRING },
136 { "--network", 'n', RTGETOPT_REQ_STRING },
137 { "--trunk-name", 't', RTGETOPT_REQ_STRING },
138 { "--trunk-type", 'T', RTGETOPT_REQ_STRING },
139 { "--mac-address", 'a', RTGETOPT_REQ_MACADDR },
140 { "--ip-address", 'i', RTGETOPT_REQ_IPV4ADDR },
141 { "--netmask", 'm', RTGETOPT_REQ_IPV4ADDR },
142 { "--verbose", 'v', RTGETOPT_REQ_NOTHING },
143 { "--need-main", 'M', RTGETOPT_REQ_BOOL },
144};
145
146
147int VBoxNetBaseService::Data::recvLoop(RTTHREAD, void *pvUser)
148{
149 VBoxNetBaseService *pThis = static_cast<VBoxNetBaseService *>(pvUser);
150
151 HRESULT hrc = com::Initialize();
152 AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
153
154 pThis->doReceiveLoop();
155
156 return VINF_SUCCESS;
157}
158
159
160VBoxNetBaseService::VBoxNetBaseService(const std::string& aName, const std::string& aNetworkName):m(NULL)
161{
162 m = new VBoxNetBaseService::Data(aName, aNetworkName);
163
164 for(unsigned int i = 0; i < RT_ELEMENTS(g_aGetOptDef); ++i)
165 m->m_vecOptionDefs.push_back(&g_aGetOptDef[i]);
166}
167
168
169VBoxNetBaseService::~VBoxNetBaseService()
170{
171 /*
172 * Close the interface connection.
173 */
174 if (m != NULL)
175 {
176 shutdown();
177 if (m->m_hIf != INTNET_HANDLE_INVALID)
178 {
179 INTNETIFCLOSEREQ CloseReq;
180 CloseReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
181 CloseReq.Hdr.cbReq = sizeof(CloseReq);
182 CloseReq.pSession = m->m_pSession;
183 CloseReq.hIf = m->m_hIf;
184 m->m_hIf = INTNET_HANDLE_INVALID;
185 int rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_RTCPUID, VMMR0_DO_INTNET_IF_CLOSE, 0, &CloseReq.Hdr);
186 AssertRC(rc);
187 }
188
189 if (m->m_pSession != NIL_RTR0PTR)
190 {
191 SUPR3Term(false /*fForced*/);
192 m->m_pSession = NIL_RTR0PTR;
193 }
194
195 RTCritSectDelete(&m->m_csThis);
196
197 delete m;
198 m = NULL;
199 }
200}
201
202
203int VBoxNetBaseService::init()
204{
205 if (isMainNeeded())
206 {
207 HRESULT hrc = com::Initialize();
208 AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
209
210 hrc = virtualbox.createLocalObject(CLSID_VirtualBox);
211 AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
212 }
213
214 return VINF_SUCCESS;
215}
216
217
218bool VBoxNetBaseService::isMainNeeded() const
219{
220 return m->m_fNeedMain;
221}
222
223
224int VBoxNetBaseService::run()
225{
226 /**
227 * If child class need Main we start receving thread which calls doReceiveLoop and enter to event polling loop
228 * and for the rest clients we do receiving on the current (main) thread.
229 */
230 if (isMainNeeded())
231 return startReceiveThreadAndEnterEventLoop();
232 else
233 {
234 doReceiveLoop();
235 return VINF_SUCCESS;
236 }
237}
238
239/**
240 * Parse the arguments.
241 *
242 * @returns 0 on success, fully bitched exit code on failure.
243 *
244 * @param argc Argument count.
245 * @param argv Argument vector.
246 */
247int VBoxNetBaseService::parseArgs(int argc, char **argv)
248{
249
250 RTGETOPTSTATE State;
251 PRTGETOPTDEF paOptionArray = getOptionsPtr();
252 int rc = RTGetOptInit(&State, argc, argv, paOptionArray, m->m_vecOptionDefs.size(), 0, 0 /*fFlags*/);
253 AssertRCReturn(rc, 49);
254#if 0
255 /* default initialization */
256 m_enmTrunkType = kIntNetTrunkType_WhateverNone;
257#endif
258 Log2(("BaseService: parseArgs enter\n"));
259
260 for (;;)
261 {
262 RTGETOPTUNION Val;
263 rc = RTGetOpt(&State, &Val);
264 if (!rc)
265 break;
266 switch (rc)
267 {
268 case 'N': // --name
269 m->m_Name = Val.psz;
270 break;
271
272 case 'n': // --network
273 m->m_Network = Val.psz;
274 break;
275
276 case 't': //--trunk-name
277 m->m_TrunkName = Val.psz;
278 break;
279
280 case 'T': //--trunk-type
281 if (!strcmp(Val.psz, "none"))
282 m->m_enmTrunkType = kIntNetTrunkType_None;
283 else if (!strcmp(Val.psz, "whatever"))
284 m->m_enmTrunkType = kIntNetTrunkType_WhateverNone;
285 else if (!strcmp(Val.psz, "netflt"))
286 m->m_enmTrunkType = kIntNetTrunkType_NetFlt;
287 else if (!strcmp(Val.psz, "netadp"))
288 m->m_enmTrunkType = kIntNetTrunkType_NetAdp;
289 else if (!strcmp(Val.psz, "srvnat"))
290 m->m_enmTrunkType = kIntNetTrunkType_SrvNat;
291 else
292 {
293 RTStrmPrintf(g_pStdErr, "Invalid trunk type '%s'\n", Val.psz);
294 return 1;
295 }
296 break;
297
298 case 'a': // --mac-address
299 m->m_MacAddress = Val.MacAddr;
300 break;
301
302 case 'i': // --ip-address
303 m->m_Ipv4Address = Val.IPv4Addr;
304 break;
305
306 case 'm': // --netmask
307 m->m_Ipv4Netmask = Val.IPv4Addr;
308 break;
309
310 case 'v': // --verbose
311 m->m_cVerbosity++;
312 break;
313
314 case 'V': // --version (missed)
315 RTPrintf("%sr%u\n", RTBldCfgVersion(), RTBldCfgRevision());
316 return 1;
317
318 case 'M': // --need-main
319 m->m_fNeedMain = true;
320 break;
321
322 case 'h': // --help (missed)
323 RTPrintf("%s Version %sr%u\n"
324 "(C) 2009-" VBOX_C_YEAR " " VBOX_VENDOR "\n"
325 "All rights reserved.\n"
326 "\n"
327 "Usage: %s <options>\n"
328 "\n"
329 "Options:\n",
330 RTProcShortName(),
331 RTBldCfgVersion(),
332 RTBldCfgRevision(),
333 RTProcShortName());
334 for (unsigned int i = 0; i < m->m_vecOptionDefs.size(); i++)
335 RTPrintf(" -%c, %s\n", m->m_vecOptionDefs[i]->iShort, m->m_vecOptionDefs[i]->pszLong);
336 usage(); /* to print Service Specific usage */
337 return 1;
338
339 default:
340 int rc1 = parseOpt(rc, Val);
341 if (RT_FAILURE(rc1))
342 {
343 rc = RTGetOptPrintError(rc, &Val);
344 RTPrintf("Use --help for more information.\n");
345 return rc;
346 }
347 }
348 }
349
350 RTMemFree(paOptionArray);
351 return rc;
352}
353
354
355int VBoxNetBaseService::tryGoOnline(void)
356{
357 /*
358 * Open the session, load ring-0 and issue the request.
359 */
360 int rc = SUPR3Init(&m->m_pSession);
361 if (RT_FAILURE(rc))
362 {
363 m->m_pSession = NIL_RTR0PTR;
364 LogRel(("VBoxNetBaseService: SUPR3Init -> %Rrc\n", rc));
365 return rc;
366 }
367
368 char szPath[RTPATH_MAX];
369 rc = RTPathExecDir(szPath, sizeof(szPath) - sizeof("/VMMR0.r0"));
370 if (RT_FAILURE(rc))
371 {
372 LogRel(("VBoxNetBaseService: RTPathExecDir -> %Rrc\n", rc));
373 return rc;
374 }
375
376 rc = SUPR3LoadVMM(strcat(szPath, "/VMMR0.r0"));
377 if (RT_FAILURE(rc))
378 {
379 LogRel(("VBoxNetBaseService: SUPR3LoadVMM(\"%s\") -> %Rrc\n", szPath, rc));
380 return rc;
381 }
382
383 /*
384 * Create the open request.
385 */
386 PINTNETBUF pBuf;
387 INTNETOPENREQ OpenReq;
388 OpenReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
389 OpenReq.Hdr.cbReq = sizeof(OpenReq);
390 OpenReq.pSession = m->m_pSession;
391 strncpy(OpenReq.szNetwork, m->m_Network.c_str(), sizeof(OpenReq.szNetwork));
392 OpenReq.szNetwork[sizeof(OpenReq.szNetwork) - 1] = '\0';
393 strncpy(OpenReq.szTrunk, m->m_TrunkName.c_str(), sizeof(OpenReq.szTrunk));
394 OpenReq.szTrunk[sizeof(OpenReq.szTrunk) - 1] = '\0';
395 OpenReq.enmTrunkType = m->m_enmTrunkType;
396 OpenReq.fFlags = 0; /** @todo check this */
397 OpenReq.cbSend = m->m_cbSendBuf;
398 OpenReq.cbRecv = m->m_cbRecvBuf;
399 OpenReq.hIf = INTNET_HANDLE_INVALID;
400
401 /*
402 * Issue the request.
403 */
404 Log2(("attempting to open/create network \"%s\"...\n", OpenReq.szNetwork));
405 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_OPEN, 0, &OpenReq.Hdr);
406 if (RT_FAILURE(rc))
407 {
408 Log2(("VBoxNetBaseService: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_OPEN,) failed, rc=%Rrc\n", rc));
409 return rc;
410 }
411 m->m_hIf = OpenReq.hIf;
412 Log2(("successfully opened/created \"%s\" - hIf=%#x\n", OpenReq.szNetwork, m->m_hIf));
413
414 /*
415 * Get the ring-3 address of the shared interface buffer.
416 */
417 INTNETIFGETBUFFERPTRSREQ GetBufferPtrsReq;
418 GetBufferPtrsReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
419 GetBufferPtrsReq.Hdr.cbReq = sizeof(GetBufferPtrsReq);
420 GetBufferPtrsReq.pSession = m->m_pSession;
421 GetBufferPtrsReq.hIf = m->m_hIf;
422 GetBufferPtrsReq.pRing3Buf = NULL;
423 GetBufferPtrsReq.pRing0Buf = NIL_RTR0PTR;
424 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS, 0, &GetBufferPtrsReq.Hdr);
425 if (RT_FAILURE(rc))
426 {
427 Log2(("VBoxNetBaseService: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS,) failed, rc=%Rrc\n", rc));
428 return rc;
429 }
430 pBuf = GetBufferPtrsReq.pRing3Buf;
431 Log2(("pBuf=%p cbBuf=%d cbSend=%d cbRecv=%d\n",
432 pBuf, pBuf->cbBuf, pBuf->cbSend, pBuf->cbRecv));
433 m->m_pIfBuf = pBuf;
434
435 /*
436 * Activate the interface.
437 */
438 INTNETIFSETACTIVEREQ ActiveReq;
439 ActiveReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
440 ActiveReq.Hdr.cbReq = sizeof(ActiveReq);
441 ActiveReq.pSession = m->m_pSession;
442 ActiveReq.hIf = m->m_hIf;
443 ActiveReq.fActive = true;
444 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SET_ACTIVE, 0, &ActiveReq.Hdr);
445 if (RT_SUCCESS(rc))
446 return 0;
447
448 /* bail out */
449 Log2(("VBoxNetBaseService: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE,) failed, rc=%Rrc\n", rc));
450
451 /* ignore this error */
452 return VINF_SUCCESS;
453}
454
455
456void VBoxNetBaseService::shutdown(void)
457{
458 syncEnter();
459 m->fShutdown = true;
460 if (m->m_hThrRecv != NIL_RTTHREAD)
461 {
462 int rc = m->m_EventQ->interruptEventQueueProcessing();
463 if (RT_SUCCESS(rc))
464 {
465 rc = RTThreadWait(m->m_hThrRecv, 60000, NULL);
466 if (RT_FAILURE(rc))
467 LogWarningFunc(("RTThreadWait(%RTthrd) -> %Rrc\n", m->m_hThrRecv, rc));
468 }
469 else
470 {
471 AssertMsgFailed(("interruptEventQueueProcessing() failed\n"));
472 RTThreadWait(m->m_hThrRecv , 0, NULL);
473 }
474 }
475 syncLeave();
476}
477
478
479int VBoxNetBaseService::syncEnter()
480{
481 return RTCritSectEnter(&m->m_csThis);
482}
483
484
485int VBoxNetBaseService::syncLeave()
486{
487 return RTCritSectLeave(&m->m_csThis);
488}
489
490
491int VBoxNetBaseService::waitForIntNetEvent(int cMillis)
492{
493 int rc = VINF_SUCCESS;
494 INTNETIFWAITREQ WaitReq;
495 LogFlowFunc(("ENTER:cMillis: %d\n", cMillis));
496 WaitReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
497 WaitReq.Hdr.cbReq = sizeof(WaitReq);
498 WaitReq.pSession = m->m_pSession;
499 WaitReq.hIf = m->m_hIf;
500 WaitReq.cMillies = cMillis;
501
502 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_WAIT, 0, &WaitReq.Hdr);
503 LogFlowFuncLeaveRC(rc);
504 return rc;
505}
506
507/* S/G API */
508int VBoxNetBaseService::sendBufferOnWire(PCINTNETSEG pcSg, int cSg, size_t cbFrame)
509{
510 PINTNETHDR pHdr = NULL;
511 uint8_t *pu8Frame = NULL;
512
513 /* Allocate frame */
514 int rc = IntNetRingAllocateFrame(&m->m_pIfBuf->Send, cbFrame, &pHdr, (void **)&pu8Frame);
515 AssertRCReturn(rc, rc);
516
517 /* Now we fill pvFrame with S/G above */
518 int offFrame = 0;
519 for (int idxSg = 0; idxSg < cSg; ++idxSg)
520 {
521 memcpy(&pu8Frame[offFrame], pcSg[idxSg].pv, pcSg[idxSg].cb);
522 offFrame+=pcSg[idxSg].cb;
523 }
524
525 /* Commit */
526 IntNetRingCommitFrameEx(&m->m_pIfBuf->Send, pHdr, cbFrame);
527
528 LogFlowFuncLeaveRC(rc);
529 return rc;
530}
531
532/**
533 * forcible ask for send packet on the "wire"
534 */
535void VBoxNetBaseService::flushWire()
536{
537 int rc = VINF_SUCCESS;
538 INTNETIFSENDREQ SendReq;
539 SendReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
540 SendReq.Hdr.cbReq = sizeof(SendReq);
541 SendReq.pSession = m->m_pSession;
542 SendReq.hIf = m->m_hIf;
543 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SEND, 0, &SendReq.Hdr);
544 AssertRCReturnVoid(rc);
545 LogFlowFuncLeave();
546
547}
548
549
550int VBoxNetBaseService::hlpUDPBroadcast(unsigned uSrcPort, unsigned uDstPort,
551 void const *pvData, size_t cbData) const
552{
553 return VBoxNetUDPBroadcast(m->m_pSession, m->m_hIf, m->m_pIfBuf,
554 m->m_Ipv4Address, &m->m_MacAddress, uSrcPort,
555 uDstPort, pvData, cbData);
556
557}
558
559
560const std::string VBoxNetBaseService::getName() const
561{
562 return m->m_Name;
563}
564
565
566void VBoxNetBaseService::setName(const std::string& aName)
567{
568 m->m_Name = aName;
569}
570
571
572const std::string VBoxNetBaseService::getNetwork() const
573{
574 return m->m_Network;
575}
576
577
578void VBoxNetBaseService::setNetwork(const std::string& aNetwork)
579{
580 m->m_Network = aNetwork;
581}
582
583
584const RTMAC VBoxNetBaseService::getMacAddress() const
585{
586 return m->m_MacAddress;
587}
588
589
590void VBoxNetBaseService::setMacAddress(const RTMAC& aMac)
591{
592 m->m_MacAddress = aMac;
593}
594
595
596const RTNETADDRIPV4 VBoxNetBaseService::getIpv4Address() const
597{
598 return m->m_Ipv4Address;
599}
600
601
602void VBoxNetBaseService::setIpv4Address(const RTNETADDRIPV4& aAddress)
603{
604 m->m_Ipv4Address = aAddress;
605}
606
607
608const RTNETADDRIPV4 VBoxNetBaseService::getIpv4Netmask() const
609{
610 return m->m_Ipv4Netmask;
611}
612
613
614void VBoxNetBaseService::setIpv4Netmask(const RTNETADDRIPV4& aNetmask)
615{
616 m->m_Ipv4Netmask = aNetmask;
617}
618
619
620uint32_t VBoxNetBaseService::getSendBufSize() const
621{
622 return m->m_cbSendBuf;
623}
624
625
626void VBoxNetBaseService::setSendBufSize(uint32_t cbBuf)
627{
628 m->m_cbSendBuf = cbBuf;
629}
630
631
632uint32_t VBoxNetBaseService::getRecvBufSize() const
633{
634 return m->m_cbRecvBuf;
635}
636
637
638void VBoxNetBaseService::setRecvBufSize(uint32_t cbBuf)
639{
640 m->m_cbRecvBuf = cbBuf;
641}
642
643
644int32_t VBoxNetBaseService::getVerbosityLevel() const
645{
646 return m->m_cVerbosity;
647}
648
649
650void VBoxNetBaseService::setVerbosityLevel(int32_t aVerbosity)
651{
652 m->m_cVerbosity = aVerbosity;
653}
654
655
656void VBoxNetBaseService::addCommandLineOption(const PRTGETOPTDEF optDef)
657{
658 m->m_vecOptionDefs.push_back(optDef);
659}
660
661
662void VBoxNetBaseService::doReceiveLoop()
663{
664 int rc;
665 /* Well we're ready */
666 PINTNETRINGBUF pRingBuf = &m->m_pIfBuf->Recv;
667
668 for (;;)
669 {
670 /*
671 * Wait for a packet to become available.
672 */
673 /* 2. waiting for request for */
674 rc = waitForIntNetEvent(2000);
675 if (RT_FAILURE(rc))
676 {
677 if (rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED)
678 {
679 /* do we want interrupt anyone ??? */
680 continue;
681 }
682 LogRel(("VBoxNetNAT: waitForIntNetEvent returned %Rrc\n", rc));
683 AssertRCReturnVoid(rc);
684 }
685
686 /*
687 * Process the receive buffer.
688 */
689 PCINTNETHDR pHdr;
690
691 while ((pHdr = IntNetRingGetNextFrameToRead(pRingBuf)) != NULL)
692 {
693 uint8_t const u8Type = pHdr->u8Type;
694 size_t cbFrame = pHdr->cbFrame;
695 switch (u8Type)
696 {
697
698 case INTNETHDR_TYPE_FRAME:
699 {
700 void *pvFrame = IntNetHdrGetFramePtr(pHdr, m->m_pIfBuf);
701 rc = processFrame(pvFrame, cbFrame);
702 if (RT_FAILURE(rc) && rc == VERR_IGNORED)
703 {
704 /* XXX: UDP + ARP for DHCP */
705 VBOXNETUDPHDRS Hdrs;
706 size_t cb;
707 void *pv = VBoxNetUDPMatch(m->m_pIfBuf, RTNETIPV4_PORT_BOOTPS, &m->m_MacAddress,
708 VBOXNETUDP_MATCH_UNICAST | VBOXNETUDP_MATCH_BROADCAST
709 | VBOXNETUDP_MATCH_CHECKSUM
710 | (m->m_cVerbosity > 2 ? VBOXNETUDP_MATCH_PRINT_STDERR : 0),
711 &Hdrs, &cb);
712 if (pv && cb)
713 processUDP(pv, cb);
714 else
715 VBoxNetArpHandleIt(m->m_pSession, m->m_hIf, m->m_pIfBuf, &m->m_MacAddress, m->m_Ipv4Address);
716 }
717 }
718 break;
719 case INTNETHDR_TYPE_GSO:
720 {
721 PCPDMNETWORKGSO pGso = IntNetHdrGetGsoContext(pHdr, m->m_pIfBuf);
722 rc = processGSO(pGso, cbFrame);
723 if (RT_FAILURE(rc) && rc == VERR_IGNORED)
724 break;
725 }
726 break;
727 case INTNETHDR_TYPE_PADDING:
728 break;
729 default:
730 break;
731 }
732 IntNetRingSkipFrame(&m->m_pIfBuf->Recv);
733
734 } /* loop */
735 }
736
737}
738
739
740int VBoxNetBaseService::startReceiveThreadAndEnterEventLoop()
741{
742 AssertMsgReturn(isMainNeeded(), ("It's expected that we need Main"), VERR_INTERNAL_ERROR);
743
744 /* start receiving thread */
745 int rc = RTThreadCreate(&m->m_hThrRecv, /* thread handle*/
746 &VBoxNetBaseService::Data::recvLoop, /* routine */
747 this, /* user data */
748 128 * _1K, /* stack size */
749 RTTHREADTYPE_IO, /* type */
750 0, /* flags, @todo: waitable ?*/
751 "RECV");
752 AssertRCReturn(rc, rc);
753
754 m->m_EventQ = com::NativeEventQueue::getMainEventQueue();
755 AssertPtrReturn(m->m_EventQ, VERR_INTERNAL_ERROR);
756
757 while (!m->fShutdown)
758 {
759 rc = m->m_EventQ->processEventQueue(RT_INDEFINITE_WAIT);
760 if (rc == VERR_INTERRUPTED)
761 {
762 LogFlow(("Event queue processing ended with rc=%Rrc\n", rc));
763 break;
764 }
765 }
766
767 return VINF_SUCCESS;
768}
769
770
771void VBoxNetBaseService::debugPrint(int32_t iMinLevel, bool fMsg, const char *pszFmt, ...) const
772{
773 if (iMinLevel <= m->m_cVerbosity)
774 {
775 va_list va;
776 va_start(va, pszFmt);
777 debugPrintV(iMinLevel, fMsg, pszFmt, va);
778 va_end(va);
779 }
780}
781
782
783/**
784 * Print debug message depending on the m_cVerbosity level.
785 *
786 * @param iMinLevel The minimum m_cVerbosity level for this message.
787 * @param fMsg Whether to dump parts for the current service message.
788 * @param pszFmt The message format string.
789 * @param va Optional arguments.
790 */
791void VBoxNetBaseService::debugPrintV(int iMinLevel, bool fMsg, const char *pszFmt, va_list va) const
792{
793 if (iMinLevel <= m->m_cVerbosity)
794 {
795 va_list vaCopy; /* This dude is *very* special, thus the copy. */
796 va_copy(vaCopy, va);
797 RTStrmPrintf(g_pStdErr, "%s: %s: %N\n",
798 RTProcShortName(),
799 iMinLevel >= 2 ? "debug" : "info",
800 pszFmt,
801 &vaCopy);
802 va_end(vaCopy);
803 }
804
805}
806
807
808PRTGETOPTDEF VBoxNetBaseService::getOptionsPtr()
809{
810 PRTGETOPTDEF pOptArray = NULL;
811 pOptArray = (PRTGETOPTDEF)RTMemAlloc(sizeof(RTGETOPTDEF) * m->m_vecOptionDefs.size());
812 if (!pOptArray)
813 return NULL;
814 for (unsigned int i = 0; i < m->m_vecOptionDefs.size(); ++i)
815 {
816 PRTGETOPTDEF pOpt = m->m_vecOptionDefs[i];
817 memcpy(&pOptArray[i], m->m_vecOptionDefs[i], sizeof(RTGETOPTDEF));
818 }
819 return pOptArray;
820}
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