PageRenderTime 49ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/servers/media/core/server-impl/src/main/java/org/mobicents/media/server/resource/Channel.java

http://mobicents.googlecode.com/
Java | 463 lines | 263 code | 60 blank | 140 comment | 63 complexity | 5a279de0a4b6200a6b685c27345e3717 MD5 | raw file
Possible License(s): LGPL-3.0, GPL-3.0, LGPL-2.1, GPL-2.0, CC-BY-SA-3.0, CC0-1.0, Apache-2.0, BSD-3-Clause
  1. /*
  2. * JBoss, Home of Professional Open Source
  3. * Copyright XXXX, Red Hat Middleware LLC, and individual contributors as indicated
  4. * by the @authors tag. All rights reserved.
  5. * See the copyright.txt in the distribution for a full listing
  6. * of individual contributors.
  7. * This copyrighted material is made available to anyone wishing to use,
  8. * modify, copy, or redistribute it subject to the terms and conditions
  9. * of the GNU General Public License, v. 2.0.
  10. * This program is distributed in the hope that it will be useful, but WITHOUT A
  11. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
  12. * PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. * You should have received a copy of the GNU General Public License,
  14. * v. 2.0 along with this distribution; if not, write to the Free Software
  15. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  16. * MA 02110-1301, USA.
  17. */
  18. package org.mobicents.media.server.resource;
  19. import java.util.ArrayList;
  20. import java.util.Collection;
  21. import java.util.HashMap;
  22. import java.util.List;
  23. import org.mobicents.media.Component;
  24. import org.mobicents.media.Format;
  25. import org.mobicents.media.Inlet;
  26. import org.mobicents.media.MediaSink;
  27. import org.mobicents.media.MediaSource;
  28. import org.mobicents.media.Outlet;
  29. import org.mobicents.media.server.impl.resource.Proxy;
  30. import org.mobicents.media.server.spi.Connection;
  31. import org.mobicents.media.server.spi.Endpoint;
  32. /**
  33. * Channel is used to join media source with media sink with
  34. * customized media path.
  35. *
  36. * For customization of media path inner pipes are used where each pipe has c
  37. * onfigured its inlet and outlet.
  38. *
  39. * @author kulikov
  40. */
  41. public class Channel {
  42. //holders for components classified by its type
  43. //one component can be holded in more then one map
  44. protected HashMap<String, MediaSource> sources;
  45. protected HashMap<String, MediaSink> sinks;
  46. protected HashMap<String, Inlet> inlets;
  47. protected HashMap<String, Outlet> outlets;
  48. //The list of internal pipes
  49. private List<Pipe> pipes = new ArrayList();
  50. private Proxy localPipe = new Proxy("Channel");
  51. private Proxy input = new Proxy("input.channel");
  52. private Proxy output = new Proxy("output.channel");
  53. //The component connected to extenal source.
  54. private MediaSink intake;
  55. //The component connected to extenal sink.
  56. private MediaSource exhaust;
  57. private Endpoint endpoint;
  58. private Connection connection;
  59. private Channel txChannel;
  60. private Channel rxChannel;
  61. private HashMap<String, ? extends Component> components;
  62. /**
  63. * Constructs new channel with specified components.
  64. *
  65. * @param sources the map of components of type MediaSource
  66. * @param sinks the map of components of type MediaSink
  67. * @param inlets the map of components of type Inlet
  68. * @param outlets the map of components of type Outlet
  69. */
  70. protected Channel(
  71. HashMap<String, MediaSource> sources,
  72. HashMap<String, MediaSink> sinks,
  73. HashMap<String, Inlet> inlets,
  74. HashMap<String, Outlet> outlets) {
  75. this.sources = sources;
  76. this.sinks = sinks;
  77. this.inlets = inlets;
  78. this.outlets = outlets;
  79. this.intake = localPipe.getInput();
  80. this.exhaust = localPipe.getOutput();
  81. }
  82. protected Channel(HashMap<String, ? extends Component> components) {
  83. this.components = components;
  84. }
  85. public Format[] getFormats() {
  86. return null;
  87. }
  88. public Endpoint getEndpoint() {
  89. return this.endpoint;
  90. }
  91. public Connection getConnection() {
  92. return connection;
  93. }
  94. public void setEndpoint(Endpoint endpoint) {
  95. Collection<MediaSource> list = sources.values();
  96. for (MediaSource s : list) {
  97. s.setEndpoint(endpoint);
  98. }
  99. Collection<MediaSink> list1 = sinks.values();
  100. for (MediaSink s : list1) {
  101. s.setEndpoint(endpoint);
  102. }
  103. Collection<Inlet> list2 = inlets.values();
  104. for (Inlet s : list2) {
  105. s.setEndpoint(endpoint);
  106. }
  107. Collection<Outlet> list3 = outlets.values();
  108. for (Outlet s : list3) {
  109. s.setEndpoint(endpoint);
  110. }
  111. intake.setEndpoint(endpoint);
  112. exhaust.setEndpoint(endpoint);
  113. }
  114. public void setConnection(Connection connection) {
  115. this.connection = connection;
  116. Collection<MediaSource> list = sources.values();
  117. for (MediaSource s : list) {
  118. s.setConnection(connection);
  119. }
  120. Collection<MediaSink> list1 = sinks.values();
  121. for (MediaSink s : list1) {
  122. s.setConnection(connection);
  123. }
  124. Collection<Inlet> list2 = inlets.values();
  125. for (Inlet s : list2) {
  126. s.setConnection(connection);
  127. }
  128. Collection<Outlet> list3 = outlets.values();
  129. for (Outlet s : list3) {
  130. s.setConnection(connection);
  131. }
  132. intake.setConnection(connection);
  133. exhaust.setConnection(connection);
  134. }
  135. public void start() {
  136. for (Pipe pipe : pipes) {
  137. pipe.start();
  138. }
  139. /* Collection <Inlet> list3 = inlets.values();
  140. for (Inlet s : list3) {
  141. if (s instanceof Outlet || s instanceof MediaSource) {
  142. s.getInput().start();
  143. s.start();
  144. }
  145. }
  146. Collection <Outlet> list4 = outlets.values();
  147. for (Outlet s : list4) {
  148. if (s instanceof Inlet || s instanceof MediaSink) {
  149. s.getOutput().start();
  150. s.start();
  151. }
  152. }
  153. */
  154. intake.start();
  155. exhaust.start();
  156. }
  157. public void stop() {
  158. for (Pipe pipe : pipes) {
  159. pipe.stop();
  160. }
  161. Collection <MediaSource> list = sources.values();
  162. for (MediaSource s : list) {
  163. s.stop();
  164. }
  165. Collection <MediaSink> list2 = sinks.values();
  166. for (MediaSink s : list2) {
  167. s.stop();
  168. }
  169. Collection <Inlet> list3 = inlets.values();
  170. for (Inlet s : list3) {
  171. s.getInput().stop();
  172. }
  173. Collection <Outlet> list4 = outlets.values();
  174. for (Outlet s : list4) {
  175. s.getOutput().stop();
  176. }
  177. intake.stop();
  178. exhaust.stop();
  179. }
  180. /**
  181. * Opens pipes between source and sink.
  182. *
  183. * @param pipe the pipe to be opened
  184. * @param inlet the name of the source
  185. * @param outlet the name of the destination. *
  186. * @throws org.mobicents.media.server.resource.UnknownComponentException
  187. * if name of the sink or source is not known.
  188. */
  189. public void openPipe(Pipe pipe, String inlet, String outlet) throws UnknownComponentException {
  190. //when inlet is null pipe acts as intake for the channel
  191. //so component with name outlet will be connected to external source
  192. //we have to consider it as intake.
  193. if (inlet == null && outlet != null) {
  194. if (sinks.containsKey(outlet)) {
  195. intake = input.getInput();
  196. input.getOutput().connect(sinks.get(outlet));
  197. // intake = sinks.get(outlet);
  198. } else throw new UnknownComponentException(outlet);
  199. }
  200. //when outlet is null then pipe acts as exhaust for the channel
  201. //the component with name inlet will be connected to an external sink
  202. //we are assigning this component to exhaust varibale
  203. else if (inlet != null && outlet == null) {
  204. if (sources.containsKey(inlet)) {
  205. exhaust = output.getOutput();
  206. output.getInput().connect(sources.get(inlet));
  207. // exhaust = sources.get(inlet);
  208. } else throw new UnknownComponentException(inlet);
  209. }
  210. //it is an internal pipe. just join to components and save
  211. //pipe in the list
  212. else {
  213. pipe.open(inlet, outlet);
  214. pipes.add(pipe);
  215. }
  216. }
  217. /**
  218. * Closes specified pipe.
  219. *
  220. * @param pipe the pipe to be closed.
  221. */
  222. public void closePipe(Pipe pipe) {
  223. //pipes.remove(pipe);
  224. pipe.close();
  225. }
  226. public Format[] getInputFormats() {
  227. return intake.getFormats();
  228. }
  229. public Format[] getOutputFormats() {
  230. return exhaust.getFormats();
  231. }
  232. /**
  233. * Connects channel to a sink.
  234. *
  235. * @param sink the sink to connect to
  236. */
  237. public Format[] connect(MediaSink sink) {
  238. //sink may be connected if this channel is not connected to other channel
  239. //as source of media
  240. if (rxChannel != null) {
  241. throw new IllegalStateException("Channel is connected as source for other channel");
  242. }
  243. exhaust.connect(sink);
  244. return null;//this.getSubset(exhaust.getFormats(), sink.getFormats());
  245. }
  246. /**
  247. * Disconnects channel from a sink.
  248. *
  249. * @param sink the sink to connect from
  250. */
  251. public void disconnect(MediaSink sink) {
  252. //sink may be connected if this channel is not connected to other channel
  253. //as source of media
  254. if (rxChannel != null) {
  255. throw new IllegalStateException("Channel is connected as source for other channel");
  256. }
  257. exhaust.disconnect(sink);
  258. }
  259. /**
  260. * Connects channel to a source.
  261. *
  262. * @param source the source to connect to
  263. */
  264. public Format[] connect(MediaSource source) {
  265. //source may be connected if this channel is not connected to other channel
  266. //as source of media
  267. if (txChannel != null) {
  268. throw new IllegalStateException("Channel is connected as sink for other channel");
  269. }
  270. intake.connect(source);
  271. return null;//getSubset(intake.getFormats(), source.getFormats());
  272. }
  273. /**
  274. * Disconnects channel from a source.
  275. *
  276. * @param source the source to connect from
  277. */
  278. public void disconnect(MediaSource source) {
  279. //source may be connected if this channel is not connected to other channel
  280. //as source of media
  281. if (txChannel != null) {
  282. throw new IllegalStateException("Channel is connected as sink for other channel");
  283. }
  284. intake.disconnect(source);
  285. }
  286. /**
  287. * Establish a connection with other channel
  288. *
  289. * @param other
  290. */
  291. public void connect(Channel rxChannel) {
  292. this.rxChannel = rxChannel;
  293. rxChannel.txChannel = this;
  294. exhaust.connect(rxChannel.intake);
  295. }
  296. /**
  297. * Deletes connection with other channel
  298. *
  299. * @param other
  300. */
  301. public void disconnect(Channel channel) {
  302. if (rxChannel != null && rxChannel == channel) {
  303. exhaust.disconnect(rxChannel.intake);
  304. rxChannel.txChannel = null;
  305. rxChannel = null;
  306. } else if (txChannel != null && txChannel == channel) {
  307. intake.disconnect(txChannel.exhaust);
  308. txChannel.rxChannel = null;
  309. txChannel = null;
  310. } else {
  311. throw new IllegalArgumentException("Channels " + this + " and " + channel + " was never connected");
  312. }
  313. }
  314. /**
  315. * Searches the component with specified name that can be explicitly added
  316. * to this channel.
  317. *
  318. * @param name the name of the component to find.
  319. * @return component that was found or null if component with specified name
  320. * absent.
  321. */
  322. public Component getComponent(String name) {
  323. //search result depends from the order of maps observation!
  324. //inlet/outlet implicitly registers input/output in source or sink map
  325. //and as result can be returned implicit sink/source of the complex
  326. //component. To prevent such kind of search error let's start to search
  327. //from inlets/outlets and look into sink,source only if explicitly added
  328. //component was not found yet
  329. //inlets outlets are never searched! for I think?
  330. if (inlets.containsKey(name)) {
  331. return inlets.get(name);
  332. } else if (outlets.containsKey(name)){
  333. return outlets.get(name);
  334. } else if (sources.containsKey(name)) {
  335. return sources.get(name);
  336. } else if (sinks.containsKey(name)) {
  337. return sinks.get(name);
  338. }
  339. return null;
  340. }
  341. public Component getComponent(Class _interface) {
  342. //search result depends from the order of maps observation!
  343. //inlet/outlet implicitly registers input/output in source or sink map
  344. //and as result can be returned implicit sink/source of the complex
  345. //component. To prevent such kind of search error let's start to search
  346. //from inlets/outlets and look into sink,source only if explicitly added
  347. //component was not found yet
  348. //inlets outlets are never searched! for I think?
  349. for(MediaSource src:this.sources.values())
  350. {
  351. Component c = (Component) src.getInterface(_interface);
  352. if(c!=null)
  353. {
  354. return src;
  355. }
  356. }
  357. for(MediaSink sink:this.sinks.values())
  358. {
  359. Component c = (Component) sink.getInterface(_interface);
  360. if(c!=null)
  361. {
  362. return sink;
  363. }
  364. }
  365. return null;
  366. }
  367. public void close() {
  368. for (Pipe pipe : pipes) {
  369. closePipe(pipe);
  370. }
  371. pipes.clear();
  372. sources.clear();
  373. sinks.clear();
  374. outlets.clear();
  375. inlets.clear();
  376. }
  377. private Format[] getSubset(Format[] f1, Format[] f2) {
  378. ArrayList<Format> list = new ArrayList();
  379. for (int i = 0; i < f1.length; i++) {
  380. for (int j = 0; j < f2.length; j++) {
  381. if (f1[i].matches(f2[j])) {
  382. list.add(f1[i]);
  383. }
  384. }
  385. }
  386. Format[] f = new Format[list.size()];
  387. list.toArray(f);
  388. return f;
  389. }
  390. public long getPacketsTransmitted() {
  391. return exhaust.getPacketsTransmitted();
  392. }
  393. public long getBytesTransmitted() {
  394. return exhaust.getBytesTransmitted();
  395. }
  396. @Override
  397. public String toString() {
  398. String enpName = getEndpoint() != null ? getEndpoint().getLocalName() : "unknown";
  399. String conID = getConnection() != null ? getConnection().getId() : " unknown";
  400. return "Channel[endpoint=" + enpName + " connection=" + conID + "]";
  401. }
  402. }