/** * dumper.cpp * This file is part of the YATE Project http://YATE.null.ro * * Yet Another Signalling Stack - implements the support for SS7, ISDN and PSTN * * Yet Another Telephony Engine - a fully featured software PBX and IVR * Copyright (C) 2004-2006 Null Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "yatesig.h" using namespace TelEngine; SignallingDumper::SignallingDumper(Type type) : m_type(type), m_output(0) { } SignallingDumper::~SignallingDumper() { terminate(); } void SignallingDumper::setStream(Stream* stream) { if (stream == m_output) return; Stream* tmp = m_output; m_output = stream; head(); delete tmp; } // Check if dumper is active bool SignallingDumper::active() const { return m_output && m_output->valid(); } // Close the output stream void SignallingDumper::terminate() { setStream(); } // Dump the actual data bool SignallingDumper::dump(void* buf, unsigned int len, bool sent, int link) { if (!(active() && buf && len)) return false; if (m_type == Raw) { int wr = m_output->writeData(buf,len); return (wr == (int)len); } else if (m_type == Hexa) { String str; str.hexify(buf,len); str = "0 " + str + "\n"; int wr = m_output->writeData(str); return (wr == (int)str.length()); } Time t; struct timeval tv; u_int32_t hdr[4]; t.toTimeval(&tv); hdr[0] = tv.tv_sec; hdr[1] = tv.tv_usec; hdr[2] = len; hdr[3] = len; DataBlock blk(hdr,sizeof(hdr)); DataBlock dat(buf,len,false); blk += dat; dat.clear(false); int wr = m_output->writeData(blk); return (wr == (int)blk.length()); } // Write whatever header the format needs void SignallingDumper::head() { if (!active()) return; if (m_type == Raw || m_type == Hexa) return; u_int32_t hdr[6]; hdr[0] = 0xa1b2c3d4; // libpcap magic // FIXME: handle big endian hdr[1] = 0x00040002; // version lo, hi hdr[2] = 0; // offset from GMT hdr[3] = 0; // timestamp accuracy hdr[4] = 65535; // rather arbitrary snaplen switch (m_type) { case Hdlc: hdr[5] = 0; break; case Mtp2: hdr[5] = 140; break; case Mtp3: hdr[5] = 141; break; case Sccp: hdr[5] = 142; break; default: // compiler, please shut up break; } m_output->writeData(hdr,sizeof(hdr)); } // Create a dumper SignallingDumper* SignallingDumper::create(DebugEnabler* dbg, const char* filename, Type type, bool create, bool append) { if (!filename) return 0; SignallingDumper* dumper = 0; File* f = new File; if (f->openPath(filename,true,false,create,append,true)) { dumper = new SignallingDumper(type); dumper->setStream(f); } else { Debug(dbg,DebugWarn,"Failed to create dumper '%s'",filename); delete f; } return dumper; } /* vi: set ts=8 sw=4 sts=4 noet: */