All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sourceforge.peers.rtp.RtpSession Maven / Gradle / Ivy

There is a newer version: 2.1.6
Show newest version
/*
    This file is part of Peers, a java SIP softphone.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see .
    
    Copyright 2010-2013 Yohann Martineau 
*/

package net.sourceforge.peers.rtp;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;

import net.sourceforge.peers.Logger;
import net.sourceforge.peers.media.AbstractSoundManager;

/**
 * can be instantiated on UAC INVITE sending or on UAS 200 OK sending
 */
public class RtpSession {

	private InetAddress remoteAddress;
	private int remotePort;
	private DatagramSocket datagramSocket;
	private ExecutorService executorService;
	private List rtpListeners;
	private RtpParser rtpParser;
	private FileOutputStream rtpSessionOutput;
	private FileOutputStream rtpSessionInput;
	private boolean mediaDebug;
	private Logger logger;
	private String peersHome;

	public RtpSession(InetAddress localAddress, DatagramSocket datagramSocket, boolean mediaDebug, Logger logger,
			String peersHome) {
		this.mediaDebug = mediaDebug;
		this.logger = logger;
		this.peersHome = peersHome;
		this.datagramSocket = datagramSocket;
		rtpListeners = new ArrayList();
		rtpParser = new RtpParser(logger);
		executorService = Executors.newSingleThreadExecutor();
	}

	public synchronized void start() {
		if (mediaDebug) {
			SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
			String date = simpleDateFormat.format(new Date());
			String dir = peersHome + File.separator + AbstractSoundManager.MEDIA_DIR + File.separator;
			String fileName = dir + date + "_rtp_session.output";
			try {
				rtpSessionOutput = new FileOutputStream(fileName);
				fileName = dir + date + "_rtp_session.input";
				rtpSessionInput = new FileOutputStream(fileName);
			} catch (FileNotFoundException e) {
				logger.error("cannot create file", e);
				return;
			}
		}
		executorService.submit(new Receiver());
	}

	public void stop() {
		// AccessController.doPrivileged added for plugin compatibility
		AccessController.doPrivileged(new PrivilegedAction() {
			public Void run() {
				executorService.shutdown();
				return null;
			}
		});
	}

	public void addRtpListener(RtpListener rtpListener) {
		rtpListeners.add(rtpListener);
	}

	public synchronized void send(RtpPacket rtpPacket) {
		if (datagramSocket == null) {
			return;
		}
		
		if (!datagramSocket.isClosed()) {
			byte[] buf = rtpParser.encode(rtpPacket);
			final DatagramPacket datagramPacket = new DatagramPacket(buf, buf.length, remoteAddress, remotePort);
			// AccessController.doPrivileged added for plugin compatibility
			AccessController.doPrivileged(new PrivilegedAction() {

				@Override
				public Void run() {
					try {
						datagramSocket.send(datagramPacket);
					} catch (IOException e) {
						logger.error("cannot send rtp packet", e);
					} catch (SecurityException e) {
						logger.error("security exception", e);
					}
					return null;
				}
			});

			if (mediaDebug) {
				try {
					rtpSessionOutput.write(buf);
				} catch (IOException e) {
					logger.error("cannot write to file", e);
				}
			}
		}
	}

	public void setRemoteAddress(InetAddress remoteAddress) {
		this.remoteAddress = remoteAddress;
	}

	public void setRemotePort(int remotePort) {
		this.remotePort = remotePort;
	}

	private void closeFileAndDatagramSocket() {
		if (mediaDebug) {
			try {
				rtpSessionOutput.close();
			} catch (IOException e) {
				logger.error("cannot close file", e);
			}
			try {
				rtpSessionInput.close();
			} catch (IOException e) {
				logger.error("cannot close file", e);
			}
		}
		// AccessController.doPrivileged added for plugin compatibility
		AccessController.doPrivileged(new PrivilegedAction() {
			@Override
			public Void run() {
				datagramSocket.close();
				datagramSocket = null;
				return null;
			}
		});

	}

	class Receiver implements Runnable {

		@Override
		public void run() {
			int receiveBufferSize;
			try {
				receiveBufferSize = datagramSocket.getReceiveBufferSize();
			} catch (SocketException e) {
				logger.error("cannot get datagram socket receive buffer size", e);
				return;
			}
			byte[] buf = new byte[receiveBufferSize];
			final DatagramPacket datagramPacket = new DatagramPacket(buf, buf.length);
			final int noException = 0;
			final int socketTimeoutException = 1;
			final int ioException = 2;
			int result = AccessController.doPrivileged(new PrivilegedAction() {
				public Integer run() {
					try {
						if (isSocketClosed()) {
							logger.info("Receiver datagramSocket is closed , skip to receive !");
						}else{
							datagramSocket.receive(datagramPacket);
						}
					} catch (SocketTimeoutException e) {
						return socketTimeoutException;
					} catch (IOException e) {
						logger.error("cannot receive packet", e);
						return ioException;
					}
					return noException;
				}
			});
			switch (result) {
			case socketTimeoutException:
				try {
					executorService.execute(this);
				} catch (RejectedExecutionException rej) {
					closeFileAndDatagramSocket();
				}
				return;
			case ioException:
				return;
			case noException:
				break;
			default:
				break;
			}
			InetAddress gettedRemoteAddress = datagramPacket.getAddress();
			if (gettedRemoteAddress != null && !gettedRemoteAddress.equals(remoteAddress)) {
				remoteAddress = gettedRemoteAddress;
			}
			int gettedRemotePort = datagramPacket.getPort();
			if (gettedRemotePort != remotePort) {
				remotePort = gettedRemotePort;
			}
			byte[] data = datagramPacket.getData();
			int offset = datagramPacket.getOffset();
			int length = datagramPacket.getLength();
			byte[] trimmedData = new byte[length];
			System.arraycopy(data, offset, trimmedData, 0, length);
			if (mediaDebug) {
				try {
					rtpSessionInput.write(trimmedData);
				} catch (IOException e) {
					logger.error("cannot write to file", e);
				}
			}
			RtpPacket rtpPacket = rtpParser.decode(trimmedData);
			for (RtpListener rtpListener : rtpListeners) {
				rtpListener.receivedRtpPacket(rtpPacket);
			}
			try {
				executorService.execute(this);
			} catch (RejectedExecutionException rej) {
				closeFileAndDatagramSocket();
			}
		}

	}

	public boolean isSocketClosed() {
		if (datagramSocket == null) {
			return true;
		}
		return datagramSocket.isClosed();
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy