# 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-2011, 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