laforge
/
openbts-osmo
Archived
1
0
Fork 0
This repository has been archived on 2022-03-30. You can view files and clone it, but cannot push or open issues or pull requests.
openbts-osmo/public-trunk/GSM/GSML3NonCallSSElements.cpp

215 lines
5.5 KiB
C++

/**@file Elements for call independent Supplementary Service Control, GSM 04.80 3. */
/*
* Copyright 2008, 2009, 2010 Free Software Foundation, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "GSML3NonCallSSElements.h"
#include <Logger.h>
using namespace std;
using namespace GSM;
void L3NonCallSSElementOctetLength::writeV( L3Frame& dest, size_t &wp ) const
{
dest.writeField(wp,mValue,8);
}
void L3NonCallSSElementOctetLength::parseV( const L3Frame& src, size_t &rp)
{
mValue = src.readField(rp, 8);
setValue();
}
size_t L3NonCallSSElementUndefLength::lengthV() const
{
size_t size = sizeof(mValue);
uint64_t tmp = 0;
do
{
size--;
tmp = mValue>>(size*8);
} while ((tmp == 0) &&(size>0));
size++;
return size;
}
void L3NonCallSSElementUndefLength::writeV( L3Frame& dest, size_t &wp ) const
{
dest.writeField(wp,mValue,lengthV()*8);
}
void L3NonCallSSElementUndefLength::writeV( L3Frame& dest, size_t &wp, size_t numBits) const
{
dest.writeField(wp,mValue,numBits);
}
void L3NonCallSSElementUndefLength::parseV( const L3Frame& src, size_t &rp, size_t numOctets)
{
mValue = src.readField(rp, numOctets*8);
}
void L3NonCallSSOperationCode::text(ostream& os) const
{
switch (mOperationCode){
case ProcessUnstructuredSSRequest:
os << "ProcessUnstructuredSSRequest"; break;
case UnstructuredSSRequest:
os << "UnstructuredSSRequest"; break;
case UnstructuredSSNotify:
os << "UnstructuredSSNotify"; break;
}
}
size_t L3NonCallSSLengthField::lengthV() const
{
size_t length = 0;
if (mValue <= 0x7f) length = 1;
else
{
uint64_t tmp = mValue;
do
{
length++;
tmp>>=8;
} while(tmp!=0);
length++;
}
return length;
}
void L3NonCallSSLengthField::writeV( L3Frame& dest, size_t &wp ) const
{
if (mValue <= 0x7f) { dest.writeField(wp,mValue,8); }
else
{
uint64_t tmp = mValue;
size_t numOctets = 0;
do
{
numOctets++;
tmp>>=8;
} while(tmp!=0);
dest.writeField(wp,numOctets|0x80,8);
dest.writeField(wp,mValue,numOctets*8);
}
}
void L3NonCallSSLengthField::parseV( const L3Frame& source, size_t &rp)
{
uint64_t tmp = source.readField(rp, 8);
if ((tmp>>7)==0) mValue = tmp;
else mValue = source.readField(rp, (tmp&0x7f)*8);
}
size_t L3NonCallSSParameters::length()
{
unsigned numChar = strlen(mData);
unsigned ussdStringLength = (numChar*7)/8;
if ((numChar*7)%8!=0) ussdStringLength +=1;
mDataLength.setValue(ussdStringLength);
unsigned sequenceLength = mDataLength.value()+mDataLength.lengthV()+4;
if (mHaveAlertingPattern) sequenceLength+=0x3;
mSequenceLength.setValue(sequenceLength);
return mSequenceLength.value()+mSequenceLength.lengthV()+1;
}
void L3NonCallSSParameters::parseV(const L3Frame& src, size_t& rp)
{
rp+=8;
mSequenceLength.parseV(src, rp);
rp+=16;
mDataCodingScheme = src.readField(rp,8);
rp+=8;
mDataLength.parseV(src, rp);
unsigned numChar = mDataLength.value()*8/7;
BitVector chars(src.tail(rp));
chars.LSB8MSB();
size_t crp=0;
for (int i=0; i<numChar; i++)
{
char gsm = chars.readFieldReversed(crp,7);
mData[i] = decodeGSMChar(gsm);
}
mData[numChar]='\0';
if (crp%8) crp += 8 - crp%8;
rp += crp;
if ((mSequenceLength.value()-0x4-mDataLength.lengthV()-mDataLength.value())!=0)
if(src.readField(rp,8)==0x4)
{
rp+=8;
mAlertingPattern = src.readField(rp,8);
mHaveAlertingPattern = true;
}
}
void L3NonCallSSParameters::write(L3Frame& dest, size_t& wp)
{
dest.writeField(wp,0x30,8); //Sequence Tag GSM 04.80 3.6.5.
unsigned numChar = strlen(mData);
unsigned ussdStringLength = (numChar*7)/8;
if ((numChar*7)%8!=0) ussdStringLength +=1;
mDataLength.setValue(ussdStringLength);
unsigned sequenceLength = mDataLength.value()+mDataLength.lengthV()+4;
if (mHaveAlertingPattern) sequenceLength+=0x3;
mSequenceLength.setValue(sequenceLength);
mSequenceLength.writeV(dest, wp); //Sequence Length
dest.writeField(wp,0x4,8); // ANS1 Octet String Tag
dest.writeField(wp,0x1,8); // String Length
dest.writeField(wp,mDataCodingScheme,8); // DataCodingScheme
dest.writeField(wp,0x4,8); // ANS1 Octet String Tag
mDataLength.writeV(dest, wp); // String Length
//USSD String
BitVector chars = dest.tail(wp);
chars.zero();
for (int i=0; i<numChar; i++) {
char gsm = encodeGSMChar(mData[i]);
dest.writeFieldReversed(wp,gsm,7);
}
chars.LSB8MSB();
if (mHaveAlertingPattern)
{
dest.writeField(wp,0x4,8); // ANS1 Octet String Tag
dest.writeField(wp,0x1,8); // String Length
dest.writeField(wp,mAlertingPattern,8); // Alerting Pattern
}
}
void L3NonCallSSParameters::text(ostream& os) const
{
os << " DataCodingScheme = " << hex << "0x" << mDataCodingScheme << dec;
os << " Data = " << mData;
if (mHaveAlertingPattern) os << " AlertingPattern = " << mAlertingPattern;
}