    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