示例#1
0
 /** {@inheritDoc} */
 public void execute(ISchedulingService service) {
   // ensure the job is not already running
   if (running.compareAndSet(false, true)) {
     // get now
     long now = System.currentTimeMillis();
     // get the current bytes read count on the connection
     long currentReadBytes = getReadBytes();
     // get our last bytes read count
     long previousReadBytes = lastBytesRead.get();
     log.debug(
         "Time now: {} current read count: {} last read count: {}",
         new Object[] {now, currentReadBytes, previousReadBytes});
     if (currentReadBytes > previousReadBytes) {
       log.debug("Client is still alive, no ping needed");
       // client has sent data since last check and thus is not dead. No need to ping
       if (lastBytesRead.compareAndSet(previousReadBytes, currentReadBytes)) {
         // update the timestamp to match our update
         lastBytesReadTime = now;
       }
     } else {
       // client didn't send response to ping command and didn't sent data for too long,
       // disconnect
       long lastPingTime = lastPingSent.get();
       long lastPongTime = lastPongReceived.get();
       if (lastPongTime > 0
           && (lastPingTime - lastPongTime > maxInactivity)
           && !(now - lastBytesReadTime < maxInactivity)) {
         log.debug("Keep alive job name {}", keepAliveJobName);
         if (log.isTraceEnabled()) {
           log.trace("Scheduled job list");
           for (String jobName : service.getScheduledJobNames()) {
             log.trace("Job: {}", jobName);
           }
         }
         service.removeScheduledJob(keepAliveJobName);
         keepAliveJobName = null;
         log.warn(
             "Closing {}, with id {}, due to too much inactivity ({} ms), last ping sent {} ms ago",
             new Object[] {
               RTMPConnection.this, getId(), (lastPingTime - lastPongTime), (now - lastPingTime)
             });
         // Add the following line to (hopefully) deal with a very common support request
         // on the Red5 list
         log.warn(
             "This often happens if YOUR Red5 application generated an exception on start-up. Check earlier in the log for that exception first!");
         onInactive();
       }
       // send ping command to client to trigger sending of data
       ping();
     }
     // reset running flag
     running.compareAndSet(true, false);
   }
 }
 public void init() {
   if (schedulingService != null) {
     // set to run once per hour
     schedulingService.addScheduledJob(3600000, new ReaperJob());
   } else {
     log.warn("Session reaper job was not scheduled");
   }
 }
示例#3
0
    /** {@inheritDoc} */
    public void execute(ISchedulingService service) {
      long thisRead = getReadBytes();
      long previousReadBytes = lastBytesRead.get();
      if (thisRead > previousReadBytes) {
        // Client sent data since last check and thus is not dead. No
        // need to ping.
        if (lastBytesRead.compareAndSet(previousReadBytes, thisRead))
          lastBytesReadTime = System.currentTimeMillis();
        return;
      }
      // Client didn't send response to ping command
      // and didn't sent data for too long, disconnect
      if (lastPongReceived.get() > 0
          && (lastPingSent.get() - lastPongReceived.get() > maxInactivity)
          && !(System.currentTimeMillis() - lastBytesReadTime < maxInactivity)) {

        getWriteLock().lock();
        try {
          log.debug("Keep alive job name {}", keepAliveJobName);
          if (log.isDebugEnabled()) {
            log.debug("Scheduled job list");
            for (String jobName : service.getScheduledJobNames()) {
              log.debug("Job: {}", jobName);
            }
          }
          service.removeScheduledJob(keepAliveJobName);
          keepAliveJobName = null;
        } finally {
          getWriteLock().unlock();
        }
        log.warn(
            "Closing {}, with id {}, due to too much inactivity ({}ms), "
                + "last ping sent {}ms ago",
            new Object[] {
              RTMPConnection.this,
              getId(),
              (lastPingSent.get() - lastPongReceived.get()),
              (System.currentTimeMillis() - lastPingSent.get())
            });
        onInactive();
        return;
      }
      // Send ping command to client to trigger sending of data.
      ping();
    }
示例#4
0
 /**
  * Start waiting for a valid handshake.
  *
  * @param service The scheduling service to use
  */
 protected void startWaitForHandshake(ISchedulingService service) {
   getWriteLock().lock();
   try {
     waitForHandshakeService = service;
     waitForHandshakeJob =
         service.addScheduledOnceJob(maxHandshakeTimeout, new WaitForHandshakeJob());
   } finally {
     getWriteLock().unlock();
   }
 }
示例#5
0
 private void unscheduleWaitForHandshakeJob() {
   getWriteLock().lock();
   try {
     if (waitForHandshakeJob != null) {
       schedulingService.removeScheduledJob(waitForHandshakeJob);
       waitForHandshakeJob = null;
       log.debug("Removed waitForHandshakeJob for: {}", getId());
     }
   } finally {
     getWriteLock().unlock();
   }
 }
示例#6
0
 /** Stop this server-side stream */
 public void stop() {
   if (state == StreamState.PLAYING || state == StreamState.PAUSED) {
     if (liveJobName != null) {
       scheduler.removeScheduledJob(liveJobName);
       liveJobName = null;
     }
     if (vodJobName != null) {
       scheduler.removeScheduledJob(vodJobName);
       vodJobName = null;
     }
     if (msgIn != null) {
       msgIn.unsubscribe(this);
       msgIn = null;
     }
     if (nextRTMPMessage != null) {
       nextRTMPMessage.getBody().release();
     }
     stopRecording();
     setState(StreamState.STOPPED);
   }
 }
示例#7
0
 /**
  * Pull the next message from IMessageInput and schedule it for push according to the timestamp.
  */
 protected void scheduleNextMessage() {
   boolean first = (nextRTMPMessage == null);
   long delta = 0L;
   do {
     nextRTMPMessage = getNextRTMPMessage();
     if (nextRTMPMessage != null) {
       IRTMPEvent rtmpEvent = nextRTMPMessage.getBody();
       // filter all non-AV messages
       if (rtmpEvent instanceof VideoData || rtmpEvent instanceof AudioData) {
         rtmpEvent = nextRTMPMessage.getBody();
         nextTS = rtmpEvent.getTimestamp();
         if (first) {
           vodStartTS = nextTS;
           first = false;
         }
         delta = nextTS - vodStartTS - (System.currentTimeMillis() - serverStartTS);
         if (delta < WAIT_THRESHOLD) {
           if (doPushMessage()) {
             if (state != StreamState.PLAYING) {
               // Stream is not playing, don't load more messages
               nextRTMPMessage = null;
             }
           } else {
             nextRTMPMessage = null;
           }
         }
       }
     } else {
       onItemEnd();
     }
   } while (nextRTMPMessage != null || delta < WAIT_THRESHOLD);
   // start the job all over again
   vodJobName =
       scheduler.addScheduledOnceJob(
           delta,
           new IScheduledJob() {
             public void execute(ISchedulingService service) {
               if (vodJobName != null) {
                 vodJobName = null;
                 if (doPushMessage()) {
                   if (state == StreamState.PLAYING) {
                     scheduleNextMessage();
                   } else {
                     // Stream is paused, don't load more messages
                     nextRTMPMessage = null;
                   }
                 }
               }
             }
           });
 }
示例#8
0
 public void init() {
   // create the job and schedule it
   jobName = scheduler.addScheduledJobAfterDelay(checkInterval, new DeployJob(), 20000);
   //
   log.debug("Source directory: {}", deploymentDirectory);
   // check the deploy from directory
   File dir = new File(deploymentDirectory);
   if (!dir.exists()) {
     log.warn("Source directory not found");
   } else {
     if (!dir.isDirectory()) {
       log.warn("Source directory is not a directory");
     }
   }
   dir = null;
 }
示例#9
0
 /**
  * Play a specific IPlayItem. The strategy for now is VOD first, Live second.
  *
  * @param item Item to play
  */
 protected void play(IPlayItem item) {
   // dont play unless we are stopped
   if (state == StreamState.STOPPED) {
     // assume this is not live stream
     boolean isLive = false;
     if (providerService != null) {
       msgIn = providerService.getVODProviderInput(getScope(), item.getName());
       if (msgIn == null) {
         msgIn = providerService.getLiveProviderInput(getScope(), item.getName(), true);
         isLive = true;
       }
       if (msgIn == null) {
         log.warn("ABNORMAL Can't get both VOD and Live input from providerService");
         return;
       }
     }
     setState(StreamState.PLAYING);
     currentItem = item;
     sendResetMessage();
     if (msgIn != null) {
       msgIn.subscribe(this, null);
     }
     if (isLive) {
       if (item.getLength() >= 0) {
         liveJobName =
             scheduler.addScheduledOnceJob(
                 item.getLength(),
                 new IScheduledJob() {
                   public void execute(ISchedulingService service) {
                     if (liveJobName == null) {
                       return;
                     }
                     liveJobName = null;
                     onItemEnd();
                   }
                 });
       }
     } else {
       long start = item.getStart();
       if (start < 0) {
         start = 0;
       }
       sendVODInitCM(msgIn, (int) start);
       startBroadcastVOD();
     }
   }
 }
示例#10
0
 /** Starts measurement. */
 public void startRoundTripMeasurement() {
   if (pingInterval <= 0) {
     // Ghost detection code disabled
     return;
   }
   getWriteLock().lock();
   try {
     if (keepAliveJobName == null) {
       // log.debug("Scope null = {}", (scope == null));
       // log.debug("getScope null = {}", (getScope() == null));
       // log.debug("Context null = {}", (scope.getContext() == null));
       // ISchedulingService schedulingService = (ISchedulingService)
       // scope.getContext().getBean(ISchedulingService.BEAN_NAME);
       keepAliveJobName = schedulingService.addScheduledJob(pingInterval, new KeepAliveJob());
     }
     log.debug("Keep alive job name {} for client id {}", keepAliveJobName, getId());
   } finally {
     getWriteLock().unlock();
   }
 }
示例#11
0
  /** {@inheritDoc} */
  @Override
  public void close() {
    getWriteLock().lock();
    try {
      if (keepAliveJobName != null) {
        schedulingService.removeScheduledJob(keepAliveJobName);
        keepAliveJobName = null;
      }
    } finally {
      getWriteLock().unlock();
    }
    Red5.setConnectionLocal(this);
    IStreamService streamService =
        (IStreamService) getScopeService(scope, IStreamService.class, StreamService.class);
    if (streamService != null) {
      for (Map.Entry<Integer, IClientStream> entry : streams.entrySet()) {
        IClientStream stream = entry.getValue();
        if (stream != null) {
          log.debug("Closing stream: {}", stream.getStreamId());
          streamService.deleteStream(this, stream.getStreamId());
          usedStreams.decrementAndGet();
        }
      }
      streams.clear();
    }
    channels.clear();

    getWriteLock().lock();
    try {
      if (bwContext != null && getScope() != null && getScope().getContext() != null) {
        IBWControlService bwController =
            (IBWControlService) getScope().getContext().getBean(IBWControlService.KEY);
        bwController.unregisterBWControllable(bwContext);
        bwContext = null;
      }
    } finally {
      getWriteLock().unlock();
    }
    super.close();
  }
示例#12
0
 /** Starts measurement. */
 public void startRoundTripMeasurement() {
   if (pingInterval > 0 && keepAliveJobName == null) {
     keepAliveJobName = schedulingService.addScheduledJob(pingInterval, new KeepAliveJob());
     log.debug("Keep alive job name {} for client id {}", keepAliveJobName, getId());
   }
 }
示例#13
0
 /** {@inheritDoc} */
 @Override
 public void close() {
   getWriteLock().lock();
   try {
     if (keepAliveJobName != null) {
       schedulingService.removeScheduledJob(keepAliveJobName);
       keepAliveJobName = null;
     }
   } finally {
     getWriteLock().unlock();
   }
   Red5.setConnectionLocal(this);
   IStreamService streamService =
       (IStreamService) getScopeService(scope, IStreamService.class, StreamService.class);
   if (streamService != null) {
     for (Map.Entry<Integer, IClientStream> entry : streams.entrySet()) {
       IClientStream stream = entry.getValue();
       if (stream != null) {
         log.debug("Closing stream: {}", stream.getStreamId());
         streamService.deleteStream(this, stream.getStreamId());
         usedStreams.decrementAndGet();
       }
     }
   }
   // close the base connection - disconnect scopes and unregister client
   super.close();
   // kill all the collections etc
   if (channels != null) {
     channels.clear();
     channels = null;
   } else {
     log.trace("Channels collection was null");
   }
   if (streams != null) {
     streams.clear();
     streams = null;
   } else {
     log.trace("Streams collection was null");
   }
   if (pendingCalls != null) {
     pendingCalls.clear();
     pendingCalls = null;
   } else {
     log.trace("PendingCalls collection was null");
   }
   if (deferredResults != null) {
     deferredResults.clear();
     deferredResults = null;
   } else {
     log.trace("DeferredResults collection was null");
   }
   if (pendingVideos != null) {
     pendingVideos.clear();
     pendingVideos = null;
   } else {
     log.trace("PendingVideos collection was null");
   }
   if (streamBuffers != null) {
     streamBuffers.clear();
     streamBuffers = null;
   } else {
     log.trace("StreamBuffers collection was null");
   }
 }
示例#14
0
 /**
  * Start waiting for a valid handshake.
  *
  * @param service The scheduling service to use
  */
 protected void startWaitForHandshake(ISchedulingService service) {
   waitForHandshakeJob =
       service.addScheduledOnceJob(maxHandshakeTimeout, new WaitForHandshakeJob());
 }
示例#15
0
 public void shutdown() {
   scheduler.removeScheduledJob(jobName);
 }