1363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang/* 2363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Copyright (C) 2010 The Android Open Source Project 3363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 4363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Licensed under the Apache License, Version 2.0 (the "License"); 5363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * you may not use this file except in compliance with the License. 6363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * You may obtain a copy of the License at 7363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 8363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * http://www.apache.org/licenses/LICENSE-2.0 9363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 10363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Unless required by applicable law or agreed to in writing, software 11363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * distributed under the License is distributed on an "AS IS" BASIS, 12363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * See the License for the specific language governing permissions and 14363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * limitations under the License. 15363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 16363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 17363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangpackage android.net.rtp; 18363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 19363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangimport java.net.InetAddress; 20363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangimport java.net.Inet4Address; 21363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangimport java.net.Inet6Address; 22363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangimport java.net.SocketException; 23363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 24363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang/** 2532e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * RtpStream represents the base class of streams which send and receive network 2632e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * packets with media payloads over Real-time Transport Protocol (RTP). 2753aa6ef70d8692277f9403f94d43918ad9712dd0Chia-chi Yeh * 2853aa6ef70d8692277f9403f94d43918ad9712dd0Chia-chi Yeh * <p class="note">Using this class requires 2953aa6ef70d8692277f9403f94d43918ad9712dd0Chia-chi Yeh * {@link android.Manifest.permission#INTERNET} permission.</p> 30363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 31363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wangpublic class RtpStream { 3232e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh /** 3332e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * This mode indicates that the stream sends and receives packets at the 3432e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * same time. This is the initial mode for new streams. 3532e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh */ 36363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public static final int MODE_NORMAL = 0; 3732e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh 3832e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh /** 3932e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * This mode indicates that the stream only sends packets. 4032e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh */ 41363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public static final int MODE_SEND_ONLY = 1; 4232e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh 4332e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh /** 4432e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * This mode indicates that the stream only receives packets. 4532e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh */ 46363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public static final int MODE_RECEIVE_ONLY = 2; 47363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 4853aa6ef70d8692277f9403f94d43918ad9712dd0Chia-chi Yeh private static final int MODE_LAST = 2; 4953aa6ef70d8692277f9403f94d43918ad9712dd0Chia-chi Yeh 50363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang private final InetAddress mLocalAddress; 51363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang private final int mLocalPort; 52363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 53363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang private InetAddress mRemoteAddress; 54363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang private int mRemotePort = -1; 55363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang private int mMode = MODE_NORMAL; 56363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 57e66950506c473e660f2e5762d7a71e13808be387Chia-chi Yeh private int mSocket = -1; 58363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang static { 59363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang System.loadLibrary("rtp_jni"); 60363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 61363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 62363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 63363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Creates a RtpStream on the given local address. Note that the local 64363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * port is assigned automatically to conform with RFC 3550. 65363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 66363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param address The network address of the local host to bind to. 67363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @throws SocketException if the address cannot be bound or a problem 68363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * occurs during binding. 69363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 70363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang RtpStream(InetAddress address) throws SocketException { 71363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang mLocalPort = create(address.getHostAddress()); 72363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang mLocalAddress = address; 73363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 74363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 75363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang private native int create(String address) throws SocketException; 76363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 77363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 78363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Returns the network address of the local host. 79363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 80363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public InetAddress getLocalAddress() { 81363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang return mLocalAddress; 82363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 83363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 84363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 85363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Returns the network port of the local host. 86363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 87363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public int getLocalPort() { 88363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang return mLocalPort; 89363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 90363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 91363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 92363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Returns the network address of the remote host or {@code null} if the 93363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * stream is not associated. 94363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 95363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public InetAddress getRemoteAddress() { 96363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang return mRemoteAddress; 97363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 98363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 99363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 100363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Returns the network port of the remote host or {@code -1} if the stream 101363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * is not associated. 102363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 103363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public int getRemotePort() { 104363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang return mRemotePort; 105363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 106363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 107363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 10832e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * Returns {@code true} if the stream is busy. In this case most of the 10932e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * setter methods are disabled. This method is intended to be overridden 11032e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * by subclasses. 111363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 112363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public boolean isBusy() { 113363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang return false; 114363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 115363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 116363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 11732e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * Returns the current mode. 118363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 119363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public int getMode() { 120363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang return mMode; 121363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 122363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 123363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 124363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Changes the current mode. It must be one of {@link #MODE_NORMAL}, 125363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * {@link #MODE_SEND_ONLY}, and {@link #MODE_RECEIVE_ONLY}. 126363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 127363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param mode The mode to change to. 128363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @throws IllegalArgumentException if the mode is invalid. 129363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @throws IllegalStateException if the stream is busy. 130363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @see #isBusy() 131363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 132363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public void setMode(int mode) { 133363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang if (isBusy()) { 134363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throw new IllegalStateException("Busy"); 135363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 13653aa6ef70d8692277f9403f94d43918ad9712dd0Chia-chi Yeh if (mode < 0 || mode > MODE_LAST) { 137363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throw new IllegalArgumentException("Invalid mode"); 138363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 139363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang mMode = mode; 140363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 141363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 142363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 14332e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * Associates with a remote host. This defines the destination of the 14432e106b7bdd57c82ee67705871f6116d92bce79bChia-chi Yeh * outgoing packets. 145363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 146363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param address The network address of the remote host. 147363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @param port The network port of the remote host. 148363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @throws IllegalArgumentException if the address is not supported or the 149363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * port is invalid. 150363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @throws IllegalStateException if the stream is busy. 151363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @see #isBusy() 152363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 153363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public void associate(InetAddress address, int port) { 154363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang if (isBusy()) { 155363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throw new IllegalStateException("Busy"); 156363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 157363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang if (!(address instanceof Inet4Address && mLocalAddress instanceof Inet4Address) && 158363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang !(address instanceof Inet6Address && mLocalAddress instanceof Inet6Address)) { 159363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throw new IllegalArgumentException("Unsupported address"); 160363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 161363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang if (port < 0 || port > 65535) { 162363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang throw new IllegalArgumentException("Invalid port"); 163363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 164363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang mRemoteAddress = address; 165363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang mRemotePort = port; 166363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 167363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 168e66950506c473e660f2e5762d7a71e13808be387Chia-chi Yeh int getSocket() { 169e66950506c473e660f2e5762d7a71e13808be387Chia-chi Yeh return mSocket; 170e66950506c473e660f2e5762d7a71e13808be387Chia-chi Yeh } 171363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 172363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang /** 173363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * Releases allocated resources. The stream becomes inoperable after calling 174363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * this method. 175363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * 176363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @throws IllegalStateException if the stream is busy. 177363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang * @see #isBusy() 178363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang */ 179363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang public void release() { 180e66950506c473e660f2e5762d7a71e13808be387Chia-chi Yeh synchronized (this) { 181e66950506c473e660f2e5762d7a71e13808be387Chia-chi Yeh if (isBusy()) { 182e66950506c473e660f2e5762d7a71e13808be387Chia-chi Yeh throw new IllegalStateException("Busy"); 183e66950506c473e660f2e5762d7a71e13808be387Chia-chi Yeh } 184e66950506c473e660f2e5762d7a71e13808be387Chia-chi Yeh close(); 185363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 186363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 187363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 188e66950506c473e660f2e5762d7a71e13808be387Chia-chi Yeh private native void close(); 189363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang 190363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang @Override 191363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang protected void finalize() throws Throwable { 192363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang close(); 193363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang super.finalize(); 194363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang } 195363c2ab82cca4f095e9e0c8465e28f6d27a24bf8Chung-yih Wang} 196