package org.yamcs.archive; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.yamcs.YamcsException; import org.yamcs.protobuf.Yamcs.NamedObjectId; import org.yamcs.protobuf.Yamcs.NamedObjectList; import org.yamcs.protobuf.Yamcs.PacketReplayRequest; import org.yamcs.protobuf.Yamcs.ReplayRequest; import org.yamcs.security.AuthenticationToken; import org.yamcs.security.InvalidAuthenticationToken; import org.yamcs.security.Privilege; import org.yamcs.xtce.MdbMappings; import org.yamcs.xtceproc.XtceDbFactory; import com.google.common.util.concurrent.AbstractService; /** * Yarch replay server * * A note about terminology: we call this replay because it provides capability to speed control/pause/resume. * However, it is not replay in terms of reprocessing the data - the data is sent as recorded in the streams. * * @author nm * */ public class ReplayServer extends AbstractService { static Logger log=LoggerFactory.getLogger(ReplayServer.class); final int MAX_REPLAYS=200; final String instance; AtomicInteger replayCount = new AtomicInteger(); public ReplayServer(String instance ) { this.instance = instance; } public ReplayServer(String instance , Map<String, Object> config) { this.instance = instance; } /** * create a new packet replay object * @param replayRequest * @param replayListener * @param authToken * @return a replay object * @throws YamcsException * @throws InvalidAuthenticationToken */ public YarchReplay createReplay(ReplayRequest replayRequest, ReplayListener replayListener, AuthenticationToken authToken) throws YamcsException, InvalidAuthenticationToken { if(replayCount.get()>=MAX_REPLAYS) { throw new YamcsException("maximum number of replays reached"); } if( Privilege.usePrivileges ) { Privilege priv = Privilege.getInstance(); // Check privileges for requested parameters if (replayRequest.hasParameterRequest()) { List<NamedObjectId> invalidParameters = new ArrayList<NamedObjectId>(); for( NamedObjectId noi : replayRequest.getParameterRequest().getNameFilterList() ) { if( ! priv.hasPrivilege(authToken, Privilege.Type.TM_PARAMETER, noi.getName() ) ) { invalidParameters.add( noi ); } } if( ! invalidParameters.isEmpty() ) { NamedObjectList nol=NamedObjectList.newBuilder().addAllList( invalidParameters ).build(); log.warn( "Cannot create replay - No privilege for parameters: {}", invalidParameters ); throw new YamcsException("InvalidIdentification", "No privilege", nol); } } // Check privileges for requested packets if (replayRequest.hasPacketRequest()) { Collection<String> allowedPackets = priv.getTmPacketNames(instance, authToken, MdbMappings.MDB_OPSNAME); List<NamedObjectId> invalidPackets = new ArrayList<NamedObjectId>(); for (NamedObjectId noi : replayRequest.getPacketRequest().getNameFilterList()) { // TODO: fix and not comment // if (! allowedPackets.contains(noi.getName())) { // invalidPackets.add(noi); // } } if( ! invalidPackets.isEmpty() ) { NamedObjectList nol=NamedObjectList.newBuilder().addAllList( invalidPackets ).build(); log.warn( "Cannot create replay - InvalidIdentification for packets: {}", invalidPackets ); throw new YamcsException("InvalidIdentification", "Invalid identification", nol); } // Even when no filter is specified, limit request to authorized packets only if (replayRequest.getPacketRequest().getNameFilterList().isEmpty()) { PacketReplayRequest.Builder prr = PacketReplayRequest.newBuilder(replayRequest.getPacketRequest()); for (String allowedPacket : allowedPackets) { prr.addNameFilter(NamedObjectId.newBuilder().setName(allowedPacket) .setNamespace(MdbMappings.MDB_OPSNAME)); } replayRequest = ReplayRequest.newBuilder(replayRequest).setPacketRequest(prr).build(); } } } try { YarchReplay yr=new YarchReplay(this, replayRequest, replayListener, XtceDbFactory.getInstance(instance), authToken); replayCount.incrementAndGet(); return yr; } catch (final YamcsException e) { log.warn("Got YamcsException when creating a replay object: ", e); throw e; } catch (Exception e) { log.warn("Got exception when creating a replay object: ", e); throw new YamcsException("Got exception when creating a replay. " + e.getMessage(), e); } } public void replayFinished() { replayCount.decrementAndGet(); } @Override protected void doStart() { notifyStarted(); } @Override public void doStop() { notifyStopped(); } public String getInstance() { return instance; } }