PageRenderTime 26ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

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

http://mobicents.googlecode.com/
Java | 472 lines | 325 code | 66 blank | 81 comment | 63 complexity | bdca4b68c9cf13e4458b53bf51cb8b10 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;
  19. import java.util.ArrayList;
  20. import java.util.Collection;
  21. import java.util.HashMap;
  22. import java.util.Hashtable;
  23. import java.util.concurrent.locks.ReentrantLock;
  24. import org.apache.log4j.Logger;
  25. import org.mobicents.media.Component;
  26. import org.mobicents.media.MediaSink;
  27. import org.mobicents.media.MediaSource;
  28. import org.mobicents.media.server.impl.clock.LocalTask;
  29. import org.mobicents.media.server.spi.Connection;
  30. import org.mobicents.media.server.spi.ConnectionState;
  31. import org.mobicents.media.server.spi.Endpoint;
  32. import org.mobicents.media.server.spi.EndpointState;
  33. import org.mobicents.media.server.spi.MediaType;
  34. import org.mobicents.media.server.spi.NotificationListener;
  35. import org.mobicents.media.server.spi.ResourceUnavailableException;
  36. import org.mobicents.media.server.spi.TooManyConnectionsException;
  37. import org.mobicents.media.server.spi.rtp.RtpManager;
  38. /**
  39. *
  40. * @author kulikov
  41. * @author amit bhayani
  42. */
  43. public abstract class BaseEndpointImpl implements Endpoint {
  44. private String localName;
  45. private EndpointState state = EndpointState.READY;
  46. private LocalTask stateHandler;
  47. protected ConnectionFactory connectionFactory;
  48. protected RtpManager rtpFactory;
  49. private HashMap<MediaType, MediaSource> sources = new HashMap();
  50. private HashMap<MediaType, MediaSink> sinks = new HashMap();
  51. private ArrayList<MediaType> mediaTypes = new ArrayList();
  52. /** The list of indexes available for connection enumeration within endpoint */
  53. private ArrayList<Integer> index = new ArrayList();
  54. /** The last generated connection's index */
  55. private int lastIndex = -1;
  56. /** Holder for created connections */
  57. // protected transient HashMap<String, Connection> connections = new
  58. // HashMap();
  59. //private int maxConnections = 10;
  60. //private static final int _CONNECTION_TAB_SIZE = 10;
  61. // collection of prestarted local connections
  62. private int connectionPoolSize = 0; //def is 0. connectionTableSize might be better for impl, but "pool" sounds better from user POV
  63. private LocalConnectionImpl[] localConnections; // collection of prestarted network connections
  64. private RtpConnectionImpl[] networkConnections; // collection of active connections
  65. private Connection[] connections; // collection of activly used connections
  66. private int count;
  67. protected ReentrantLock stateLock = new ReentrantLock();
  68. private final Logger logger = Logger.getLogger(BaseEndpointImpl.class);
  69. private long lastUsed;
  70. public BaseEndpointImpl(String localName) {
  71. this.localName = localName;
  72. }
  73. public int getConnectionPoolSize() {
  74. return connectionPoolSize;
  75. }
  76. public void setConnectionPoolSize(int connectionTableSize) {
  77. this.connectionPoolSize = connectionTableSize;
  78. }
  79. public String getLocalName() {
  80. return localName;
  81. }
  82. public void setLocalName(String localName) {
  83. this.localName = localName;
  84. }
  85. public EndpointState getState() {
  86. return state;
  87. }
  88. public Collection<MediaType> getMediaTypes() {
  89. return mediaTypes;
  90. }
  91. protected void setMediaTypes(Collection<MediaType> mediaTypes) {
  92. this.mediaTypes.addAll(mediaTypes);
  93. }
  94. public MediaSink getSink(MediaType media) {
  95. MediaSink sink = sinks.get(media);
  96. return sink;
  97. }
  98. protected void setSinks(HashMap<MediaType, MediaSink> sinks) {
  99. this.sinks.putAll(sinks);
  100. }
  101. public MediaSource getSource(MediaType media) {
  102. return sources.get(media);
  103. }
  104. protected void setSources(HashMap<MediaType, MediaSource> sources) {
  105. this.sources.putAll(sources);
  106. }
  107. /**
  108. * Calculates index of the new connection.
  109. *
  110. * The connection uses this method to ask endpoint for new lowerest index.
  111. * The index is unique withing endpoint but it is not used as connection
  112. * identifier outside of the endpoint.
  113. *
  114. * @return the lowerest available integer value.
  115. */
  116. public int getConnectionIndex() {
  117. return index.isEmpty() ? ++lastIndex : index.remove(0);
  118. }
  119. public void start() throws ResourceUnavailableException {
  120. //baranowb: why all 3 have the same size.
  121. networkConnections = new RtpConnectionImpl[connectionPoolSize];
  122. localConnections = new LocalConnectionImpl[connectionPoolSize];
  123. connections = new ConnectionImpl[connectionPoolSize];
  124. // let's create several connections
  125. for (int i = 0; i < connections.length; i++) {
  126. localConnections[i] = new LocalConnectionImpl(this, connectionFactory);
  127. this.setLifeTime(localConnections[i]);
  128. }
  129. // let's create several connections
  130. if (this.rtpFactory != null) {
  131. for (int i = 0; i < connections.length; i++) {
  132. networkConnections[i] = new RtpConnectionImpl(this, connectionFactory, rtpFactory);
  133. this.setLifeTime(networkConnections[i]);
  134. }
  135. }
  136. }
  137. private void setLifeTime(Connection connection) {
  138. //lets set the LifeTime for connection
  139. if (this.connectionFactory != null && this.connectionFactory.getConnectionStateManager() != null) {
  140. Hashtable<ConnectionState, Integer> connStateLifeTime = this.connectionFactory.getConnectionStateManager().getConnStateLifeTime();
  141. for (ConnectionState connState : connStateLifeTime.keySet()) {
  142. connection.getLifeTime()[connState.getCode()] = connStateLifeTime.get(connState);
  143. if (logger.isDebugEnabled()) {
  144. logger.debug("silence for state " + connState + " is " + connStateLifeTime.get(connState));
  145. }
  146. }
  147. }
  148. }
  149. public void stop() {
  150. logger.info("Stopped " + localName);
  151. }
  152. public ConnectionFactory getConnectionFactory() {
  153. return connectionFactory;
  154. }
  155. public void setConnectionFactory(ConnectionFactory connectionFactory) {
  156. this.connectionFactory = connectionFactory;
  157. }
  158. public void setRtpManager(RtpManager rtpFactory) {
  159. this.rtpFactory = rtpFactory;
  160. }
  161. public RtpManager getRtpManager() {
  162. return this.rtpFactory;
  163. }
  164. public Collection<Connection> getConnections() {
  165. return null;// connections.values();
  166. }
  167. public String describe(MediaType mediaType) throws ResourceUnavailableException {
  168. String sdp = null;
  169. stateLock.lock();
  170. try {
  171. RtpConnectionImpl connection = null;
  172. for (int i = 0; i < networkConnections.length; i++) {
  173. if (networkConnections[i].getState() == ConnectionState.NULL) {
  174. connection = networkConnections[i];
  175. break;
  176. }
  177. }
  178. // connection not found?
  179. if (connection == null) {
  180. throw new ResourceUnavailableException(
  181. "The limit of network connection is exeeded");
  182. }
  183. if (mediaType == null) {
  184. connection.join();
  185. sdp = connection.getLocalDescriptor();
  186. connection.close();
  187. } else {
  188. connection.join(mediaType);
  189. sdp = connection.getLocalDescriptor();
  190. connection.close(mediaType);
  191. }
  192. } catch (Exception e) {
  193. logger.error("Could not create RTP connection", e);
  194. throw new ResourceUnavailableException(e.getMessage());
  195. } finally {
  196. stateLock.unlock();
  197. }
  198. return sdp;
  199. }
  200. /**
  201. * (Non Java-doc.)
  202. *
  203. * @see org.mobicents.media.server.spi.Endpoint#createConnection(org.mobicents.media.server.spi.ConnectionMode);
  204. */
  205. public Connection createConnection() throws TooManyConnectionsException, ResourceUnavailableException {
  206. stateLock.lock();
  207. try {
  208. if (count == connections.length) {
  209. throw new TooManyConnectionsException("The limit of connections exceeded");
  210. }
  211. // what we need is to find the first unused connection from list
  212. // of network connections and return it.
  213. RtpConnectionImpl connection = null;
  214. for (int i = 0; i < networkConnections.length; i++) {
  215. if (networkConnections[i].getState() == ConnectionState.NULL) {
  216. connection = networkConnections[i];
  217. break;
  218. }
  219. }
  220. // connection not found?
  221. if (connection == null) {
  222. throw new ResourceUnavailableException(
  223. "The limit of network connection is exeeded");
  224. }
  225. // connection found. put this connection to the list of used
  226. // connections
  227. // searching first suitable place
  228. for (int i = 0; i < connections.length; i++) {
  229. if (connections[i] == null) {
  230. connection.setIndex(i);
  231. connections[i] = connection;
  232. break;
  233. }
  234. }
  235. connection.join();
  236. connection.bind();
  237. //Sync the Connection for LifeTime handling
  238. //logger.info("Synced Connection "+ connection);
  239. // connection.setStartTime(System.currentTimeMillis());
  240. // stateHandler = Server.scheduler.execute(connection);
  241. count++;
  242. this.state = EndpointState.BUSY;
  243. return connection;
  244. } catch (Exception e) {
  245. logger.error("Could not create RTP connection", e);
  246. throw new ResourceUnavailableException(e.getMessage());
  247. } finally {
  248. stateLock.unlock();
  249. }
  250. }
  251. /**
  252. * (Non Java-doc.)
  253. *
  254. * @see org.mobicents.media.server.spi.Endpoint#createConnection(org.mobicents.media.server.spi.ConnectionMode);
  255. */
  256. public Connection createLocalConnection() throws TooManyConnectionsException, ResourceUnavailableException {
  257. stateLock.lock();
  258. try {
  259. if (count == connections.length) {
  260. throw new TooManyConnectionsException("The limit of connections exceeded");
  261. }
  262. // what we need is to find the first unused connection from list
  263. // of local connections and return it.
  264. LocalConnectionImpl connection = null;
  265. for (int i = 0; i < localConnections.length; i++) {
  266. if (localConnections[i].getState() == ConnectionState.NULL) {
  267. connection = localConnections[i];
  268. break;
  269. }
  270. }
  271. // connection not found?
  272. if (connection == null) {
  273. throw new ResourceUnavailableException(
  274. "The limit of network connection is exeeded");
  275. }
  276. // connection found. put this connection to the list of used
  277. // connections
  278. // searching first suitable place
  279. for (int i = 0; i < connections.length; i++) {
  280. if (connections[i] == null) {
  281. connection.setIndex(i);
  282. connections[i] = connection;
  283. if (logger.isInfoEnabled()) {
  284. logger.info("Connection index: " + i + ", on endpoint: " + this.localName);
  285. }
  286. break;
  287. }
  288. }
  289. connection.join();
  290. connection.bind();
  291. //Sync the Connection for LifeTime handling
  292. // connection.setStartTime(System.currentTimeMillis());
  293. // stateHandler = Server.scheduler.execute(connection);
  294. count++;
  295. this.state = EndpointState.BUSY;
  296. return connection;
  297. } catch (Exception e) {
  298. logger.error("Could not create Local connection", e);
  299. throw new ResourceUnavailableException(e.getMessage());
  300. } finally {
  301. stateLock.unlock();
  302. }
  303. }
  304. public void deleteConnection(String connectionID) {
  305. stateLock.lock();
  306. try {
  307. // find this connection
  308. ConnectionImpl connection = null;
  309. for (int i = 0; i < connections.length; i++) {
  310. if (connections[i] != null && ((ConnectionImpl) connections[i]).getId().equals(
  311. connectionID)) {
  312. connection = (ConnectionImpl) connections[i];
  313. // do not forget to remove it from list of active
  314. // connections
  315. connections[i] = null;
  316. break;
  317. }
  318. }
  319. if (connection != null) {
  320. connection.close();
  321. count--;
  322. } else {
  323. logger.warn(String.format("*********** connection not found ****, endpoint=%s, id=%s, total amount=%d, list=%s", this.getLocalName(), connectionID, count, this.getUsedConnections()));
  324. }
  325. if(count > 0){
  326. this.state = EndpointState.BUSY;
  327. } else {
  328. this.state = EndpointState.READY;
  329. this.lastUsed = System.currentTimeMillis();
  330. }
  331. } finally {
  332. stateLock.unlock();
  333. }
  334. }
  335. private String getUsedConnections() {
  336. String s = "{";
  337. for (int i = 0; i < connections.length; i++) {
  338. if (connections[i] != null ) {
  339. s += connections[i].getId() + " ";
  340. }
  341. }
  342. s+= "}";
  343. return s;
  344. }
  345. /**
  346. * (Non Java-doc).
  347. *
  348. * @see org.mobicents.media.server.spi.Endpoint#deleteAllConnections();
  349. */
  350. public void deleteAllConnections() {
  351. stateLock.lock();
  352. try {
  353. for (int i = 0; i < connections.length; i++) {
  354. if (connections[i] != null) {
  355. ((ConnectionImpl) connections[i]).close();
  356. connections[i] = null;
  357. }
  358. }
  359. count = 0;
  360. this.state = EndpointState.READY;
  361. this.lastUsed = System.currentTimeMillis();
  362. } finally {
  363. stateLock.unlock();
  364. }
  365. }
  366. public void addNotificationListener(NotificationListener listener) {
  367. throw new UnsupportedOperationException("Not supported yet.");
  368. }
  369. public void removeNotificationListener(NotificationListener listener) {
  370. throw new UnsupportedOperationException("Not supported yet.");
  371. }
  372. public Connection getConnection(String connectionID) {
  373. for (int i = 0; i < connections.length; i++) {
  374. if (connections[i] != null && connections[i].getId().equals(connectionID)) {
  375. return connections[i];
  376. }
  377. }
  378. return null;
  379. }
  380. public Component getComponent(String name) {
  381. Collection<MediaSource> components = sources.values();
  382. for (MediaSource source : components) {
  383. if (source.getName().matches(name)) {
  384. return source;
  385. }
  386. }
  387. Collection<MediaSink> components2 = sinks.values();
  388. for (MediaSink sink : components2) {
  389. if (sink.getName().matches(name)) {
  390. return sink;
  391. }
  392. }
  393. return null;
  394. }
  395. public String getLocalAddress(String media) {
  396. return rtpFactory != null ? rtpFactory.getBindAddress() : "0.0.0.0";
  397. }
  398. public int getLocalPort(String media) {
  399. throw new UnsupportedOperationException("Not supported yet.");
  400. }
  401. public abstract void unblock();
  402. public abstract void block();
  403. public long lastTimeUsed() {
  404. return this.lastUsed;
  405. }
  406. }