001: ///////////////////////////////////////////////////////////////////////////////
002: //
003: // This program is free software; you can redistribute it and/or modify
004: // it under the terms of the GNU General Public License and GNU Library
005: // General Public License as published by the Free Software Foundation;
006: // either version 2, or (at your option) any later version.
007: //
008: // This program is distributed in the hope that it will be useful,
009: // but WITHOUT ANY WARRANTY; without even the implied warranty of
010: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
011: // GNU General Public License and GNU Library General Public License
012: // for more details.
013: //
014: // You should have received a copy of the GNU General Public License
015: // and GNU Library General Public License along with this program; if
016: // not, write to the Free Software Foundation, 675 Mass Ave, Cambridge,
017: // MA 02139, USA.
018: //
019: ///////////////////////////////////////////////////////////////////////////////
020:
021: package org.rdesktop.server.rdp.rdp5;
022:
023: import java.io.IOException;
024: import java.lang.reflect.Array;
025:
026: import org.rdesktop.server.rdp.*;
027: import org.rdesktop.server.rdp.crypto.CryptoException;
028:
029: public class VChannels {
030: public static final int WAVE_FORMAT_PCM = 1;
031: public static final int WAVE_FORMAT_ADPCM = 2;
032: public static final int WAVE_FORMAT_ALAW = 6;
033: public static final int WAVE_FORMAT_MULAW = 7;
034:
035: public static final int MAX_CHANNELS = 4;
036: public static final int CHANNEL_OPTION_INITIALIZED = 0x80000000;
037: public static final int CHANNEL_OPTION_ENCRYPT_RDP = 0x40000000;
038: public static final int CHANNEL_OPTION_COMPRESS_RDP = 0x00800000;
039: public static final int CHANNEL_OPTION_SHOW_PROTOCOL = 0x00200000;
040:
041: public static final int CHANNEL_CHUNK_LENGTH = 1600;
042: public static final int CHANNEL_FLAG_FIRST = 0x01;
043: public static final int CHANNEL_FLAG_LAST = 0x02;
044: public static final int CHANNEL_FLAG_SHOW_PROTOCOL = 0x10;
045:
046: public static final int STATUS_SUCCESS = 0x00000000;
047: public static final int STATUS_ACCESS_DENIED = 0xc0000022;
048: public static final int STATUS_INVALID_PARAMETER = 0xc000000d;
049: public static final int STATUS_INVALID_DEVICE_REQUEST = 0xc0000010;
050:
051: private int m_num_channels;
052: private byte[] m_fragment_buffer = null;
053: private VChannel m_channels[] = new VChannel[MAX_CHANNELS];
054:
055: protected static Object arrayExpand(Object a, int amount) {
056: Class cl = a.getClass();
057: if (cl.isArray() == false) {
058: return null;
059: }
060:
061: int length = Array.getLength(a);
062: int newLength = length + amount;
063:
064: Class componentType = a.getClass().getComponentType();
065: Object newArray = Array.newInstance(componentType, newLength);
066: System.arraycopy(a, 0, newArray, 0, length);
067: return newArray;
068: }
069:
070: protected static byte[] append(byte[] target, byte[] source) {
071: if (target == null || target.length <= 0) {
072: return source;
073: } else if (source == null || source.length <= 0) {
074: return target;
075: } else {
076: byte[] out = (byte[]) arrayExpand(target, source.length);
077: System.arraycopy(source, 0, out, target.length,
078: source.length);
079: return out;
080: }
081: }
082:
083: public VChannels() {
084: m_channels = new VChannel[MAX_CHANNELS];
085: }
086:
087: public int num_channels() {
088: return m_num_channels;
089: }
090:
091: public int mcs_id(int c) {
092: return RdpMCS.MCS_GLOBAL_CHANNEL + 1 + c;
093: }
094:
095: public VChannel channel(int c) {
096: if (c < m_num_channels) {
097: return m_channels[c];
098: } else {
099: return null;
100: }
101: }
102:
103: public VChannel find_channel_by_channelno(int channelno) {
104: if (channelno > RdpMCS.MCS_GLOBAL_CHANNEL + m_num_channels) {
105: return null;
106: } else {
107: return m_channels[channelno - RdpMCS.MCS_GLOBAL_CHANNEL - 1];
108: }
109: }
110:
111: public void clear() {
112: m_channels = new VChannel[MAX_CHANNELS];
113: m_num_channels = 0;
114: }
115:
116: public boolean register(VChannel v) throws RdpDesktopException {
117: if (RdpOptions.use_rdp5 == false) {
118: return false;
119: }
120:
121: if (m_num_channels >= MAX_CHANNELS) {
122: throw new RdpDesktopException(
123: "Channel table full. Could not register channel.");
124: }
125:
126: m_channels[m_num_channels] = v;
127: v.set_mcs_id(RdpMCS.MCS_GLOBAL_CHANNEL + 1 + m_num_channels);
128: m_num_channels++;
129:
130: return true;
131: }
132:
133: public void channel_process(RdpPacket data, int mcsChannel)
134: throws RdpDesktopException, IOException, CryptoException {
135: int i;
136: int flags;
137: int length;
138: int this length = 0;
139: VChannel channel = null;
140:
141: for (i = 0; i < m_num_channels; i++) {
142: if (mcs_id(i) == mcsChannel) {
143: channel = m_channels[i];
144: break;
145: }
146: }
147:
148: if (i >= m_num_channels) {
149: return;
150: }
151:
152: length = data.getLittleEndian32();
153: flags = data.getLittleEndian32();
154:
155: if (((flags & CHANNEL_FLAG_FIRST) != 0)
156: && ((flags & CHANNEL_FLAG_LAST) != 0)) {
157: channel.process(data);
158: } else {
159: byte[] content = new byte[data.getEnd()
160: - data.getPosition()];
161: data.copyToByteArray(content, 0, data.getPosition(),
162: content.length);
163: m_fragment_buffer = append(m_fragment_buffer, content);
164:
165: if ((flags & CHANNEL_FLAG_LAST) != 0) {
166: RdpPacket fullpacket = new RdpPacket(
167: m_fragment_buffer.length);
168: fullpacket.copyFromByteArray(m_fragment_buffer, 0, 0,
169: m_fragment_buffer.length);
170: channel.process(fullpacket);
171: m_fragment_buffer = null;
172: }
173: }
174: }
175: }
|