void L2LAPDm::receiveUFrameUI(const L2Frame& frame) { // The zero-length frame is the idle frame. if (frame.L()==0) return; OBJLOG(INFO) << "state=" << mState << " " << frame; mL3Out.write(new L3Frame(frame,UNIT_DATA)); }
void L2LAPDm::sendUFrameUA(const L2Frame& frame) { // Send UA frame with a echoed payload. // This is used in the contention resolution procedure. // GSM 04.06 5.4.1.4. // The caller need not hold mLock. OBJLOG(INFO) << "state=" << mState << " " << frame; L2Address address(mR,mSAPI); L2Control control(L2Control::UFormat,frame.PF(),0x0C); L2Length length(frame.L()); L2Header header(address,control,length); writeL1NoAck(L2Frame(header,frame.L3Part())); }
void L2LAPDm::receiveUFrameSABM(const L2Frame& frame) { // Caller should hold mLock. // Process the incoming SABM command. // GSM 04.06 3.8.2, 5.4.1 // Q.921 5.5.1.2. // Also borrows from vISDN datalink.c:lapd_socket_handle_uframe_sabm. OBJLOG(INFO) << "state=" << mState << " " << frame; // Ignore frame if P!=1. // See GSM 04.06 5.4.1.2. if (!frame.PF()) return; // Dispatch according to current state. // BTW, LAPDm can always enter multiframe mode when requested, // so that's another big simplification over ISDN/LAPD. switch (mState) { case LinkReleased: // GSM 04.06 5.4.5, 5.4.1.2, 5.4.1.4 clearCounters(); mEstablishmentInProgress = true; // Tell L3 what happened. mL3Out.write(new L3Frame(ESTABLISH)); if (frame.L()) { // Presence of an L3 payload indicates contention resolution. // GSM 04.06 5.4.1.4. mState=ContentionResolution; mContentionCheck = frame.sum(); mL3Out.write(new L3Frame(frame.L3Part(),DATA)); // Echo back payload. sendUFrameUA(frame); } else { mState=LinkEstablished; sendUFrameUA(frame.PF()); } break; case ContentionResolution: // GSM 04.06 5.4.1.4 // This guards against the remote possibility that two handsets // are sending on the same channel at the same time. // vISDN's LAPD doesn't need/do this since peers are hard-wired if (frame.sum()!=mContentionCheck) break; mState=LinkEstablished; sendUFrameUA(frame); break; case AwaitingEstablish: // Huh? This would mean both sides sent SABM at the same time/ // That should not happen in GSM. sendUFrameUA(frame.PF()); OBJLOG(WARN) << "simulatenous SABM attempts"; break; case AwaitingRelease: // If we are awaiting release, we will not enter ABM. // So we send DM to indicate that. sendUFrameDM(frame.PF()); break; case LinkEstablished: // Latency in contention resolution, GSM 04.06 5.4.2.1. if (mEstablishmentInProgress) { if (frame.L()) sendUFrameUA(frame); else sendUFrameUA(frame.PF()); break; } if (frame.L()) { abnormalRelease(); break; } // Re-establishment procedure, GSM 04.06 5.6.3. // This basically resets the ack engine. // We should not actually see this, as of rev 2.4. OBJLOG(WARN) << "reestablishment not really supported"; sendUFrameUA(frame.PF()); clearCounters(); break; default: unexpectedMessage(); return; } }