    001    package com.skype.ipc;
    002
    003    import java.io.EOFException;
    004    import java.io.File;
    005    import java.io.FileNotFoundException;
    006    import java.io.FileOutputStream;
    007    import java.io.IOException;
    008    import java.io.InputStream;
    009    import java.io.OutputStream;
    010    import java.net.InetAddress;
    011    import java.net.InetSocketAddress;
    012    import java.net.Socket;
    013    import java.net.SocketAddress;
    014
    015    import com.skype.util.Log;
    016
    017    public class TCPSocketTransport implements Transport {
    018
    019            // INTERFACE IMPLEMENTATION
    020            private static final String TAG = "TCPSocketTransport";
    021
    022            public TCPSocketTransport(String IpAddress, int Port) {
    023                    super();
    024                    this.mIpAddress = IpAddress;
    025                    this.mPort = Port;
    026                    buffer=new byte[BUFFERSIZE];
    027                    bufferidx=0;
    028                    bufferend=0;
    029                    try {
    030                            mInetAddress = InetAddress.getByName(mIpAddress);
    031                            mSocketAddress = new InetSocketAddress(mInetAddress, mPort);
    032                    } catch (java.net.UnknownHostException e) {
    033                            Log.d(TAG,"UnknownHost: "+ e.getMessage());
    034                    }
    035            }
    036
    037            private String mIpAddress = null;
    038            private int mPort = 0;
    039            private boolean mConnected = false;
    040            private Socket mSocket;
    041            private InetAddress mInetAddress;
    042            private SocketAddress mSocketAddress;
    043            private static int mSocketTimeout = 1 * 1000;  // x * 1 sec(in millis)
    044            private boolean isLogging = false;
    045        private FileOutputStream logFileOut = null;
    046        private FileOutputStream logFileIn = null;
    047
    048            public boolean connect() throws IOException {
    049                    Log.d(TAG, "TCPSocketTransport::connect() called");
    050                    if (!mConnected) {
    051                            try {
    052                    mSocket = new Socket(); // create unconnected socket
    053                                    mSocket.connect(mSocketAddress, mSocketTimeout);
    054
    055                                    Log.d(TAG,"Socket created:"+mSocket);
    056                                    // Get the input/output streams
    057                                    ins = mSocket.getInputStream();
    058                                    outs = mSocket.getOutputStream();
    059
    060                                    // We successfully connected our socket
    061                                    mConnected = true;
    062                            } catch (java.net.UnknownHostException e) {
    063                                    Log.e(TAG,"UnknownHost: "+ e.getMessage());
    064                            } catch (java.io.IOException e) {
    065                                    Log.e(TAG,"IO: "+e.getMessage());
    066                            }
    067                    }
    068                    return mConnected;
    069            }
    070
    071            public void disconnect() throws IOException {
    072                    if (mConnected) {
    073                            try {
    074                                    ins.close();
    075                                    ins = null;
    076                                    outs.close();
    077                                    outs = null;
    078                                    mSocket.close();
    079                            } catch (IOException e) {
    080                                    Log.e(e.getClass().getName(), e.getMessage());
    081                            }
    082                            mConnected = false;
    083                    }
    084            }
    085
    086            public boolean isConnected() throws IOException {
    087                    return mConnected;
    088        }
    089
    090            @Override
    091        public void startLogging(String logFileName)
    092        {
    093            assert( ! isLogging);
    094
    095            if (logFileName != null && ! logFileName.isEmpty()) {
    096                try {
    097                    logFileOut = new FileOutputStream(new File(logFileName + ".out.bin"), false);
    098                    logFileIn  = new FileOutputStream(new File(logFileName + ".in.bin"), false);
    099                    isLogging = true;
    100                    Log.d(TAG, "Transport logging started");
    101                }
    102                catch (FileNotFoundException e) {
    103                    Log.e(TAG, "Unable to open transport log files using:" + logFileName);
    104                }
    105            }
    106            }
    107
    108        public int peek() throws IOException
    109        {
    110            // Log.d(TAG, "TCPSocketTransport::peek() called");
    111            synchronized (ins) {
    112                return (ReadByte(true));
    113            }
    114        }
    115
    116            public int read() throws IOException
    117            {
    118                synchronized(ins)
    119                {
    120                    return(ReadByte(false));
    121                }
    122            }
    123
    124            public int read(int numBytes, byte[] bytes) throws IOException
    125            {
    126                synchronized(ins)
    127                {
    128                    for(int n=0;n<numBytes;n++)
    129                    {
    130                        bytes[n]=ReadByte(false);
    131                    }
    132                }
    133                    return numBytes;
    134                    /*
    135                    if (mConnected) {
    136                            try {
    137                                    instream.read(bytes, 0, numBytes);
    138                            }
    139                            catch (IOException e) {
    140                                    Log.e(e.getClass().getName(), e.getMessage());
    141                            }
    142                    }
    143                    return true;
    144                     */
    145            }
    146
    147            public int read(int numBytes, byte[] bytes, boolean requirenumbytes) throws IOException
    148            {
    149                    if(!requirenumbytes)
    150                    {
    151                            return read(numBytes,bytes);
    152                    }
    153                    for(int n=0;n<numBytes;n++)
    154                    {
    155                        synchronized(ins)
    156                        {
    157                            bytes[n]=ReadByte(false);
    158                        }
    159                    }
    160                    //Log.d(TAG, "TCPSocketTransport - bytes read from chunk are:");
    161                    //dumpBytes(bytes,numBytes);
    162                    return numBytes;
    163            }
    164
    165            public boolean write(byte b) throws IOException {
    166                    if (mConnected) {
    167                            try {
    168                                    synchronized(outs)
    169                                    {
    170                                            outs.write(b);
    171                                            //Log.d(TAG,"Write: " + Integer.toHexString(b & 0xFF) + " " + (char)b + " " + (int)(b & 0xFF));
    172                                            if (isLogging) {
    173                                                logFileOut.write(b);
    174                                            }
    175                                    }
    176                            }
    177                            catch (EOFException e) {
    178                                Log.e(TAG, e.getMessage());
    179                                throw e;
    180                            }
    181                            catch (IOException e) {
    182                                    Log.e(TAG, e.getMessage());
    183                                    throw e;
    184                            }
    185                    }
    186                    return true;
    187            }
    188
    189            public boolean write(int numBytes, byte[] bytes) throws IOException
    190            {
    191                    if (mConnected) {
    192                            try {
    193                                    synchronized(outs)
    194                                    {
    195                                            outs.write(bytes, 0, numBytes);
    196    //                                      for(int i=0;i<numBytes;i++)
    197    //                                      {
    198    //                                              Log.d(TAG,"Write: " + Integer.toHexString(bytes[i] & 0xFF) + " " + (char)bytes[i] + " " + (int)(bytes[i] & 0xFF));
    199    //                                      }
    200                                            if (isLogging) {
    201                                                logFileOut.write(bytes,0, numBytes);
    202                                            }
    203                                    }
    204                            }
    205                            catch (IOException e) {
    206                                    Log.e(e.getClass().getName(), e.getMessage());
    207                                    throw e;
    208                            }
    209                    }
    210                    return true;
    211            }
    212
    213            public InputStream GetInputStream()
    214            {
    215                    return ins;
    216            }
    217
    218            public OutputStream GetOutputStream()
    219            {
    220                    return outs;
    221            }
    222
    223            //// CLASS INTERNALS
    224
    225            public static final int BUFFERSIZE=1024*64; //bytes
    226            public static final int STREAMTIMEOUT=1000*60*10; //ms
    227
    228            private InputStream ins;
    229            private OutputStream outs;
    230            private byte[] buffer;
    231            private int bufferidx;
    232            private int bufferend;
    233
    234            private byte ReadByte(boolean peek) throws IOException
    235            {
    236                    //Log.d(TAG,"ReadByte entered");
    237                    while(bufferidx==bufferend)
    238                    {
    239                            //Log.d(TAG, "Transport buffer reading more...");
    240                            bufferidx=0;
    241                            bufferend=0;
    242                            bufferend=ins.read(buffer); // blocks
    243
    244                            if(bufferend==-1)
    245                            {
    246                                    Log.e(TAG,"Socket transport is returning -1.");
    247                                    mConnected = false;
    248                                    throw new EOFException("Socket transport stream EOF");
    249                            }
    250                            else
    251                            {
    252                                    //Log.d(TAG, "Transport buffer read some more...");
    253                            }
    254                    }
    255                    byte retbyte=buffer[bufferidx];
    256                    if(peek)
    257                    {
    258    //                      Log.d(TAG,"Peek: " + Integer.toHexString(retbyte & 0xFF) + " " + (char)retbyte + " " + (int)(retbyte & 0xFF));
    259                    }
    260                    else
    261                    {
    262    //                      Log.d(TAG,"Read: " + Integer.toHexString(retbyte & 0xFF) + " " + (char)retbyte + " " + (int)(retbyte & 0xFF));
    263                if (isLogging) {
    264                    logFileIn.write(retbyte);
    265                }
    266
    267                            bufferidx++;
    268                    }
    269                    return retbyte;
    270            }
    271
    272            @Override
    273            public boolean hasMore() throws IOException {
    274                    return !(bufferidx==bufferend);
    275            }
    276    }