Logo Search packages:      
Sourcecode: t38modem version File versions  Download package

int T38Engine::PreparePacket ( T38_IFPPacket &  ifp,
BOOL  enableTimeout 
) [protected]

Prepare outgoing T.38 packet.

If returns 0, then the writing loop should be terminated. If returns >0, then the ifp packet is correct and should be sent. If returns <0, then the ifp packet is not correct.

Definition at line 1119 of file t38engine.cxx.

{
  PWaitAndSignal mutexWaitOut(MutexOut);

  if(!IsT38Mode())
    return 0;
  
  //myPTRACE(1, "T38Engine::PreparePacket begin stM=" << stateModem << " stO=" << stateOut);
  
  ifp = T38_IFPPacket();
  BOOL doDalay = TRUE;
  BOOL wasCarrierIn = FALSE;

  for(;;) {
    BOOL redo = FALSE;
    
    if (doDalay) {
      int outDelay;
      
      if (delayRestOut > 0)
        outDelay = delayRestOut;
      else switch( stateOut ) {
        case stOutIdle:             outDelay = msPerOut; break;

        case stOutCedWait:          outDelay = ModParsOut.lenInd; break;
        case stOutSilenceWait:            outDelay = ModParsOut.lenInd; break;
        case stOutIndWait:          outDelay = ModParsOut.lenInd; break;

        case stOutData:
        case stOutHdlcFcs:
          outDelay = int((PInt64(hdlcOut.getRawCount()) * 8 * 1000)/ModParsOut.br +
                     msPerOut - (PTime() - timeBeginOut).GetMilliSeconds());
          break;

        case stOutDataNoSig:        outDelay = msPerOut; break;

        case stOutNoSig:            outDelay = msPerOut; break;
        default:              outDelay = 0;
      }

      //myPTRACE(1, "T38Engine::PreparePacket outDelay=" << outDelay);

      if (outDelay > 0) {
        if (enableTimeout && outDelay > msTimeout) {
          delayRestOut = outDelay - msTimeout;
          outDelay = msTimeout;
          mySleep(outDelay);
          return -1;
        } else {
          while(outDelay > msMaxOutDelay) {
            mySleep(msMaxOutDelay);
            if (!IsT38Mode())
              return 0;
            outDelay -= msMaxOutDelay;
          }
          mySleep(outDelay);
        }
      }
    } else
      doDalay = TRUE;
      
    delayRestOut = 0;

    if (!IsT38Mode())
      return 0;

    for(;;) {
      BOOL waitData = FALSE;
      {
        PWaitAndSignal mutexWait(Mutex);
        if( isStateModemOut() || stateOut != stOutIdle ) {
          switch( stateOut ) {
            case stOutIdle:
              if (isCarrierIn) {
                myPTRACE(1, "T38Engine::PreparePacket isCarrierIn for dataType=" << ModParsOut.dataType);
                int waitms = 0;
                /*
                 * We can't to begin sending data while the carrier is detected because
                 * it's possible that all data (including indication) will be losted.
                 * It's too critical for image data because it's possible to receive
                 * MCF generated for previous page after sending small page that was
                 * not delivered.
                 */
                switch( ModParsOut.dataType ) {
                  case dtHdlc:            waitms = 500; break;    // it's can't be too long
                  case dtRaw:       waitms = 2000; break;   // it's can't be too short
                }
                
                if (waitms) {
                  if (!wasCarrierIn) {
                    wasCarrierIn = TRUE;
                    timeBeginOut = PTime() + PTimeInterval(1000);
                    redo = TRUE;
                    break;
                  } else if (timeBeginOut > PTime()) {
                    redo = TRUE;
                    break;
                  } else {
                    myPTRACE(1, "T38Engine::PreparePacket isCarrierIn expired");
                  }
                }
              }

              wasCarrierIn = FALSE;

              switch (ModParsOut.dataTypeT38) {
                case dtHdlc:
                case dtRaw:
                  t38indicator(ifp, ModParsOut.ind);
                  stateOut = stOutIndWait;
                  break;
                case dtCed:
                  t38indicator(ifp, ModParsOut.ind);
                  stateOut = stOutCedWait;
                  break;
                case dtSilence:
                  stateOut = stOutSilenceWait;
                  redo = TRUE;
                  break;
                default:
                  myPTRACE(1, "T38Engine::PreparePacket bad dataTypeT38=" << ModParsOut.dataTypeT38);
                  return 0;
              }
              break;
            ////////////////////////////////////////////////////
            case stOutCedWait:
              stateOut = stOutNoSig;
              stateModem = stmIdle;
              ModemCallbackWithUnlock(callbackParamOut);
              redo = TRUE;
              break;
            ////////////////////////////////////////////////////
            case stOutSilenceWait:
              stateOut = stOutIdle;
              stateModem = stmIdle;
              ModemCallbackWithUnlock(callbackParamOut);
              doDalay = FALSE;
              redo = TRUE;
              break;
            ////////////////////////////////////////////////////
            case stOutIndWait:
              stateOut = stOutData;
              countOut = 0;
              timeBeginOut = PTime();
              hdlcOut = HDLC();
              if (ModParsOut.msgType == T38D(e_v21))
                t30.v21Begin();

              switch (ModParsOut.dataType) {
                case dtHdlc:
                  hdlcOut.PutHdlcData(&bufOut);
                  break;
                case dtRaw:
                  hdlcOut.PutRawData(&bufOut);
                  break;
                default:
                  myPTRACE(1, "T38Engine::PreparePacket bad dataType=" << ModParsOut.dataType);
                  return 0;
              }

              switch (ModParsOut.dataTypeT38) {
                case dtHdlc:
                  hdlcOut.GetHdlcStart(TRUE);
                  break;
                case dtRaw:
                  if (ModParsOut.dataType == dtHdlc) {
                    myPTRACE(1, "T38Engine::PreparePacket sending dtHdlc like dtRaw not implemented");
                    return 0;
                  }
                  hdlcOut.GetRawStart();
                  break;
                default:
                  myPTRACE(1, "T38Engine::PreparePacket bad dataTypeT38=" << ModParsOut.dataTypeT38);
                  return 0;
              }

              redo = TRUE;
              break;
            ////////////////////////////////////////////////////
            case stOutData:
              {
                BYTE b[(msPerOut * 14400)/(8*1000)];
                PINDEX len = (msPerOut * ModParsOut.br)/(8*1000);
                if (len > PINDEX(sizeof(b)))
                  len = sizeof(b);
                BOOL wasFull = bufOut.isFull();
                int count = hdlcOut.GetData(b, len);
                if (wasFull && !bufOut.isFull())
                  ModemCallbackWithUnlock(cbpOutBufNoFull);

                switch( count ) {
                  case -1:
                    switch (ModParsOut.dataTypeT38) {
                      case dtHdlc:
                        stateOut = stOutHdlcFcs;
                        break;
                      case dtRaw:
                        stateOut = stOutDataNoSig;
                        break;
                      default:
                        myPTRACE(1, "T38Engine::PreparePacket stOutData bad dataTypeT38=" << ModParsOut.dataTypeT38);
                        return 0;
                    }
                    redo = TRUE;
                    break;
                  case 0:
                    if (hdlcOut.getLastChar() != -1)
                      if (ModParsOut.dataType == dtHdlc || hdlcOut.getLastChar() != 0)
                        ModemCallbackWithUnlock(cbpOutBufEmpty);
                    waitData = TRUE;
                    break;
                  default:
                    switch (ModParsOut.dataTypeT38) {
                      case dtHdlc:
                        if (ModParsOut.msgType == T38D(e_v21)) {
                          t30.v21Data(b, count);
                        }
                        t38data(ifp, ModParsOut.msgType, T38F(e_hdlc_data), PBYTEArray(b, count));
                        break;
                      case dtRaw:
                        t38data(ifp, ModParsOut.msgType, T38F(e_t4_non_ecm_data), PBYTEArray(b, count));
                        break;
                      default:
                        myPTRACE(1, "T38Engine::PreparePacket stOutData bad dataTypeT38=" << ModParsOut.dataTypeT38);
                        return 0;
                    }
                    countOut += count;
                }
              }
              break;
            ////////////////////////////////////////////////////
            case stOutHdlcFcs:
              if (ModParsOut.msgType == T38D(e_v21)) {
                t30.v21End(TRUE);
                t30.v21Begin();
              }
              if (ModParsOut.dataType == dtRaw) {
                if (countOut)
                  t38data(ifp, ModParsOut.msgType, hdlcOut.isFcsOK() ? T38F(e_hdlc_fcs_OK) : T38F(e_hdlc_fcs_BAD));
                hdlcOut.GetHdlcStart(FALSE);
                countOut = 0;
                if (hdlcOut.GetData(NULL, 0) != -1) {
                  stateOut = stOutData;
                } else {
                  stateOut = stOutDataNoSig;
                }
              } else {
                if( stateModem != stmOutNoMoreData ) {
                  myPTRACE(1, "T38Engine::PreparePacket stOutHdlcFcs stateModem(" << stateModem << ") != stmOutNoMoreData");
                  return 0;
                }
                if (countOut)
                  t38data(ifp, ModParsOut.msgType, T38F(e_hdlc_fcs_OK));
                bufOut.Clean();           // reset eof
                hdlcOut.PutHdlcData(&bufOut);
                hdlcOut.GetHdlcStart(FALSE);
                if (moreFramesOut) {
                  stateOut = stOutData;
                  stateModem = stmOutMoreData;
                  ModemCallbackWithUnlock(callbackParamOut);
                } else {
                  stateOut = stOutDataNoSig;
                }
              }
              break;
            ////////////////////////////////////////////////////
            case stOutDataNoSig:
#if PTRACING
              if (myCanTrace(3) || (myCanTrace(2) && ModParsOut.dataType == dtRaw)) {
                PInt64 msTime = (PTime() - timeBeginOut).GetMilliSeconds();
                myPTRACE(2, "Sent " << hdlcOut.getRawCount() << " bytes in " << msTime << " ms ("
                  << (PInt64(hdlcOut.getRawCount()) * 8 * 1000)/(msTime ? msTime : 1) << " bits/s)");
              }
#endif
              if( stateModem != stmOutNoMoreData ) {
                myPTRACE(1, "T38Engine::PreparePacket stOutDataNoSig stateModem(" << stateModem << ") != stmOutNoMoreData");
                return 0;
              }
              switch (ModParsOut.dataTypeT38) {
                case dtHdlc:
                  t38data(ifp, ModParsOut.msgType, T38F(e_hdlc_sig_end));
                  break;
                case dtRaw:
                  t38data(ifp, ModParsOut.msgType, T38F(e_t4_non_ecm_sig_end));
                  break;
                default:
                  myPTRACE(1, "T38Engine::PreparePacket stOutDataNoSig bad dataTypeT38=" << ModParsOut.dataTypeT38);
                  return 0;
              }
              stateOut = stOutNoSig;
              stateModem = stmIdle;
              ModemCallbackWithUnlock(callbackParamOut);
              break;
            ////////////////////////////////////////////////////
            case stOutNoSig:
              t38indicator(ifp, T38I(e_no_signal));
              stateOut = stOutIdle;
              break;
            default:
              myPTRACE(1, "T38Engine::PreparePacket bad stateOut=" << stateOut);
              return 0;
          }
        } else {
          switch( onIdleOut ) {
            case dtCng:
              t38indicator(ifp, T38I(e_cng));
              break;
            case dtSilence:
              t38indicator(ifp, T38I(e_no_signal));
              break;
            default:
              waitData = TRUE;
          }
          onIdleOut = dtNone;
        }
      }
      if (!waitData)
        break;
      if (enableTimeout) {
        if (!WaitOutDataReady(msTimeout))
          return -1;
      } else
        WaitOutDataReady();
      if (!IsT38Mode())
        return 0;

      {
        PWaitAndSignal mutexWait(Mutex);
        if( stateOut == stOutData ) {
          myPTRACE(1, "T38Engine::PreparePacket DTE's data delay, reset " << hdlcOut.getRawCount());
          hdlcOut.resetRawCount();
          timeBeginOut = PTime() - PTimeInterval(msPerOut);
          doDalay = FALSE;
        }
      }
    }
    if( !redo ) break;
  }
  return 1;
}

Generated by  Doxygen 1.6.0   Back to index