// ----------------------------------- void OggVorbisSubStream::procHeaders(Channel *ch) { unsigned int packPtr=0; for(int i=0; i<pack.numPackets; i++) { MemoryStream vin(&pack.body[packPtr],pack.packetSizes[i]); packPtr += pack.packetSizes[i]; char id[8]; vin.read(id,7); id[7]=0; switch (id[0]) { case 1: // ident LOG_CHANNEL("OGG Vorbis Header: Ident (%d bytes)",vin.len); readIdent(vin,ch->info); break; case 3: // comment { LOG_CHANNEL("OGG Vorbis Header: Comment (%d bytes)",vin.len); ChanInfo newInfo = ch->info; readComment(vin,newInfo); ch->updateInfo(newInfo); } break; case 5: // setup LOG_CHANNEL("OGG Vorbis Header: Setup (%d bytes)",vin.len); //readSetup(vin); break; default: throw StreamException("Unknown Vorbis packet header type"); break; } } }
// ----------------------------------- ASFInfo parseASFHeader(Stream & in) { ASFInfo asf; try { int numHeaders = in.readLong(); in.readChar(); in.readChar(); LOG_CHANNEL("ASF Headers: %d", numHeaders); for (int i = 0; i < numHeaders; i++) { ASFObject obj; unsigned int l = obj.readHead(in); obj.readData(in, l); MemoryStream data(obj.data, obj.lenLo); switch (obj.type) { case ASFObject::T_FILE_PROP: { data.skip(32); unsigned int dpLo = data.readLong(); unsigned int dpHi = data.readLong(); data.skip(24); data.readLong(); //data.writeLong(1); // flags = broadcast, not seekable int min = data.readLong(); int max = data.readLong(); int br = data.readLong(); if (min != max) throw StreamException("ASF packetsizes (min/max) must match"); asf.packetSize = max; asf.bitrate = br; asf.numPackets = dpLo; break; } case ASFObject::T_STREAM_BITRATE: { int cnt = data.readShort(); for (int i = 0; i < cnt; i++) { unsigned int id = data.readShort(); int bitrate = data.readLong(); if (id < ASFInfo::MAX_STREAMS) asf.streams[id].bitrate = bitrate; } break; } case ASFObject::T_STREAM_PROP: { ASFStream s; s.read(data); asf.streams[s.id].id = s.id; asf.streams[s.id].type = s.type; break; } } } } catch (StreamException &e) { LOG_ERROR("ASF: %s", e.msg); } return asf; }
// ------------------------------------------ int PCPStream::procAtom(AtomStream &atom, ID4 id, int numc, int dlen, BroadcastState &bcs) { int r = 0; ChanHit hit; int rBan = 0; if (id == PCP_CHAN) { readChanAtoms(atom, numc, bcs); } else if (id == PCP_ROOT) { if (servMgr->isRoot) throw StreamException("Unauthorized root message"); else readRootAtoms(atom, numc, bcs); } else if (id == PCP_HOST) { readHostAtoms(atom, numc, bcs, hit); Channel *ch = chanMgr->findChannelByID(hit.chanID); if (ch && (ch->isBroadcasting() || servMgr->vpDebug)) { if (servMgr->autoPort0Kick && (hit.numHops == 1) && (hit.firewalled || (!hit.relay && !hit.numRelays))) { char tmp[32]; hit.host.IPtoStr(tmp); LOG_DEBUG("host that can't relay is disconnect: %s", tmp); rBan = PCP_ERROR_BANNED; } if (servMgr->allowOnlyVP && (hit.numHops == 1) && !hit.version_vp) { char tmp[32]; hit.host.IPtoStr(tmp); LOG_DEBUG("host that is not VP is disconnect: %s", tmp); rBan = PCP_ERROR_BANNED; } } } else if ((id == PCP_MESG_ASCII) || (id == PCP_MESG)) // PCP_MESG_ASCII to be depreciated { String msg; atom.readString(msg.data, sizeof(msg.data), dlen); LOG_DEBUG("PCP got text: %s", msg.cstr()); } else if (id == PCP_BCST) { r = readBroadcastAtoms(atom, numc, bcs); } else if (id == PCP_HELO) { atom.skip(numc, dlen); atom.writeParent(PCP_OLEH, 1); atom.writeBytes(PCP_HELO_SESSIONID, servMgr->sessionID.id, 16); } else if (id == PCP_PUSH) { readPushAtoms(atom, numc, bcs); } else if (id == PCP_OK) { atom.readInt(); } else if (id == PCP_QUIT) { r = atom.readInt(); if (!r) r = PCP_ERROR_QUIT; } else if (id == PCP_ATOM) { for (int i = 0; i < numc; i++) { int nc, nd; ID4 aid = atom.read(nc, nd); int ar = procAtom(atom, aid, nc, nd, bcs); if (ar) r = ar; } } else { LOG_CHANNEL("PCP skip: %s", id.getString().str()); atom.skip(numc, dlen); } if (!r) r = rBan; return r; }
// ------------------------------------------ void PCPStream::readPktAtoms(Channel *ch, AtomStream &atom, int numc, BroadcastState &bcs) { ChanPacket pack; ID4 type; for (int i = 0; i < numc; i++) { int c, d; ID4 id = atom.read(c, d); if (id == PCP_CHAN_PKT_TYPE) { type = atom.readID4(); if (type == PCP_CHAN_PKT_HEAD) pack.type = ChanPacket::T_HEAD; else if (type == PCP_CHAN_PKT_DATA) pack.type = ChanPacket::T_DATA; else pack.type = ChanPacket::T_UNKNOWN; } else if (id == PCP_CHAN_PKT_POS) { pack.pos = atom.readInt(); } else if (id == PCP_CHAN_PKT_DATA) { pack.len = d; atom.readBytes(pack.data, pack.len); } else { LOG_DEBUG("PCP skip: %s,%d,%d", id.getString().str(), c, d); atom.skip(c, d); } } if (ch) { int diff = pack.pos - ch->streamPos; if (diff) { LOG_DEBUG("PCP skipping %s%8d (%10d -> %10d) count=%2d", (diff > 0) ? "+" : "", diff, ch->streamPos, pack.pos, ch->skipCount); if (ch->lastSkipTime + 120 < sys->getTime()) { ch->skipCount = 0; } ch->lastSkipTime = sys->getTime(); ch->skipCount++; //JP-EX pack.skip = true; } if (servMgr->autoBumpSkipCount) //JP-EX { if ((ch->skipCount > servMgr->autoBumpSkipCount) && !(servMgr->disableAutoBumpIfDirect && ch->sourceHost.tracker)) //JP-MOD { LOG_DEBUG("Auto bump"); ch->bump = true; } } if (pack.type == ChanPacket::T_HEAD) { LOG_DEBUG("New head packet at %d", pack.pos); bool renewhead; if (servMgr->keepDownstreams) renewhead = (memcmp(ch->headPack.data, pack.data, pack.len) != 0); else renewhead = true; /* // check for stream restart if (pack.pos == 0) { LOG_CHANNEL("PCP resetting stream"); ch->streamIndex++; ch->rawData.init(); } */ if (renewhead || ch->lastStopTime + 30 < sys->getTime()) { // check for stream restart if (pack.pos == 0) { LOG_CHANNEL("PCP resetting stream"); ch->streamIndex++; ch->rawData.init(); } ch->headPack = pack; ch->rawData.writePacket(pack, true); ch->streamPos = pack.pos + pack.len; } } else if (pack.type == ChanPacket::T_DATA) { ch->rawData.writePacket(pack, true); ch->streamPos = pack.pos + pack.len; } } // update this parent packet stream position if ((pack.pos) && (!bcs.streamPos || (pack.pos < bcs.streamPos))) bcs.streamPos = pack.pos; }
// ------------------------------------------ int OGGStream::readPacket(Stream &in,Channel *ch) { OggPage ogg; ChanPacket pack; ogg.read(in); if (ogg.isBOS()) { if (!vorbis.needHeader() && !theora.needHeader()) { ch->headPack.len = 0; } if (ogg.detectVorbis()) vorbis.bos(ogg.getSerialNo()); if (ogg.detectTheora()) theora.bos(ogg.getSerialNo()); } if (ogg.isEOS()) { if (ogg.getSerialNo() == vorbis.serialNo) { LOG_CHANNEL("Vorbis stream: EOS"); vorbis.eos(); } if (ogg.getSerialNo() == theora.serialNo) { LOG_CHANNEL("Theora stream: EOS"); theora.eos(); } } if (vorbis.needHeader() || theora.needHeader()) { if (ogg.getSerialNo() == vorbis.serialNo) vorbis.readHeader(ch,ogg); else if (ogg.getSerialNo() == theora.serialNo) theora.readHeader(ch,ogg); else throw StreamException("Bad OGG serial no."); if (!vorbis.needHeader() && !theora.needHeader()) { ch->info.bitrate = 0; if (vorbis.isActive()) ch->info.bitrate += vorbis.bitrate; if (theora.isActive()) { ch->info.bitrate += theora.bitrate; ch->info.contentType = ChanInfo::T_OGM; } ch->headPack.type = ChanPacket::T_HEAD; ch->headPack.pos = ch->streamPos; ch->startTime = sys->getDTime(); ch->streamPos += ch->headPack.len; ch->newPacket(ch->headPack); LOG_CHANNEL("Got %d bytes of headers",ch->headPack.len); } }else { pack.init(ChanPacket::T_DATA,ogg.data,ogg.headLen+ogg.bodyLen,ch->streamPos); ch->newPacket(pack); ch->streamPos+=pack.len; if (theora.isActive()) { if (ogg.getSerialNo() == theora.serialNo) { ch->sleepUntil(theora.getTime(ogg)); } }else if (vorbis.isActive()) { if (ogg.getSerialNo() == vorbis.serialNo) { ch->sleepUntil(vorbis.getTime(ogg)); } } } return 0; }