/** @return scopes on this client */ public Collection<IScope> getScopes() { Set<IScope> scopes = new HashSet<IScope>(); for (IConnection conn : connections) { scopes.add(conn.getScope()); } return scopes; }
/** {@inheritDoc} */ public void setPermissions(IConnection conn, Collection<String> permissions) { if (permissions == null) { conn.removeAttribute(PERMISSIONS); } else { conn.setAttribute(PERMISSIONS, permissions); } }
/** * Connects client to the scope * * @param conn Client conneciton * @param scope Scope * @param params Params passed from client side with connect call * @return true if client was registred within scope, false otherwise */ public boolean connect(IConnection conn, IScope scope, Object[] params) { log.debug("Connect to core handler ?"); // Get session id String id = conn.getSessionId(); // Use client registry from scope the client connected to. IScope connectionScope = Red5.getConnectionLocal().getScope(); // Get client registry for connection scope IClientRegistry clientRegistry = connectionScope.getContext().getClientRegistry(); // Get client from registry by id or create a new one IClient client = clientRegistry.hasClient(id) ? clientRegistry.lookupClient(id) : clientRegistry.newClient(params); // We have a context, and a client object.. time to init the conneciton. conn.initialize(client); // we could checked for banned clients here return true; }
/** * Remote method invokation * * @param conn Connection to invoke method on * @param call Service call context * @return true on success */ public boolean serviceCall(IConnection conn, IServiceCall call) { final IContext context = conn.getScope().getContext(); if (call.getServiceName() != null) { context.getServiceInvoker().invoke(call, context); } else { context.getServiceInvoker().invoke(call, conn.getScope().getHandler()); } return true; }
/** {@inheritDoc} */ @Override public void dispatchEvent(IEvent event) { Set<IConnection> conns = getClientConnections(); for (IConnection conn : conns) { try { conn.dispatchEvent(event); } catch (RuntimeException e) { log.error("Exception during dispatching event: {}", event, e); } } }
/** {@inheritDoc} */ public void receiveAudio(boolean receive) { IConnection conn = Red5.getConnectionLocal(); if (conn instanceof IStreamCapableConnection) { IStreamCapableConnection streamConn = (IStreamCapableConnection) conn; int streamId = conn.getStreamId(); IClientStream stream = streamConn.getStreamById(streamId); if (stream != null && stream instanceof ISubscriberStream) { ISubscriberStream subscriberStream = (ISubscriberStream) stream; subscriberStream.receiveAudio(receive); } } }
@Override public boolean roomConnect(IConnection connection, Object[] params) { log.debug(APP + ":roomConnect"); ISharedObject so = getSharedObject(connection.getScope(), LAYOUT_SO); log.debug("Setting up Listener"); LayoutSender sender = new LayoutSender(so); String room = connection.getScope().getName(); log.debug("Adding event listener to " + room); log.debug("Adding room listener"); layoutApplication.addRoomListener(room, sender); log.debug("Done setting up listener"); return true; }
/** * A hook to record a sample stream. A file is written in webapps/sip/streams/ * * @param stream */ private void recordStream(IBroadcastStream stream) { IConnection conn = Red5.getConnectionLocal(); String streamName = stream.getPublishedName(); try { ClientBroadcastStream cstream = (ClientBroadcastStream) this.getBroadcastStream(conn.getScope(), stream.getPublishedName()); cstream.saveAs(streamName, false); } catch (Exception e) { System.out.println("ERROR while recording stream " + e.getMessage()); e.printStackTrace(); } }
/** {@inheritDoc} */ public void play(Boolean dontStop) { log.debug("Play called. Dont stop param: {}", dontStop); if (!dontStop) { IConnection conn = Red5.getConnectionLocal(); if (conn instanceof IStreamCapableConnection) { IStreamCapableConnection streamConn = (IStreamCapableConnection) conn; int streamId = conn.getStreamId(); IClientStream stream = streamConn.getStreamById(streamId); if (stream != null) { stream.stop(); } } } }
/** * Disconnect connection from scope * * @param conn Connection object */ public void disconnect(IConnection conn) { log.debug("Disconnect: {}", conn); // call disconnect handlers in reverse order of connection. ie. roomDisconnect is called before // appDisconnect. final IClient client = conn.getClient(); if (client == null) { // early bail out removeEventListener(conn); connectionStats.decrement(); if (hasParent()) { parent.disconnect(conn); } return; } // remove it if it exists if (clients.remove(client)) { IScopeHandler handler = getHandler(); if (handler != null) { try { handler.disconnect(conn, this); } catch (Exception e) { log.error( "Error while executing \"disconnect\" for connection {} on handler {}. {}", new Object[] {conn, handler, e}); } try { // there may be a timeout here ? handler.leave(client, this); } catch (Exception e) { log.error( "Error while executing \"leave\" for client {} on handler {}. {}", new Object[] {conn, handler, e}); } } // remove listener removeEventListener(conn); // decrement if there was a set of connections connectionStats.decrement(); if (this.equals(conn.getScope())) { final IServer server = getServer(); if (server instanceof Server) { ((Server) server).notifyDisconnected(conn); } } } if (hasParent()) { parent.disconnect(conn); } }
/** * Close stream. This method can close both IClientBroadcastStream (coming from Flash Player to * Red5) and ISubscriberStream (from Red5 to Flash Player). Corresponding application handlers * (streamSubscriberClose, etc.) are called as if close was initiated by Flash Player. * * <p>It is recommended to remember stream id in application handlers, ex.: * * <pre> * public void streamBroadcastStart(IBroadcastStream stream) { * super.streamBroadcastStart(stream); * if (stream instanceof IClientBroadcastStream) { * int publishedStreamId = ((ClientBroadcastStream)stream).getStreamId(); * Red5.getConnectionLocal().setAttribute(PUBLISHED_STREAM_ID_ATTRIBUTE, publishedStreamId); * } * } * </pre> * * <pre> * public void streamPlaylistItemPlay(IPlaylistSubscriberStream stream, IPlayItem item, boolean isLive) { * super.streamPlaylistItemPlay(stream, item, isLive); * Red5.getConnectionLocal().setAttribute(WATCHED_STREAM_ID_ATTRIBUTE, stream.getStreamId()); * } * </pre> * * When stream is closed, corresponding NetStream status will be sent to stream provider / * consumers. Implementation is based on Red5's StreamService.close() * * @param conn client connection * @param streamId stream ID (number: 1,2,...) */ public void closeStream(IConnection conn, int streamId) { log.info("closeStream: streamId={}, connection={}", streamId, conn); if (conn instanceof IStreamCapableConnection) { IStreamCapableConnection scConn = (IStreamCapableConnection) conn; IClientStream stream = scConn.getStreamById(streamId); if (stream != null) { if (stream instanceof IClientBroadcastStream) { // this is a broadcasting stream (from Flash Player to Red5) IClientBroadcastStream bs = (IClientBroadcastStream) stream; IBroadcastScope bsScope = getBroadcastScope(conn.getScope(), bs.getPublishedName()); if (bsScope != null && conn instanceof BaseConnection) { ((BaseConnection) conn).unregisterBasicScope(bsScope); } } stream.close(); scConn.deleteStreamById(streamId); // in case of broadcasting stream, status is sent automatically by Red5 if (!(stream instanceof IClientBroadcastStream)) { StreamService.sendNetStreamStatus( conn, StatusCodes.NS_PLAY_STOP, "Stream closed by server", stream.getName(), Status.STATUS, streamId); } } else { log.info("Stream not found: streamId={}, connection={}", streamId, conn); } } else { log.warn("Connection is not instance of IStreamCapableConnection: {}", conn); } }
/** * Connect to scope with parameters. To successfully connect to scope it must have handler that * will accept this connection with given set of parameters. Client associated with connection is * added to scope clients set, connection is registered as scope event listener. * * @param conn Connection object * @param params Parameters passed with connection * @return * <pre> * true * </pre> * on success, * <pre> * false * </pre> * otherwise */ public boolean connect(IConnection conn, Object[] params) { log.debug("Connect - scope: {} connection: {}", this, conn); if (enabled) { if (hasParent() && !parent.connect(conn, params)) { log.debug("Connection to parent failed"); return false; } if (hasHandler() && !getHandler().connect(conn, this, params)) { log.debug("Connection to handler failed"); return false; } if (!conn.isConnected()) { log.debug("Connection is not connected"); // timeout while connecting client return false; } final IClient client = conn.getClient(); // we would not get this far if there is no handler if (hasHandler() && !getHandler().join(client, this)) { return false; } // checking the connection again? why? if (!conn.isConnected()) { // timeout while connecting client return false; } // add the client and event listener if (clients.add(client) && addEventListener(conn)) { log.debug("Added client"); // increment conn stats connectionStats.increment(); // get connected scope IScope connScope = conn.getScope(); log.trace("Connection scope: {}", connScope); if (this.equals(connScope)) { final IServer server = getServer(); if (server instanceof Server) { ((Server) server).notifyConnected(conn); } } return true; } } else { log.debug("Connection failed, scope is disabled"); } return false; }
/** {@inheritDoc} */ @SuppressWarnings("unchecked") public Collection<String> getPermissions(IConnection conn) { Collection<String> result = (Collection<String>) conn.getAttribute(PERMISSIONS); if (result == null) { result = Collections.emptySet(); } return result; }
@Override public void streamBroadcastClose(IBroadcastStream stream) { String clientId = Red5.getConnectionLocal().getClient().getId(); String userid = getUserId(); String username = getUsername(); log.debug( "{} has stopped publishing stream [{}]", username + "[uid=" + userid + "][clientid=" + clientId + "]", stream.getPublishedName()); IConnection conn = Red5.getConnectionLocal(); String peerId = (String) conn.getAttribute("VOICE_CONF_PEER"); if (peerId != null) { super.streamPublishStart(stream); sipPeerManager.stopTalkStream(peerId, clientId, stream, conn.getScope()); super.streamBroadcastClose(stream); } }
/** Disconnects client from Red5 application */ public void disconnect() { log.debug("Disconnect - id: {}", id); if (connections != null && !connections.isEmpty()) { log.debug("Closing {} scope connections", connections.size()); // close all connections held to Red5 by client for (IConnection con : getConnections()) { try { con.close(); } catch (Exception e) { // closing a connection calls into application code, so exception possible log.error("Unexpected exception closing connection {}", e); } } } else { log.debug("Connection map is empty or null"); } // unregister client removeInstance(); }
@Override public void roomDisconnect(IConnection connection) { log.debug( "***** " + APP + " [ " + " roomDisconnect [ " + connection.getScope().getName() + "] *********"); }
/** * Pause at given position. Required as "pausePlayback" can be "null" if no flag is passed by the * client * * @param pausePlayback Pause playback or not * @param position Pause position */ public void pause(Boolean pausePlayback, int position) { IConnection conn = Red5.getConnectionLocal(); if (conn instanceof IStreamCapableConnection) { IStreamCapableConnection streamConn = (IStreamCapableConnection) conn; int streamId = conn.getStreamId(); IClientStream stream = streamConn.getStreamById(streamId); if (stream != null && stream instanceof ISubscriberStream) { ISubscriberStream subscriberStream = (ISubscriberStream) stream; // pausePlayback can be "null" if "pause" is called without any parameters from flash if (pausePlayback == null) { pausePlayback = !subscriberStream.isPaused(); } if (pausePlayback) { subscriberStream.pause(position); } else { subscriberStream.resume(position); } } } }
/** {@inheritDoc} */ public void close() { session.invalidate(); // set a quick local ref final IConnection con = this; String threadId = String.format("RemotingCloseNotifier-%s", con.getClient().getId()); // alert our listeners Thread t = new Thread( new Runnable() { public void run() { for (IConnectionListener listener : connectionListeners) { listener.notifyDisconnected(con); } connectionListeners.clear(); } }, threadId); t.setDaemon(true); t.start(); }
@Override public boolean roomConnect(IConnection connection, Object[] params) { log.debug( "***** " + APP + " [ " + " roomConnect [ " + connection.getScope().getName() + "] *********"); return true; }
/** {@inheritDoc} */ public void initStream(int streamId) { IConnection conn = Red5.getConnectionLocal(); log.info("initStream: id={} current id: {} connection={}", streamId, conn.getStreamId(), conn); if (conn instanceof IStreamCapableConnection) { ((IStreamCapableConnection) conn).reserveStreamId(streamId); IClientStream stream = ((IStreamCapableConnection) conn).getStreamById(streamId); if (stream != null) { if (stream instanceof IClientBroadcastStream) { IClientBroadcastStream bs = (IClientBroadcastStream) stream; IBroadcastScope bsScope = getBroadcastScope(conn.getScope(), bs.getPublishedName()); if (bsScope != null && conn instanceof BaseConnection) { ((BaseConnection) conn).unregisterBasicScope(bsScope); } } stream.close(); } ((IStreamCapableConnection) conn).deleteStreamById(streamId); } else { log.warn("ERROR in intiStream, connection is not stream capable"); } }
/** {@inheritDoc} */ public void seek(int position) { log.trace("seek - position:{}", position); IConnection conn = Red5.getConnectionLocal(); if (conn instanceof IStreamCapableConnection) { IStreamCapableConnection streamConn = (IStreamCapableConnection) conn; int streamId = conn.getStreamId(); IClientStream stream = streamConn.getStreamById(streamId); if (stream != null && stream instanceof ISubscriberStream) { ISubscriberStream subscriberStream = (ISubscriberStream) stream; try { subscriberStream.seek(position); } catch (OperationNotSupportedException err) { sendNSFailed( streamConn, StatusCodes.NS_SEEK_FAILED, "The stream doesn't support seeking.", stream.getName(), streamId); } } } }
/** * Associate connection with client * * @param conn Connection object */ protected void register(IConnection conn) { log.debug("Registering connection for this client {}", id); if (conn != null) { IScope scope = conn.getScope(); if (scope != null) { log.debug("Registering for scope: {}", scope); connections.add(conn); } else { log.warn("Clients scope is null. Id: {}", id); } } else { log.warn("Clients connection is null. Id: {}", id); } }
/** {@inheritDoc} */ public void publish(Boolean dontStop) { if (!dontStop) { IConnection conn = Red5.getConnectionLocal(); if (conn instanceof IStreamCapableConnection) { IStreamCapableConnection streamConn = (IStreamCapableConnection) conn; int streamId = conn.getStreamId(); IClientStream stream = streamConn.getStreamById(streamId); if (stream instanceof IBroadcastStream) { IBroadcastStream bs = (IBroadcastStream) stream; if (bs.getPublishedName() != null) { IBroadcastScope bsScope = getBroadcastScope(conn.getScope(), bs.getPublishedName()); if (bsScope != null) { bsScope.unsubscribe(bs.getProvider()); if (conn instanceof BaseConnection) { ((BaseConnection) conn).unregisterBasicScope(bsScope); } } bs.close(); streamConn.deleteStreamById(streamId); } } } } }
@Override public boolean roomConnect(IConnection connection, Object[] params) { String username = ((String) params[0]).toString(); String role = ((String) params[1]).toString(); String room = ((String) params[2]).toString(); String voiceBridge = ((String) params[3]).toString(); boolean record = (Boolean) params[4]; String externalUserID = ((String) params[5]).toString(); String internalUserID = ((String) params[6]).toString(); Boolean muted = false; if (params.length >= 7 && ((Boolean) params[7])) { muted = true; } Map<String, Boolean> lsMap = null; if (params.length >= 8) { try { lsMap = (Map<String, Boolean>) params[8]; } catch (Exception e) { lsMap = new HashMap<String, Boolean>(); } } String userId = internalUserID; String sessionId = CONN + userId; BigBlueButtonSession bbbSession = new BigBlueButtonSession( room, internalUserID, username, role, voiceBridge, record, externalUserID, muted, sessionId); connection.setAttribute(Constants.SESSION, bbbSession); connection.setAttribute("INTERNAL_USER_ID", internalUserID); connection.setAttribute("USER_SESSION_ID", sessionId); connection.setAttribute("TIMESTAMP", System.currentTimeMillis()); red5InGW.initLockSettings(room, lsMap); red5InGW.initAudioSettings(room, internalUserID, muted); String meetingId = bbbSession.getRoom(); String connType = getConnectionType(Red5.getConnectionLocal().getType()); String userFullname = bbbSession.getUsername(); String connId = Red5.getConnectionLocal().getSessionId(); String remoteHost = Red5.getConnectionLocal().getRemoteAddress(); int remotePort = Red5.getConnectionLocal().getRemotePort(); Map<String, Object> logData = new HashMap<String, Object>(); logData.put("meetingId", meetingId); logData.put("connType", connType); logData.put("connId", connId); logData.put("conn", remoteHost + ":" + remotePort); logData.put("userId", userId); logData.put("externalUserId", externalUserID); logData.put("sessionId", sessionId); logData.put("username", userFullname); logData.put("event", "user_joining_bbb_apps"); logData.put("description", "User joining BBB Apps."); Gson gson = new Gson(); String logStr = gson.toJson(logData); log.info("User joining bbb-apps: data={}", logStr); userConnections.addUserConnection(userId, connId); return super.roomConnect(connection, params); }
/** {@inheritDoc} */ public void publish(String name, String mode) { Map<String, String> params = null; if (name != null && name.contains("?")) { // read and utilize the query string values params = new HashMap<String, String>(); String tmp = name; // check if we start with '?' or not if (name.charAt(0) != '?') { tmp = name.split("\\?")[1]; } else if (name.charAt(0) == '?') { tmp = name.substring(1); } // now break up into key/value blocks String[] kvs = tmp.split("&"); // take each key/value block and break into its key value parts for (String kv : kvs) { String[] split = kv.split("="); params.put(split[0], split[1]); } // grab the streams name name = name.substring(0, name.indexOf("?")); } log.debug("publish called with name {} and mode {}", name, mode); IConnection conn = Red5.getConnectionLocal(); if (conn instanceof IStreamCapableConnection) { IScope scope = conn.getScope(); IStreamCapableConnection streamConn = (IStreamCapableConnection) conn; int streamId = conn.getStreamId(); if (StringUtils.isEmpty(name)) { sendNSFailed( streamConn, StatusCodes.NS_FAILED, "The stream name may not be empty.", name, streamId); log.error("The stream name may not be empty."); return; } IStreamSecurityService security = (IStreamSecurityService) ScopeUtils.getScopeService(scope, IStreamSecurityService.class); if (security != null) { Set<IStreamPublishSecurity> handlers = security.getStreamPublishSecurity(); for (IStreamPublishSecurity handler : handlers) { if (!handler.isPublishAllowed(scope, name, mode)) { sendNSFailed( streamConn, StatusCodes.NS_PUBLISH_BADNAME, "You are not allowed to publish the stream.", name, streamId); log.error("You are not allowed to publish the stream {}", name); return; } } } IBroadcastScope bsScope = getBroadcastScope(scope, name); if (bsScope != null && !bsScope.getProviders().isEmpty()) { // another stream with that name is already published sendNSFailed(streamConn, StatusCodes.NS_PUBLISH_BADNAME, name, name, streamId); log.error("Bad name {}", name); return; } IClientStream stream = streamConn.getStreamById(streamId); if (stream != null && !(stream instanceof IClientBroadcastStream)) { log.error( "Stream not found or is not instance of IClientBroadcastStream, name: {}, streamId: {}", name, streamId); return; } boolean created = false; if (stream == null) { stream = streamConn.newBroadcastStream(streamId); created = true; } IClientBroadcastStream bs = (IClientBroadcastStream) stream; try { // set publish name bs.setPublishedName(name); // set stream parameters if they exist if (params != null) { bs.setParameters(params); } IContext context = conn.getScope().getContext(); IProviderService providerService = (IProviderService) context.getBean(IProviderService.BEAN_NAME); // TODO handle registration failure if (providerService.registerBroadcastStream(conn.getScope(), name, bs)) { bsScope = getBroadcastScope(conn.getScope(), name); bsScope.setClientBroadcastStream(bs); if (conn instanceof BaseConnection) { ((BaseConnection) conn).registerBasicScope(bsScope); } } log.debug("Mode: {}", mode); if (IClientStream.MODE_RECORD.equals(mode)) { bs.start(); bs.saveAs(name, false); } else if (IClientStream.MODE_APPEND.equals(mode)) { bs.start(); bs.saveAs(name, true); } else { bs.start(); } bs.startPublishing(); } catch (IOException e) { log.warn("Stream I/O exception", e); sendNSFailed( streamConn, StatusCodes.NS_RECORD_NOACCESS, "The file could not be created/written to.", name, streamId); bs.close(); if (created) { streamConn.deleteStreamById(streamId); } } catch (Exception e) { log.warn("Exception on publish", e); } } }
/** * Dynamic streaming play method. * * <p>The following properties are supported on the play options: * * <pre> * streamName: String. The name of the stream to play or the new stream to switch to. * oldStreamName: String. The name of the initial stream that needs to be switched out. This is not needed and ignored * when play2 is used for just playing the stream and not switching to a new stream. * start: Number. The start time of the new stream to play, just as supported by the existing play API. and it has the * same defaults. This is ignored when the method is called for switching (in other words, the transition * is either NetStreamPlayTransition.SWITCH or NetStreamPlayTransitions.SWAP) * len: Number. The duration of the playback, just as supported by the existing play API and has the same defaults. * transition: String. The transition mode for the playback command. It could be one of the following: * NetStreamPlayTransitions.RESET * NetStreamPlayTransitions.APPEND * NetStreamPlayTransitions.SWITCH * NetStreamPlayTransitions.SWAP * </pre> * * NetStreamPlayTransitions: * * <pre> * APPEND : String = "append" - Adds the stream to a playlist and begins playback with the first stream. * APPEND_AND_WAIT : String = "appendAndWait" - Builds a playlist without starting to play it from the first stream. * RESET : String = "reset" - Clears any previous play calls and plays the specified stream immediately. * RESUME : String = "resume" - Requests data from the new connection starting from the point at which the previous connection ended. * STOP : String = "stop" - Stops playing the streams in a playlist. * SWAP : String = "swap" - Replaces a content stream with a different content stream and maintains the rest of the playlist. * SWITCH : String = "switch" - Switches from playing one stream to another stream, typically with streams of the same content. * </pre> * * @see <a * href="http://www.adobe.com/devnet/flashmediaserver/articles/dynstream_actionscript.html">ActionScript * guide to dynamic streaming</a> * @see <a * href="http://www.adobe.com/devnet/flashmediaserver/articles/dynstream_advanced_pt1.html">Dynamic * streaming in Flash Media Server - Part 1: Overview of the new capabilities</a> * @see <a * href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/NetStreamPlayTransitions.html">NetStreamPlayTransitions</a> * @param playOptions play options */ public void play2(Map<String, ?> playOptions) { log.debug("play2 options: {}", playOptions.toString()); /* { streamName=streams/new.flv, oldStreamName=streams/old.flv, start=0, len=-1, offset=12.195, transition=switch } */ // get the transition type String transition = (String) playOptions.get("transition"); String streamName = (String) playOptions.get("streamName"); String oldStreamName = (String) playOptions.get("oldStreamName"); // now initiate new playback int start = (Integer) playOptions.get("start"); int length = (Integer) playOptions.get("len"); // get the clients connection IConnection conn = Red5.getConnectionLocal(); if (conn != null && conn instanceof IStreamCapableConnection) { // get the stream id int streamId = conn.getStreamId(); IStreamCapableConnection streamConn = (IStreamCapableConnection) conn; if ("stop".equals(transition)) { play(Boolean.FALSE); } else if ("reset".equals(transition)) { // just reset the currently playing stream play(streamName); } else if ("switch".equals(transition)) { try { // set the playback type simplePlayback.set(Boolean.FALSE); // send the "start" of transition sendNSStatus( conn, StatusCodes.NS_PLAY_TRANSITION, String.format("Transitioning from %s to %s.", oldStreamName, streamName), streamName, streamId); // support offset? // playOptions.get("offset") play(streamName, start, length); } finally { // clean up simplePlayback.remove(); } } else if ("append".equals(transition) || "appendAndWait".equals(transition)) { IPlaylistSubscriberStream playlistStream = (IPlaylistSubscriberStream) streamConn.getStreamById(streamId); IPlayItem item = SimplePlayItem.build(streamName); playlistStream.addItem(item); if ("append".equals(transition)) { play(streamName, start, length, false); } } else if ("swap".equals(transition)) { IPlaylistSubscriberStream playlistStream = (IPlaylistSubscriberStream) streamConn.getStreamById(streamId); IPlayItem item = SimplePlayItem.build(streamName); int itemCount = playlistStream.getItemSize(); for (int i = 0; i < itemCount; i++) { IPlayItem tmpItem = playlistStream.getItem(i); if (tmpItem.getName().equals(oldStreamName)) { if (!playlistStream.replace(tmpItem, item)) { log.warn("Playlist item replacement failed"); sendNSFailed( streamConn, StatusCodes.NS_PLAY_FAILED, "Playlist swap failed.", streamName, streamId); } break; } } } else { log.warn("Unhandled transition: {}", transition); sendNSFailed( conn, StatusCodes.NS_FAILED, "Transition type not supported", streamName, streamId); } } else { log.info("Connection was null ?"); } }
@Override public boolean appConnect(IConnection conn, Object[] params) { IServiceCapableConnection service = (IServiceCapableConnection) conn; loginfo("Red5SIP Client connected " + conn.getClient().getId() + " service " + service); return true; }
/** {@inheritDoc} */ public void play(String name, int start, int length, boolean flushPlaylist) { log.debug( "Play called - name: {} start: {} length: {} flush playlist: {}", new Object[] {name, start, length, flushPlaylist}); IConnection conn = Red5.getConnectionLocal(); if (conn instanceof IStreamCapableConnection) { IScope scope = conn.getScope(); IStreamCapableConnection streamConn = (IStreamCapableConnection) conn; int streamId = conn.getStreamId(); if (StringUtils.isEmpty(name)) { sendNSFailed( streamConn, StatusCodes.NS_FAILED, "The stream name may not be empty.", name, streamId); return; } IStreamSecurityService security = (IStreamSecurityService) ScopeUtils.getScopeService(scope, IStreamSecurityService.class); if (security != null) { Set<IStreamPlaybackSecurity> handlers = security.getStreamPlaybackSecurity(); for (IStreamPlaybackSecurity handler : handlers) { if (!handler.isPlaybackAllowed(scope, name, start, length, flushPlaylist)) { sendNSFailed( streamConn, StatusCodes.NS_FAILED, "You are not allowed to play the stream.", name, streamId); return; } } } boolean created = false; IClientStream stream = streamConn.getStreamById(streamId); if (stream == null) { if (streamId <= 0) { streamId = streamConn.reserveStreamId(); } stream = streamConn.newPlaylistSubscriberStream(streamId); stream.setBroadcastStreamPublishName(name); stream.start(); created = true; } if (stream != null && stream instanceof ISubscriberStream) { ISubscriberStream subscriberStream = (ISubscriberStream) stream; IPlayItem item = simplePlayback.get() ? SimplePlayItem.build(name, start, length) : DynamicPlayItem.build(name, start, length); if (subscriberStream instanceof IPlaylistSubscriberStream) { IPlaylistSubscriberStream playlistStream = (IPlaylistSubscriberStream) subscriberStream; if (flushPlaylist) { playlistStream.removeAllItems(); } playlistStream.addItem(item); } else if (subscriberStream instanceof ISingleItemSubscriberStream) { ISingleItemSubscriberStream singleStream = (ISingleItemSubscriberStream) subscriberStream; singleStream.setPlayItem(item); } else { // not supported by this stream service log.warn( "Stream instance type: {} is not supported", subscriberStream.getClass().getName()); return; } try { subscriberStream.play(); } catch (IOException err) { if (created) { stream.close(); streamConn.deleteStreamById(streamId); } sendNSFailed(streamConn, StatusCodes.NS_FAILED, err.getMessage(), name, streamId); } } } else { log.debug("Connection was not stream capable"); } }
@Override public boolean roomConnect(IConnection connection, Object[] params) { String remoteHost = Red5.getConnectionLocal().getRemoteAddress(); int remotePort = Red5.getConnectionLocal().getRemotePort(); String clientId = Red5.getConnectionLocal().getClient().getId(); log.info("[clientid=" + clientId + "] connected from " + remoteHost + ":" + remotePort + "."); String username = ((String) params[0]).toString(); String role = ((String) params[1]).toString(); String conference = ((String) params[2]).toString(); /* * Convert the id to Long because it gets converted to ascii decimal * equivalent (i.e. zero (0) becomes 48) if we don't. */ long userid = Long.parseLong(Red5.getConnectionLocal().getClient().getId()); String sessionName = connection.getScope().getName(); String voiceBridge = ((String) params[4]).toString(); String room = sessionName; assert recorderApplication != null; boolean record = (Boolean) params[5]; log.debug("record value - [" + record + "]"); String externUserID = ((String) params[6]).toString(); if (record == true) { recorderApplication.createRecordSession(sessionName); } BigBlueButtonSession bbbSession = new BigBlueButtonSession( sessionName, userid, username, role, conference, room, voiceBridge, record, externUserID); connection.setAttribute(Constants.SESSION, bbbSession); String debugInfo = "userid=" + userid + ",username="******",role=" + role + ",conference=" + conference + "," + "session=" + sessionName + ",voiceConf=" + voiceBridge + ",room=" + room + ",externsUserid=" + externUserID; log.debug("User [{}] connected to room [{}]", debugInfo, room); participantsApplication.createRoom(room); super.roomConnect(connection, params); return true; }
/** Close stream */ public void closeStream() { IConnection conn = Red5.getConnectionLocal(); closeStream(conn, conn.getStreamId()); }