Esempio n. 1
0
void UDPSocket::open(unsigned short localPort)
{
	// create
	mSocketFD = socket(AF_INET,SOCK_DGRAM,0);
	if (mSocketFD<0) {
		perror("socket() failed");
		devassert(0);
		throw SocketError();
	}

	// pat added: This lets the socket be reused immediately, which is needed if OpenBTS crashes.
	int on = 1;
	setsockopt(mSocketFD, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));


	// bind
	struct sockaddr_in address;
	size_t length = sizeof(address);
	bzero(&address,length);
	address.sin_family = AF_INET;
	address.sin_addr.s_addr = INADDR_ANY;
	address.sin_port = htons(localPort);
	if (bind(mSocketFD,(struct sockaddr*)&address,length)<0) {
		char buf[100];
		sprintf(buf,"bind(port %d) failed",localPort);
		perror(buf);
		devassert(0);
		throw SocketError();
	}
}
Esempio n. 2
0
void UDDSocket::open(const char* localPath)
{
	// create
	mSocketFD = socket(AF_UNIX,SOCK_DGRAM,0);
	if (mSocketFD<0) {
		perror("socket() failed");
		devassert(0);
		throw SocketError();
	}

	// bind
	struct sockaddr_un address;
	size_t length = sizeof(address);
	bzero(&address,length);
	address.sun_family = AF_UNIX;
	strcpy(address.sun_path,localPath);
	unlink(localPath);
	if (bind(mSocketFD,(struct sockaddr*)&address,length)<0) {
		char buf[1100];
		sprintf(buf,"bind(path %s) failed",localPath);
		perror(buf);
		devassert(0);
		throw SocketError();
	}
}
Esempio n. 3
0
void SipTransaction::sendAuthFailMessage(int code, string rand, string gsmRejectCode)
{
	devassert(mstTranId);
	// The tran id is 0 for unregister messages.  If one of those gets this far it is a bug.
	if (! mstTranId) { return; }

	DialogChallengeMessage *dmsg = new DialogChallengeMessage(mstTranId, DialogState::dialogFail,code);
	dmsg->dmRand = rand;
	dmsg->dmRejectCause = atoi(gsmRejectCode.c_str());
	devassert(mstTranId);
	// The tran id is 0 for unregister messages.  If one of those gets this far it is a bug.
	if (mstTranId) { SipCallbacks::ttAddMessage(mstTranId,dmsg); }
}
Esempio n. 4
0
// For DCCH channels (FACCH, SACCH, SDCCH):
// This function calls virtual L2DL::l2dlWriteHighSide(L3Frame) which maps
// to L2LAPDm::l2dlWriteHighSide() which interprets the primitive, and then
// sends traffic data through sendUFrameUI(L3Frame) which creates an L2Frame
// and sends it through several irrelevant functions to L2LAPDm::writeL1
// which calls (SAPMux)mDownstream->SAPMux::writeHighSide(L2Frame),
// which does nothing but call mL1->writeHighSide(L2Frame), which is a pass-through
// except that the SapMux uses mDownStream which is copied from mL1, so there is a
// chance to redirect it.  But wouldn't that be an error?
// Anyway, L1Encoder::writeHighSide is usually overridden.
// For TCH, it goes to XCCHL1Encoder::writeHighSide() which processes
// the L2Frame primitive, then sends traffic data to TCHFACCHL1Encoder::sendFrame(),
// which just enqueues the frame - it does not block.
// A thread runs GSM::TCHFACCHL1EncoderRoutine() which
// calls TCHFACCHL1Encoder::dispatch() which is synchronized with the gBTS clock,
// unsynchronized with the queue, because it must send data no matter what.
// Eventually it encodes the data and
// calls (ARFCNManager*)mDownStream->writeHighSideTx(), which writes to the socket.
// 
// From here and below only SAPI0 and SAPI3 are used.
void L2SAPMux::sapWriteFromL3(const L3Frame& frame)
{
	LOG(DEBUG) <<LOGVAR(frame);
	SAPI_t sap = frame.getSAPI();
	if (!(sap == SAPI0 || sap == SAPI3 || sap == SAPI0Sacch || sap == SAPI3Sacch)) {
		devassert(0);
		sap = SAPI0;	// This is a bug fix to avoid a crash.
	}
	unsigned sapi = SAP2SAPI(sap);
	devassert(mL2[sapi]);
	if (!mL2[sapi]) { return; }	// Not initialized yet?  Should never happen.
	// On SACCH L3_UNIT_DATA frames block for 480ms.
	// L3_DATA frames could block for minutes.
	if (mL2[sapi]) mL2[sapi]->l2dlWriteHighSide(frame);
}
Esempio n. 5
0
void L2SAPMux::sapWriteFromL1(const L2Frame& frame)
{
	OBJLOG(DEBUG) << frame;
	unsigned sap;

	// (pat) Add switch to validate upstream primitives.  The upstream only generates a few primitives;
	// the rest are created in L2LAPDm.
	switch (frame.primitive()) {
		case L2_DATA:
			sap = frame.SAPI();	
			assert(sap == SAPI0 || sap == SAPI3);
			if (mL2[sap]) {
				mL2[sap]->l2dlWriteLowSide(frame);
			} else {
				LOG(WARNING) << "received DATA for unsupported"<<LOGVAR(sap);
			}
			return;
		case PH_CONNECT:
			// All this does is fully reset LAPDm; copy it out to every SAP.
			for (int s = 0; s <= 3; s++) {
				if (mL2[s]) mL2[s]->l2dlWriteLowSide(frame);	// Note: the frame may have the wrong SAP in it, but LAPDm doesnt care.
			}
			return;
		default:
			// If you get this assertion, make SURE you know what will happen upstream to that primitive.
			devassert(0);
			return;		// make g++ happy.
	}
}
Esempio n. 6
0
void PDCHL1Downlink::send1Frame(BitVector& frame,ChannelCodingType encoding, bool idle)
{
	if (!idle && gConfig.getBool("Control.GSMTAP.GPRS")) {
		// Send to GSMTAP.
		gWriteGSMTAP(ARFCN(),TN(),gBSNNext.FN(),
				frame2GsmTapType(frame),
				false,	// not SACCH
				false,	// this is a downlink
				frame);	// The data.
	}

	switch (encoding) {
	case ChannelCodingCS1:
		// Process the 184 bit (23 byte) frame, leave result in mI.
		//mchCS1Enc.encodeFrame41(frame,0);
		//transmit(gBSNNext,mchCS1Enc.mI,qCS1,0);
		mchEnc.encodeCS1(frame);
		transmit(gBSNNext,mchEnc.mI,qCS1,0);
		break;
	case ChannelCodingCS4:
		//std::cout << "WARNING: Using CS4\n";
		// This did not help the 3105/3101 errors:
		//mchCS4Enc.initCS4();	// DEBUG TEST!!  Didnt help.
		//mchCS4Enc.encodeCS4(frame);	// Result left in mI[].
		//transmit(gBSNNext,mchCS4Enc.mI,qCS4,0);
		mchEnc.encodeCS4(frame);	// Result left in mI[].
		transmit(gBSNNext,mchEnc.mI,qCS4,0);
		break;
	default:
		LOG(ERR) << "unrecognized GPRS channel coding " << (int)encoding;
		devassert(0);
	}
}
Esempio n. 7
0
void SipClientTrLayer::sctStart()
{
	LOG(DEBUG);
	ScopedLock lock(mstLock);
	// Must add to the tu map before sending the message because the reply can be fast enough to cause a race.
	gSipInterface.tuMapAdd(this);
	devassert(mstState == stInitializing);
	stWrite(&mstOutRequest);	// Send the initial message.
	mstState = stCallingOrTrying;
}
Esempio n. 8
0
void L2SAPMux::sapStart()
{
	LOG(DEBUG) <<descriptiveString();
	devassert(mL1);
	startl1();
	for (int s=0; s<4; s++) {
		// (pat) This starts sending LAPDm idle frames.
		if (mL2[s]) mL2[s]->l2dlOpen(descriptiveString());
	}
}
Esempio n. 9
0
void CBCHLogicalChannel::cbchOpen()
{
	if (mL1) mL1->l1init();		// (pat) L1FEC::l1init()
	sapStart(); // startl1();
	devassert(mSACCH);
	if (mSACCH) {
		mSACCH->sacchInit();
		mSACCH->sapStart();
	}
}
Esempio n. 10
0
void SipTransaction::sendAuthOKMessage(SipMessage *sipmsg)
{
	devassert(mstTranId);
	// The tran id is 0 for unregister messages.  If one of those gets this far it is a bug.
	if (! mstTranId) { return; }

	string imsi = sipmsg->msmTo.uriUsername(); // The To: and From: have the same value for a REGISTER message.
	// Validate the imsi:
	if (imsi.empty()) {
		LOG(ERR) << "can't find imsi to store kc";
		sendAuthFailMessage(400,"","");
		return;
	}
	if (0 == strncasecmp(imsi.c_str(),"imsi",4)) {
		// happiness
	} else if (0 == strncasecmp(imsi.c_str(),"tmsi",4)) {
		// TODO: In future the user name could be a TMSI.
		LOG(ERR) << "SIP REGISTER message with TMSI not supported, userid="<<imsi;
		sendAuthFailMessage(400,"","");
		return;
	} else {
		LOG(ERR) << "SIP REGISTER message with invalid IMSI:"<<imsi<<" Message:"<<sipmsg->msmContent;
		sendAuthFailMessage(400,"","");
		return;
	}

	DialogAuthMessage *dmsg = new DialogAuthMessage(mstTranId, DialogState::dialogActive,200);
	dmsg->dmPAssociatedUri = sipmsg->msmHeaders.paramFind("P-Associated-URI");	// case doesnt matter
	dmsg->dmPAssertedIdentity = sipmsg->msmHeaders.paramFind("P-Asserted-Identity");

	string authinfo = sipmsg->msmHeaders.paramFind("Authentication-Info");
	if (! authinfo.empty()) {
		SipParamList params;
		parseToParams(authinfo, params);
		dmsg->dmKc = params.paramFind("cnonce"); // This is the way SR passes the Kc.
	} else {
		// There will not be a cnonce if the Registrar does not know it.  Dont worry about it.
		//LOG(INFO) << "No Authenticate-Info header in SIP REGISTER response:"<<sipmsg->msmContent;
	}

	if (dmsg->dmKc.empty()) {
		dmsg->dmKc = sipmsg->msmHeaders.paramFind("P-GSM-Kc"); // This is the way Yate passes the Kc.
	}

	WATCHF("CNONCE: imsi=%s Kc=%s\n",imsi.c_str(),dmsg->dmKc.c_str());
	if (! dmsg->dmKc.empty()) {
		LOG(DEBUG) << "Storing Kc:"<<LOGVAR(imsi)<<LOGVAR(dmsg->dmKc.size());	// We dont put Kc itself in the log.
		//gTMSITable.putKc(imsi.c_str()+4, kc, pAssociatedUri, pAssertedIdentity);
	} else {
		LOG(NOTICE) << "No Kc in SIP REGISTER response:"<<sipmsg->msmContent;
	}

	//NewTransactionTable_ttAddMessage(mstTranId,dmsg);
	SipCallbacks::ttAddMessage(mstTranId,dmsg);
}
Esempio n. 11
0
// FIXME: It blocks until L2LAPDm::sendIdle returns.  That does not need to block.
// Other channels call it too, which is somewhat nonsensical; the l2open for other channels is empty.
// There is no close in L2 - the L1 encoder/decoder are closed individually when L2 sends a RELEASE/HARDRELEASE primitive.
void L2LogicalChannel::lcstart()
{
	LOG(DEBUG) <<this;
	devassert(mSACCH);
	if (mSACCH) mSACCH->sapStart();
	sapStart();
	mL3Out.clear();
	mT3101.set(T3101ms);
	mT3109.reset(gConfig.GSM.Timer.T3109);	// redundant with init in lcinit but cant be too careful.
	mT3111.reset(T3111ms);					// redundant with init in lcinit but cant be too careful.
}
Esempio n. 12
0
// This only gets called once.
// Looks like it never gets called SVG
// Outbound
void SipClientTrLayer::TLWriteLowSideV(SipMessage *request)
{
	LOG(DEBUG);
	ScopedLock lock(mstLock);
	// For an Outbound Transaction, there is only one request except for invite, which also sends an ACK.
	if (! mstOutRequest.msmReqMethod.empty()) { assert(request->isACK()); }
	mstOutRequest = *request;
	devassert(mstState == stInitializing);
	stWrite(request);
	mstState = stCallingOrTrying;
}
Esempio n. 13
0
unsigned short UDPSocket::port() const
{
	struct sockaddr_in name;
	socklen_t nameSize = sizeof(name);
	int retVal = getsockname(mSocketFD, (struct sockaddr*)&name, &nameSize);
	if (retVal==-1) {
		devassert(0);
		throw SocketError();
	}
	return ntohs(name.sin_port);
}
Esempio n. 14
0
BitVector *GprsDecoder::getResult()
{
	switch (getCS()) {
	case ChannelCodingCS4:
		return &mD_CS4;
	case ChannelCodingCS1:
		return &mD;
	default: devassert(0);	// Others not supported yet.
		return NULL;
	}
}
Esempio n. 15
0
int DatagramSocket::read(char* buffer)
{
	socklen_t temp_len = sizeof(mSource);
	int length = recvfrom(mSocketFD, (void*)buffer, MAX_UDP_LENGTH, 0,
	    (struct sockaddr*)&mSource,&temp_len);
	if ((length==-1) && (errno!=EAGAIN)) {
		perror("DatagramSocket::read() failed");
		devassert(0);
		throw SocketError();
	}
	return length;
}
Esempio n. 16
0
// Send the idle frame at specified Transceiver::SET_FILLER_FRAME)
// Do not call send1msgframe, because it would try to set MAC fields.
void PDCHL1Downlink::sendIdleFrame(RLCBSN_t bsn)
{
	RLCMsgPacketDownlinkDummyControlBlock *msg = new RLCMsgPacketDownlinkDummyControlBlock();
	devassert(msg->mUSF == 0);
	BitVector tobits(RLCBlockSizeInBits[ChannelCodingCS1]);
	msg->write(tobits);
	delete msg;
	//mchCS1Enc.encodeFrame41(tobits,0);
	//transmit(bsn,mchCS1Enc.mI,qCS1,Transceiver::SET_FILLER_FRAME);
	mchEnc.encodeCS1(tobits);
	transmit(bsn,mchEnc.mI,qCS1,Transceiver::SET_FILLER_FRAME);
}
Esempio n. 17
0
// Send the specified BitVector at the specified block time.
void PDCHL1Downlink::transmit(RLCBSN_t bsn, BitVector *mI, const int *qbits, int transceiverflags)
{
	parent()->debug_test();
	// Format the bits into the bursts.
	// GSM 05.03 4.1.5, 05.02 5.2.3
	// NO! Dont do a wait here.  The MAC serviceloop does this for all channels.
	// waitToSend();		// Don't get too far ahead of the clock.

	ARFCNManager *radio = getRadio();
	if (!radio) {
		// For some testing, we might not have a radio connected.
		// That's OK, as long as we know it.
		GLOG(INFO) << "XCCHL1Encoder with no radio, dumping frames";
		return;
	}

	int fn = bsn.FN();
	int tn = TN();

	for (int qi=0,B=0; B<4; B++) {
		Time nextWriteTime(fn,tn | transceiverflags);
		mchBurst.time(nextWriteTime);
		// Copy in the "encrypted" bits, GSM 05.03 4.1.5, 05.02 5.2.3.
		//OBJLOG(DEBUG) << "transmit mI["<<B<<"]=" << mI[B];
		mI[B].segment(0,57).copyToSegment(mchBurst,3);
		mI[B].segment(57,57).copyToSegment(mchBurst,88);
		mchBurst.Hl(qbits[qi++]);
		mchBurst.Hu(qbits[qi++]);
		// Send it to the radio.
		//OBJLOG(DEBUG) << "transmit mchBurst=" << mchBurst;
		if (gConfig.getBool("Control.GSMTAP.GPRS")) {
			// Send to GSMTAP.
			gWriteGSMTAP(ARFCN(),TN(),gBSNNext.FN(),
					TDMA_PDCH,
					false,	// not SACCH
					false,	// this is a downlink
					mchBurst,
					GSMTAP_TYPE_UM_BURST);
		}
#if FEC_DEBUG
		if (1) {
			// Try decoding the frame we just encoded to see if it is correct.
			devassert(mchBurst.size() == gSlotLen);
			RxBurst rxb(mchBurst);
			ChannelCodingType cc;
			decodeLowSide(rxb, B, debugDecoder, &cc);
		}
#endif
		radio->writeHighSideTx(mchBurst,"GPRS");
		fn++;	// This cannot overflow because it is within an RLC block.
	}
}
Esempio n. 18
0
// We dont really need to remember the LogicalChannel, but maybe we'll need it in the future.
void PDCHL1FEC::mchOpen(TCHFACCHLogicalChannel *wlogchan)
{
	// setGPRS has two affects: getTCH will consider the channel in-use;
	// and bursts start being delivered to us.
	// Note that the getTCH function normally doesnt even pay attention to whether
	// the channel is 'open' or not; it calls recyclable() that checks timers
	// and reuses the chan if they have expired.
	mchLogChan = wlogchan;
	devassert(mchLogChan->inUseByGPRS());
	mchOldFec = mchLogChan->debugGetL1();
	//mchReady = true;		// finally

}
Esempio n. 19
0
void SACCHLogicalChannel::writeToL1(const L2Frame& frame)
{
	// The SAP may or may not be present, depending on the channel type.
	OBJLOG(DEBUG) << frame;
	switch (frame.primitive()) {
		case L2_DATA:
			mL1->writeHighSide(frame);
			break;
		default:
			OBJLOG(ERR) << "unhandled primitive " << frame.primitive() << " in L2->L1";
			devassert(0);
	}
}
Esempio n. 20
0
void L3SupServRegisterMessage::writeBody( L3Frame &dest, size_t &wp ) const
{
	mFacility.writeTLV(0x1c,dest,wp);		// Facility IE is mandatory, but it is permitted to be empty.
	// The network to MS direction does not have a version indicator.
	devassert(haveVersionIndicator() == false);
	// However, we are going to write the message anyway in case of bugs
	// where messages are converted to L3Frame and back.
	if (haveVersionIndicator()) {
		mVersionIndicator.writeTLV(0x7f,dest,wp);
		//dest.writeField(wp,0x7F,8);		// The SS Version indicator IEI.
		//dest.writeField(wp,1,8);		// Extreme dopeyness - it is a one byte field with a length specified.
		//dest.writeField(wp,mVersionIndicator.mValue,8);
	}
}
Esempio n. 21
0
// There can be a max of two simultaneous MO-SMS.
// The CM Service Request to start a new MO-SMS during an existing one may arrive before the final ACK of the previous MO-SMS, as per GSM 4.11 5.4
// Therefore there are two MO-SMS possible: MMContext::TE_MOSMS1 is the old one and TE_MOSMS2 is the new one.
void startMOSMS(const GSM::L3MMMessage *l3msg, MMContext *mmchan)
{
	LOG(DEBUG) <<mmchan;
	//now we allocate below: TranEntry *tran = TranEntry::newMO(dcch, L3CMServiceType::ShortMessage);

	//MMContext *set = dcch->chanGetContext(true);
	RefCntPointer<TranEntry> prevMOSMS = mmchan->mmGetTran(MMContext::TE_MOSMS1);
	if (! prevMOSMS.self()) {
		// happiness.
		//set->setTran(MMContext::TE_MOSMS1,tran);
		//tran->teConnectChannel(dcch,TE_MOSMS1);
	} else {
		// Check for perfidy on the part of the MS: it cannot start a new MO-SMS unless the previous is nearly finished.
		//SmsState smsState = getCurrentSMSState();
		MachineBase *base = prevMOSMS->currentProcedure();
		bool badbunny = false;
		if (base) {	// This may happen if the MS is a bad bunny and sends two CM Sevice Requests effectively simultaneously.
			MOSMSMachine *smssm = dynamic_cast<typeof(smssm)>(base);
			if (! smssm || smssm->mSmsState != MoSmsWaitForAck) {
				badbunny = true;
			}
		} else {
			badbunny = true;
		}

		if (badbunny) {
			LOG(ERR) << "Received new MO-SMS before previous MO-SMS completed"<<LOGVAR2("MOSMS",prevMOSMS.self())<<l3msg;
			// Now what?  We've already got an SMS running...
			return;		// Just ignore it.
		}

		RefCntPointer<TranEntry> prevMOSMS2 = mmchan->mmGetTran(MMContext::TE_MOSMS2);
		if (prevMOSMS2.self()) {
			LOG(ERR) <<"Received third simultaneous MO-SMS, which is illegal:"<<LOGVAR2("MO-SMS1",prevMOSMS.self())<<LOGVAR2("MO-SMS2",prevMOSMS2.self());
			// Now what?  We could kill the oldest one or reject the new one.
			// Kill the oldest one, on the assumption that this indicates a bug in our code and that SMS is hung.
			prevMOSMS->teCancel(TermCause::Local(L3Cause::SMS_Error));	// Promotes TE_MOSMS2 to TE_MOSMS1
			devassert(mmchan->mmGetTran(MMContext::TE_MOSMS2) == NULL);
		}
		//mmchan->setTran(MMContext::TE_MOSMS2,tran);
		//tran->teConnectChannel(mmchan,MMContext::TE_MOSMS2);
	}
	TranEntry *tran = TranEntry::newMOSMS(mmchan);

	// Fire up an SMS state machine for this transaction.
	MOSMSMachine *mocp = new MOSMSMachine(tran);
	// The message is CMServiceRequest.
	tran->lockAndStart(mocp,(GSM::L3Message*)l3msg);
}
Esempio n. 22
0
void GprsEncoder::encodeCS4(const BitVector &src)
{
	//if (sFecDebug) GPRSLOG(1) <<"encodeCS4 src\n"<<src;
	src.copyToSegment(mD_CS4,0,53*8);
	//if (sFecDebug) GPRSLOG(1) <<"encodeCS4 mD_CS4\n"<<mD_CS4;
	// mC.zero();	// DEBUG TEST!!  Did not help.
	mD_CS4.fillField(53*8,0,7);		// zero out 7 spare bits.
	mD_CS4.LSB8MSB();	// Ignores the last incomplete byte of 7 zero bits.
	//if (sFecDebug) GPRSLOG(1) <<"mC before parity\n"<<mC;
	// Parity is computed on original D before doing the USF translation above.
	mBlockCoder_CS4.writeParityWord(mD_CS4,mP_CS4);
	// Note that usf has been moved to the first three bits by the byte swapping above,
	// so when we write the 12 bits of GPRSUSFEncoding for usf into mC, it will overwrite
	// the original 3 parity bits.
	int reverseUsf = mD_CS4.peekField(0,3);
	// mU overwrites the first 3 bits of mD within mC.
	mU_CS4.fillField(0,GPRS::GPRSUSFEncoding[reverseUsf],12);
	// Result is left in mC.
	devassert(mC.peekField(0,12) == (unsigned) GPRS::GPRSUSFEncoding[reverseUsf]);
	devassert(mC.peekField(433,7) == 0);	// unused bits not modified.
	//if (sFecDebug) GPRSLOG(1) <<"mC before interleave\n"<<mC;

	interleave41();	// Interleaves mC into mI.
}
Esempio n. 23
0
int DatagramSocket::read(char* buffer, unsigned timeout)
{
	fd_set fds;
	FD_ZERO(&fds);
	FD_SET(mSocketFD,&fds);
	struct timeval tv;
	tv.tv_sec = timeout/1000;
	tv.tv_usec = (timeout%1000)*1000;
	int sel = select(mSocketFD+1,&fds,NULL,NULL,&tv);
	if (sel<0) {
		perror("DatagramSocket::read() select() failed");
		devassert(0);
		throw SocketError();
	}
	if (sel==0) return -1;
	if (FD_ISSET(mSocketFD,&fds)) return read(buffer);
	return -1;
}
Esempio n. 24
0
void SACCHLogicalChannel::l2sendf(const L3Frame& frame)
{
	SAPI_t sap = frame.getSAPI();
	devassert(SAPIsSacch(sap));
	if (sap != SAPI3Sacch) { LOG(NOTICE) << "unexpected"<<LOGVAR(sap)<<" in "<<LOGVAR(frame); }
	LOG(INFO) <<channelDescription() <<LOGVAR(sap) <<LOGVAR(chtype()) <<" " <<frame;
	switch (frame.primitive()) {
		case L3_ESTABLISH_REQUEST:
			// Fall through.
		case L3_DATA:
		case L3_UNIT_DATA:
		case L3_RELEASE_REQUEST:
		case L3_HARDRELEASE_REQUEST:
			mL3In.write(new L3Frame(frame));
			return;
		default:
			assert(0);
	}
}
Esempio n. 25
0
// (pat) For data channels this is called by getTCH or getSDCCH.
// TODO: Go through all the getTCH/getSDCCH users and make sure they lcstart.
void L2LogicalChannel::lcinit()
{
	LOG(DEBUG) <<this;
	assert(mL1);
	if (mL1) mL1->l1init();		// (pat) L1FEC::l1init()
	devassert(mSACCH);
	if (mSACCH) mSACCH->sacchInit();
	// We set T3101 now so the channel will become recyclable if the caller does nothing with it;
	// the caller has this long to call lcstart before the channel goes back to the recyclable pool.
	mT3101.set(T3101ms);	// It will be started again in l2start.
	mT3109.reset(gConfig.GSM.Timer.T3109);
	mT3111.reset(T3111ms);
	//mTRecycle.reset(500);	// (pat) Must set a dummy value.
	if (!mlcMessageLoopRunning) {
		mlcMessageLoopRunning=true;
		mlcMessageServiceThread.start2((void*(*)(void*))MessageServiceLoop,this,8000*sizeof(void*));
	}
	if (!mlcControlLoopRunning) {
		mlcControlLoopRunning=true;
		mlcControlServiceThread.start2((void*(*)(void*))ControlServiceLoop,this,8000*sizeof(void*));
	}
}
Esempio n. 26
0
// Return decoded frame if success and B == 3, otherwise NULL.
static BitVector *decodeLowSide(const RxBurst &inBurst, int B, GprsDecoder &decoder, ChannelCodingType *ccPtr)
{
	inBurst.data1().copyToSegment(decoder.mI[B],0);
	inBurst.data2().copyToSegment(decoder.mI[B],57);
	// Save the stealing bits:
	// TODO: Save these as floats and do a correlation to pick the encoding.
	decoder.qbits[2*B] = inBurst.Hl();
	decoder.qbits[2*B+1] = inBurst.Hu();

	if (B != 3) { return NULL; }

	decoder.deinterleave();

	bool success;
	BitVector *result;
	switch ((*ccPtr = decoder.getCS())) {
	case ChannelCodingCS4:
		success = decoder.decodeCS4();
		LOG(DEBUG) << "CS-4 success=" << success;
		result = &decoder.mD_CS4;
		break;
	case ChannelCodingCS1:
		success = decoder.decode();
		LOG(DEBUG) << "CS-1 success=" << success;
		result = &decoder.mD;
		break;
	default: devassert(0);	// Others not supported yet.
		return NULL;
	}

	if (success) {
		result->LSB8MSB();
		return result;
	}
	return NULL;
}
Esempio n. 27
0
// Return true if we send a block on the downlink.
bool PDCHL1Downlink::send1DataFrame(  //SVGDBG
	RLCDownEngine *engdown,
	RLCDownlinkDataBlock *block,	// block to send.
	int makeres,					// 0 = no res, 1 = optional res, 2 = required res.
	MsgTransactionType mttype,	// Type of reservation
	unsigned *pcounter)
{
	//ScopedLock lock(testlock);
	TBF *tbf = engdown->getTBF();
	if (! setMACFields(block,mchParent,tbf,makeres,mttype,pcounter)) { return false; }
	// The rest of the RLC header is already set, but we did not know the tfi
	// when we created the RLCDownlinkDataBlocks (because tbf not yet attached)
	// so set tfi now that we know.  Update 8-2012: Above comment is stale because we
	// make the RLCDownlinkBlocks on the fly now.
	block->mTFI = tbf->mtTFI;
	// block->mPR = 1;	// DEBUG test; made no diff.

	tbf->talkedDown();

	BitVector tobits = block->getBitVector(); // tobits deallocated when this function exits.
	if (block->mChannelCoding == 0) { devassert(tobits.size() == 184); }
	if (GPRSDebug & 1) {
		RLCBlockReservation *res = mchParent->getReservation(gBSNNext);
		std::ostringstream sshdr;
		block->text(sshdr,false); //block->RLCDownlinkDataBlockHeader::text(sshdr);
		ByteVector content(tobits);
		GPRSLOG(1) << "send1DataFrame "<<parent()<<" "<<tbf<<LOGVAR(tbf->mtExpectedAckBSN)
			<< " "<<sshdr.str()
			<<" "<<(res ? res->str() : "")
			<< LOGVAR2("content",content);
		//<< " enc="<<tbf->mtChannelCoding <<" "<<os.str() << "\nbits:" <<bits.str();
		//<<" " <<block->str() <<"\nbits:" <<tobits.hexstr();
	}
#if FEC_DEBUG
	BitVector copybits; copybits.clone(tobits);
#endif
	send1Frame(tobits,block->mChannelCoding,0);
#if FEC_DEBUG
	BitVector *result = debugDecoder.getResult();
	devassert(result);
	devassert(copybits == tobits);
	if (result && !(*result == tobits)) {
		int diffbit = -1;
		char thing[500];
		for (int i = 0; i < (int)result->size(); i++) {
			thing[i] = '-';
			if (result->bit(i) != tobits.bit(i)) {
				if (diffbit == -1) diffbit = i;
				thing[i] = '0' + result->bit(i);
			}
		}
		thing[result->size()] = 0;
		GPRSLOG(1) <<"encoding error" <<LOGVAR2("cs",(int)debugDecoder.getCS())
			<<LOGVAR(diffbit)
			<<LOGVAR2("in:size",tobits.size()) <<LOGVAR2("out:size",result->size())
			<<"\n"<<tobits
			<<"\n"<<*result
			<<"\n"<<thing;
	} else {
		//GPRSLOG(1) <<"encoding ok" <<LOGVAR2("cs",(int)debugDecoder.getCS());
	}
#endif
	return true;
}