pppfilter.cc

Go to the documentation of this file.
00001 ///
00002 /// \file       pppfilter.cc
00003 ///             Data filter class, to morph PPP data into something that
00004 ///             the Blackberry / Rogers / ISP can handle.
00005 ///             This logic is based partly on XmBlackBerry's
00006 ///             gprs_protocol_fix.c program.
00007 ///
00008 
00009 /*
00010     Copyright (C) 2008-2012, Net Direct Inc. (http://www.netdirect.ca/)
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00020 
00021     See the GNU General Public License in the COPYING file at the
00022     root directory of this project for more details.
00023 */
00024 
00025 #include "pppfilter.h"
00026 #include <string.h>
00027 
00028 namespace Barry {
00029 
00030 //////////////////////////////////////////////////////////////////////////////
00031 // PppFilter class
00032 
00033 PppFilter::PppFilter()
00034         : m_ppp_mode(false)
00035         , m_last(0x7e)
00036 {
00037 }
00038 
00039 //
00040 // Filter
00041 //
00042 /// Copy PPP data from src to dest, creating needed space in dest,
00043 /// and inserting missing 0x7e characters wherever they are detected.
00044 /// Starts writing at the start of the dest buffer + destoffset.
00045 ///
00046 void PppFilter::Filter(Data &dest, const Data &src, unsigned int destoffset)
00047 {
00048         const unsigned char *b = src.GetData(), *e = src.GetData() + src.GetSize();
00049         size_t needed = src.GetSize() / 2 * 3 + 4 + destoffset; // worst case
00050         unsigned char *buf = dest.GetBuffer(needed) + destoffset;
00051         unsigned char *put = buf;
00052 
00053         while( b != e ) {
00054                 // if last character was 0x7e, then next one must be,
00055                 // or else we insert it ourselves
00056                 if( m_last == 0x7e ) {
00057                         m_last = 0;
00058                         if( *b != 0x7e )
00059                                 *put++ = 0x7e;
00060                         else
00061                                 *put++ = *b++;
00062                 }
00063 
00064                 // copy all non-0x7e chars verbatim
00065                 while( b != e && *b != 0x7e ) {
00066                         *put++ = *b++;
00067                 }
00068 
00069                 if( b != e ) {  // if b!=e then *b == 0x7e and must keep going
00070                         *put++ = *b++;
00071                         m_last = 0x7e;
00072                 }
00073         }
00074 
00075         dest.ReleaseBuffer(put - buf + destoffset);
00076 }
00077 
00078 //
00079 // Write
00080 //
00081 /// If PPP mode has not been detected, just return the data buffer.
00082 /// If in PPP mode, then filter data into internal write buffer,
00083 /// inserting any missing 0x7e characters and return reference
00084 /// to internal write buffer.
00085 ///
00086 const Data& PppFilter::Write(const Data &data)
00087 {
00088         if( data.GetSize() == 0 )
00089                 return data;    // nothing to do
00090 
00091         const unsigned char *b = data.GetData();
00092 
00093         if( !m_ppp_mode ) {
00094                 if( *b == 0x7e ) {
00095                         m_ppp_mode = true;
00096                         // fall through
00097                 }
00098                 else {
00099                         // not in ppp mode yet, so just pass the buffer
00100                         // straight back to the caller
00101                         return data;
00102                 }
00103         }
00104 
00105         Filter(m_writeBuf, data, 0);
00106         return m_writeBuf;
00107 }
00108 
00109 //
00110 // Write (with prepend)
00111 //
00112 /// Same as Write(data), but makes sure that prepend bytes are available
00113 /// at the beginning of the returned buffer.
00114 /// If not in PPP mode, the extra bytes are still provided.
00115 ///
00116 Data& PppFilter::Write(const Data &data, unsigned int prepend)
00117 {
00118         const unsigned char *b = data.GetData(), *e = data.GetData() + data.GetSize();
00119 
00120         if( !m_ppp_mode ) {
00121                 if( b != e && *b == 0x7e ) {
00122                         m_ppp_mode = true;
00123                         // fall through
00124                 }
00125                 else {
00126                         // make space, copy, return
00127                         unsigned int size = data.GetSize() + prepend;
00128                         unsigned char *buf = m_writeBuf.GetBuffer(size);
00129                         memcpy(&buf[prepend], data.GetData(), data.GetSize());
00130                         m_writeBuf.ReleaseBuffer(size);
00131                         return m_writeBuf;
00132                 }
00133         }
00134 
00135         Filter(m_writeBuf, data, prepend);
00136         return m_writeBuf;
00137 }
00138 
00139 } // namespace Barry
00140