summaryrefslogtreecommitdiffstats
path: root/voip/java/android/net/rtp/RtpStream.java
blob: b9d75cd07824e5c32b966688d808553a6146709c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net.rtp;

import java.net.InetAddress;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.SocketException;

/**
 * RtpStream represents the base class of streams which send and receive network
 * packets with media payloads over Real-time Transport Protocol (RTP).
 *
 * <p class="note">Using this class requires
 * {@link android.Manifest.permission#INTERNET} permission.</p>
 */
public class RtpStream {
    /**
     * This mode indicates that the stream sends and receives packets at the
     * same time. This is the initial mode for new streams.
     */
    public static final int MODE_NORMAL = 0;

    /**
     * This mode indicates that the stream only sends packets.
     */
    public static final int MODE_SEND_ONLY = 1;

    /**
     * This mode indicates that the stream only receives packets.
     */
    public static final int MODE_RECEIVE_ONLY = 2;

    private static final int MODE_LAST = 2;

    private final InetAddress mLocalAddress;
    private final int mLocalPort;

    private InetAddress mRemoteAddress;
    private int mRemotePort = -1;
    private int mMode = MODE_NORMAL;

    private int mSocket = -1;
    static {
        System.loadLibrary("rtp_jni");
    }

    /**
     * Creates a RtpStream on the given local address. Note that the local
     * port is assigned automatically to conform with RFC 3550.
     *
     * @param address The network address of the local host to bind to.
     * @throws SocketException if the address cannot be bound or a problem
     *     occurs during binding.
     */
    RtpStream(InetAddress address) throws SocketException {
        mLocalPort = create(address.getHostAddress());
        mLocalAddress = address;
    }

    private native int create(String address) throws SocketException;

    /**
     * Returns the network address of the local host.
     */
    public InetAddress getLocalAddress() {
        return mLocalAddress;
    }

    /**
     * Returns the network port of the local host.
     */
    public int getLocalPort() {
        return mLocalPort;
    }

    /**
     * Returns the network address of the remote host or {@code null} if the
     * stream is not associated.
     */
    public InetAddress getRemoteAddress() {
        return mRemoteAddress;
    }

    /**
     * Returns the network port of the remote host or {@code -1} if the stream
     * is not associated.
     */
    public int getRemotePort() {
        return mRemotePort;
    }

    /**
     * Returns {@code true} if the stream is busy. In this case most of the
     * setter methods are disabled. This method is intended to be overridden
     * by subclasses.
     */
    public boolean isBusy() {
        return false;
    }

    /**
     * Returns the current mode.
     */
    public int getMode() {
        return mMode;
    }

    /**
     * Changes the current mode. It must be one of {@link #MODE_NORMAL},
     * {@link #MODE_SEND_ONLY}, and {@link #MODE_RECEIVE_ONLY}.
     *
     * @param mode The mode to change to.
     * @throws IllegalArgumentException if the mode is invalid.
     * @throws IllegalStateException if the stream is busy.
     * @see #isBusy()
     */
    public void setMode(int mode) {
        if (isBusy()) {
            throw new IllegalStateException("Busy");
        }
        if (mode < 0 || mode > MODE_LAST) {
            throw new IllegalArgumentException("Invalid mode");
        }
        mMode = mode;
    }

    /**
     * Associates with a remote host. This defines the destination of the
     * outgoing packets.
     *
     * @param address The network address of the remote host.
     * @param port The network port of the remote host.
     * @throws IllegalArgumentException if the address is not supported or the
     *     port is invalid.
     * @throws IllegalStateException if the stream is busy.
     * @see #isBusy()
     */
    public void associate(InetAddress address, int port) {
        if (isBusy()) {
            throw new IllegalStateException("Busy");
        }
        if (!(address instanceof Inet4Address && mLocalAddress instanceof Inet4Address) &&
                !(address instanceof Inet6Address && mLocalAddress instanceof Inet6Address)) {
            throw new IllegalArgumentException("Unsupported address");
        }
        if (port < 0 || port > 65535) {
            throw new IllegalArgumentException("Invalid port");
        }
        mRemoteAddress = address;
        mRemotePort = port;
    }

    int getSocket() {
        return mSocket;
    }

    /**
     * Releases allocated resources. The stream becomes inoperable after calling
     * this method.
     *
     * @throws IllegalStateException if the stream is busy.
     * @see #isBusy()
     */
    public void release() {
        synchronized (this) {
            if (isBusy()) {
                throw new IllegalStateException("Busy");
            }
            close();
        }
    }

    private native void close();

    @Override
    protected void finalize() throws Throwable {
        close();
        super.finalize();
    }
}