InetAddr UDPRawDatagramSocket::getLocalAddr (void)
{
    InetAddr localAddr;
    struct sockaddr_in saLocal;
    socklen_t saLen = sizeof (saLocal);
    if (getsockname (sockfd, (struct sockaddr *) &saLocal, &saLen)) {
        return localAddr;
    }
    localAddr.setIPAddress (saLocal.sin_addr.s_addr);
    localAddr.setPort (saLocal.sin_port);
    return localAddr;
}
int ProxyDatagramSocket::sendTo (uint32 ui32IPAddr, uint16 ui16Port, const void *pBuf, int iBufSize, const char *pszHints)
{
    int rc;
    if (_bConnectedToServer) {
        if (iBufSize < 0) {
            checkAndLogMsg ("ProxyDatagramSocket::sendTo", Logger::L_MildError,
                            "packet size cannot be negative\n");
            return -1;
        }
        if (iBufSize > (MAXIMUM_PROXY_PACKET_SIZE - 17)) {
            checkAndLogMsg ("ProxyDatagramSocket::sendTo", Logger::L_MildError,
                            "packet too large to be sent - maximum size is <%d>\n",
                            (int) (MAXIMUM_PROXY_PACKET_SIZE - 17));
            return -2;
        }
        try {
            bool bExcludeAddr = false;
            bool bIncludeAddr = false;
            InetAddr excludeAddr;
            InetAddr includeAddr;
            if (pszHints != NULL) {
                // Check to see if we can handle the hints
                StringTokenizer st (pszHints, ';');
                const char *pszHint = NULL;
                while ((pszHint = st.getNextToken()) != NULL) {
                    StringTokenizer st2 (pszHint, '=');
                    const char *pszAttr = st2.getNextToken();
                    const char *pszValue = st2.getNextToken();
                    if ((pszAttr == NULL) || (pszValue == NULL)) {
                        checkAndLogMsg ("ProxyDatagramSocket::sendTo", Logger::L_Warning,
                                        "could not parse hint <%s> - ignoring\n", pszHint);
                    }
                    // Check to see if an exclude address has been specified in the hints
                    else if (0 == stricmp (pszAttr, "exclude")) {
                        if (InetAddr::isIPv4Addr (pszValue)) {
                            excludeAddr.setIPAddress (pszValue);
                            bExcludeAddr = true;
                        }
                        else {
                            checkAndLogMsg ("ProxyDatagramSocket::sendTo", Logger::L_Warning,
                                            "could not parse exclude address <%s> - ignoring\n", pszValue);
                        }
                    }
                    // Check to see if an include address has been specified in the hints
                    else if (0 == stricmp (pszAttr, "include")) {
                        if (InetAddr::isIPv4Addr (pszValue)) {
                            includeAddr.setIPAddress (pszValue);
                            bIncludeAddr = true;
                        }
                        else {
                            checkAndLogMsg ("ProxyDatagramSocket::sendTo", Logger::L_Warning,
                                            "could not parse include address <%s> - ignoring\n", pszValue);
                        }
                    }
                    // Check to see if we are doing a forced unicast
                    else if (0 == stricmp (pszAttr, "unicast")) {
                        if (InetAddr::isIPv4Addr (pszValue)) {
                            InetAddr unicastAddr (pszValue);
                            ui32IPAddr = unicastAddr.getIPAddress();
                            checkAndLogMsg ("ProxyDatagramSocket::sendTo", Logger::L_Info,
                                            "overwrote destination address with unicast address %s\n", unicastAddr.getIPAsString());
                        }
                    }
                    else {
                        checkAndLogMsg ("ProxyDatagramSocket::sendTo", Logger::L_Warning,
                                        "unknown hint attribute <%s> - ignoring\n", pszAttr);
                    }
                }
            }
            /*!!*/ // Improve the efficiency of this by implementing a two-argument sendBlock() method
                   // so that a memcpy is not needed
            uint8 aui8Buf [MAXIMUM_PROXY_PACKET_SIZE];
            uint8 ui8Offset = 0;
            if (bIncludeAddr) {
                aui8Buf[ui8Offset] = 'I';
            }
            else if (bExcludeAddr) {
                aui8Buf[ui8Offset] = 'X';
            }
            else {
                aui8Buf[ui8Offset] = 'D';
            }
            ui8Offset += 1;
            (*((uint32*)(aui8Buf+ui8Offset))) = _ui32LocalAddr;
            ui8Offset += 4;
            (*((uint16*)(aui8Buf+ui8Offset))) = EndianHelper::htons (_ui16LocalPort);
            ui8Offset += 2;
            (*((uint32*)(aui8Buf+ui8Offset))) = ui32IPAddr;
            ui8Offset += 4;
            if (bIncludeAddr) {
                (*((uint32*)(aui8Buf+ui8Offset))) = includeAddr.getIPAddress();
                ui8Offset += 4;
            }
            else if (bExcludeAddr) {
                (*((uint32*)(aui8Buf+ui8Offset))) = excludeAddr.getIPAddress();
                ui8Offset += 4;
            }
            (*((uint16*)(aui8Buf+ui8Offset))) = EndianHelper::htons (ui16Port);
            ui8Offset += 2;
            memcpy (aui8Buf+ui8Offset, pBuf, iBufSize);
            _pchToServer->sendBlock (aui8Buf, iBufSize + ui8Offset);
            _ui32SentPacketCount++;
            return iBufSize;
        }
        catch (Exception e) {
            checkAndLogMsg ("ProxyDatagramSocket::sendTo", Logger::L_MildError,
                            "exception occurred when sending data to proxy server; message = <%s>\n",
                            e.getMsg());
            close();
            rc = -3;
        }
    }
    else {
        checkAndLogMsg ("ProxyDatagramSocket::sendTo", Logger::L_MildError,
                        "cannot send - not connected to the proxy server\n");
        rc = -4;
    }
    connectToProxyServer();
    return rc;
}