001 /**
002 * Copyright (C) 2010, Skype Limited
003 *
004 * All intellectual property rights, including but not limited to copyrights,
005 * trademarks and patents, as well as know how and trade secrets contained in,
006 * relating to, or arising from the internet telephony software of
007 * Skype Limited (including its affiliates, "Skype"), including without
008 * limitation this source code, Skype API and related material of such
009 * software proprietary to Skype and/or its licensors ("IP Rights") are and
010 * shall remain the exclusive property of Skype and/or its licensors.
011 * The recipient hereby acknowledges and agrees that any unauthorized use of
012 * the IP Rights is a violation of intellectual property laws.
013 *
014 * Skype reserves all rights and may take legal action against infringers of
015 * IP Rights.
016 *
017 * The recipient agrees not to remove, obscure, make illegible or alter any
018 * notices or indications of the IP Rights and/or Skype's rights and
019 * ownership thereof.
020 */
021
022 package com.skype.ipc;
023
024 import java.io.ByteArrayOutputStream;
025 import java.io.IOException;
026
027 import com.skype.util.Log;
028
029 public class Request {
030 private static final String TAG = "Request";
031 ByteArrayOutputStream tokens;
032 protected int oid;
033 private int listdepth;
034
035 public Request() {
036 tokens = new ByteArrayOutputStream(128);
037 tokens.write('Z');
038 listdepth=0;
039 }
040
041 public byte[] send() {
042 terminateList();
043 tokens.write('z');
044 byte[] res = tokens.toByteArray();
045 tokens = null;
046 return res;
047 }
048
049 void encodeVarint(int i) {
050 //Log.d(TAG,"encoding Varint "+i);
051 int number = i;
052 if (i >= 0) number = number << 1;
053 else number = (number << 1) ^ (~0);
054 encodeVaruint(number);
055 }
056
057 void encodeVaruint(int i) {
058 //Log.d(TAG,"encoding Varuint "+i);
059 int number = i;
060 while(true) {
061 int towrite = number & 0x7f;
062 number = number >> 7;
063 if (number == 0) {
064 tokens.write(towrite);
065 break;
066 }
067 tokens.write(0x80|towrite);
068 }
069 }
070
071 /*
072 'u' - encodeVaruint
073 'e' - encodeVaruint
074 'o' - encodeVaruint
075 */
076
077 void encodeObjectid(Object o) {
078 Log.d(TAG,"next encoded varuint "+o+" is objectid");
079 encodeVaruint(o.hashCode());
080 }
081
082 /*
083 'O' - encodeObjectid
084 */
085
086 void encodeString(String s) {
087 //Log.d(TAG,"encoding string '"+s+"'");
088 byte[] bytes = s.getBytes();
089 encodeVaruint(bytes.length);
090 try {
091 if (bytes.length > 0)
092 tokens.write(bytes);
093 } catch (IOException e) {
094 e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
095 }
096
097 /*
098 'S' - encodeString
099 'X' - encodeString
100 'f' - encodeString
101 */
102 }
103
104 void encodeBinary(byte[] bytes) {
105 encodeVaruint(bytes.length);
106 try {
107 if (bytes.length > 0)
108 tokens.write(bytes);
109 } catch (IOException e) {
110 e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
111 }
112
113 /*
114 'B' - encodeBinary
115 */
116 }
117
118 public void addParm(int kind, int tag, String val) {
119 terminateList();
120 //Log.d(TAG,"addParm kind="+kind+",tag="+tag+",(String)val="+val);
121 if (kind != 'S' && kind != 'X' && kind != 'f' && kind != 'B')
122 {
123 Log.e(TAG,"Illegal kind '" + (char)kind + " is not allowed to Strings.");
124 //throw new IllegalArgumentException("Kind '" + (char)kind + " is not allowed to Strings");
125 }
126 tokens.write(kind);
127 if (tag == 0) oid = val.hashCode();
128 encodeVaruint(tag);
129 encodeString(val);
130 }
131
132 public void addParm(int kind, int tag, byte[] val) {
133 terminateList();
134 if(kind!='B')
135 {
136 Log.e(TAG,"Illegal kind '" + (char)kind + " is not allowed to bytearrays.");
137 //throw new IllegalArgumentException("Kind '" + (char)kind + " is not allowed to Strings");
138 }
139 tokens.write(kind);
140 encodeVaruint(tag);
141 encodeBinary(val);
142 }
143
144 public void addParm(int kind, int tag, Number val) {
145 terminateList();
146 //Log.d(TAG,"addParm kind="+kind+",tag="+tag+",(Number)val="+val);
147 if (kind == 'u' || kind == 'e' || kind == 'o' || kind == 'O')
148 {
149 tokens.write(kind);
150 if (tag == 0) oid = val.hashCode();
151 encodeVaruint(tag);
152 encodeVaruint(val.intValue());
153 }
154 else if (kind == 'i')
155 {
156 tokens.write(kind);
157 if (tag == 0) oid = val.hashCode();
158 encodeVaruint(tag);
159 encodeVarint(val.intValue());
160 }
161 else
162 {
163 Log.e(TAG,"Illegal kind '" + (char)kind + "' is not allowed to Number. Parameter not added.");
164 //throw new IllegalArgumentException("Kind '" + (char)kind + "' is not allowed to Number");
165 }
166 }
167
168 public void addParm(int kind, int tag, int val) {
169 terminateList();
170 //Log.d(TAG,"addParm kind="+kind+",tag="+tag+",(int)val="+val);
171 addParm(kind, tag, new Integer(val));
172 }
173
174 public void addParm(int kind, int tag, boolean val) {
175 terminateList();
176 //Log.d(TAG,"addParm kind="+kind+",tag="+tag+",(boolean)val="+val);
177 if (kind != 'b')
178 {
179 Log.e(TAG,"Illegal kind '" + (char)kind + " is not allowed to booleans.");
180 //throw new IllegalArgumentException("Kind '" + (char)kind + " is not allowed to booleans");
181 }
182 tokens.write((val)?'T':'F');
183 tokens.write(tag);
184 }
185
186 // LIST FUNCTIONS
187
188 public void addListStart(int tag)
189 {
190 tokens.write('[');
191 encodeVaruint(tag);
192 listdepth++;
193 if(listdepth>1)
194 {
195 Log.e(TAG,"Nested lists are not supported!!");
196 }
197 }
198
199 private void terminateList()
200 {
201 if(listdepth>0)
202 {
203 tokens.write(']');
204 listdepth--;
205 }
206 }
207
208 public void addParm(int kind, String val) {
209 //terminateList();
210 //Log.d(TAG,"addParm kind="+kind+",tag="+tag+",(String)val="+val);
211 if (kind != 'S' && kind != 'X' && kind != 'f' && kind != 'B')
212 throw new IllegalArgumentException("Kind '" + (char)kind + " is not allowed to Strings");
213 tokens.write(kind);
214 encodeString(val);
215 }
216
217 public void addParm(int kind, byte[] val) {
218 //terminateList();
219 if(kind!='B')
220 throw new IllegalArgumentException("Kind '" + (char)kind + " is not allowed to Strings");
221 tokens.write(kind);
222 String temps=new String(val);
223 encodeString(temps);
224 }
225
226 public void addParm(int kind, Number val) {
227 //terminateList();
228 //Log.d(TAG,"addParm kind="+kind+",tag="+tag+",(Number)val="+val);
229 if (kind == 'u' || kind == 'e' || kind == 'o' || kind == 'O')
230 {
231 tokens.write(kind);
232 encodeVaruint(val.intValue());
233 }
234 else if (kind == 'i')
235 {
236 tokens.write(kind);
237 encodeVarint(val.intValue());
238 }
239 else
240 {
241 throw new IllegalArgumentException("Kind '" + (char)kind + " is not allowed to Number");
242 }
243 }
244
245 public void addParm(int kind, int val) {
246 //terminateList();
247 //Log.d(TAG,"addParm kind="+kind+",tag="+tag+",(int)val="+val);
248 addParm(kind, new Integer(val));
249 }
250
251 public void addParm(int kind, boolean val) {
252 //terminateList();
253 //Log.d(TAG,"addParm kind="+kind+",tag="+tag+",(boolean)val="+val);
254 if (kind != 'b') throw new IllegalArgumentException("Kind '" + (char)kind + " is not allowed to booleans");
255 tokens.write((val)?'T':'F');
256 }
257 /*
258 public void addParm(int kind, int tag, Object val) {
259 //Log.d(TAG,"addParm kind="+kind+",tag="+tag+",(Object)val="+val);
260 //Log.d(TAG,val);
261 if (val instanceof boolean[] || val instanceof int[] || val instanceof String[] || val instanceof Collection) {
262 tokens.write('[');
263 encodeVaruint(tag);
264 if (val instanceof String[]) Log.d(TAG,"is array");
265 if (val instanceof Collection) Log.d(TAG,"is Collection");
266 // TODO: arrays support.
267 tokens.write(']');
268 }
269 }
270 */
271 }
272
273