/* * Copyright 2013-2014 High-Level Technologies * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package org.zodiark.service.wowza; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.atmosphere.cpr.AtmosphereResource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.zodiark.protocol.Envelope; import org.zodiark.protocol.Message; import org.zodiark.protocol.Paths; import org.zodiark.server.Reply; import javax.inject.Inject; import org.zodiark.server.ReplyException; import org.zodiark.service.Endpoint; import org.zodiark.service.session.StreamingSession; import org.zodiark.service.state.EndpointState; import org.zodiark.service.subscriber.SubscriberEndpoint; import org.zodiark.service.util.UUID; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import static org.zodiark.protocol.Paths.*; /** * Represent a Wowza endpoint. */ public class WowzaEndpoint implements Endpoint { private final Logger logger = LoggerFactory.getLogger(WowzaEndpoint.class); @Inject public ObjectMapper mapper; private String uuid; private final List<Endpoint> supportedEndpoints = new LinkedList<Endpoint>(); private AtmosphereResource resource; private Message message; public WowzaEndpoint() { } /** * {@inheritDoc} */ @Override public TYPE type() { return TYPE.WOWZA; } /** * {@inheritDoc} */ @Override public void terminate() { // TODO: Not Implemented } /** * {@inheritDoc} */ @Override public String uuid() { return uuid; } @Override public EndpointState state() { // TODO: State return null; } /** * TODO: For later use * @return list of Endpoint */ public List<Endpoint> supportedEndpoints() { return supportedEndpoints; } /** * Send a {@link Paths#SERVER_VALIDATE_OK} to Wowza and listen for the response. The response will be delivered * to the {@link org.zodiark.service.publisher.PublisherService} * <p/> * {@link Paths#START_PUBLISHER_STREAMING_SESSION} if the streaming session is accepted. * </p> * {@link Paths#FAILED_PUBLISHER_STREAMING_SESSION} if the streaming session is not accepted, for whatever reason. * * @param p * @param l */ public void isEndpointConnected(Endpoint p, Reply l) { Message m = new Message(); m.setPath(SERVER_VALIDATE_OK); try { m.setData(mapper.writeValueAsString(new UUID(p.uuid()))); Envelope e = Envelope.newStreamToServerRequest(REQUEST_ACTION, uuid, m); resource.write(mapper.writeValueAsString(e)); } catch (Exception e) { logger.error("", e); l.fail(ReplyException.DEFAULT); } } /** * Set the Wowza UUID * * @param uuid Wowza UUID * @return this */ public WowzaEndpoint uuid(String uuid) { this.uuid = uuid; return this; } /** * Set a {@link Message} who most probably will contains some information like geo localisation. * * @param m a {@link Message} * @return this. */ public WowzaEndpoint message(Message m) { this.message = m; return this; } /** * Set the {@link AtmosphereResource} representing the underlying connection. * * @param r {@link AtmosphereResource} * @return this */ public WowzaEndpoint resource(AtmosphereResource r) { this.resource = r; return this; } /** * Obfuscate {@link SubscriberEndpoint} that are not allowed to participate to a streaming session. This * method will send an {@link Envelope} to the targeted remote Wowza endpoint with a list of {@link SubscriberEndpoint} * 's uuid that must be obfuscated. * * @param session the current {@link StreamingSession} * @param reply a {@link Reply} in case a failure occurs. If the operation works, an I/O events will be delivered * and no {@link Reply#ok(Object)} will be called. */ public void obfuscate(StreamingSession session, Reply reply) { String executorUuid = session.pendingAction().getSubscriberUUID(); List<String> uuids = new ArrayList<>(); for (SubscriberEndpoint s : session.subscribers()) { if (!s.uuid().equalsIgnoreCase(executorUuid)) { uuids.add(s.uuid()); } } WowzaMessage w = new WowzaMessage(uuids); w.setPublisherUUID(session.publisher().uuid()); Message m = new Message(); m.setPath(WOWZA_OBFUSCATE); try { m.setData(mapper.writeValueAsString(w)); Envelope e = Envelope.newStreamToServerRequest(REQUEST_ACTION, uuid, m); resource.write(mapper.writeValueAsString(e)); } catch (JsonProcessingException e1) { logger.error("", e1); reply.fail(ReplyException.DEFAULT); } } /** * The {@link org.zodiark.service.action.Action} completed, send a message to the remote Wowza with a list * of {@link SubscriberEndpoint} that can now be re-added to a streaming session. If the operation works, an I/O events will be delivered * and no {@link Reply#ok(Object)} will be called. * * @param session {@link StreamingSession} * @param reply a {@link Reply} in case a failure occurs. */ public void deobfuscate(StreamingSession session, Reply reply) { String executorUuid = session.pendingAction().getSubscriberUUID(); List<String> uuids = new ArrayList<>(); for (SubscriberEndpoint s : session.subscribers()) { if (!s.uuid().equalsIgnoreCase(executorUuid)) { uuids.add(s.uuid()); } } WowzaMessage w = new WowzaMessage(uuids); w.setPublisherUUID(session.publisher().uuid()); Message m = new Message(); m.setPath(WOWZA_DEOBFUSCATE); try { m.setData(mapper.writeValueAsString(w)); Envelope e = Envelope.newStreamToServerRequest(MESSAGE_ACTION, uuid, m); resource.write(mapper.writeValueAsString(e)); } catch (JsonProcessingException e1) { logger.error("", e1); reply.fail(ReplyException.DEFAULT); } } }