text:
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "db.h"
#include "net.h"
#include "init.h"
#include "addrman.h"
#include "ui_interface.h"
#include "script.h"

#ifdef WIN32
#include <string.h>
#endif

#ifdef USE_UPNP
#include <miniupnpc/miniwget.h>
#include <miniupnpc/miniupnpc.h>
#include <miniupnpc/upnpcommands.h>
#include <miniupnpc/upnperrors.h>
#endif

// Dump addresses to peers.dat every 15 minutes (900s)
#define DUMP_ADDRESSES_INTERVAL 900

using namespace std;
using namespace boost;

static const int MAX_OUTBOUND_CONNECTIONS = 8;

bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false);

struct LocalServiceInfo {
    int nScore;
    int nPort;
};

//
// Global state variables
//
bool fDiscover = true;
uint64 nLocalServices = NODE_NETWORK;
static CCriticalSection cs_mapLocalHost;
static map<CNetAddr, LocalServiceInfo> mapLocalHost;
static bool vfReachable[NET_MAX] = {};
static bool vfLimited[NET_MAX] = {};
static CNode* pnodeLocalHost = NULL;
static CNode* pnodeSync = NULL;
uint64 nLocalHostNonce = 0;
static std::vector<SOCKET> vhListenSocket;
CAddrMan addrman;
int nMaxConnections = 125;

vector<CNode*> vNodes;
CCriticalSection cs_vNodes;
map<CInv, CDataStream> mapRelay;
deque<pair<int64, CInv> > vRelayExpiration;
CCriticalSection cs_mapRelay;
limitedmap<CInv, int64> mapAlreadyAskedFor(MAX_INV_SZ);

static deque<string> vOneShots;
CCriticalSection cs_vOneShots;

set<CNetAddr> setservAddNodeAddresses;
CCriticalSection cs_setservAddNodeAddresses;

vector<std::string> vAddedNodes;
CCriticalSection cs_vAddedNodes;

static CSemaphore *semOutbound = NULL;

void AddOneShot(string strDest)
{
    LOCK(cs_vOneShots);
    vOneShots.push_back(strDest);
}

unsigned short GetListenPort()
{
    return (unsigned short)(GetArg("-port", GetDefaultPort()));
}

void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
{
    // Filter out duplicate requests
    if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
        return;
    pindexLastGetBlocksBegin = pindexBegin;
    hashLastGetBlocksEnd = hashEnd;

    PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
}

// find 'best' local address for a particular peer
bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
{
    if (fNoListen)
        return false;

    int nBestScore = -1;
    int nBestReachability = -1;
    {
        LOCK(cs_mapLocalHost);
        for (map<CNetAddr, LocalServiceInfo>::iterator it = mapLocalHost.begin(); it != mapLocalHost.end(); it++)
        {
            int nScore = (*it).second.nScore;
            int nReachability = (*it).first.GetReachabilityFrom(paddrPeer);
            if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore))
            {
                addr = CService((*it).first, (*it).second.nPort);
                nBestReachability = nReachability;
                nBestScore = nScore;
            }
        }
    }
    return nBestScore >= 0;
}

// get best local address for a particular peer as a CAddress
CAddress GetLocalAddress(const CNetAddr *paddrPeer)
{
    CAddress ret(CService("0.0.0.0",0),0);
    CService addr;
    if (GetLocal(addr, paddrPeer))
    {
        ret = CAddress(addr);
        ret.nServices = nLocalServices;
        ret.nTime = GetAdjustedTime();
    }
    return ret;
}

bool RecvLine(SOCKET hSocket, string& strLine)
{
    strLine = "";
    loop
    {
        char c;
        int nBytes = recv(hSocket, &c, 1, 0);
        if (nBytes > 0)
        {
            if (c == '\n')
                continue;
            if (c == '\r')
                return true;
            strLine += c;
            if (strLine.size() >= 9000)
                return true;
        }
        else if (nBytes <= 0)
        {
            boost::this_thread::interruption_point();
            if (nBytes < 0)
            {
                int nErr = WSAGetLastError();
                if (nErr == WSAEMSGSIZE)
                    continue;
                if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS)
                {
                    MilliSleep(10);
                    continue;
                }
            }
            if (!strLine.empty())
                return true;
            if (nBytes == 0)
            {
                // socket closed
                printf("socket closed\n");
                return false;
            }
            else
            {
                // socket error
                int nErr = WSAGetLastError();
                printf("recv failed: %d\n", nErr);
                return false;
            }
        }
    }
}

// used when scores of local addresses may have changed
// pushes better local address to peers
void static AdvertizeLocal()
{
    LOCK(cs_vNodes);
    BOOST_FOREACH(CNode* pnode, vNodes)
    {
        if (pnode->fSuccessfullyConnected)
        {
            CAddress addrLocal = GetLocalAddress(&pnode->addr);
            if (addrLocal.IsRoutable() && (CService)addrLocal != (CService)pnode->addrLocal)
            {
                pnode->PushAddress(addrLocal);
                pnode->addrLocal = addrLocal;
            }
        }
    }
}

void SetReachable(enum Network net, bool fFlag)
{
    LOCK(cs_mapLocalHost);
    vfReachable[net] = fFlag;
    if (net == NET_IPV6 && fFlag)
        vfReachable[NET_IPV4] = true;
}

// learn a new local address
bool AddLocal(const CService& addr, int nScore)
{
    if (!addr.IsRoutable())
        return false;

    if (!fDiscover && nScore < LOCAL_MANUAL)
        return false;

    if (IsLimited(addr))
        return false;

    printf("AddLocal(%s,%i)\n", addr.ToString().c_str(), nScore);

    {
        LOCK(cs_mapLocalHost);
        bool fAlready = mapLocalHost.count(addr) > 0;
        LocalServiceInfo &info = mapLocalHost[addr];
        if (!fAlready || nScore >= info.nScore) {
            info.nScore = nScore + (fAlready ? 1 : 0);
            info.nPort = addr.GetPort();
        }
        SetReachable(addr.GetNetwork());
    }

    AdvertizeLocal();

    return true;
}

bool AddLocal(const CNetAddr &addr, int nScore)
{
    return AddLocal(CService(addr, GetListenPort()), nScore);
}

/** Make a particular network entirely off-limits (no automatic connects to it) */
void SetLimited(enum Network net, bool fLimited)
{
    if (net == NET_UNROUTABLE)
        return;
    LOCK(cs_mapLocalHost);
    vfLimited[net] = fLimited;
}

bool IsLimited(enum Network net)
{
    LOCK(cs_mapLocalHost);
    return vfLimited[net];
}

bool IsLimited(const CNetAddr &addr)
{
    return IsLimited(addr.GetNetwork());
}

/** vote for a local address */
bool SeenLocal(const CService& addr)
{
    {
        LOCK(cs_mapLocalHost);
        if (mapLocalHost.count(addr) == 0)
            return false;
        mapLocalHost[addr].nScore++;
    }

    AdvertizeLocal();

    return true;
}

/** check whether a given address is potentially local */
bool IsLocal(const CService& addr)
{
    LOCK(cs_mapLocalHost);
    return mapLocalHost.count(addr) > 0;
}

/** check whether a given address is in a network we can probably connect to */
bool IsReachable(const CNetAddr& addr)
{
    LOCK(cs_mapLocalHost);
    enum Network net = addr.GetNetwork();
    return vfReachable[net] && !vfLimited[net];
}

bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const char* pszKeyword, CNetAddr& ipRet)
{
    SOCKET hSocket;
    if (!ConnectSocket(addrConnect, hSocket))
        return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString().c_str());

    send(hSocket, pszGet, strlen(pszGet), MSG_NOSIGNAL);

    string strLine;
    while (RecvLine(hSocket, strLine))
    {
        if (strLine.empty()) // HTTP response is separated from headers by blank line
        {
            loop
            {
                if (!RecvLine(hSocket, strLine))
                {
                    closesocket(hSocket);
                    return false;
                }
                if (pszKeyword == NULL)
                    break;
                if (strLine.find(pszKeyword) != string::npos)
                {
                    strLine = strLine.substr(strLine.find(pszKeyword) + strlen(pszKeyword));
                    break;
                }
            }
            closesocket(hSocket);
            if (strLine.find("<") != string::npos)
                strLine = strLine.substr(0, strLine.find("<"));
            strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r"));
            while (strLine.size() > 0 && isspace(strLine[strLine.size()-1]))
                strLine.resize(strLine.size()-1);
            CService addr(strLine,0,true);
            printf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str());
            if (!addr.IsValid() || !addr.IsRoutable())
                return false;
            ipRet.SetIP(addr);
            return true;
        }
    }
    closesocket(hSocket);
    return error("GetMyExternalIP() : connection closed");
}

bool GetMyExternalIP(CNetAddr& ipRet)
{
    CService addrConnect;
    const char* pszGet;
    const char* pszKeyword;

    for (int nLookup = 0; nLookup <= 1; nLookup++)
    for (int nHost = 1; nHost <= 2; nHost++)
    {
        // We should be phasing out our use of sites like these. If we need
        // replacements, we should ask for volunteers to put this simple
        // php file on their web server that prints the client IP:
        //  <?php echo $_SERVER["REMOTE_ADDR"]; ?>
        if (nHost == 1)
        {
            addrConnect = CService("91.198.22.70", 80); // checkip.dyndns.org

            if (nLookup == 1)
            {
                CService addrIP("checkip.dyndns.org", 80, true);
                if (addrIP.IsValid())
                    addrConnect = addrIP;
            }

            pszGet = "GET / HTTP/1.1\r\n"
                     "Host: checkip.dyndns.org\r\n"
                     "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
                     "Connection: close\r\n"
                     "\r\n";

            pszKeyword = "Address:";
        }
        else if (nHost == 2)
        {
            addrConnect = CService("74.208.43.192", 80); // www.showmyip.com

            if (nLookup == 1)
            {
                CService addrIP("www.showmyip.com", 80, true);
                if (addrIP.IsValid())
                    addrConnect = addrIP;
            }

            pszGet = "GET /simple/ HTTP/1.1\r\n"
                     "Host: www.showmyip.com\r\n"
                     "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
                     "Connection: close\r\n"
                     "\r\n";

            pszKeyword = NULL; // Returns just IP address
        }

        if (GetMyExternalIP2(addrConnect, pszGet, pszKeyword, ipRet))
            return true;
    }

    return false;
}

void ThreadGetMyExternalIP(void* parg)
{
    // Make this thread recognisable as the external IP detection thread
    RenameThread("bitcoin-ext-ip");

    CNetAddr addrLocalHost;
    if (GetMyExternalIP(addrLocalHost))
    {
        printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
        AddLocal(addrLocalHost, LOCAL_HTTP);
    }
}

void AddressCurrentlyConnected(const CService& addr)
{
    addrman.Connected(addr);
}

CNode* FindNode(const CNetAddr& ip)
{
    LOCK(cs_vNodes);
    BOOST_FOREACH(CNode* pnode, vNodes)
        if ((CNetAddr)pnode->addr == ip)
            return (pnode);
    return NULL;
}

CNode* FindNode(std::string addrName)
{
    LOCK(cs_vNodes);
    BOOST_FOREACH(CNode* pnode, vNodes)
        if (pnode->addrName == addrName)
            return (pnode);
    return NULL;
}

CNode* FindNode(const CService& addr)
{
    LOCK(cs_vNodes);
    BOOST_FOREACH(CNode* pnode, vNodes)
        if ((CService)pnode->addr == addr)
            return (pnode);
    return NULL;
}

CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
{
    if (pszDest == NULL) {
        if (IsLocal(addrConnect))
            return NULL;

        // Look for an existing connection
        CNode* pnode = FindNode((CService)addrConnect);
        if (pnode)
        {
            pnode->AddRef();
            return pnode;
        }
    }

    /// debug print
    printf("trying connection %s lastseen=%.1fhrs\n",
        pszDest ? pszDest : addrConnect.ToString().c_str(),
        pszDest ? 0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);

    // Connect
    SOCKET hSocket;
    if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, GetDefaultPort()) : ConnectSocket(addrConnect, hSocket))
    {
        addrman.Attempt(addrConnect);

        /// debug print
        printf("connected %s\n", pszDest ? pszDest : addrConnect.ToString().c_str());

        // Set to non-blocking
#ifdef WIN32
        u_long nOne = 1;
        if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
            printf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %d\n", WSAGetLastError());
#else
        if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
            printf("ConnectSocket() : fcntl non-blocking setting failed, error %d\n", errno);
#endif

        // Add node
        CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false);
        pnode->AddRef();

        {
            LOCK(cs_vNodes);
            vNodes.push_back(pnode);
        }

        pnode->nTimeConnected = GetTime();
        return pnode;
    }
    else
    {
        return NULL;
    }
}

void CNode::CloseSocketDisconnect()
{
    fDisconnect = true;
    if (hSocket != INVALID_SOCKET)
    {
        printf("disconnecting node %s\n", addrName.c_str());
        closesocket(hSocket);
        hSocket = INVALID_SOCKET;
    }

    // in case this fails, we'll empty the recv buffer when the CNode is deleted
    TRY_LOCK(cs_vRecvMsg, lockRecv);
    if (lockRecv)
        vRecvMsg.clear();

    // if this was the sync node, we'll need a new one
    if (this == pnodeSync)
        pnodeSync = NULL;
}

void CNode::Cleanup()
{
}

void CNode::PushVersion()
{
    /// when NTP implemented, change to just nTime = GetAdjustedTime()
    int64 nTime = (fInbound ? GetAdjustedTime() : GetTime());
    CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0)));
    CAddress addrMe = GetLocalAddress(&addr);
    RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
    printf("send version message: version %d, blocks=%d, us=%s, them=%s, peer=%s\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString().c_str(), addrYou.ToString().c_str(), addr.ToString().c_str());
    PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
                nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight);
}

std::map<CNetAddr, int64> CNode::setBanned;
CCriticalSection CNode::cs_setBanned;

void CNode::ClearBanned()
{
    setBanned.clear();
}

bool CNode::IsBanned(CNetAddr ip)
{
    bool fResult = false;
    {
        LOCK(cs_setBanned);
        std::map<CNetAddr, int64>::iterator i = setBanned.find(ip);
        if (i != setBanned.end())
        {
            int64 t = (*i).second;
            if (GetTime() < t)
                fResult = true;
        }
    }
    return fResult;
}

bool CNode::Misbehaving(int howmuch)
{
    if (addr.IsLocal())
    {
        printf("Warning: Local node %s misbehaving (delta: %d)!\n", addrName.c_str(), howmuch);
        return false;
    }

    nMisbehavior += howmuch;
    if (nMisbehavior >= GetArg("-banscore", 100))
    {
        int64 banTime = GetTime()+GetArg("-bantime", 60*60*24);  // Default 24-hour ban
        printf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
        {
            LOCK(cs_setBanned);
            if (setBanned[addr] < banTime)
                setBanned[addr] = banTime;
        }
        CloseSocketDisconnect();
        return true;
    } else
        printf("Misbehaving: %s (%d -> %d)\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
    return false;
}

#undef X
#define X(name) stats.name = name
void CNode::copyStats(CNodeStats &stats)
{
    X(nServices);
    X(nLastSend);
    X(nLastRecv);
    X(nTimeConnected);
    X(addrName);
    X(nVersion);
    X(cleanSubVer);
    X(fInbound);
    X(nStartingHeight);
    X(nMisbehavior);
    X(nSendBytes);
    X(nRecvBytes);
    X(nBlocksRequested);
    stats.fSyncNode = (this == pnodeSync);
}
#undef X

// requires LOCK(cs_vRecvMsg)
bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes)
{
    while (nBytes > 0) {

        // get current incomplete message, or create a new one
        if (vRecvMsg.empty() ||
            vRecvMsg.back().complete())
            vRecvMsg.push_back(CNetMessage(SER_NETWORK, nRecvVersion));

        CNetMessage& msg = vRecvMsg.back();

        // absorb network data
        int handled;
        if (!msg.in_data)
            handled = msg.readHeader(pch, nBytes);
        else
            handled = msg.readData(pch, nBytes);

        if (handled < 0)
                return false;

        pch += handled;
        nBytes -= handled;
    }

    return true;
}

int CNetMessage::readHeader(const char *pch, unsigned int nBytes)
{
    // copy data to temporary parsing buffer
    unsigned int nRemaining = 24 - nHdrPos;
    unsigned int nCopy = std::min(nRemaining, nBytes);

    memcpy(&hdrbuf[nHdrPos], pch, nCopy);
    nHdrPos += nCopy;

    // if header incomplete, exit
    if (nHdrPos < 24)
        return nCopy;

    // deserialize to CMessageHeader
    try {
        hdrbuf >> hdr;
    }
    catch (std::exception &e) {
        return -1;
    }

    // reject messages larger than MAX_SIZE
    if (hdr.nMessageSize > MAX_SIZE)
            return -1;

    // switch state to reading message data
    in_data = true;
    vRecv.resize(hdr.nMessageSize);

    return nCopy;
}

int CNetMessage::readData(const char *pch, unsigned int nBytes)
{
    unsigned int nRemaining = hdr.nMessageSize - nDataPos;
    unsigned int nCopy = std::min(nRemaining, nBytes);

    memcpy(&vRecv[nDataPos], pch, nCopy);
    nDataPos += nCopy;

    return nCopy;
}

// requires LOCK(cs_vSend)
void SocketSendData(CNode *pnode)
{
    std::deque<CSerializeData>::iterator it = pnode->vSendMsg.begin();

    while (it != pnode->vSendMsg.end()) {
        const CSerializeData &data = *it;
        assert(data.size() > pnode->nSendOffset);
        int nBytes = send(pnode->hSocket, &data[pnode->nSendOffset], data.size() - pnode->nSendOffset, MSG_NOSIGNAL | MSG_DONTWAIT);
        if (nBytes > 0) {
            pnode->nLastSend = GetTime();
            pnode->nSendBytes += nBytes;
            pnode->nSendOffset += nBytes;
            if (pnode->nSendOffset == data.size()) {
                pnode->nSendOffset = 0;
                pnode->nSendSize -= data.size();
                it++;
            } else {
                // could not send full message; stop sending more
                break;
            }
        } else {
            if (nBytes < 0) {
                // error
                int nErr = WSAGetLastError();
                if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
                {
                    printf("socket send error %d\n", nErr);
                    pnode->CloseSocketDisconnect();
                }
            }
            // couldn't send anything at all
            break;
        }
    }

    if (it == pnode->vSendMsg.end()) {
        assert(pnode->nSendOffset == 0);
        assert(pnode->nSendSize == 0);
    }
    pnode->vSendMsg.erase(pnode->vSendMsg.begin(), it);
}

static list<CNode*> vNodesDisconnected;

void ThreadSocketHandler()
{
    unsigned int nPrevNodeCount = 0;
    loop
    {
        //
        // Disconnect nodes
        //
        {
            LOCK(cs_vNodes);
            // Disconnect unused nodes
            vector<CNode*> vNodesCopy = vNodes;
            BOOST_FOREACH(CNode* pnode, vNodesCopy)
            {
                if (pnode->fDisconnect ||
                    (pnode->GetRefCount() <= 0 && pnode->vRecvMsg.empty() && pnode->nSendSize == 0 && pnode->ssSend.empty()))
                {
                    // remove from vNodes
                    vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());

                    // release outbound grant (if any)
                    pnode->grantOutbound.Release();

                    // close socket and cleanup
                    pnode->CloseSocketDisconnect();
                    pnode->Cleanup();

                    // hold in disconnected pool until all refs are released
                    if (pnode->fNetworkNode || pnode->fInbound)
                        pnode->Release();
                    vNodesDisconnected.push_back(pnode);
                }
            }

            // Delete disconnected nodes
            list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
            BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
            {
                // wait until threads are done using it
                if (pnode->GetRefCount() <= 0)
                {
                    bool fDelete = false;
                    {
                        TRY_LOCK(pnode->cs_vSend, lockSend);
                        if (lockSend)
                        {
                            TRY_LOCK(pnode->cs_vRecvMsg, lockRecv);
                            if (lockRecv)
                            {
                                TRY_LOCK(pnode->cs_inventory, lockInv);
                                if (lockInv)
                                    fDelete = true;
                            }
                        }
                    }
                    if (fDelete)
                    {
                        vNodesDisconnected.remove(pnode);
                        delete pnode;
                    }
                }
            }
        }
        if (vNodes.size() != nPrevNodeCount)
        {
            nPrevNodeCount = vNodes.size();
            uiInterface.NotifyNumConnectionsChanged(vNodes.size());
        }

        //
        // Find which sockets have data to receive
        //
        struct timeval timeout;
        timeout.tv_sec  = 0;
        timeout.tv_usec = 50000; // frequency to poll pnode->vSend

        fd_set fdsetRecv;
        fd_set fdsetSend;
        fd_set fdsetError;
        FD_ZERO(&fdsetRecv);
        FD_ZERO(&fdsetSend);
        FD_ZERO(&fdsetError);
        SOCKET hSocketMax = 0;
        bool have_fds = false;

        BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) {
            FD_SET(hListenSocket, &fdsetRecv);
            hSocketMax = max(hSocketMax, hListenSocket);
            have_fds = true;
        }
        {
            LOCK(cs_vNodes);
            BOOST_FOREACH(CNode* pnode, vNodes)
            {
                if (pnode->hSocket == INVALID_SOCKET)
                    continue;
                FD_SET(pnode->hSocket, &fdsetError);
                hSocketMax = max(hSocketMax, pnode->hSocket);
                have_fds = true;

                // Implement the following logic:
                // * If there is data to send, select() for sending data. As this only
                //   happens when optimistic write failed, we choose to first drain the
                //   write buffer in this case before receiving more. This avoids
                //   needlessly queueing received data, if the remote peer is not themselves
                //   receiving data. This means properly utilizing TCP flow control signalling.
                // * Otherwise, if there is no (complete) message in the receive buffer,
                //   or there is space left in the buffer, select() for receiving data.
                // * (if neither of the above applies, there is certainly one message
                //   in the receiver buffer ready to be processed).
                // Together, that means that at least one of the following is always possible,
                // so we don't deadlock:
                // * We send some data.
                // * We wait for data to be received (and disconnect after timeout).
                // * We process a message in the buffer (message handler thread).
                {
                    TRY_LOCK(pnode->cs_vSend, lockSend);
                    if (lockSend && !pnode->vSendMsg.empty()) {
                        FD_SET(pnode->hSocket, &fdsetSend);
                        continue;
                    }
                }
                {
                    TRY_LOCK(pnode->cs_vRecvMsg, lockRecv);
                    if (lockRecv && (
                        pnode->vRecvMsg.empty() || !pnode->vRecvMsg.front().complete() ||
                        pnode->GetTotalRecvSize() <= ReceiveFloodSize()))
                        FD_SET(pnode->hSocket, &fdsetRecv);
                }
            }
        }

        int nSelect = select(have_fds ? hSocketMax + 1 : 0,
                             &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
        boost::this_thread::interruption_point();

        if (nSelect == SOCKET_ERROR)
        {
            if (have_fds)
            {
                int nErr = WSAGetLastError();
                printf("socket select error %d\n", nErr);
                for (unsigned int i = 0; i <= hSocketMax; i++)
                    FD_SET(i, &fdsetRecv);
            }
            FD_ZERO(&fdsetSend);
            FD_ZERO(&fdsetError);
            MilliSleep(timeout.tv_usec/1000);
        }

        //
        // Accept new connections
        //
        BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
        if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
        {
#ifdef USE_IPV6
            struct sockaddr_storage sockaddr;
#else
            struct sockaddr sockaddr;
#endif
            socklen_t len = sizeof(sockaddr);
            SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
            CAddress addr;
            int nInbound = 0;

            if (hSocket != INVALID_SOCKET)
                if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
                    printf("Warning: Unknown socket family\n");

            {
                LOCK(cs_vNodes);
                BOOST_FOREACH(CNode* pnode, vNodes)
                    if (pnode->fInbound)
                        nInbound++;
            }

            if (hSocket == INVALID_SOCKET)
            {
                int nErr = WSAGetLastError();
                if (nErr != WSAEWOULDBLOCK)
                    printf("socket error accept failed: %d\n", nErr);
            }
            else if (nInbound >= nMaxConnections - MAX_OUTBOUND_CONNECTIONS)
            {
                {
                    LOCK(cs_setservAddNodeAddresses);
                    if (!setservAddNodeAddresses.count(addr))
                        closesocket(hSocket);
                }
            }
            else if (CNode::IsBanned(addr))
            {
                printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
                closesocket(hSocket);
            }
            else
            {
                printf("accepted connection %s\n", addr.ToString().c_str());
                CNode* pnode = new CNode(hSocket, addr, "", true);
                pnode->AddRef();
                {
                    LOCK(cs_vNodes);
                    vNodes.push_back(pnode);
                }
            }
        }

        //
        // Service each socket
        //
        vector<CNode*> vNodesCopy;
        {
            LOCK(cs_vNodes);
            vNodesCopy = vNodes;
            BOOST_FOREACH(CNode* pnode, vNodesCopy)
                pnode->AddRef();
        }
        BOOST_FOREACH(CNode* pnode, vNodesCopy)
        {
            boost::this_thread::interruption_point();

            //
            // Receive
            //
            if (pnode->hSocket == INVALID_SOCKET)
                continue;
            if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
            {
                TRY_LOCK(pnode->cs_vRecvMsg, lockRecv);
                if (lockRecv)
                {
                    {
                        // typical socket buffer is 8K-64K
                        char pchBuf[0x10000];
                        int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
                        if (nBytes > 0)
                        {
                            if (!pnode->ReceiveMsgBytes(pchBuf, nBytes))
                                pnode->CloseSocketDisconnect();
                            pnode->nLastRecv = GetTime();
                            pnode->nRecvBytes += nBytes;
                        }
                        else if (nBytes == 0)
                        {
                            // socket closed gracefully
                            if (!pnode->fDisconnect)
                                printf("socket closed\n");
                            pnode->CloseSocketDisconnect();
                        }
                        else if (nBytes < 0)
                        {
                            // error
                            int nErr = WSAGetLastError();
                            if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
                            {
                                if (!pnode->fDisconnect)
                                    printf("socket recv error %d\n", nErr);
                                pnode->CloseSocketDisconnect();
                            }
                        }
                    }
                }
            }

            //
            // Send
            //
            if (pnode->hSocket == INVALID_SOCKET)
                continue;
            if (FD_ISSET(pnode->hSocket, &fdsetSend))
            {
                TRY_LOCK(pnode->cs_vSend, lockSend);
                if (lockSend)
                    SocketSendData(pnode);
            }

            //
            // Inactivity checking
            //
            if (pnode->vSendMsg.empty())
                pnode->nLastSendEmpty = GetTime();
            if (GetTime() - pnode->nTimeConnected > 60)
            {
                if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
                {
                    printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
                    pnode->fDisconnect = true;
                }
                else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
                {
                    printf("socket not sending\n");
                    pnode->fDisconnect = true;
                }
                else if (GetTime() - pnode->nLastRecv > 90*60)
                {
                    printf("socket inactivity timeout\n");
                    pnode->fDisconnect = true;
                }
            }
        }
        {
            LOCK(cs_vNodes);
            BOOST_FOREACH(CNode* pnode, vNodesCopy)
                pnode->Release();
        }

        MilliSleep(10);
    }
}

#ifdef USE_UPNP
void ThreadMapPort()
{
    std::string port = strprintf("%u", GetListenPort());
    const char * multicastif = 0;
    const char * minissdpdpath = 0;
    struct UPNPDev * devlist = 0;
    char lanaddr[64];

#ifndef UPNPDISCOVER_SUCCESS
    /* miniupnpc 1.5 */
    devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0);
#else
    /* miniupnpc 1.6 */
    int error = 0;
    devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
#endif

    struct UPNPUrls urls;
    struct IGDdatas data;
    int r;

    r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
    if (r == 1)
    {
        if (fDiscover) {
            char externalIPAddress[40];
            r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
            if(r != UPNPCOMMAND_SUCCESS)
                printf("UPnP: GetExternalIPAddress() returned %d\n", r);
            else
            {
                if(externalIPAddress[0])
                {
                    printf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
                    AddLocal(CNetAddr(externalIPAddress), LOCAL_UPNP);
                }
                else
                    printf("UPnP: GetExternalIPAddress failed.\n");
            }
        }

        string strDesc = "Vertcoin " + FormatFullVersion();

        try {
            loop {
#ifndef UPNPDISCOVER_SUCCESS
                /* miniupnpc 1.5 */
                r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
                                    port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
#else
                /* miniupnpc 1.6 */
                r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
                                    port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
#endif

                if(r!=UPNPCOMMAND_SUCCESS)
                    printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
                        port.c_str(), port.c_str(), lanaddr, r, strupnperror(r));
                else
                    printf("UPnP Port Mapping successful.\n");;

                MilliSleep(20*60*1000); // Refresh every 20 minutes
            }
        }
        catch (boost::thread_interrupted)
        {
            r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
            printf("UPNP_DeletePortMapping() returned : %d\n", r);
            freeUPNPDevlist(devlist); devlist = 0;
            FreeUPNPUrls(&urls);
            throw;
        }
    } else {
        printf("No valid UPnP IGDs found\n");
        freeUPNPDevlist(devlist); devlist = 0;
        if (r != 0)
            FreeUPNPUrls(&urls);
    }
}

void MapPort(bool fUseUPnP)
{
    static boost::thread* upnp_thread = NULL;

    if (fUseUPnP)
    {
        if (upnp_thread) {
            upnp_thread->interrupt();
            upnp_thread->join();
            delete upnp_thread;
        }
        upnp_thread = new boost::thread(boost::bind(&TraceThread<boost::function<void()> >, "upnp", &ThreadMapPort));
    }
    else if (upnp_thread) {
        upnp_thread->interrupt();
        upnp_thread->join();
        delete upnp_thread;
        upnp_thread = NULL;
    }
}

#else
void MapPort(bool)
{
    // Intentionally left blank.
}
#endif

// DNS seeds
// Each pair gives a source name and a seed name.
// The first name is used as information source for addrman.
// The second name should resolve to a list of seed addresses.
static const char *strMainNetDNSSeed[][2] = {
    {"dnsseed.meningslos.info", "dnsseed.meningslos.info"},
    {"ams1.vertcoin.org", "ams1.vertcoin.org"},
    {"ams2.vertcoin.org", "ams2.vertcoin.org"},
    {"ams3.vertcoin.org", "ams3.vertcoin.org"},
    {"ams4.vertcoin.org", "ams4.vertcoin.org"},
    {"nl1.vertcoin.org", "nl1.vertcoin.org"},
    {"nl2.vertcoin.org", "nl2.vertcoin.org"},
    {"se1.vertcoin.org", "se1.vertcoin.org"},
    {"ny.vertcoin.org", "ny.vertcoin.org"},
    {"la.vertcoin.org", "la.vertcoin.org"},
    {"eu.vertcoin.org", "eu.vertcoin.org"},
    {NULL, NULL}
};

static const char *strTestNetDNSSeed[][2] = {
    {"testnet-seed.vertcoin.org", "testnet-seed.vertcoin.org"},
    {NULL, NULL}
};

void ThreadDNSAddressSeed()
{
    static const char *(*strDNSSeed)[2] = fTestNet ? strTestNetDNSSeed : strMainNetDNSSeed;

    int found = 0;

    printf("Loading addresses from DNS seeds (could take a while)\n");

    for (unsigned int seed_idx = 0; strDNSSeed[seed_idx][0] != NULL; seed_idx++) {
        if (HaveNameProxy()) {
            AddOneShot(strDNSSeed[seed_idx][1]);
        } else {
            vector<CNetAddr> vaddr;
            vector<CAddress> vAdd;
            if (LookupHost(strDNSSeed[seed_idx][1], vaddr))
            {
                BOOST_FOREACH(CNetAddr& ip, vaddr)
                {
                    int nOneDay = 24*3600;
                    CAddress addr = CAddress(CService(ip, GetDefaultPort()));
                    addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
                    vAdd.push_back(addr);
                    found++;
                }
            }
            addrman.Add(vAdd, CNetAddr(strDNSSeed[seed_idx][0], true));
        }
    }

    printf("%d addresses found from DNS seeds\n", found);
}

unsigned int pnSeed[] =
{
    0xf3f0f3a2, 0x3f77f436, 0xf00b555f, 0xaf83b992, 0xb897f4cf, 0x07f7aa6b,
    0x8902c452, 0x0f183b25, 0x67b74c90, 0x113e9632, 0xac06aa6b, 0x73ecaa6b,
    0x176d5436, 0x8a25555f, 0x45011617, 0x5cfcaa6b, 0x1a0a6fb7, 0xcd9bf1c0,
    0xeeaa1e8b, 0xadadcb62, 0xbc7ed536, 0xa8f8f3a2, 0x0e80a7c7, 0x5b19bb25,
    0x7224aa6b, 0x7946bb25, 0xd885bb25, 0x630cfb94, 0xb2991318, 0xf3136e41,
    0xf9e6e460, 0x330a63c0, 0x0b02555f, 0xd43c4c90, 0xca11aa6b, 0x5bbee2bc,
    0x0e1b3b25, 0xa9c4ec57, 0xc63aaa6b, 0x8fa7e2bc, 0x66a74b3e, 0x84dfa5bc,
    0xeec21955, 0x5394e2bc, 0x73609925, 0x4e158b25, 0x7a7cba6a, 0x86b1e2bc,
    0xe82caa6b, 0x30381cb9, 0x8f404448, 0x2bb2e2bc, 0x4053ee2e, 0x7410e162,
    0x5b78c7c6, 0x4c0a39ad, 0xc7153b25, 0x60c2a5bc, 0x6f808502, 0xc18a654b,
    0xe2ba986b, 0xefc8d86f, 0xdc63134c, 0xf1a134d0, 0x5e7baf70, 0x7d0963c0,
    0x02627e4c, 0x3ec9d431, 0xf120ea5b, 0xdf0e3b25, 0x1227bb6a, 0xbcd9f3a2,
    0x8d6faa6b, 0x80a4b347, 0x164eaa6b, 0xdf1f175e, 0x614f55d4, 0x07e8c780,
    0x0f36ed82, 0xc4576332, 0xa63f07c6, 0x6cfad5a2, 0x0bd7f74d, 0x3f38c3ad,
    0xade0c780, 0x1df9d243, 0x4dc4ec57, 0xb4ace2bc, 0xb249dc62, 0x8bf3f071,
    0xe489e2bc, 0x9aced2c0, 0x5d7ade50, 0x51fa754c, 0x0b6fc7c6, 0x809f8705,
    0xfe1b686d, 0xe3b44e5b, 0x08561f6c, 0x5c590ccf, 0x35e4aa6b, 0x2eddc780,
    0x1fe7aead, 0xbea0f1c0, 0x94108abc, 0xef340118, 0xe8b0e2bc, 0xf22835a1,
    0x31fae3bc, 0x516b4c90, 0x95dff1c0, 0x672baa6b, 0x71b9bf58, 0x13543025,
    0x7e91b46c, 0xfbe15b8a, 0x26601b4c, 0x63a4a844, 0xd6b470d5, 0x09daf150,
    0x526d5fbc, 0x2fe45f55, 0x64412e9e, 0x3cfa9a5f, 0x12ded35e, 0x4a85bac0,
    0x956aaa6b, 0x34ff2d42, 0xf798819e, 0x211c9044, 0x2591fd3e, 0x87bdd23e,
    0x56c3ba18, 0x763b1bcc, 0x65169532, 0x2e16c870, 0x9a3c0cc3, 0x6c808502,
    0x2bd4ad3a, 0x0fdca73b, 0x3b9c61c2, 0x091c6f5f, 0x0360fe05, 0x7a80a7c7,
    0xf6e4df62, 0xc50a20b9, 0x3e30aa6b, 0x32679a5f, 0x52206c4a, 0x71bd1e4c,
    0xb38b7ed0, 0xc8f26744, 0xe1998705, 0x6b808502, 0x1cb7a26c, 0xb2116c4a,
    0x3e53fca2, 0xf6986e4f, 0x75c8bb25, 0x1ce5b259, 0xd56228bc, 0x58c9f94e,
    0xbfacba62, 0xe99ef2c5, 0x967b1d25, 0x24c6f432, 0xe1c8194c, 0x3056dbd5,
    0x026a1bc6, 0x0669aa6b, 0x454502c6, 0x04681eb9, 0x8b201ead, 0x3199824a,
    0xf1e0c780, 0xe6b4844b, 0xe8aa1e8b, 0xc409ba32, 0x326d1e32, 0x016a1bc6,
    0x2783bb25, 0xe02bb049, 0xe522a8d5, 0x68484c90, 0x7678aa6b, 0xa9631f32,
    0x6714d431, 0xc617b843, 0x78ceb742, 0x3787ff40, 0x6162b74b, 0xd0b51fb0,
    0x046a1bc6, 0x7d6da75f, 0x3bdb854f, 0x11a0cc44, 0xed155e48, 0xd86cf62e,
    0x1cf66a57, 0x8cb35743, 0xefeef75c, 0xc16b5f5f, 0xa2dbaa6b, 0xeb3ca04f,
    0x170763c0, 0x5fe6f285, 0x0a2d08cc, 0xc90b1256, 0xa3f75432, 0x1b71aa6b,
    0x546e4473, 0xcb0bc962, 0x8b929f31, 0x926faa55, 0x6c550025, 0x71440e6c,
    0xa8521856, 0x3289103e, 0x919309b0, 0xcad97a5b, 0xcb06ab46, 0x71cdd23e,
    0x330c1c71, 0xeb2bd548, 0x7594b159, 0x640363c0, 0x6bfdb158, 0x93623f5c,
    0x07975444, 0xa5f99b5d, 0x4ae848c6, 0x49b821c2, 0x0480ff60, 0xfce66d4a,
    0x8b005758, 0x5fc09d25, 0xfb80fc63, 0xf2006e41, 0xdbf5bb25, 0x71b89832,
    0x9c44d1d2, 0xe7580756, 0x923ee85e, 0x89431bc6, 0xfa41276c, 0x0561b0ad,
    0x08c01e54, 0xb51b534e, 0xeb0ffb94, 0xbc48c547, 0xbbb4bc3b, 0x19c31955,
    0xec59c0bc, 0x22f6f460, 0x3ae8b982, 0x60644f46, 0x8842eaa2, 0x73d0ff9e,
    0x3052c247, 0x074ded5b, 0xb4222648, 0x4199684c, 0xef333a05, 0x279af845,
    0x223d3044, 0x4a4716b2, 0x7951bb25, 0x177becd1, 0x578a0f18, 0xb0687c70,
    0x4a6f57da, 0xdf604c5b, 0x78f3a0d8, 0x808f5146, 0x36b79ac3, 0x1032b059,
    0x7c664248, 0x9c5fe860, 0xce5a2f4e, 0x3d8fb743, 0xb567762e, 0x8a0dd318,
    0x39cd0844, 0x72185fc0, 0x1ccdc344, 0x694faa6b, 0x3a197432, 0x94b6f0bb,
    0x46420018, 0x0fde871f, 0xe7cde2bc, 0x1dd9e451, 0x62707e60, 0x17faaa6b,
    0xadb24a4c, 0x6df25cd4, 0x9ebc9ac3, 0x2e525661, 0x21f232c6, 0xb01d5fc0,
    0x8ef0254d, 0xee9039ad, 0x88edaa6b, 0x59d5601b, 0x5b3a792a, 0x125414c6,
    0x8478fc60, 0x5a1e5b4a, 0xf562b46c, 0x05cbc780, 0x6ab04c90, 0x9b6ede4a,
    0xbec6015e, 0xa720c658, 0x0b880032, 0xbb6fb74c, 0x1aa8c962, 0xdf161a6c,
    0x18401418, 0xba4fbb4c, 0x569fd295, 0xf68df3a2, 0x25195fc0, 0x7b4abb25,
    0x63d94c90, 0x8038e55e, 0x57cde593, 0xe56c0d54, 0x4881066c, 0x07ee0118,
    0xcc8dd23e, 0x617e464d, 0x576d6fb0, 0xdd5b0856, 0xb03ac14e, 0x799ac445,
    0xb321cf45, 0x0c2d306c, 0x5026ed55, 0x3dd3c940, 0x4ab821c2, 0x665aaa6b,
    0xb7361147, 0xd0939b6d, 0x98aec3be, 0x20f232c6, 0xeef2bb25, 0x7ad05e4c,
    0x789cc152, 0xbaeef257, 0x3270c3d1, 0xa34c58ad, 0x32bde2bc, 0x79d0d162,
    0xce1afeb2, 0x13d40167, 0x9b234e4d, 0x101bdc1f, 0x3712f618, 0x1e732ac3,
    0x80d6a743, 0x729870ae, 0x08e9ed50, 0xe4d8e555, 0x9a27644d, 0x0d363b25,
    0xa247ff60, 0x00ba3e18, 0x41edbb25, 0xdb2e6d50, 0x3e3ac962, 0x0e86f767,
    0x05f21b32, 0x9d951581, 0xead00ed9, 0x8b2fecad, 0x96f7967a, 0x50bf5046,
    0x666a2172, 0x1c5f5f18, 0xfa145b4a, 0xdecd6476, 0x5115b032, 0x0b3515ae,
    0x173cfe1b, 0xd507a956, 0xf34329d9, 0xdd3c343c, 0x3302a86c, 0xfc67b94c,
    0x8089f13c, 0xee9a0856, 0x3cc0b45e, 0xabccc818, 0x4c55112f, 0x2e07e9dc,
    0x5292c150, 0x1c9ad855, 0x45648baf, 0x7e0dea5c, 0x8a992ec6, 0xb37b6b51,
    0x3ba8ee47, 0x0c78cc62, 0x1b6a6fb0, 0xcf7b1fb0, 0x82042ed5, 0x283788af,
    0x9b0daa6b, 0x6e22b73e, 0xf0de19bc, 0x40987118, 0xdd00ac43, 0xe10031b2,
    0xc13ee054, 0x2070a547, 0x0745f545, 0x2371ff45, 0x15101871, 0xe2214045,
    0x91d5685d, 0x86c20418, 0x49e6cf4a, 0xec22e8bc, 0xeb54aa6b, 0x3020d0d9,
    0xf851d754, 0x9fc51c5f, 0x47b1144c, 0xd1e0dd5f, 0xbecc8b5e, 0x8ec256c5,
    0xd215f663, 0xa158dc79, 0x9345bcca, 0xc0216751, 0xf2025d02, 0xad59d754,
    0x149fab80, 0x97f9b84c, 0xb70a6602, 0xa9a3753e, 0x8c409a95, 0x30e49344,
    0x603900ca, 0x9c344646, 0x36f605b8, 0x326d6a59, 0xab172077, 0xc3271756,
    0xb3eadb8d, 0xe525b84c, 0x116fce05, 0x32794ebc, 0x51716acb, 0x27f73f4e,
    0x7ab743ad, 0x5b1ec0ad, 0x1cda9c5e, 0x9813feb2, 0xcd607e5d, 0x7c3d9b32,
    0xea1f2a64, 0xa850aa6b, 0x1116ca47, 0x278acd45, 0x9518dc1f, 0x26c01b41,
    0x144a135e, 0xb45f184c, 0x2c8efab0, 0x0ac31e55, 0xadc194b1, 0x8f90c257,
    0x70201c1f, 0xf4881d73, 0x26ab54c6, 0x1653f017, 0xc878e260, 0xcc36df5f,
    0xe193a16b, 0xc52d0644, 0x59362fb5, 0x9b5caa6b, 0x375aaa6b, 0x0cf600c0,
    0x07833aae, 0xdeace2bc, 0x087b7457, 0x72ada853, 0x02903b4d, 0x14110467,
    0x6bd6f3a2, 0xf5747691, 0x671a4a4b, 0x1e6e4563, 0x23423a47, 0xc988236c,
    0x3ac116ba, 0xa2b4ad43, 0xb6c9775c, 0x5221ec5c, 0x2aa25947, 0x6aa16244,
    0x72700551, 0x7412f3a2, 0x426906ae, 0x2bf96f51, 0x61964c4d, 0xc8b8352e,
    0x4be8d754, 0x51e31118, 0xb5f1844b, 0x7fa2ae32, 0x0b01654f, 0xb35cdf40,
    0x6c23dc79, 0x6a13a673, 0x68665453, 0xb3989b51, 0x5ef525b0, 0x6c6b06ae,
    0xb851f560, 0x5e6ae497, 0x5cdfeead, 0x62c81c73, 0x8b58f181, 0x2dbb8932,
    0x6914ff9f, 0xbaebd9ad, 0xa63e6b44, 0x1fcf04bc, 0x71d6254d, 0xf4812460,
    0x768fcfbe, 0xcef33918, 0x9c25e48b, 0xf94fb74b, 0x27c46562, 0x013da9b2,
    0x2c8e32c6, 0xdd33282e, 0xea2d867b, 0x0b51b63a, 0x385ece4a, 0x84cdc552,
    0xb8945c47, 0x2aaaa14b, 0x4d58d018, 0xc3eea032, 0x35350344, 0xe7c5aa6b,
    0x9a4730d4, 0x6230ed4e, 0x5852b96c, 0xe776e542, 0x5fe08618, 0xfd833249,
    0xb344dd59, 0x2b703ac6, 0x1db8b15d, 0x413dec63, 0x1b30bb4b, 0x4ac31955,
    0x54caaa6b, 0xd332b875, 0x4a51d918, 0x50a23532, 0xbb8eff63, 0x133e5d02,
    0xf286694a, 0xa7000250, 0xce25a518, 0xbeb84094, 0xacecc780, 0x675a4c46,
    0xcc254b80, 0x1fea5a54, 0x3111742e, 0xd54aca1b, 0x34325c76, 0x2cd8dc57,
    0xfc8f5343, 0x9f81ec69, 0x8eb88b52, 0x711a6144, 0x9f60b74c, 0xef172d3e,
    0xc4e789d9, 0x665fb57b, 0x5973aa6b, 0x9621042e, 0xe54ac725, 0xf407cc78,
    0xca827fd5, 0x2cf9a377, 0x4999ab80, 0x0a694eb2, 0x8098085e, 0x80994dbc
};

void DumpAddresses()
{
    int64 nStart = GetTimeMillis();

    CAddrDB adb;
    adb.Write(addrman);

    printf("Flushed %d addresses to peers.dat  %"PRI64d"ms\n",
           addrman.size(), GetTimeMillis() - nStart);
}

void static ProcessOneShot()
{
    string strDest;
    {
        LOCK(cs_vOneShots);
        if (vOneShots.empty())
            return;
        strDest = vOneShots.front();
        vOneShots.pop_front();
    }
    CAddress addr;
    CSemaphoreGrant grant(*semOutbound, true);
    if (grant) {
        if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
            AddOneShot(strDest);
    }
}

void ThreadOpenConnections()
{
    // Connect to specific addresses
    if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
    {
        for (int64 nLoop = 0;; nLoop++)
        {
            ProcessOneShot();
            BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
            {
                CAddress addr;
                OpenNetworkConnection(addr, NULL, strAddr.c_str());
                for (int i = 0; i < 10 && i < nLoop; i++)
                {
                    MilliSleep(500);
                }
            }
            MilliSleep(500);
        }
    }

    // Initiate network connections
    int64 nStart = GetTime();
    loop
    {
        ProcessOneShot();

        MilliSleep(500);

        CSemaphoreGrant grant(*semOutbound);
        boost::this_thread::interruption_point();

        // Add seed nodes if IRC isn't working
        if (addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
        {
            std::vector<CAddress> vAdd;
            for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
            {
                // It'll only connect to one or two seed nodes because once it connects,
                // it'll get a pile of addresses with newer timestamps.
                // Seed nodes are given a random 'last seen time' of between one and two
                // weeks ago.
                const int64 nOneWeek = 7*24*60*60;
                struct in_addr ip;
                memcpy(&ip, &pnSeed[i], sizeof(ip));
                CAddress addr(CService(ip, GetDefaultPort()));
                addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
                vAdd.push_back(addr);
            }
            addrman.Add(vAdd, CNetAddr("127.0.0.1"));
        }

        //
        // Choose an address to connect to based on most recently seen
        //
        CAddress addrConnect;

        // Only connect out to one peer per network group (/16 for IPv4).
        // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
        int nOutbound = 0;
        set<vector<unsigned char> > setConnected;
        {
            LOCK(cs_vNodes);
            BOOST_FOREACH(CNode* pnode, vNodes) {
                if (!pnode->fInbound) {
                    setConnected.insert(pnode->addr.GetGroup());
                    nOutbound++;
                }
            }
        }

        int64 nANow = GetAdjustedTime();

        int nTries = 0;
        loop
        {
            // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
            CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);

            // if we selected an invalid address, restart
            if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
                break;

            // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
            // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
            // already-connected network ranges, ...) before trying new addrman addresses.
            nTries++;
            if (nTries > 100)
                break;

            if (IsLimited(addr))
                continue;

            // only consider very recently tried nodes after 30 failed attempts
            if (nANow - addr.nLastTry < 600 && nTries < 30)
                continue;

            // do not allow non-default ports, unless after 50 invalid addresses selected already
            if (addr.GetPort() != GetDefaultPort() && nTries < 50)
                continue;

            addrConnect = addr;
            break;
        }

        if (addrConnect.IsValid())
            OpenNetworkConnection(addrConnect, &grant);
    }
}

void ThreadOpenAddedConnections()
{
    {
        LOCK(cs_vAddedNodes);
        vAddedNodes = mapMultiArgs["-addnode"];
    }

    if (HaveNameProxy()) {
        while(true) {
            list<string> lAddresses(0);
            {
                LOCK(cs_vAddedNodes);
                BOOST_FOREACH(string& strAddNode, vAddedNodes)
                    lAddresses.push_back(strAddNode);
            }
            BOOST_FOREACH(string& strAddNode, lAddresses) {
                CAddress addr;
                CSemaphoreGrant grant(*semOutbound);
                OpenNetworkConnection(addr, &grant, strAddNode.c_str());
                MilliSleep(500);
            }
            MilliSleep(120000); // Retry every 2 minutes
        }
    }

    for (unsigned int i = 0; true; i++)
    {
        list<string> lAddresses(0);
        {
            LOCK(cs_vAddedNodes);
            BOOST_FOREACH(string& strAddNode, vAddedNodes)
                lAddresses.push_back(strAddNode);
        }

        list<vector<CService> > lservAddressesToAdd(0);
        BOOST_FOREACH(string& strAddNode, lAddresses)
        {
            vector<CService> vservNode(0);
            if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
            {
                lservAddressesToAdd.push_back(vservNode);
                {
                    LOCK(cs_setservAddNodeAddresses);
                    BOOST_FOREACH(CService& serv, vservNode)
                        setservAddNodeAddresses.insert(serv);
                }
            }
        }
        // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
        // (keeping in mind that addnode entries can have many IPs if fNameLookup)
        {
            LOCK(cs_vNodes);
            BOOST_FOREACH(CNode* pnode, vNodes)
                for (list<vector<CService> >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
                    BOOST_FOREACH(CService& addrNode, *(it))
                        if (pnode->addr == addrNode)
                        {
                            it = lservAddressesToAdd.erase(it);
                            it--;
                            break;
                        }
        }
        BOOST_FOREACH(vector<CService>& vserv, lservAddressesToAdd)
        {
            CSemaphoreGrant grant(*semOutbound);
            OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
            MilliSleep(500);
        }
        MilliSleep(120000); // Retry every 2 minutes
    }
}

// if successful, this moves the passed grant to the constructed node
bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
{
    //
    // Initiate outbound network connection
    //
    boost::this_thread::interruption_point();
    if (!strDest)
        if (IsLocal(addrConnect) ||
            FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
            FindNode(addrConnect.ToStringIPPort().c_str()))
            return false;
    if (strDest && FindNode(strDest))
        return false;

    CNode* pnode = ConnectNode(addrConnect, strDest);
    boost::this_thread::interruption_point();

    if (!pnode)
        return false;
    if (grantOutbound)
        grantOutbound->MoveTo(pnode->grantOutbound);
    pnode->fNetworkNode = true;
    if (fOneShot)
        pnode->fOneShot = true;

    return true;
}

// for now, use a very simple selection metric: the node from which we received
// most recently
double static NodeSyncScore(const CNode *pnode) {
    return -pnode->nLastRecv;
}

void static StartSync(const vector<CNode*> &vNodes) {
    CNode *pnodeNewSync = NULL;
    double dBestScore = 0;

    // fImporting and fReindex are accessed out of cs_main here, but only
    // as an optimization - they are checked again in SendMessages.
    if (fImporting || fReindex)
        return;

    // Iterate over all nodes
    BOOST_FOREACH(CNode* pnode, vNodes) {
        // check preconditions for allowing a sync
        if (!pnode->fClient && !pnode->fOneShot &&
            !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
            (pnode->nStartingHeight > (nBestHeight - 144)) &&
            (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
            // if ok, compare node's score with the best so far
            double dScore = NodeSyncScore(pnode);
            if (pnodeNewSync == NULL || dScore > dBestScore) {
                pnodeNewSync = pnode;
                dBestScore = dScore;
            }
        }
    }
    // if a new sync candidate was found, start sync!
    if (pnodeNewSync) {
        pnodeNewSync->fStartSync = true;
        pnodeSync = pnodeNewSync;
    }
}

void ThreadMessageHandler()
{
    SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
    while (true)
    {
        bool fHaveSyncNode = false;

        vector<CNode*> vNodesCopy;
        {
            LOCK(cs_vNodes);
            vNodesCopy = vNodes;
            BOOST_FOREACH(CNode* pnode, vNodesCopy) {
                pnode->AddRef();
                if (pnode == pnodeSync)
                    fHaveSyncNode = true;
            }
        }

        if (!fHaveSyncNode)
            StartSync(vNodesCopy);

        // Poll the connected nodes for messages
        CNode* pnodeTrickle = NULL;
        if (!vNodesCopy.empty())
            pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];

        bool fSleep = true;

        BOOST_FOREACH(CNode* pnode, vNodesCopy)
        {
            if (pnode->fDisconnect)
                continue;

            // Receive messages
            {
                TRY_LOCK(pnode->cs_vRecvMsg, lockRecv);
                if (lockRecv)
                {
                    if (!ProcessMessages(pnode))
                        pnode->CloseSocketDisconnect();

                    if (pnode->nSendSize < SendBufferSize())
                    {
                        if (!pnode->vRecvGetData.empty() || (!pnode->vRecvMsg.empty() && pnode->vRecvMsg[0].complete()))
                        {
                            fSleep = false;
                        }
                    }
                }
            }
            boost::this_thread::interruption_point();

            // Send messages
            {
                TRY_LOCK(pnode->cs_vSend, lockSend);
                if (lockSend)
                    SendMessages(pnode, pnode == pnodeTrickle);
            }
            boost::this_thread::interruption_point();
        }

        {
            LOCK(cs_vNodes);
            BOOST_FOREACH(CNode* pnode, vNodesCopy)
                pnode->Release();
        }

        if (fSleep)
            MilliSleep(100);
    }
}

bool BindListenPort(const CService &addrBind, string& strError)
{
    strError = "";
    int nOne = 1;

    // Create socket for listening for incoming connections
#ifdef USE_IPV6
    struct sockaddr_storage sockaddr;
#else
    struct sockaddr sockaddr;
#endif
    socklen_t len = sizeof(sockaddr);
    if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
    {
        strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
        printf("%s\n", strError.c_str());
        return false;
    }

    SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
    if (hListenSocket == INVALID_SOCKET)
    {
        strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
        printf("%s\n", strError.c_str());
        return false;
    }

#ifdef SO_NOSIGPIPE
    // Different way of disabling SIGPIPE on BSD
    setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
#endif

#ifndef WIN32
    // Allow binding if the port is still in TIME_WAIT state after
    // the program was closed and restarted.  Not an issue on windows.
    setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
#endif

#ifdef WIN32
    // Set to non-blocking, incoming connections will also inherit this
    if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
#else
    if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
#endif
    {
        strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
        printf("%s\n", strError.c_str());
        return false;
    }

#ifdef USE_IPV6
    // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
    // and enable it by default or not. Try to enable it, if possible.
    if (addrBind.IsIPv6()) {
#ifdef IPV6_V6ONLY
#ifdef WIN32
        setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
#else
        setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
#endif
#endif
#ifdef WIN32
        int nProtLevel = 10 /* PROTECTION_LEVEL_UNRESTRICTED */;
        int nParameterId = 23 /* IPV6_PROTECTION_LEVEl */;
        // this call is allowed to fail
        setsockopt(hListenSocket, IPPROTO_IPV6, nParameterId, (const char*)&nProtLevel, sizeof(int));
#endif
    }
#endif

    if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
    {
        int nErr = WSAGetLastError();
        if (nErr == WSAEADDRINUSE)
            strError = strprintf(_("Unable to bind to %s on this computer. Vertcoin is probably already running."), addrBind.ToString().c_str());
        else
            strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
        printf("%s\n", strError.c_str());
        return false;
    }
    printf("Bound to %s\n", addrBind.ToString().c_str());

    // Listen for incoming connections
    if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
    {
        strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
        printf("%s\n", strError.c_str());
        return false;
    }

    vhListenSocket.push_back(hListenSocket);

    if (addrBind.IsRoutable() && fDiscover)
        AddLocal(addrBind, LOCAL_BIND);

    return true;
}

void static Discover()
{
    if (!fDiscover)
        return;

#ifdef WIN32
    // Get local host IP
    char pszHostName[1000] = "";
    if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
    {
        vector<CNetAddr> vaddr;
        if (LookupHost(pszHostName, vaddr))
        {
            BOOST_FOREACH (const CNetAddr &addr, vaddr)
            {
                AddLocal(addr, LOCAL_IF);
            }
        }
    }
#else
    // Get local host ip
    struct ifaddrs* myaddrs;
    if (getifaddrs(&myaddrs) == 0)
    {
        for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
        {
            if (ifa->ifa_addr == NULL) continue;
            if ((ifa->ifa_flags & IFF_UP) == 0) continue;
            if (strcmp(ifa->ifa_name, "lo") == 0) continue;
            if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
            if (ifa->ifa_addr->sa_family == AF_INET)
            {
                struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
                CNetAddr addr(s4->sin_addr);
                if (AddLocal(addr, LOCAL_IF))
                    printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
            }
#ifdef USE_IPV6
            else if (ifa->ifa_addr->sa_family == AF_INET6)
            {
                struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
                CNetAddr addr(s6->sin6_addr);
                if (AddLocal(addr, LOCAL_IF))
                    printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
            }
#endif
        }
        freeifaddrs(myaddrs);
    }
#endif

    // Don't use external IPv4 discovery, when -onlynet="IPv6"
    if (!IsLimited(NET_IPV4))
        NewThread(ThreadGetMyExternalIP, NULL);
}

void StartNode(boost::thread_group& threadGroup)
{
    if (semOutbound == NULL) {
        // initialize semaphore
        int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, nMaxConnections);
        semOutbound = new CSemaphore(nMaxOutbound);
    }

    if (pnodeLocalHost == NULL)
        pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices));

    Discover();

    //
    // Start threads
    //

    if (!GetBoolArg("-dnsseed", true))
        printf("DNS seeding disabled\n");
    else
        threadGroup.create_thread(boost::bind(&TraceThread<boost::function<void()> >, "dnsseed", &ThreadDNSAddressSeed));

#ifdef USE_UPNP
    // Map ports with UPnP
    MapPort(GetBoolArg("-upnp", USE_UPNP));
#endif

    // Send and receive from sockets, accept connections
    threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "net", &ThreadSocketHandler));

    // Initiate outbound connections from -addnode
    threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "addcon", &ThreadOpenAddedConnections));

    // Initiate outbound connections
    threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "opencon", &ThreadOpenConnections));

    // Process messages
    threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "msghand", &ThreadMessageHandler));

    // Dump network addresses
    threadGroup.create_thread(boost::bind(&LoopForever<void (*)()>, "dumpaddr", &DumpAddresses, DUMP_ADDRESSES_INTERVAL * 1000));
}

bool StopNode()
{
    printf("StopNode()\n");
    GenerateBitcoins(false, NULL);
    MapPort(false);
    nTransactionsUpdated++;
    if (semOutbound)
        for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
            semOutbound->post();
    MilliSleep(50);
    DumpAddresses();

    return true;
}

class CNetCleanup
{
public:
    CNetCleanup()
    {
    }
    ~CNetCleanup()
    {
        // Close sockets
        BOOST_FOREACH(CNode* pnode, vNodes)
            if (pnode->hSocket != INVALID_SOCKET)
                closesocket(pnode->hSocket);
        BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
            if (hListenSocket != INVALID_SOCKET)
                if (closesocket(hListenSocket) == SOCKET_ERROR)
                    printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());

        // clean up some globals (to help leak detection)
        BOOST_FOREACH(CNode *pnode, vNodes)
            delete pnode;
        BOOST_FOREACH(CNode *pnode, vNodesDisconnected)
            delete pnode;
        vNodes.clear();
        vNodesDisconnected.clear();
        delete semOutbound;
        semOutbound = NULL;
        delete pnodeLocalHost;
        pnodeLocalHost = NULL;

#ifdef WIN32
        // Shutdown Windows Sockets
        WSACleanup();
#endif
    }
}
instance_of_cnetcleanup;

void RelayTransaction(const CTransaction& tx, const uint256& hash)
{
    CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
    ss.reserve(10000);
    ss << tx;
    RelayTransaction(tx, hash, ss);
}

void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
{
    CInv inv(MSG_TX, hash);
    {
        LOCK(cs_mapRelay);
        // Expire old relay messages
        while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
        {
            mapRelay.erase(vRelayExpiration.front().second);
            vRelayExpiration.pop_front();
        }

        // Save original serialized message so newer versions are preserved
        mapRelay.insert(std::make_pair(inv, ss));
        vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
    }
    LOCK(cs_vNodes);
    BOOST_FOREACH(CNode* pnode, vNodes)
    {
        if(!pnode->fRelayTxes)
            continue;
        LOCK(pnode->cs_filter);
        if (pnode->pfilter)
        {
            if (pnode->pfilter->IsRelevantAndUpdate(tx, hash))
                pnode->PushInventory(inv);
        } else
            pnode->PushInventory(inv);
    }
}


text:
<!DOCTYPE html>

    <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
    <meta charset="UTF-8">
    <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
    <meta name="format-detection" content="telephone=no">
    <meta name="msapplication-tap-highlight" content="no">
    <title>AbcLeia</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
    <link rel="stylesheet" href="assets/styles/css/bootstrap.css">
    <link rel="stylesheet" href="assets/styles/css/main.css">
    <link rel="stylesheet" href="assets/styles/css/responsive.css">

Abecedario

            <button class="play">
                a
            </button>
            <audio src="letras/a.mp3" controls></audio>

            <button class="play">
                b
            </button>
            <audio src="letras/b.mp3" controls></audio>

            <button class="play">
                c
            </button>
            <audio src="letras/c.mp3" controls></audio>

            <button class="play">
                d
            </button>
            <audio src="letras/d.mp3" controls></audio>

            <button class="play">
                e
            </button>
            <audio src="letras/e.mp3" controls></audio>

            <button class="play">
                f
            </button>
            <audio src="letras/f.mp3" controls></audio>

            <button class="play">
                g
            </button>
            <audio src="letras/g.mp3" controls></audio>

            <button class="play">
                j
            </button>
            <audio src="letras/j.mp3" controls></audio>

            <button class="play">
                k
            </button>
            <audio src="letras/k.mp3" controls></audio>

            <button class="play">
                l
            </button>
            <audio src="letras/l.mp3" controls></audio>

            <button class="play">
                m
            </button>
            <audio src="letras/m.mp3" controls></audio>

            <button class="play">
                n
            </button>
            <audio src="letras/n.mp3" controls></audio>

            <button class="play">
                o
            </button>
            <audio src="letras/o.mp3" controls></audio>

            <button class="play">
                p
            </button>
            <audio src="letras/p.mp3" controls></audio>

            <button class="play">
                q
            </button>
            <audio src="letras/q.mp3" controls></audio>

            <button class="play">
                r
            </button>
            <audio src="letras/r.mp3" controls></audio>

            <button class="play">
                s
            </button>
            <audio src="letras/s.mp3" controls></audio>

            <button class="play">
                t
            </button>
            <audio src="letras/t.mp3" controls></audio>

            <button class="play">
                u
            </button>
            <audio src="letras/u.mp3" controls></audio>

            <button class="play">
                v
            </button>
            <audio src="letras/v.mp3" controls></audio>

            <button class="play">
                w
            </button>
            <audio src="letras/w.mp3" controls></audio>

            <button class="play">
                x
            </button>
            <audio src="letras/x.mp3" controls></audio>

            <button class="play">
                q
            </button>
            <audio src="letras/q.mp3" controls></audio>

            <button class="play">
                y
            </button>
            <audio src="letras/y.mp3" controls></audio>

            <button class="play">
                z
            </button>
            <audio src="letras/z.mp3" controls></audio>

redpajama_set_name: RedPajamaGithub


text:
{% extends "admin/change_form.html" %}
{% block breadcrumbs %}

  Home › Disassociate Accounts

{% endblock %}
{% block content %}

  {% if success %}

    Votes for the {{election}} election have been succesfully disassociated from
    the voter accounts.

  Return to Admin Page
  {% else %}

    Clicking "Disassociate" will irreversibly disassociate all votes for the
    {{election}}  election from the account that entered the vote.

    This makes it impossible to tell who cast what vote, thus protecting
    voter identity. All other data will remain.

    Please make sure this is what you want before proceeding.

  <form method="post" action="index.html">{% csrf_token %}
    <input type="submit" name="confirm" value="Disassociate Accounts">
  </form>
  {% endif %}

{% endblock %}


text:
package io.aeron.archive.client;

import io.aeron.ControlledFragmentAssembler;
import io.aeron.Subscription;
import io.aeron.archive.codecs.*;
import io.aeron.logbuffer.Header;
import org.agrona.DirectBuffer;
import org.agrona.ErrorHandler;

/**
 * Encapsulate the polling, decoding, dispatching of recording descriptors from an archive.
 *
 * @see RecordingSubscriptionDescriptorConsumer
 * @see ArchiveProxy#listRecordingSubscriptions(int, int, String, int, boolean, long, long)
 * @see AeronArchive#listRecordingSubscriptions(int, int, String, int, boolean, RecordingSubscriptionDescriptorConsumer)
 */
public final class RecordingSubscriptionDescriptorPoller
{
    private final MessageHeaderDecoder messageHeaderDecoder = new MessageHeaderDecoder();
    private final ControlResponseDecoder controlResponseDecoder = new ControlResponseDecoder();
    private final RecordingSubscriptionDescriptorDecoder recordingSubscriptionDescriptorDecoder =
        new RecordingSubscriptionDescriptorDecoder();
    private final RecordingSignalEventDecoder recordingSignalEventDecoder = new RecordingSignalEventDecoder();

    private final long controlSessionId;
    private final int fragmentLimit;
    private final Subscription subscription;
    private final ControlledFragmentAssembler fragmentAssembler = new ControlledFragmentAssembler(this::onFragment);
    private final ErrorHandler errorHandler;
    private final RecordingSignalConsumer recordingSignalConsumer;

    private long correlationId;
    private int remainingSubscriptionCount;
    private boolean isDispatchComplete = false;
    private RecordingSubscriptionDescriptorConsumer subscriptionDescriptorConsumer;

    /**
     * Create a poller for a given subscription to an archive for control response messages.
     *
     * @param subscription     to poll for new events.
     * @param errorHandler     to call for asynchronous errors.
     * @param controlSessionId to filter the responses.
     * @param fragmentLimit    to apply for each polling operation.
     */
    public RecordingSubscriptionDescriptorPoller(
        final Subscription subscription,
        final ErrorHandler errorHandler,
        final long controlSessionId,
        final int fragmentLimit)
    {
        this(
            subscription,
            errorHandler,
            AeronArchive.Configuration.NO_OP_RECORDING_SIGNAL_CONSUMER,
            controlSessionId,
            fragmentLimit);
    }

    /**
     * Create a poller for a given subscription to an archive for control response messages.
     *
     * @param subscription            to poll for new events.
     * @param errorHandler            to call for asynchronous errors.
     * @param recordingSignalConsumer for consuming interleaved recording signals on the control session.
     * @param controlSessionId        to filter the responses.
     * @param fragmentLimit           to apply for each polling operation.
     */
    public RecordingSubscriptionDescriptorPoller(
        final Subscription subscription,
        final ErrorHandler errorHandler,
        final RecordingSignalConsumer recordingSignalConsumer,
        final long controlSessionId,
        final int fragmentLimit)
    {
        this.subscription = subscription;
        this.errorHandler = errorHandler;
        this.recordingSignalConsumer = recordingSignalConsumer;
        this.fragmentLimit = fragmentLimit;
        this.controlSessionId = controlSessionId;
    }

    /**
     * Get the {@link Subscription} used for polling responses.
     *
     * @return the {@link Subscription} used for polling responses.
     */
    public Subscription subscription()
    {
        return subscription;
    }

    /**
     * Poll for recording subscriptions and delegate to the {@link RecordingSubscriptionDescriptorConsumer}.
     *
     * @return the number of fragments read during the operation. Zero if no events are available.
     */
    public int poll()
    {
        if (isDispatchComplete)
        {
            isDispatchComplete = false;
        }

        return subscription.controlledPoll(fragmentAssembler, fragmentLimit);
    }

    /**
     * Control session id for filtering responses.
     *
     * @return control session id for filtering responses.
     */
    public long controlSessionId()
    {
        return controlSessionId;
    }

    /**
     * Is the dispatch of descriptors complete?
     *
     * @return true if the dispatch of descriptors complete?
     */
    public boolean isDispatchComplete()
    {
        return isDispatchComplete;
    }

    /**
     * Get the number of remaining subscriptions expected.
     *
     * @return the number of remaining subscriptions expected.
     */
    public int remainingSubscriptionCount()
    {
        return remainingSubscriptionCount;
    }

    /**
     * Reset the poller to dispatch the descriptors returned from a query.
     *
     * @param correlationId     for the response.
     * @param subscriptionCount of descriptors to expect.
     * @param consumer          to which the recording subscription descriptors are to be dispatched.
     */
    public void reset(
        final long correlationId, final int subscriptionCount, final RecordingSubscriptionDescriptorConsumer consumer)
    {
        this.correlationId = correlationId;
        this.subscriptionDescriptorConsumer = consumer;
        this.remainingSubscriptionCount = subscriptionCount;
        isDispatchComplete = false;
    }

    @SuppressWarnings("MethodLength")
    ControlledFragmentAssembler.Action onFragment(
        final DirectBuffer buffer, final int offset, final int length, final Header header)
    {
        if (isDispatchComplete)
        {
            return ControlledFragmentAssembler.Action.ABORT;
        }

        messageHeaderDecoder.wrap(buffer, offset);

        final int schemaId = messageHeaderDecoder.schemaId();
        if (schemaId != MessageHeaderDecoder.SCHEMA_ID)
        {
            throw new ArchiveException("expected schemaId=" + MessageHeaderDecoder.SCHEMA_ID + ", actual=" + schemaId);
        }

        final int templateId = messageHeaderDecoder.templateId();
        switch (templateId)
        {
            case ControlResponseDecoder.TEMPLATE_ID:
                controlResponseDecoder.wrap(
                    buffer,
                    offset + MessageHeaderEncoder.ENCODED_LENGTH,
                    messageHeaderDecoder.blockLength(),
                    messageHeaderDecoder.version());

                if (controlResponseDecoder.controlSessionId() == controlSessionId)
                {
                    final ControlResponseCode code = controlResponseDecoder.code();
                    final long correlationId = controlResponseDecoder.correlationId();

                    if (ControlResponseCode.SUBSCRIPTION_UNKNOWN == code && correlationId == this.correlationId)
                    {
                        isDispatchComplete = true;
                        return ControlledFragmentAssembler.Action.BREAK;
                    }

                    if (ControlResponseCode.ERROR == code)
                    {
                        final ArchiveException ex = new ArchiveException(
                            "response for correlationId=" + this.correlationId +
                            ", error: " + controlResponseDecoder.errorMessage(),
                            (int)controlResponseDecoder.relevantId(),
                            correlationId);

                        if (correlationId == this.correlationId)
                        {
                            throw ex;
                        }
                        else if (null != errorHandler)
                        {
                            errorHandler.onError(ex);
                        }
                    }
                }
                break;

            case RecordingSubscriptionDescriptorDecoder.TEMPLATE_ID:
                recordingSubscriptionDescriptorDecoder.wrap(
                    buffer,
                    offset + MessageHeaderEncoder.ENCODED_LENGTH,
                    messageHeaderDecoder.blockLength(),
                    messageHeaderDecoder.version());

                if (recordingSubscriptionDescriptorDecoder.controlSessionId() == controlSessionId &&
                    recordingSubscriptionDescriptorDecoder.correlationId() == correlationId)
                {
                    subscriptionDescriptorConsumer.onSubscriptionDescriptor(
                        controlSessionId,
                        correlationId,
                        recordingSubscriptionDescriptorDecoder.subscriptionId(),
                        recordingSubscriptionDescriptorDecoder.streamId(),
                        recordingSubscriptionDescriptorDecoder.strippedChannel());

                    if (0 == --remainingSubscriptionCount)
                    {
                        isDispatchComplete = true;
                        return ControlledFragmentAssembler.Action.BREAK;
                    }
                }
                break;

            case RecordingSignalEventDecoder.TEMPLATE_ID:
                recordingSignalEventDecoder.wrap(
                    buffer,
                    offset + MessageHeaderDecoder.ENCODED_LENGTH,
                    messageHeaderDecoder.blockLength(),
                    messageHeaderDecoder.version());

                if (controlSessionId == recordingSignalEventDecoder.controlSessionId())
                {
                    recordingSignalConsumer.onSignal(
                        recordingSignalEventDecoder.controlSessionId(),
                        recordingSignalEventDecoder.correlationId(),
                        recordingSignalEventDecoder.recordingId(),
                        recordingSignalEventDecoder.subscriptionId(),
                        recordingSignalEventDecoder.position(),
                        recordingSignalEventDecoder.signal());
                }
                break;
        }

        return ControlledFragmentAssembler.Action.CONTINUE;
    }
}


text:
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var core_1 = require("@angular/core");
var router_1 = require("@angular/router");
var LoginComponent = (function () {
    function LoginComponent(router) {
        this.router = router;
        this.cr = true;
    }
    LoginComponent.prototype.check = function () {
        return this.cr;
    };
    LoginComponent.prototype.onSubmit = function (value) {
        console.log(value);
        if (value.password == "123456") {
            console.log("here");
            //    Cookie.set('LoggedIn', true);
            this.router.navigate(['success']);
        }
        else {
            //this._router.navigate(['Success']);
            //   this.router.navigate(['./su']);
            this.cr = false;
        }
    };
    return LoginComponent;
}());
LoginComponent = __decorate([
    core_1.Component({
        selector: 'login',
        templateUrl: "app/login/login.component.html",
        styleUrls: ['app/login/login.component.css']
    }),
    __metadata("design:paramtypes", [router_1.Router])
], LoginComponent);
exports.LoginComponent = LoginComponent;
//# sourceMappingURL=login.component.js.map


text:
/**
 * @author Toru Nagashima <https://github.com/mysticatea>
 * See LICENSE file in root directory for full license.
 */
"use strict"

/**
 * Merge two visitors.
 * This function modifies `visitor1` directly to merge.
 * @param {Visitor} visitor1 The visitor which is assigned.
 * @param {Visitor} visitor2 The visitor which is assigning.
 * @returns {Visitor} `visitor1`.
 */
module.exports = function mergeVisitorsInPlace(visitor1, visitor2) {
    for (const key of Object.keys(visitor2)) {
        const handler1 = visitor1[key]
        const handler2 = visitor2[key]

        if (typeof handler1 === "function") {
            if (handler1._handlers) {
                handler1._handlers.push(handler2)
            } else {
                const handlers = [handler1, handler2]
                visitor1[key] = Object.assign(dispatch.bind(null, handlers), {
                    _handlers: handlers,
                })
            }
        } else {
            visitor1[key] = handler2
        }
    }

    return visitor1
}

/**
 * Dispatch all given functions with a node.
 * @param {function[]} handlers The function list to call.
 * @param {Node} node The AST node to be handled.
 * @returns {void}
 */
function dispatch(handlers, node) {
    for (const h of handlers) {
        h(node)
    }
}


text:
module Dialogue
  module Storable
    def data
      @data ||= {}
    end

    def fetch(key, default=nil, &block)
      data.fetch key, default, &block
    end

    def has_data?(*keys)
      present = keys.all? { |key| data.has_key?(key) }
      if present
        present = keys.all? do |key|
          !data[key].nil? &&
            (!data[key].respond_to?(:empty?) || !data[key].empty?)
        end
      end
      present
    end

    def store!(hash)
      data.merge! hash
    end
  end
end


text:
require 'spec_helper'

describe "ProviderTypes" do

  shared_examples_for "having XML with provider types" do
    subject { Nokogiri::XML(response.body) }
    context "list of provider types" do
      let(:xml_provider_types) { subject.xpath('//provider_types/provider_type') }
      context "number of provider types" do
        it { ProviderType.all; xml_provider_types.size.should be_eql(number_of_provider_types) }
      end
      it "should have correct provider types" do
        provider_types.each do |provider_type|
          xml_provider_type = xml_provider_types.xpath("//provider_type[@id=\"#{provider_type.id}\"]")
          xml_provider_type.xpath('@href').text.should be_eql(api_provider_type_url(provider_type))
          # it should have details of provider_types
          %w{name deltacloud_driver}.each do |element|
            xml_provider_type.xpath(element).text.should be_eql(provider_type.attributes[element])
          end
          # it should not have details of provider_types
          %w{ssh_user home_dir}.each do |element|
            xml_provider_type.xpath(element).should be_empty
          end
        end
      end
    end

    shared_examples_for "having XML with provider type" do
      subject { Nokogiri::XML(response.body) }
      it "should have correct provider type" do
        xml_provider_type = subject.xpath("//provider_type")
        xml_provider_type.xpath('@id').text.should be_eql(provider_type.id.to_s)
        xml_provider_type.xpath('@href').text.should be_eql(api_provider_type_url(provider_type))
        # it should have details of provider_types
        %w{name deltacloud_driver ssh_user home_dir}.each do |element|
          xml_provider_type.xpath(element).text.should be_eql(provider_type.attributes[element].to_s)
        end
        # it should not have details of provider_types
        %w{}.each do |element|
          xml_provider_type.xpath(element).should be_empty
        end
      end
      it "should have correct set of credential definitions" do
        xml_credential_definitions = subject.xpath("//provider_type/credential_definitions")
        # puts provider_type.inspect
        # puts provider_type.credential_definitions.inspect
        provider_type.credential_definitions.each do |credential_definition|
          xml_credential_definition = xml_credential_definitions.xpath("//credential_definition[@id=\"#{credential_definition.id}\"]")
          # it should have details for credential definition
          %w{name label input_type}.each do |element|
            xml_credential_definition.xpath(element).text.should be_eql(credential_definition.attributes[element].to_s)
          end
        end
      end
    end
  end

  let(:headers) { {
    'HTTP_ACCEPT' => 'application/xml',
    'CONTENT_TYPE' => 'application/xml'
  } }
  before(:each) do
    user = FactoryGirl.create(:admin_permission).user
    login_as(user)
  end

  describe "GET /api/provider_types" do
    let(:number_of_provider_types) { 3 }
    let!(:provider_types) { ProviderType.destroy_all; number_of_provider_types.times{ FactoryGirl.create(:provider_type) }; ProviderType.all }

    before(:each) do
      resp = get '/api/provider_types', nil, headers
    end

    it_behaves_like 'http', 'OK'
    it_behaves_like "responding with XML"

    context "XML body" do
      it_behaves_like "having XML with provider types"
    end
  end

  describe "GET /api/provider_types/:id" do
    let!(:provider_type) { FactoryGirl.create(:provider_type_with_credential_definitions) }

    context "provider type exists" do
      before(:each) do
        get "/api/provider_types/#{provider_type.id}", nil, headers
      end

      it_behaves_like 'http', 'OK'
      it_behaves_like "responding with XML"

      context "XML body" do
        it_behaves_like "having XML with provider type"
      end
    end

    context "provider type does not exist" do

       before(:each) do
         provider_type.destroy
         get "/api/provider_types/#{provider_type.id}", nil, headers
       end

       it_behaves_like 'http', 'Not Found'
       it_behaves_like "responding with XML"
    end
  end

  describe "DELETE /api/provider_types/:id" do
    let!(:provider_type) { FactoryGirl.create(:provider_type_with_credential_definitions) }

    context "provider type exists" do
      before(:each) do
        @provider_type_count = ProviderType.count
        delete "/api/provider_types/#{provider_type.id}", nil, headers
      end

      it_behaves_like 'http', 'No Content'

      it "should be deleted" do
        expect { ProviderType.find(provider_type.id) }.to raise_error(ActiveRecord::RecordNotFound)
      end

      it "should not delete other provider types" do
        (@provider_type_count - ProviderType.count).should eql(1)
      end
    end

    context "provider type does not exist" do
      before(:each) do
        ProviderType.destroy(provider_type.id)
        @provider_type_count = ProviderType.count
        delete "/api/provider_types/#{provider_type.id}", nil, headers
      end

      it_behaves_like 'http', 'Not Found'
      it_behaves_like "responding with XML"

      it "should not delete any provider type" do
        ProviderType.count.should eql(@provider_type_count)
      end
    end
  end
end


text:
package db

//
// A TotalOrderId expressed the total order of Ledgers, Transactions and
// Operations.
//
// Operations within the stellar network have a total order, expressed by three
// pieces of information:  the ledger sequence the operation was validated in,
// the order which the operation's containing transaction was applied in
// that ledger, and the index of the operation within that parent transaction.
//
// We express this order by packing those three pieces of information into a
// single signed 64-bit number (we used a signed number for SQL compatibility).
//
// The follow diagram shows this format:
//
//    0                   1                   2                   3
//    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//   |                    Ledger Sequence Number                     |
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//   |     Transaction Application Order     |       Op Index        |
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
// By component:
//
// Ledger Sequence: 32-bits
//
//   A complete ledger sequence number in which the operation was validated.
//
//   Expressed in network byte order.
//
// Transaction Application Order: 20-bits
//
//   The order that the transaction was applied within the ledger it was
//   validated.  Accommodates up to 1,048,575 transactions in a single ledger.
//
//   Expressed in network byte order.
//
// Operation Index: 10-bits
//
//   The index of the operation within its parent transaction. Accommodates up
//   to 4095 operations per transaction.
//
//   Expressed in network byte order.
//
//
// Note: API Clients should not be interpreting this value.  We will use it
// as an opaque paging token that clients can parrot back to us after having read
// it within a resource to page from the represented position in time.
//
// Note: This does not uniquely identify an object.  Given a ledger, it will
// share its id with its first transaction and the first operation of that
// transaction as well.  Given that this ID is only meant for ordering within a
// single type of object, the sharing of ids across object types seems
// acceptable.
//
type TotalOrderId struct {
	LedgerSequence   int32
	TransactionOrder int32
	OperationOrder   int32
}

const (
	TotalOrderLedgerMask      = (1 << 32) - 1
	TotalOrderTransactionMask = (1 << 20) - 1
	TotalOrderOperationMask   = (1 << 12) - 1

	TotalOrderLedgerShift      = 32
	TotalOrderTransactionShift = 12
	TotalOrderOperationShift   = 0
)

func (id TotalOrderId) ToInt64() (result int64) {

	if id.LedgerSequence < 0 {
		panic("invalid ledger sequence")
	}

	if id.TransactionOrder > TotalOrderTransactionMask {
		panic("transaction order overflow")
	}

	if id.OperationOrder > TotalOrderOperationMask {
		panic("operation order overflow")
	}

	result = result | ((int64(id.LedgerSequence) & TotalOrderLedgerMask) << TotalOrderLedgerShift)
	result = result | ((int64(id.TransactionOrder) & TotalOrderTransactionMask) << TotalOrderTransactionShift)
	result = result | ((int64(id.OperationOrder) & TotalOrderOperationMask) << TotalOrderOperationShift)
	return
}

func ParseTotalOrderId(id int64) (result TotalOrderId) {
	result.LedgerSequence = int32((id >> TotalOrderLedgerShift) & TotalOrderLedgerMask)
	result.TransactionOrder = int32((id >> TotalOrderTransactionShift) & TotalOrderTransactionMask)
	result.OperationOrder = int32((id >> TotalOrderOperationShift) & TotalOrderOperationMask)

	return
}