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