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 Log.d(TAG,"New request...");
037 tokens = new ByteArrayOutputStream(128);
038 tokens.write('Z');
039 listdepth=0;
040 }
041
042 public byte[] send() {
043 terminateList();
044 tokens.write('z');
045 byte[] res = tokens.toByteArray();
046 tokens = null;
047 return res;
048 }
049
050 void encodeVarint(int i) {
051 //Log.d(TAG,"encoding Varint "+i);
052 int number = i;
053 if (i >= 0) number = number << 1;
054 else number = (number << 1) ^ (~0);
055 encodeVaruint(number);
056 }
057
058 void encodeVaruint(int i) {
059 //Log.d(TAG,"encoding Varuint "+i);
060 int number = i;
061 while(true) {
062 int towrite = number & 0x7f;
063 number = number >> 7;
064 if (number == 0) {
065 tokens.write(towrite);
066 break;
067 }
068 tokens.write(0x80|towrite);
069 }
070 }
071
072 /*
073 'u' - encodeVaruint
074 'e' - encodeVaruint
075 'o' - encodeVaruint
076 */
077
078 void encodeObjectid(Object o) {
079 Log.d(TAG,"next encoded varuint "+o+" is objectid");
080 encodeVaruint(o.hashCode());
081 }
082
083 /*
084 'O' - encodeObjectid
085 */
086
087 void encodeString(String s) {
088 //Log.d(TAG,"encoding string '"+s+"'");
089 byte[] bytes = s.getBytes();
090 encodeVaruint(bytes.length);
091 try {
092 if (bytes.length > 0)
093 tokens.write(bytes);
094 } catch (IOException e) {
095 e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
096 }
097
098 /*
099 'S' - encodeString
100 'X' - encodeString
101 'f' - encodeString
102 */
103 }
104
105 void encodeBinary(byte[] bytes) {
106 encodeVaruint(bytes.length);
107 try {
108 if (bytes.length > 0)
109 tokens.write(bytes);
110 } catch (IOException e) {
111 e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
112 }
113
114 /*
115 'B' - encodeBinary
116 */
117 }
118
119 public void addParm(int kind, int tag, String val) {
120 terminateList();
121 //Log.d(TAG,"addParm kind="+kind+",tag="+tag+",(String)val="+val);
122 if (kind != 'S' && kind != 'X' && kind != 'f' && kind != 'B')
123 {
124 Log.e(TAG,"Illegal kind '" + (char)kind + " is not allowed to Strings.");
125 //throw new IllegalArgumentException("Kind '" + (char)kind + " is not allowed to Strings");
126 }
127 tokens.write(kind);
128 if (tag == 0) oid = val.hashCode();
129 encodeVaruint(tag);
130 encodeString(val);
131 }
132
133 public void addParm(int kind, int tag, byte[] val) {
134 terminateList();
135 if(kind!='B')
136 {
137 Log.e(TAG,"Illegal kind '" + (char)kind + " is not allowed to bytearrays.");
138 //throw new IllegalArgumentException("Kind '" + (char)kind + " is not allowed to Strings");
139 }
140 tokens.write(kind);
141 encodeVaruint(tag);
142 encodeBinary(val);
143 }
144
145 public void addParm(int kind, int tag, Number val) {
146 terminateList();
147 //Log.d(TAG,"addParm kind="+kind+",tag="+tag+",(Number)val="+val);
148 if (kind == 'u' || kind == 'e' || kind == 'o' || kind == 'O')
149 {
150 tokens.write(kind);
151 if (tag == 0) oid = val.hashCode();
152 encodeVaruint(tag);
153 encodeVaruint(val.intValue());
154 }
155 else if (kind == 'i')
156 {
157 tokens.write(kind);
158 if (tag == 0) oid = val.hashCode();
159 encodeVaruint(tag);
160 encodeVarint(val.intValue());
161 }
162 else
163 {
164 Log.e(TAG,"Illegal kind '" + (char)kind + "' is not allowed to Number. Parameter not added.");
165 //throw new IllegalArgumentException("Kind '" + (char)kind + "' is not allowed to Number");
166 }
167 }
168
169 public void addParm(int kind, int tag, int val) {
170 terminateList();
171 //Log.d(TAG,"addParm kind="+kind+",tag="+tag+",(int)val="+val);
172 addParm(kind, tag, new Integer(val));
173 }
174
175 public void addParm(int kind, int tag, boolean val) {
176 terminateList();
177 //Log.d(TAG,"addParm kind="+kind+",tag="+tag+",(boolean)val="+val);
178 if (kind != 'b')
179 {
180 Log.e(TAG,"Illegal kind '" + (char)kind + " is not allowed to booleans.");
181 //throw new IllegalArgumentException("Kind '" + (char)kind + " is not allowed to booleans");
182 }
183 tokens.write((val)?'T':'F');
184 tokens.write(tag);
185 }
186
187 // LIST FUNCTIONS
188
189 public void addListStart(int tag)
190 {
191 tokens.write('[');
192 encodeVaruint(tag);
193 listdepth++;
194 if(listdepth>1)
195 {
196 Log.e(TAG,"Nested lists are not supported!!");
197 }
198 }
199
200 private void terminateList()
201 {
202 if(listdepth>0)
203 {
204 tokens.write(']');
205 listdepth--;
206 }
207 }
208
209 public void addParm(int kind, String val) {
210 //terminateList();
211 //Log.d(TAG,"addParm kind="+kind+",tag="+tag+",(String)val="+val);
212 if (kind != 'S' && kind != 'X' && kind != 'f' && kind != 'B')
213 throw new IllegalArgumentException("Kind '" + (char)kind + " is not allowed to Strings");
214 tokens.write(kind);
215 encodeString(val);
216 }
217
218 public void addParm(int kind, byte[] val) {
219 //terminateList();
220 if(kind!='B')
221 throw new IllegalArgumentException("Kind '" + (char)kind + " is not allowed to Strings");
222 tokens.write(kind);
223 String temps=new String(val);
224 encodeString(temps);
225 }
226
227 public void addParm(int kind, Number val) {
228 //terminateList();
229 //Log.d(TAG,"addParm kind="+kind+",tag="+tag+",(Number)val="+val);
230 if (kind == 'u' || kind == 'e' || kind == 'o' || kind == 'O')
231 {
232 tokens.write(kind);
233 encodeVaruint(val.intValue());
234 }
235 else if (kind == 'i')
236 {
237 tokens.write(kind);
238 encodeVarint(val.intValue());
239 }
240 else
241 {
242 throw new IllegalArgumentException("Kind '" + (char)kind + " is not allowed to Number");
243 }
244 }
245
246 public void addParm(int kind, int val) {
247 //terminateList();
248 //Log.d(TAG,"addParm kind="+kind+",tag="+tag+",(int)val="+val);
249 addParm(kind, new Integer(val));
250 }
251
252 public void addParm(int kind, boolean val) {
253 //terminateList();
254 //Log.d(TAG,"addParm kind="+kind+",tag="+tag+",(boolean)val="+val);
255 if (kind != 'b') throw new IllegalArgumentException("Kind '" + (char)kind + " is not allowed to booleans");
256 tokens.write((val)?'T':'F');
257 }
258 /*
259 public void addParm(int kind, int tag, Object val) {
260 //Log.d(TAG,"addParm kind="+kind+",tag="+tag+",(Object)val="+val);
261 //Log.d(TAG,val);
262 if (val instanceof boolean[] || val instanceof int[] || val instanceof String[] || val instanceof Collection) {
263 tokens.write('[');
264 encodeVaruint(tag);
265 if (val instanceof String[]) Log.d(TAG,"is array");
266 if (val instanceof Collection) Log.d(TAG,"is Collection");
267 // TODO: arrays support.
268 tokens.write(']');
269 }
270 }
271 */
272 }
273
274