VirtualBox

source: vbox/trunk/src/VBox/Devices/Serial/DrvNamedPipe.cpp@ 26430

Last change on this file since 26430 was 26173, checked in by vboxsync, 15 years ago

PDM: s/pCfgHandle/pCfg/g - part 2.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.9 KB
Line 
1/* $Id: DrvNamedPipe.cpp 26173 2010-02-02 21:11:09Z vboxsync $ */
2/** @file
3 * VBox stream drivers: Named pipe stream
4 */
5
6/*
7 * Copyright (C) 2006-2010 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#define LOG_GROUP LOG_GROUP_DRV_NAMEDPIPE
27#include <VBox/pdmdrv.h>
28#include <iprt/assert.h>
29#include <iprt/file.h>
30#include <iprt/stream.h>
31#include <iprt/alloc.h>
32#include <iprt/string.h>
33#include <iprt/semaphore.h>
34#include <iprt/uuid.h>
35
36#include "Builtins.h"
37
38#ifdef RT_OS_WINDOWS
39# include <windows.h>
40#else /* !RT_OS_WINDOWS */
41# include <errno.h>
42# include <unistd.h>
43# include <sys/types.h>
44# include <sys/socket.h>
45# include <sys/un.h>
46#endif /* !RT_OS_WINDOWS */
47
48
49/*******************************************************************************
50* Defined Constants And Macros *
51*******************************************************************************/
52/** Converts a pointer to DRVNAMEDPIPE::IMedia to a PDRVNAMEDPIPE. */
53#define PDMISTREAM_2_DRVNAMEDPIPE(pInterface) ( (PDRVNAMEDPIPE)((uintptr_t)pInterface - RT_OFFSETOF(DRVNAMEDPIPE, IStream)) )
54
55/** Converts a pointer to PDMDRVINS::IBase to a PPDMDRVINS. */
56#define PDMIBASE_2_DRVINS(pInterface) ( (PPDMDRVINS)((uintptr_t)pInterface - RT_OFFSETOF(PDMDRVINS, IBase)) )
57
58
59/*******************************************************************************
60* Structures and Typedefs *
61*******************************************************************************/
62/**
63 * Named pipe driver instance data.
64 *
65 * @implements PDMISTREAM
66 */
67typedef struct DRVNAMEDPIPE
68{
69 /** The stream interface. */
70 PDMISTREAM IStream;
71 /** Pointer to the driver instance. */
72 PPDMDRVINS pDrvIns;
73 /** Pointer to the named pipe file name. (Freed by MM) */
74 char *pszLocation;
75 /** Flag whether VirtualBox represents the server or client side. */
76 bool fIsServer;
77#ifdef RT_OS_WINDOWS
78 /* File handle of the named pipe. */
79 HANDLE NamedPipe;
80 /* Overlapped structure for writes. */
81 OVERLAPPED OverlappedWrite;
82 /* Overlapped structure for reads. */
83 OVERLAPPED OverlappedRead;
84 /* Listen thread wakeup semaphore */
85 RTSEMEVENT ListenSem;
86#else /* !RT_OS_WINDOWS */
87 /** Socket handle of the local socket for server. */
88 RTSOCKET LocalSocketServer;
89 /** Socket handle of the local socket. */
90 RTSOCKET LocalSocket;
91#endif /* !RT_OS_WINDOWS */
92 /** Thread for listening for new connections. */
93 RTTHREAD ListenThread;
94 /** Flag to signal listening thread to shut down. */
95 bool fShutdown;
96} DRVNAMEDPIPE, *PDRVNAMEDPIPE;
97
98
99/*******************************************************************************
100* Internal Functions *
101*******************************************************************************/
102
103
104/** @copydoc PDMISTREAM::pfnRead */
105static DECLCALLBACK(int) drvNamedPipeRead(PPDMISTREAM pInterface, void *pvBuf, size_t *pcbRead)
106{
107 int rc = VINF_SUCCESS;
108 PDRVNAMEDPIPE pThis = PDMISTREAM_2_DRVNAMEDPIPE(pInterface);
109 LogFlow(("%s: pvBuf=%p *pcbRead=%#x (%s)\n", __FUNCTION__, pvBuf, *pcbRead, pThis->pszLocation));
110
111 Assert(pvBuf);
112#ifdef RT_OS_WINDOWS
113 if (pThis->NamedPipe != INVALID_HANDLE_VALUE)
114 {
115 DWORD cbReallyRead;
116 pThis->OverlappedRead.Offset = 0;
117 pThis->OverlappedRead.OffsetHigh = 0;
118 if (!ReadFile(pThis->NamedPipe, pvBuf, (DWORD)*pcbRead, &cbReallyRead, &pThis->OverlappedRead))
119 {
120 DWORD uError = GetLastError();
121
122 if ( uError == ERROR_PIPE_LISTENING
123 || uError == ERROR_PIPE_NOT_CONNECTED)
124 {
125 /* No connection yet/anymore */
126 cbReallyRead = 0;
127
128 /* wait a bit or else we'll be called right back. */
129 RTThreadSleep(100);
130 }
131 else
132 {
133 if (uError == ERROR_IO_PENDING)
134 {
135 uError = 0;
136
137 /* Wait for incoming bytes. */
138 if (GetOverlappedResult(pThis->NamedPipe, &pThis->OverlappedRead, &cbReallyRead, TRUE) == FALSE)
139 uError = GetLastError();
140 }
141
142 rc = RTErrConvertFromWin32(uError);
143 Log(("drvNamedPipeRead: ReadFile returned %d (%Rrc)\n", uError, rc));
144 }
145 }
146
147 if (RT_FAILURE(rc))
148 {
149 Log(("drvNamedPipeRead: FileRead returned %Rrc fShutdown=%d\n", rc, pThis->fShutdown));
150 if ( !pThis->fShutdown
151 && ( rc == VERR_EOF
152 || rc == VERR_BROKEN_PIPE
153 )
154 )
155
156 {
157 FlushFileBuffers(pThis->NamedPipe);
158 DisconnectNamedPipe(pThis->NamedPipe);
159 if (!pThis->fIsServer)
160 {
161 CloseHandle(pThis->NamedPipe);
162 pThis->NamedPipe = INVALID_HANDLE_VALUE;
163 }
164 /* pretend success */
165 rc = VINF_SUCCESS;
166 }
167 cbReallyRead = 0;
168 }
169 *pcbRead = (size_t)cbReallyRead;
170 }
171#else /* !RT_OS_WINDOWS */
172 if (pThis->LocalSocket != NIL_RTSOCKET)
173 {
174 ssize_t cbReallyRead;
175 cbReallyRead = recv(pThis->LocalSocket, pvBuf, *pcbRead, 0);
176 if (cbReallyRead == 0)
177 {
178 RTSOCKET tmp = pThis->LocalSocket;
179 pThis->LocalSocket = NIL_RTSOCKET;
180 close(tmp);
181 }
182 else if (cbReallyRead == -1)
183 {
184 cbReallyRead = 0;
185 rc = RTErrConvertFromErrno(errno);
186 }
187 *pcbRead = cbReallyRead;
188 }
189#endif /* !RT_OS_WINDOWS */
190 else
191 {
192 RTThreadSleep(100);
193 *pcbRead = 0;
194 }
195
196 LogFlow(("%s: *pcbRead=%zu returns %Rrc\n", __FUNCTION__, *pcbRead, rc));
197 return rc;
198}
199
200
201/** @copydoc PDMISTREAM::pfnWrite */
202static DECLCALLBACK(int) drvNamedPipeWrite(PPDMISTREAM pInterface, const void *pvBuf, size_t *pcbWrite)
203{
204 int rc = VINF_SUCCESS;
205 PDRVNAMEDPIPE pThis = PDMISTREAM_2_DRVNAMEDPIPE(pInterface);
206 LogFlow(("%s: pvBuf=%p *pcbWrite=%#x (%s)\n", __FUNCTION__, pvBuf, *pcbWrite, pThis->pszLocation));
207
208 Assert(pvBuf);
209#ifdef RT_OS_WINDOWS
210 if (pThis->NamedPipe != INVALID_HANDLE_VALUE)
211 {
212 DWORD cbWritten = (DWORD)*pcbWrite;
213 pThis->OverlappedWrite.Offset = 0;
214 pThis->OverlappedWrite.OffsetHigh = 0;
215 if (!WriteFile(pThis->NamedPipe, pvBuf, cbWritten, NULL, &pThis->OverlappedWrite))
216 {
217 DWORD uError = GetLastError();
218
219 if ( uError == ERROR_PIPE_LISTENING
220 || uError == ERROR_PIPE_NOT_CONNECTED)
221 {
222 /* No connection yet/anymore; just discard the write (pretening everything was written). */;
223 }
224 else if (uError != ERROR_IO_PENDING)
225 {
226 rc = RTErrConvertFromWin32(uError);
227 Log(("drvNamedPipeWrite: WriteFile returned %d (%Rrc)\n", uError, rc));
228 cbWritten = 0;
229 }
230 else
231 {
232 /* Wait for the write to complete. */
233 if (GetOverlappedResult(pThis->NamedPipe, &pThis->OverlappedWrite, &cbWritten, TRUE /*bWait*/) == FALSE)
234 rc = RTErrConvertFromWin32(uError = GetLastError());
235 }
236 }
237
238 if (RT_FAILURE(rc))
239 {
240 if ( rc == VERR_EOF
241 || rc == VERR_BROKEN_PIPE)
242 {
243 FlushFileBuffers(pThis->NamedPipe);
244 DisconnectNamedPipe(pThis->NamedPipe);
245 if (!pThis->fIsServer)
246 {
247 CloseHandle(pThis->NamedPipe);
248 pThis->NamedPipe = INVALID_HANDLE_VALUE;
249 }
250 /* pretend success */
251 rc = VINF_SUCCESS;
252 }
253 cbWritten = 0;
254 }
255 *pcbWrite = cbWritten;
256 }
257#else /* !RT_OS_WINDOWS */
258 if (pThis->LocalSocket != NIL_RTSOCKET)
259 {
260 ssize_t cbWritten;
261 cbWritten = send(pThis->LocalSocket, pvBuf, *pcbWrite, 0);
262 if (cbWritten == 0)
263 {
264 RTSOCKET tmp = pThis->LocalSocket;
265 pThis->LocalSocket = NIL_RTSOCKET;
266 close(tmp);
267 }
268 else if (cbWritten == -1)
269 {
270 cbWritten = 0;
271 rc = RTErrConvertFromErrno(errno);
272 }
273 *pcbWrite = cbWritten;
274 }
275#endif /* !RT_OS_WINDOWS */
276
277 LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
278 return rc;
279}
280
281
282/**
283 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
284 */
285static DECLCALLBACK(void *) drvNamedPipeQueryInterface(PPDMIBASE pInterface, const char *pszIID)
286{
287 PPDMDRVINS pDrvIns = PDMIBASE_2_DRVINS(pInterface);
288 PDRVNAMEDPIPE pThis = PDMINS_2_DATA(pDrvIns, PDRVNAMEDPIPE);
289 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
290 PDMIBASE_RETURN_INTERFACE(pszIID, PDMISTREAM, &pThis->IStream);
291 return NULL;
292}
293
294
295/* -=-=-=-=- listen thread -=-=-=-=- */
296
297/**
298 * Receive thread loop.
299 *
300 * @returns 0 on success.
301 * @param ThreadSelf Thread handle to this thread.
302 * @param pvUser User argument.
303 */
304static DECLCALLBACK(int) drvNamedPipeListenLoop(RTTHREAD ThreadSelf, void *pvUser)
305{
306 PDRVNAMEDPIPE pThis = (PDRVNAMEDPIPE)pvUser;
307 int rc = VINF_SUCCESS;
308#ifdef RT_OS_WINDOWS
309 HANDLE NamedPipe = pThis->NamedPipe;
310 HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, 0);
311#endif
312
313 while (RT_LIKELY(!pThis->fShutdown))
314 {
315#ifdef RT_OS_WINDOWS
316 OVERLAPPED overlapped;
317
318 memset(&overlapped, 0, sizeof(overlapped));
319 overlapped.hEvent = hEvent;
320
321 BOOL fConnected = ConnectNamedPipe(NamedPipe, &overlapped);
322 if ( !fConnected
323 && !pThis->fShutdown)
324 {
325 DWORD hrc = GetLastError();
326
327 if (hrc == ERROR_IO_PENDING)
328 {
329 DWORD dummy;
330
331 hrc = 0;
332 if (GetOverlappedResult(pThis->NamedPipe, &overlapped, &dummy, TRUE) == FALSE)
333 hrc = GetLastError();
334
335 }
336
337 if (pThis->fShutdown)
338 break;
339
340 if (hrc == ERROR_PIPE_CONNECTED)
341 {
342 RTSemEventWait(pThis->ListenSem, 250);
343 }
344 else if (hrc != ERROR_SUCCESS)
345 {
346 rc = RTErrConvertFromWin32(hrc);
347 LogRel(("NamedPipe%d: ConnectNamedPipe failed, rc=%Rrc\n", pThis->pDrvIns->iInstance, rc));
348 break;
349 }
350 }
351#else /* !RT_OS_WINDOWS */
352 if (listen(pThis->LocalSocketServer, 0) == -1)
353 {
354 rc = RTErrConvertFromErrno(errno);
355 LogRel(("NamedPipe%d: listen failed, rc=%Rrc\n", pThis->pDrvIns->iInstance, rc));
356 break;
357 }
358 int s = accept(pThis->LocalSocketServer, NULL, NULL);
359 if (s == -1)
360 {
361 rc = RTErrConvertFromErrno(errno);
362 LogRel(("NamedPipe%d: accept failed, rc=%Rrc\n", pThis->pDrvIns->iInstance, rc));
363 break;
364 }
365 else
366 {
367 if (pThis->LocalSocket != NIL_RTSOCKET)
368 {
369 LogRel(("NamedPipe%d: only single connection supported\n", pThis->pDrvIns->iInstance));
370 close(s);
371 }
372 else
373 pThis->LocalSocket = s;
374 }
375#endif /* !RT_OS_WINDOWS */
376 }
377
378#ifdef RT_OS_WINDOWS
379 CloseHandle(hEvent);
380#endif
381 pThis->ListenThread = NIL_RTTHREAD;
382 return VINF_SUCCESS;
383}
384
385/* -=-=-=-=- PDMDRVREG -=-=-=-=- */
386
387/**
388 * Power off a named pipe stream driver instance.
389 *
390 * This does most of the destruction work, to avoid ordering dependencies.
391 *
392 * @param pDrvIns The driver instance data.
393 */
394static DECLCALLBACK(void) drvNamedPipePowerOff(PPDMDRVINS pDrvIns)
395{
396 PDRVNAMEDPIPE pThis = PDMINS_2_DATA(pDrvIns, PDRVNAMEDPIPE);
397 LogFlow(("%s: %s\n", __FUNCTION__, pThis->pszLocation));
398
399 pThis->fShutdown = true;
400
401#ifdef RT_OS_WINDOWS
402 if (pThis->NamedPipe != INVALID_HANDLE_VALUE)
403 {
404 if (pThis->fIsServer)
405 {
406 FlushFileBuffers(pThis->NamedPipe);
407 DisconnectNamedPipe(pThis->NamedPipe);
408 }
409
410 CloseHandle(pThis->NamedPipe);
411 pThis->NamedPipe = INVALID_HANDLE_VALUE;
412 CloseHandle(pThis->OverlappedRead.hEvent);
413 CloseHandle(pThis->OverlappedWrite.hEvent);
414 }
415 if (pThis->fIsServer)
416 {
417 /* Wake up listen thread */
418 RTSemEventSignal(pThis->ListenSem);
419 RTSemEventDestroy(pThis->ListenSem);
420 }
421#else /* !RT_OS_WINDOWS */
422 if (pThis->fIsServer)
423 {
424 if (pThis->LocalSocketServer != NIL_RTSOCKET)
425 close(pThis->LocalSocketServer);
426 if (pThis->pszLocation)
427 RTFileDelete(pThis->pszLocation);
428 }
429 else
430 {
431 if (pThis->LocalSocket != NIL_RTSOCKET)
432 close(pThis->LocalSocket);
433 }
434#endif /* !RT_OS_WINDOWS */
435}
436
437
438/**
439 * Destruct a named pipe stream driver instance.
440 *
441 * Most VM resources are freed by the VM. This callback is provided so that
442 * any non-VM resources can be freed correctly.
443 *
444 * @param pDrvIns The driver instance data.
445 */
446static DECLCALLBACK(void) drvNamedPipeDestruct(PPDMDRVINS pDrvIns)
447{
448 PDRVNAMEDPIPE pThis = PDMINS_2_DATA(pDrvIns, PDRVNAMEDPIPE);
449 LogFlow(("%s: %s\n", __FUNCTION__, pThis->pszLocation));
450 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
451
452 if (pThis->ListenThread)
453 { RTThreadWait(pThis->ListenThread, 250, NULL);
454 if (pThis->ListenThread != NIL_RTTHREAD)
455 LogRel(("NamedPipe%d: listen thread did not terminate\n", pDrvIns->iInstance));
456 }
457
458 if (pThis->pszLocation)
459 MMR3HeapFree(pThis->pszLocation);
460}
461
462
463/**
464 * Construct a named pipe stream driver instance.
465 *
466 * @copydoc FNPDMDRVCONSTRUCT
467 */
468static DECLCALLBACK(int) drvNamedPipeConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
469{
470 int rc;
471 char *pszLocation = NULL;
472 PDRVNAMEDPIPE pThis = PDMINS_2_DATA(pDrvIns, PDRVNAMEDPIPE);
473 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
474
475 /*
476 * Init the static parts.
477 */
478 pThis->pDrvIns = pDrvIns;
479 pThis->pszLocation = NULL;
480 pThis->fIsServer = false;
481#ifdef RT_OS_WINDOWS
482 pThis->NamedPipe = INVALID_HANDLE_VALUE;
483#else /* !RT_OS_WINDOWS */
484 pThis->LocalSocketServer = NIL_RTSOCKET;
485 pThis->LocalSocket = NIL_RTSOCKET;
486#endif /* !RT_OS_WINDOWS */
487 pThis->ListenThread = NIL_RTTHREAD;
488 pThis->fShutdown = false;
489 /* IBase */
490 pDrvIns->IBase.pfnQueryInterface = drvNamedPipeQueryInterface;
491 /* IStream */
492 pThis->IStream.pfnRead = drvNamedPipeRead;
493 pThis->IStream.pfnWrite = drvNamedPipeWrite;
494
495 /*
496 * Read the configuration.
497 */
498 if (!CFGMR3AreValuesValid(pCfg, "Location\0IsServer\0"))
499 {
500 rc = VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
501 goto l_out;
502 }
503
504 rc = CFGMR3QueryStringAlloc(pCfg, "Location", &pszLocation);
505 if (RT_FAILURE(rc))
506 {
507 AssertMsgFailed(("Configuration error: query \"Location\" resulted in %Rrc.\n", rc));
508 goto l_out;
509 }
510 pThis->pszLocation = pszLocation;
511
512 bool fIsServer;
513 rc = CFGMR3QueryBool(pCfg, "IsServer", &fIsServer);
514 if (RT_FAILURE(rc))
515 {
516 AssertMsgFailed(("Configuration error: query \"IsServer\" resulted in %Rrc.\n", rc));
517 goto l_out;
518 }
519 pThis->fIsServer = fIsServer;
520
521#ifdef RT_OS_WINDOWS
522 if (fIsServer)
523 {
524 HANDLE hPipe = CreateNamedPipe(pThis->pszLocation, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 32, 32, 10000, NULL);
525 if (hPipe == INVALID_HANDLE_VALUE)
526 {
527 rc = RTErrConvertFromWin32(GetLastError());
528 LogRel(("NamedPipe%d: CreateNamedPipe failed rc=%Rrc\n", pThis->pDrvIns->iInstance));
529 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to create named pipe %s"), pDrvIns->iInstance, pszLocation);
530 }
531 pThis->NamedPipe = hPipe;
532
533 rc = RTSemEventCreate(&pThis->ListenSem);
534 AssertRC(rc);
535
536 rc = RTThreadCreate(&pThis->ListenThread, drvNamedPipeListenLoop, (void *)pThis, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SerPipe");
537 if RT_FAILURE(rc)
538 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to create listening thread"), pDrvIns->iInstance);
539
540 }
541 else
542 {
543 /* Connect to the named pipe. */
544 HANDLE hPipe = CreateFile(pThis->pszLocation, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
545 if (hPipe == INVALID_HANDLE_VALUE)
546 {
547 rc = RTErrConvertFromWin32(GetLastError());
548 LogRel(("NamedPipe%d: CreateFile failed rc=%Rrc\n", pThis->pDrvIns->iInstance));
549 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to connect to named pipe %s"), pDrvIns->iInstance, pszLocation);
550 }
551 pThis->NamedPipe = hPipe;
552 }
553
554 memset(&pThis->OverlappedWrite, 0, sizeof(pThis->OverlappedWrite));
555 memset(&pThis->OverlappedRead, 0, sizeof(pThis->OverlappedRead));
556 pThis->OverlappedWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
557 pThis->OverlappedRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
558#else /* !RT_OS_WINDOWS */
559 int s;
560 struct sockaddr_un addr;
561
562 if ((s = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
563 return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS, N_("NamedPipe#%d failed to create local socket"), pDrvIns->iInstance);
564
565 memset(&addr, 0, sizeof(addr));
566 addr.sun_family = AF_UNIX;
567 strncpy(addr.sun_path, pszLocation, sizeof(addr.sun_path)-1);
568
569 if (fIsServer)
570 {
571 /* Bind address to the local socket. */
572 RTFileDelete(pszLocation);
573 if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1)
574 return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS, N_("NamedPipe#%d failed to bind to local socket %s"), pDrvIns->iInstance, pszLocation);
575 pThis->LocalSocketServer = s;
576 rc = RTThreadCreate(&pThis->ListenThread, drvNamedPipeListenLoop, (void *)pThis, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SerPipe");
577 if RT_FAILURE(rc)
578 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to create listening thread"), pDrvIns->iInstance);
579 }
580 else
581 {
582 /* Connect to the local socket. */
583 if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) == -1)
584 return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS, N_("NamedPipe#%d failed to connect to local socket %s"), pDrvIns->iInstance, pszLocation);
585 pThis->LocalSocket = s;
586 }
587#endif /* !RT_OS_WINDOWS */
588
589l_out:
590 if (RT_FAILURE(rc))
591 {
592 if (pszLocation)
593 MMR3HeapFree(pszLocation);
594 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to initialize"), pDrvIns->iInstance);
595 }
596
597 LogFlow(("drvNamedPipeConstruct: location %s isServer %d\n", pszLocation, fIsServer));
598 LogRel(("NamedPipe: location %s, %s\n", pszLocation, fIsServer ? "server" : "client"));
599 return VINF_SUCCESS;
600}
601
602
603/**
604 * Named pipe driver registration record.
605 */
606const PDMDRVREG g_DrvNamedPipe =
607{
608 /* u32Version */
609 PDM_DRVREG_VERSION,
610 /* szName */
611 "NamedPipe",
612 /* szRCMod */
613 "",
614 /* szR0Mod */
615 "",
616 /* pszDescription */
617 "Named Pipe stream driver.",
618 /* fFlags */
619 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
620 /* fClass. */
621 PDM_DRVREG_CLASS_STREAM,
622 /* cMaxInstances */
623 ~0,
624 /* cbInstance */
625 sizeof(DRVNAMEDPIPE),
626 /* pfnConstruct */
627 drvNamedPipeConstruct,
628 /* pfnDestruct */
629 drvNamedPipeDestruct,
630 /* pfnRelocate */
631 NULL,
632 /* pfnIOCtl */
633 NULL,
634 /* pfnPowerOn */
635 NULL,
636 /* pfnReset */
637 NULL,
638 /* pfnSuspend */
639 NULL,
640 /* pfnResume */
641 NULL,
642 /* pfnAttach */
643 NULL,
644 /* pfnDetach */
645 NULL,
646 /* pfnPowerOff */
647 drvNamedPipePowerOff,
648 /* pfnSoftReset */
649 NULL,
650 /* u32EndVersion */
651 PDM_DRVREG_VERSION
652};
653
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