198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang/* 298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Copyright (C) 2010 The Android Open Source Project 398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Licensed under the Apache License, Version 2.0 (the "License"); 598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * you may not use this file except in compliance with the License. 698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * You may obtain a copy of the License at 798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * http://www.apache.org/licenses/LICENSE-2.0 998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 1098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Unless required by applicable law or agreed to in writing, software 1198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * distributed under the License is distributed on an "AS IS" BASIS, 1298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * See the License for the specific language governing permissions and 1498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * limitations under the License. 1598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 1698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 1798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangpackage android.net.rtp; 1898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 1998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangimport java.net.InetAddress; 2098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangimport java.net.Inet4Address; 2198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangimport java.net.Inet6Address; 2298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangimport java.net.SocketException; 2398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 2498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang/** 257f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * RtpStream represents the base class of streams which send and receive network 267f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * packets with media payloads over Real-time Transport Protocol (RTP). 27a54e36694b3909ef367867eb7516b2d6f6031261Chia-chi Yeh * 28a54e36694b3909ef367867eb7516b2d6f6031261Chia-chi Yeh * <p class="note">Using this class requires 29a54e36694b3909ef367867eb7516b2d6f6031261Chia-chi Yeh * {@link android.Manifest.permission#INTERNET} permission.</p> 3098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 3198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wangpublic class RtpStream { 327f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh /** 337f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * This mode indicates that the stream sends and receives packets at the 347f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * same time. This is the initial mode for new streams. 357f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh */ 3698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang public static final int MODE_NORMAL = 0; 377f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh 387f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh /** 397f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * This mode indicates that the stream only sends packets. 407f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh */ 4198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang public static final int MODE_SEND_ONLY = 1; 427f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh 437f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh /** 447f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * This mode indicates that the stream only receives packets. 457f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh */ 4698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang public static final int MODE_RECEIVE_ONLY = 2; 4798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 48a54e36694b3909ef367867eb7516b2d6f6031261Chia-chi Yeh private static final int MODE_LAST = 2; 49a54e36694b3909ef367867eb7516b2d6f6031261Chia-chi Yeh 5098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang private final InetAddress mLocalAddress; 5198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang private final int mLocalPort; 5298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 5398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang private InetAddress mRemoteAddress; 5498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang private int mRemotePort = -1; 5598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang private int mMode = MODE_NORMAL; 5698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 572bf2e642d061e7b48dd71927752e9151a5126fb2Chia-chi Yeh private int mSocket = -1; 5898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang static { 5998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang System.loadLibrary("rtp_jni"); 6098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 6198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 6298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 6398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Creates a RtpStream on the given local address. Note that the local 6498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * port is assigned automatically to conform with RFC 3550. 6598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 6698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param address The network address of the local host to bind to. 6798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @throws SocketException if the address cannot be bound or a problem 6898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * occurs during binding. 6998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 7098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang RtpStream(InetAddress address) throws SocketException { 7198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang mLocalPort = create(address.getHostAddress()); 7298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang mLocalAddress = address; 7398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 7498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 7598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang private native int create(String address) throws SocketException; 7698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 7798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 7898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Returns the network address of the local host. 7998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 8098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang public InetAddress getLocalAddress() { 8198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang return mLocalAddress; 8298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 8398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 8498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 8598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Returns the network port of the local host. 8698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 8798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang public int getLocalPort() { 8898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang return mLocalPort; 8998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 9098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 9198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 9298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Returns the network address of the remote host or {@code null} if the 9398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * stream is not associated. 9498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 9598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang public InetAddress getRemoteAddress() { 9698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang return mRemoteAddress; 9798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 9898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 9998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 10098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Returns the network port of the remote host or {@code -1} if the stream 10198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * is not associated. 10298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 10398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang public int getRemotePort() { 10498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang return mRemotePort; 10598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 10698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 10798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 1087f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * Returns {@code true} if the stream is busy. In this case most of the 1097f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * setter methods are disabled. This method is intended to be overridden 1107f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * by subclasses. 11198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 11298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang public boolean isBusy() { 11398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang return false; 11498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 11598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 11698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 1177f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * Returns the current mode. 11898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 11998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang public int getMode() { 12098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang return mMode; 12198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 12298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 12398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 12498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Changes the current mode. It must be one of {@link #MODE_NORMAL}, 12598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * {@link #MODE_SEND_ONLY}, and {@link #MODE_RECEIVE_ONLY}. 12698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 12798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param mode The mode to change to. 12898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @throws IllegalArgumentException if the mode is invalid. 12998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @throws IllegalStateException if the stream is busy. 13098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @see #isBusy() 13198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 13298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang public void setMode(int mode) { 13398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang if (isBusy()) { 13498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang throw new IllegalStateException("Busy"); 13598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 136a54e36694b3909ef367867eb7516b2d6f6031261Chia-chi Yeh if (mode < 0 || mode > MODE_LAST) { 13798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang throw new IllegalArgumentException("Invalid mode"); 13898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 13998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang mMode = mode; 14098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 14198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 14298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 1437f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * Associates with a remote host. This defines the destination of the 1447f383063fafc54a41f91540a41bf987003fd2502Chia-chi Yeh * outgoing packets. 14598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 14698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param address The network address of the remote host. 14798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @param port The network port of the remote host. 14898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @throws IllegalArgumentException if the address is not supported or the 14998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * port is invalid. 15098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @throws IllegalStateException if the stream is busy. 15198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @see #isBusy() 15298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 15398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang public void associate(InetAddress address, int port) { 15498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang if (isBusy()) { 15598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang throw new IllegalStateException("Busy"); 15698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 15798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang if (!(address instanceof Inet4Address && mLocalAddress instanceof Inet4Address) && 15898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang !(address instanceof Inet6Address && mLocalAddress instanceof Inet6Address)) { 15998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang throw new IllegalArgumentException("Unsupported address"); 16098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 16198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang if (port < 0 || port > 65535) { 16298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang throw new IllegalArgumentException("Invalid port"); 16398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 16498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang mRemoteAddress = address; 16598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang mRemotePort = port; 16698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 16798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 1682bf2e642d061e7b48dd71927752e9151a5126fb2Chia-chi Yeh int getSocket() { 1692bf2e642d061e7b48dd71927752e9151a5126fb2Chia-chi Yeh return mSocket; 1702bf2e642d061e7b48dd71927752e9151a5126fb2Chia-chi Yeh } 17198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 17298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang /** 17398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * Releases allocated resources. The stream becomes inoperable after calling 17498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * this method. 17598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * 17698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @throws IllegalStateException if the stream is busy. 17798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang * @see #isBusy() 17898cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang */ 17998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang public void release() { 1802bf2e642d061e7b48dd71927752e9151a5126fb2Chia-chi Yeh synchronized (this) { 1812bf2e642d061e7b48dd71927752e9151a5126fb2Chia-chi Yeh if (isBusy()) { 1822bf2e642d061e7b48dd71927752e9151a5126fb2Chia-chi Yeh throw new IllegalStateException("Busy"); 1832bf2e642d061e7b48dd71927752e9151a5126fb2Chia-chi Yeh } 1842bf2e642d061e7b48dd71927752e9151a5126fb2Chia-chi Yeh close(); 18598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 18698cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 18798cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 1882bf2e642d061e7b48dd71927752e9151a5126fb2Chia-chi Yeh private native void close(); 18998cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang 19098cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang @Override 19198cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang protected void finalize() throws Throwable { 19298cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang close(); 19398cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang super.finalize(); 19498cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang } 19598cee0ce2354234e72bafb836864ec10a490ea4dChung-yih Wang} 196