Beispiel #1
0
/* format a string into an ei_x_buff, except the version token */
static int eiformat(const char** fmt, union arg** args, ei_x_buff* x)
{
    const char* p = *fmt;
    int res;
    ei_x_buff x2;

    while (isspace((int)*p))
	++p;
    switch (*p) {
    case '~':
	res = pformat(&p, args, x);
	break;
    case '[':
	res = ei_x_new(&x2);
	if (res >= 0)
	    res = plist(&p, args, &x2, 0);
	if (res > 0)
	    res = ei_x_encode_list_header(x, res);
	if (res >= 0)
	    res = ei_x_append(x, &x2);
	ei_x_free(&x2);
	break;
    case '{':
	res = ei_x_new(&x2);
	if (res >= 0)
	    res = ptuple(&p, args, &x2, 0);
	if (res >= 0)
	    res = ei_x_encode_tuple_header(x, res);
	if (res >= 0)
	    res = ei_x_append(x, &x2);
	ei_x_free(&x2);
	break;
    case '"':
	res = pstring(&p, x);
	break;
    case '\'':
	res = pquotedatom(&p, x);
	break;
    default:
	if (isdigit((int)*p))
	    res = pdigit(&p, x);
	else if ((*p == '-' || *p == '+') && isdigit((int)*(p+1)))
	    res = pdigit(&p, x);
	else if (islower((int)*p))
	    res = patom(&p, x);
	else
	    res = -1;
	break;
	/*
	Variables
	*/
    }
    *fmt = p;
    return res;
}
Beispiel #2
0
// ------------------------------------------
int PCPStream::readBroadcastAtoms(AtomStream &atom, int numc, BroadcastState &bcs) {
    ChanPacket pack;
    //int ttl=0;
    int ver = 0;
    int ver_vp = 0;
    GnuID fromID, destID;
    int r = 0;
    char ver_ex_prefix[2];
    int ver_ex_number = 0;

    fromID.clear();
    destID.clear();

    bcs.initPacketSettings();

    MemoryStream pmem(pack.data, sizeof(pack.data));
    AtomStream patom(pmem);

    patom.writeParent(PCP_BCST, numc);

    for (int i = 0; i < numc; i++) {
        int c, d;
        ID4 id = atom.read(c, d);

        if (id == PCP_BCST_TTL) {
            bcs.ttl = atom.readChar() - 1;
            patom.writeChar(id, bcs.ttl);
        } else if (id == PCP_BCST_HOPS) {
            bcs.numHops = atom.readChar() + 1;
            patom.writeChar(id, bcs.numHops);

        } else if (id == PCP_BCST_FROM) {
            atom.readBytes(fromID.id, 16);
            patom.writeBytes(id, fromID.id, 16);

            routeList.add(fromID);
        } else if (id == PCP_BCST_GROUP) {
            bcs.group = atom.readChar();
            patom.writeChar(id, bcs.group);
        } else if (id == PCP_BCST_DEST) {
            atom.readBytes(destID.id, 16);
            patom.writeBytes(id, destID.id, 16);
            bcs.forMe = destID.isSame(servMgr->sessionID);

            char idstr1[64];
            char idstr2[64];

            destID.toStr(idstr1);
            servMgr->sessionID.toStr(idstr2);

        } else if (id == PCP_BCST_CHANID) {
            atom.readBytes(bcs.chanID.id, 16);
            patom.writeBytes(id, bcs.chanID.id, 16);
        } else if (id == PCP_BCST_VERSION) {
            ver = atom.readInt();
            patom.writeInt(id, ver);
        } else if (id == PCP_BCST_VERSION_VP) {
            ver_vp = atom.readInt();
            patom.writeInt(id, ver_vp);
        } else if (id == PCP_BCST_VERSION_EX_PREFIX) {
            atom.readBytes(ver_ex_prefix, 2);
            patom.writeBytes(id, ver_ex_prefix, 2);
        } else if (id == PCP_BCST_VERSION_EX_NUMBER) {
            ver_ex_number = atom.readShort();
            patom.writeShort(id, ver_ex_number);
        } else if (id == PCP_HOST) {
            ChanHit hit;
            readHostAtoms(atom, c, bcs, hit, false);
            Servent *sv = servMgr->findServentByServentID(bcs.servent_id);
            if (hit.uphost.ip == 0) {
//				LOG_DEBUG("bcs servent_id = %d", bcs.servent_id);
                if (bcs.numHops == 1) {
                    hit.uphost.ip = servMgr->serverHost.ip;
                    hit.uphost.port = servMgr->serverHost.port;
                    hit.uphostHops = 1;
                } else {
                    //Servent *sv = servMgr->findServentByServentID(bcs.servent_id);
                    if (sv) {
                        hit.uphost.ip = sv->getHost().ip;
                        hit.uphost.port = sv->waitPort;
                        hit.uphostHops = bcs.numHops - 1;
                    }
                }
            }
            if (sv &&
                    ((hit.numHops == 1 && (hit.rhost[0].ip == sv->getHost().ip
                            && hit.uphost.ip == servMgr->serverHost.ip && hit.uphost.port == servMgr->serverHost.port)
                            || (hit.rhost[1].localIP() && hit.rhost[1].ip == sv->getHost().ip))
                            || (hit.numHops != 1 && chanMgr->findParentHit(hit)))) {
                int oldPos = pmem.pos;
                hit.writeAtoms(patom, hit.chanID);
                pmem.pos = oldPos;
                r = readAtom(patom, bcs);
            } else {
                char tmp[80], tmp2[80], tmp3[80];
                memset(tmp, 0, 80);
                memset(tmp2, 0, 80);
                memset(tmp3, 0, 80);
                hit.uphost.toStr(tmp);
                hit.host.toStr(tmp2);
                if (sv)
                    sv->getHost().toStr(tmp3);
                LOG_DEBUG("### Invalid bcst: hops=%d, l/r = %d/%d, ver=%d(VP%04d), ttl=%d",
                        bcs.numHops, hit.numListeners, hit.numRelays, ver, ver_vp, bcs.ttl);
                LOG_DEBUG("### %s <- %s <- sv(%s)",
                        tmp2, tmp, tmp3);
                bcs.ttl = 0;
            }
        } else {
            // copy and process atoms
            int oldPos = pmem.pos;
            patom.writeAtoms(id, atom.io, c, d);
            pmem.pos = oldPos;
            r = readAtom(patom, bcs);
        }
    }

    char fromStr[64];
    fromStr[0] = 0;
    if (fromID.isSet())
        fromID.toStr(fromStr);
    char destStr[64];
    destStr[0] = 0;
    if (destID.isSet())
        destID.toStr(destStr);
    char tmp[64];
    bcs.chanID.toStr(tmp);

    // Broadcast flood
    if (servMgr->lastPCPFromID.isSame(fromID)
            && time(NULL) - servMgr->lastPCPBcstTime < 3) {
        memcpy(servMgr->lastPCPFromID.id, fromID.id, 16);
        servMgr->lastPCPBcstTime = time(NULL);
        LOG_DEBUG("PCP bcst reject: group=%d, hops=%d, ver=%d(%c%c%04d), from=%s, dest=%s ttl=%d",
                bcs.group, bcs.numHops, ver, ver_ex_prefix[0], ver_ex_prefix[1], ver_ex_number, fromStr, destStr, bcs.ttl);

        return r;
    }
    memcpy(servMgr->lastPCPFromID.id, fromID.id, 16);
    servMgr->lastPCPBcstTime = time(NULL);

//	LOG_DEBUG(tmp);

    if (ver_ex_number) {
        LOG_DEBUG("PCP bcst: group=%d, hops=%d, ver=%d(%c%c%04d), from=%s, dest=%s ttl=%d",
                bcs.group, bcs.numHops, ver, ver_ex_prefix[0], ver_ex_prefix[1], ver_ex_number, fromStr, destStr, bcs.ttl);
    } else if (ver_vp) {
        LOG_DEBUG("PCP bcst: group=%d, hops=%d, ver=%d(VP%04d), from=%s, dest=%s ttl=%d", bcs.group, bcs.numHops, ver, ver_vp, fromStr, destStr, bcs.ttl);
    } else {
        LOG_DEBUG("PCP bcst: group=%d, hops=%d, ver=%d, from=%s, dest=%s ttl=%d", bcs.group, bcs.numHops, ver, fromStr, destStr, bcs.ttl);
    }

    if (fromID.isSet()) if (fromID.isSame(servMgr->sessionID)) {
        LOG_ERROR("BCST loopback");
        return PCP_ERROR_BCST + PCP_ERROR_LOOPBACK;
    }

    // broadcast back out if ttl > 0
    if ((bcs.ttl > 0) && (!bcs.forMe)) {
        pack.len = pmem.pos;
        pack.type = ChanPacket::T_PCP;

        if (bcs.group & (/*PCP_BCST_GROUP_ROOT|*/PCP_BCST_GROUP_TRACKERS | PCP_BCST_GROUP_RELAYS)) {
            pack.priority = 11 - bcs.numHops;
            chanMgr->broadcastPacketUp(pack, bcs.chanID, remoteID, destID);
        }

        if (bcs.group & (/*PCP_BCST_GROUP_ROOT|*/PCP_BCST_GROUP_TRACKERS | PCP_BCST_GROUP_RELAYS)) {
            servMgr->broadcastPacket(pack, bcs.chanID, remoteID, destID, Servent::T_COUT);
        }

        if (bcs.group & (PCP_BCST_GROUP_RELAYS | PCP_BCST_GROUP_TRACKERS)) {
            servMgr->broadcastPacket(pack, bcs.chanID, remoteID, destID, Servent::T_CIN);
        }

        if (bcs.group & (PCP_BCST_GROUP_RELAYS)) {
            servMgr->broadcastPacket(pack, bcs.chanID, remoteID, destID, Servent::T_RELAY);
        }


        //		LOG_DEBUG("ttl=%d",ttl);

    } else {
        //		LOG_DEBUG("ttl=%d",ttl);
    }
    return r;
}
Beispiel #3
0
// ------------------------------------------
int PCPStream::readPacket(Stream & in, BroadcastState & bcs) {
    int error = PCP_ERROR_GENERAL;
    try {
        AtomStream atom(in);

        ChanPacket pack;
        MemoryStream mem(pack.data, sizeof(pack.data));
        AtomStream patom(mem);


        // send outward packets
        error = PCP_ERROR_WRITE;
        if (outData.numPending()) {
            outData.readPacket(pack);
            pack.writeRaw(in);
        }
        error = PCP_ERROR_GENERAL;

        if (outData.willSkip()) {
            error = PCP_ERROR_WRITE + PCP_ERROR_SKIP;
            throw StreamException("Send too slow");
        }


        error = PCP_ERROR_READ;
        // poll for new downward packet
        if (in.readReady()) {
            int numc, numd;
            ID4 id;

            id = atom.read(numc, numd);

            mem.rewind();
            pack.len = patom.writeAtoms(id, in, numc, numd);
            pack.type = ChanPacket::T_PCP;

            //inData.writePacket(pack);
            //}
            error = PCP_ERROR_GENERAL;

            // process downward packets
            //if (inData.numPending())
            //{
            //inData.readPacket(pack);

            mem.rewind();

            //int numc,numd;
            id = patom.read(numc, numd);

            error = PCPStream::procAtom(patom, id, numc, numd, bcs);

            if (error) {
                throw StreamException("PCP exception");
            }
        }

        error = 0;

    } catch (StreamException &e) {
        LOG_ERROR("PCP readPacket: %s (%d)", e.msg, error);
    }

    return error;
}