    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