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