c58f1213e628a545081c70e26c6b67a841cff880vboxsync * Copyright (C) 2006-2012 Oracle Corporation
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * available from http://www.virtualbox.org. This file is free software;
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * you can redistribute it and/or modify it under the terms of the GNU
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * General Public License (GPL) as published by the Free Software
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * The contents of this file may alternatively be used under the terms
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * of the Common Development and Distribution License Version 1.0
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * VirtualBox OSE distribution, in which case the provisions of the
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * CDDL are applicable instead of those of the GPL.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * You may elect to license modified versions of this file under the
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * terms and conditions of either the GPL or the CDDL or both.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync/*******************************************************************************
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync* Header Files *
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync*******************************************************************************/
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync/*******************************************************************************
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync* Defined Constants And Macros *
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync*******************************************************************************/
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync/* fixup backlevel OSes. */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync/*******************************************************************************
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync* Structures and Typedefs *
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync*******************************************************************************/
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * UDP Server state.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /** Invalid. */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /** Created. */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /** Thread for incoming datagrams is starting up. */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /** Waiting for incoming datagrams. */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /** Handling an incoming datagram. */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /** Thread terminating. */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /** Thread terminated. */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /** Final cleanup before being unusable. */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Internal representation of the UDP Server handle.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /** The magic value (RTUDPSERVER_MAGIC). */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /** The server state. */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /** The server thread. */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /** The server socket. */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /** The datagram receiver function. */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /** Argument to pfnServer. */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync/*******************************************************************************
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync* Internal Functions *
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync*******************************************************************************/
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsyncstatic DECLCALLBACK(int) rtUdpServerThread(RTTHREAD ThreadSelf, void *pvServer);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsyncstatic int rtUdpServerListenCleanup(PRTUDPSERVER pServer);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsyncstatic int rtUdpServerDestroySocket(RTSOCKET volatile *pSock, const char *pszMsg);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsyncstatic int rtUdpClose(RTSOCKET Sock, const char *pszMsg);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Atomicly updates a socket variable.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @returns The old handle value.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @param phSock The socket handle variable to update.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @param hSock The new socket handle value.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsyncDECLINLINE(RTSOCKET) rtUdpAtomicXchgSock(RTSOCKET volatile *phSock, const RTSOCKET hNew)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Tries to change the UDP server state.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsyncDECLINLINE(bool) rtUdpServerTrySetState(PRTUDPSERVER pServer, RTUDPSERVERSTATE enmStateNew, RTUDPSERVERSTATE enmStateOld)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync ASMAtomicCmpXchgSize(&pServer->enmState, enmStateNew, enmStateOld, fRc);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Changes the UDP server state.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsyncDECLINLINE(void) rtUdpServerSetState(PRTUDPSERVER pServer, RTUDPSERVERSTATE enmStateNew, RTUDPSERVERSTATE enmStateOld)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync ASMAtomicCmpXchgSize(&pServer->enmState, enmStateNew, enmStateOld, fRc);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Closes a socket.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @returns IPRT status code.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsyncstatic int rtUdpServerDestroySocket(RTSOCKET volatile *pSock, const char *pszMsg)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync RTSOCKET hSocket = rtUdpAtomicXchgSock(pSock, NIL_RTSOCKET);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Create single datagram at a time UDP Server in a separate thread.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * The thread will loop waiting for datagrams and call pfnServe for
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * each of the incoming datagrams in turn. The pfnServe function can
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * return VERR_UDP_SERVER_STOP too terminate this loop. RTUdpServerDestroy()
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * should be used to terminate the server.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @returns iprt status code.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @param pszAddress The address for creating a datagram socket.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * If NULL or empty string the server is bound to all interfaces.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @param uPort The port for creating a datagram socket.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @param enmType The thread type.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @param pszThrdName The name of the worker thread.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @param pfnServe The function which will handle incoming datagrams.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @param pvUser User argument passed to pfnServe.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @param ppServer Where to store the serverhandle.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsyncRTR3DECL(int) RTUdpServerCreate(const char *pszAddress, unsigned uPort, RTTHREADTYPE enmType, const char *pszThrdName,
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync PFNRTUDPSERVE pfnServe, void *pvUser, PPRTUDPSERVER ppServer)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Validate input.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync AssertPtrReturn(pszThrdName, VERR_INVALID_POINTER);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Create the server.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync int rc = RTUdpServerCreateEx(pszAddress, uPort, &pServer);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Create the listener thread.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync rc = RTThreadCreate(&pServer->Thread, rtUdpServerThread, pServer, 0, enmType, /*RTTHREADFLAGS_WAITABLE*/0, pszThrdName);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Destroy the server.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync rtUdpServerSetState(pServer, RTUDPSERVERSTATE_CREATED, RTUDPSERVERSTATE_STARTING);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Server thread, loops waiting for datagrams until it's terminated.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @returns iprt status code. (ignored).
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @param ThreadSelf Thread handle.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @param pvServer Server handle.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsyncstatic DECLCALLBACK(int) rtUdpServerThread(RTTHREAD ThreadSelf, void *pvServer)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync if (rtUdpServerTrySetState(pServer, RTUDPSERVERSTATE_WAITING, RTUDPSERVERSTATE_STARTING))
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Create single datagram at a time UDP Server.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * The caller must call RTUdpServerReceive() to actually start the server.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @returns iprt status code.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @param pszAddress The address for creating a datagram socket.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * If NULL the server is bound to all interfaces.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @param uPort The port for creating a datagram socket.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @param ppServer Where to store the serverhandle.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsyncRTR3DECL(int) RTUdpServerCreateEx(const char *pszAddress, uint32_t uPort, PPRTUDPSERVER ppServer)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Validate input.
280173a9a1d01b33c087a762ffb9e522efe5c0d5vboxsync * Resolve the address.
280173a9a1d01b33c087a762ffb9e522efe5c0d5vboxsync int rc = RTSocketParseInetAddress(pszAddress, uPort, &LocalAddr);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Setting up socket.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync rc = rtSocketCreate(&Sock, AF_INET, SOCK_DGRAM, IPPROTO_UDP);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync RTSocketSetInheritance(Sock, false /*fInheritable*/);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Set socket options.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync if (!rtSocketSetOpt(Sock, SOL_SOCKET, SO_REUSEADDR, &fFlag, sizeof(fFlag)))
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Bind a name to the socket.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Create the server handle.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync PRTUDPSERVER pServer = (PRTUDPSERVER)RTMemPoolAlloc(RTMEMPOOL_DEFAULT, sizeof(*pServer));
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /* bail out */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Listen for incoming datagrams.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * The function will loop waiting for datagrams and call pfnServe for
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * each of the incoming datagrams in turn. The pfnServe function can
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * return VERR_UDP_SERVER_STOP too terminate this loop. A stopped server
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * can only be destroyed.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @returns IPRT status code.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @retval VERR_UDP_SERVER_STOP if stopped by pfnServe.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @retval VERR_UDP_SERVER_SHUTDOWN if shut down by RTUdpServerShutdown.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @param pServer The server handle as returned from RTUdpServerCreateEx().
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @param pfnServe The function which will handle incoming datagrams.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @param pvUser User argument passed to pfnServe.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsyncRTR3DECL(int) RTUdpServerListen(PRTUDPSERVER pServer, PFNRTUDPSERVE pfnServe, void *pvUser)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Validate input and retain the instance.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync AssertReturn(pServer->u32Magic == RTUDPSERVER_MAGIC, VERR_INVALID_HANDLE);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync AssertReturn(RTMemPoolRetain(pServer) != UINT32_MAX, VERR_INVALID_HANDLE);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync if (rtUdpServerTrySetState(pServer, RTUDPSERVERSTATE_WAITING, RTUDPSERVERSTATE_CREATED))
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync AssertMsgFailed(("enmState=%d\n", pServer->enmState));
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Internal worker common for RTUdpServerListen and the thread created by
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * RTUdpServerCreate().
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * The caller makes sure it has its own memory reference and releases it upon
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Wait for incoming datagrams loop.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Change state, getting an extra reference to the socket so we can
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * allow others to close it while we're stuck in rtSocketAccept.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync if (!rtUdpServerTrySetState(pServer, RTUDPSERVERSTATE_WAITING, enmState))
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Wait for incoming datagrams or errors.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync int rc = RTSocketSelectOneEx(hSocket, RTSOCKET_EVT_READ | RTSOCKET_EVT_ERROR, &fEvents, 1000);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /* These are typical for what can happen during destruction. */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Run a pfnServe callback.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync if (!rtUdpServerTrySetState(pServer, RTUDPSERVERSTATE_RECEIVING, RTUDPSERVERSTATE_WAITING))
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Stop the server?
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync if (rtUdpServerTrySetState(pServer, RTUDPSERVERSTATE_STOPPING, RTUDPSERVERSTATE_RECEIVING))
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Reset the server socket and change the state to stopped. After that state change
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * we cannot safely access the handle so we'll have to return here.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync hSocket = rtUdpAtomicXchgSock(&pServer->hSocket, NIL_RTSOCKET);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync rtUdpServerSetState(pServer, RTUDPSERVERSTATE_STOPPED, RTUDPSERVERSTATE_STOPPING);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Clean up after listener.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsyncstatic int rtUdpServerListenCleanup(PRTUDPSERVER pServer)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Close the server socket.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync rtUdpServerDestroySocket(&pServer->hSocket, "ListenCleanup");
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Figure the return code and make sure the state is OK.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync rtUdpServerTrySetState(pServer, RTUDPSERVERSTATE_STOPPED, enmState);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync AssertMsgFailedReturn(("pServer=%p enmState=%d\n", pServer, enmState), VERR_INTERNAL_ERROR_4);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Shuts down the server.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @returns IPRT status code.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @param pServer Handle to the server.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsyncRTR3DECL(int) RTUdpServerShutdown(PRTUDPSERVER pServer)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Validate input and retain the instance.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync AssertReturn(pServer->u32Magic == RTUDPSERVER_MAGIC, VERR_INVALID_HANDLE);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync AssertReturn(RTMemPoolRetain(pServer) != UINT32_MAX, VERR_INVALID_HANDLE);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Try change the state to stopping, then replace and destroy the server socket.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync if (rtUdpServerTrySetState(pServer, RTUDPSERVERSTATE_STOPPING, enmState))
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync rtUdpServerDestroySocket(&pServer->hSocket, "RTUdpServerShutdown");
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync rtUdpServerSetState(pServer, RTUDPSERVERSTATE_STOPPED, RTUDPSERVERSTATE_STOPPING);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Closes down and frees a UDP Server.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @returns iprt status code.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @param pServer Handle to the server.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsyncRTR3DECL(int) RTUdpServerDestroy(PRTUDPSERVER pServer)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Validate input and retain the instance.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync AssertReturn(pServer->u32Magic == RTUDPSERVER_MAGIC, VERR_INVALID_HANDLE);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync AssertReturn(RTMemPoolRetain(pServer) != UINT32_MAX, VERR_INVALID_HANDLE); /* paranoia */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Move the state along so the listener can figure out what's going on.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync fDestroyable = rtUdpServerTrySetState(pServer, RTUDPSERVERSTATE_DESTROYING, enmState);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /* destroyable states */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Everything else means user or internal misbehavior.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync AssertMsgFailed(("pServer=%p enmState=%d\n", pServer, enmState));
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Destroy it.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync ASMAtomicWriteU32(&pServer->u32Magic, ~RTUDPSERVER_MAGIC);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync rtUdpServerDestroySocket(&pServer->hSocket, "Destroyer: server");
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Release it.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Internal close function which does all the proper bitching.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsyncstatic int rtUdpClose(RTSOCKET Sock, const char *pszMsg)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /* ignore nil handles. */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Close the socket handle (drops our reference to it).
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsyncRTR3DECL(int) RTUdpRead(RTSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead, PRTNETADDR pSrcAddr)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync return RTSocketReadFrom(Sock, pvBuffer, cbBuffer, pcbRead, pSrcAddr);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsyncRTR3DECL(int) RTUdpWrite(PRTUDPSERVER pServer, const void *pvBuffer, size_t cbBuffer, PCRTNETADDR pDstAddr)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Validate input and retain the instance.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync AssertReturn(pServer->u32Magic == RTUDPSERVER_MAGIC, VERR_INVALID_HANDLE);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync AssertReturn(RTMemPoolRetain(pServer) != UINT32_MAX, VERR_INVALID_HANDLE);