Full Code of koush/android-websockets for AI

master d18376158a78 cached
22 files
64.7 KB
14.2k tokens
136 symbols
1 requests
Download .txt
Repository: koush/android-websockets
Branch: master
Commit: d18376158a78
Files: 22
Total size: 64.7 KB

Directory structure:
gitextract_fsf22rvj/

├── .gitignore
├── AndroidManifest.xml
├── README.md
├── android-websockets.iml
├── ant.properties
├── build.xml
├── proguard-project.txt
└── src/
    └── com/
        ├── codebutler/
        │   └── android_websockets/
        │       ├── HybiParser.java
        │       └── WebSocketClient.java
        └── koushikdutta/
            ├── async/
            │   ├── http/
            │   │   └── socketio/
            │   │       ├── Acknowledge.java
            │   │       ├── ConnectCallback.java
            │   │       ├── DisconnectCallback.java
            │   │       ├── ErrorCallback.java
            │   │       ├── EventCallback.java
            │   │       ├── EventEmitter.java
            │   │       ├── JSONCallback.java
            │   │       ├── ReconnectCallback.java
            │   │       ├── SocketIOClient.java
            │   │       ├── SocketIOConnection.java
            │   │       └── StringCallback.java
            │   └── util/
            │       └── HashList.java
            └── http/
                └── AsyncHttpClient.java

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
bin
gen
.classpath
.project
local.properties
/.settings
project.properties


================================================
FILE: AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.codebutler.android_websockets"
    android:versionCode="1"
    android:versionName="0.01">
    
    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="8" />
</manifest>


================================================
FILE: README.md
================================================
# THIS LIBRARY IS DEPRECATED IN FAVOR OF:

[AndroidAsync](https://github.com/koush/AndroidAsync)








# WebSocket and Socket.IO client for Android

## Credits

The hybi parser is based on code from the [faye project](https://github.com/faye/faye-websocket-node). Faye is Copyright (c) 2009-2012 James Coglan. Many thanks for the great open-source library!

The hybi parser was ported from JavaScript to Java by [Eric Butler](https://twitter.com/codebutler) <eric@codebutler.com>.

The WebSocket client was written by [Eric Butler](https://twitter.com/codebutler) <eric@codebutler.com>.

The Socket.IO client was written by [Koushik Dutta](https://twitter.com/koush).

The Socket.IO client component was ported from Koushik Dutta's AndroidAsync(https://github.com/koush/AndroidAsync) by [Vinay S Shenoy](https://twitter.com/vinaysshenoy)

## WebSocket Usage

```java
List<BasicNameValuePair> extraHeaders = Arrays.asList(
    new BasicNameValuePair("Cookie", "session=abcd")
);

WebSocketClient client = new WebSocketClient(URI.create("wss://irccloud.com"), new WebSocketClient.Listener() {
    @Override
    public void onConnect() {
        Log.d(TAG, "Connected!");
    }

    @Override
    public void onMessage(String message) {
        Log.d(TAG, String.format("Got string message! %s", message));
    }

    @Override
    public void onMessage(byte[] data) {
        Log.d(TAG, String.format("Got binary message! %s", toHexString(data)));
    }

    @Override
    public void onDisconnect(int code, String reason) {
        Log.d(TAG, String.format("Disconnected! Code: %d Reason: %s", code, reason));
    }

    @Override
    public void onError(Exception error) {
        Log.e(TAG, "Error!", error);
    }

}, extraHeaders);

client.connect();

// Later… 
client.send("hello!");
client.send(new byte[] { 0xDE, 0xAD, 0xBE, 0xEF });
client.disconnect();
```

## Socket.IO Usage

```java
SocketIOClient.connect("http://localhost:80", new ConnectCallback() {

    @Override
    public void onConnectCompleted(Exception ex, SocketIOClient client) {
        
        if (ex != null) {
            return;
        }

        //Save the returned SocketIOClient instance into a variable so you can disconnect it later
        client.setDisconnectCallback(MainActivity.this);
        client.setErrorCallback(MainActivity.this);
        client.setJSONCallback(MainActivity.this);
        client.setStringCallback(MainActivity.this);
        
        //You need to explicitly specify which events you are interested in receiving
        client.addListener("news", MainActivity.this);

        client.of("/chat", new ConnectCallback() {
        
            @Override
            public void onConnectCompleted(Exception ex, SocketIOClient client) {
                
                if (ex != null) {
                    ex.printStackTrace();
                    return;
                }

                //This client instance will be using the same websocket as the original client, 
                //but will point to the indicated endpoint
                client.setDisconnectCallback(MainActivity.this);
                client.setErrorCallback(MainActivity.this);
                client.setJSONCallback(MainActivity.this);
                client.setStringCallback(MainActivity.this);
                client.addListener("a message", MainActivity.this);

            }
        });

    }
}, new Handler());

        
@Override
public void onEvent(String event, JSONArray argument, Acknowledge acknowledge) {
    try {
        Log.d("MainActivity", "Event:" + event + "Arguments:"
                + argument.toString(2));
    } catch (JSONException e) {
        e.printStackTrace();
    }

}

@Override
public void onString(String string, Acknowledge acknowledge) {
    Log.d("MainActivity", string);

}

@Override
public void onJSON(JSONObject json, Acknowledge acknowledge) {
    try {
        Log.d("MainActivity", "json:" + json.toString(2));
    } catch (JSONException e) {
        e.printStackTrace();
    }

}

@Override
public void onError(String error) {
    Log.d("MainActivity", error);

}

@Override
public void onDisconnect(Exception e) {
    Log.d(mComponentTag, "Disconnected:" + e.getMessage());

}

```



## TODO

* Run [autobahn tests](http://autobahn.ws/testsuite)
* Investigate using [naga](http://code.google.com/p/naga/) instead of threads.

## License

(The MIT License)
	
	Copyright (c) 2009-2012 James Coglan
	Copyright (c) 2012 Eric Butler 
	Copyright (c) 2012 Koushik Dutta 
	
	Permission is hereby granted, free of charge, to any person obtaining a copy of
	this software and associated documentation files (the 'Software'), to deal in
	the Software without restriction, including without limitation the rights to use,
	copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
	Software, and to permit persons to whom the Software is furnished to do so,
	subject to the following conditions:
	
	The above copyright notice and this permission notice shall be included in all
	copies or substantial portions of the Software.
	
	THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
	FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
	COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
	IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
	CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
	 


================================================
FILE: android-websockets.iml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
  <component name="FacetManager">
    <facet type="android" name="Android">
      <configuration>
        <option name="GEN_FOLDER_RELATIVE_PATH_APT" value="/gen" />
        <option name="GEN_FOLDER_RELATIVE_PATH_AIDL" value="/gen" />
        <option name="MANIFEST_FILE_RELATIVE_PATH" value="/AndroidManifest.xml" />
        <option name="RES_FOLDER_RELATIVE_PATH" value="/res" />
        <option name="ASSETS_FOLDER_RELATIVE_PATH" value="/assets" />
        <option name="LIBS_FOLDER_RELATIVE_PATH" value="/libs" />
        <option name="REGENERATE_R_JAVA" value="true" />
        <option name="REGENERATE_JAVA_BY_AIDL" value="true" />
        <option name="USE_CUSTOM_APK_RESOURCE_FOLDER" value="false" />
        <option name="CUSTOM_APK_RESOURCE_FOLDER" value="" />
        <option name="USE_CUSTOM_COMPILER_MANIFEST" value="false" />
        <option name="CUSTOM_COMPILER_MANIFEST" value="" />
        <option name="APK_PATH" value="" />
        <option name="LIBRARY_PROJECT" value="true" />
        <option name="RUN_PROCESS_RESOURCES_MAVEN_TASK" value="true" />
        <option name="GENERATE_UNSIGNED_APK" value="false" />
        <option name="CUSTOM_DEBUG_KEYSTORE_PATH" value="" />
        <option name="PACK_TEST_CODE" value="false" />
        <option name="RUN_PROGUARD" value="false" />
        <option name="PROGUARD_CFG_PATH" value="/proguard.cfg" />
        <resOverlayFolders>
          <path>/res-overlay</path>
        </resOverlayFolders>
      </configuration>
    </facet>
  </component>
  <component name="NewModuleRootManager" inherit-compiler-output="true">
    <exclude-output />
    <content url="file://$MODULE_DIR$">
      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
      <sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" />
    </content>
    <orderEntry type="jdk" jdkName="Android 4.0 Platform" jdkType="Android SDK" />
    <orderEntry type="sourceFolder" forTests="false" />
  </component>
</module>



================================================
FILE: ant.properties
================================================
# This file is used to override default values used by the Ant build system.
#
# This file must be checked into Version Control Systems, as it is
# integral to the build system of your project.

# This file is only used by the Ant script.

# You can use this to override default values such as
#  'source.dir' for the location of your java source folder and
#  'out.dir' for the location of your output folder.

# You can also use it define how the release builds are signed by declaring
# the following properties:
#  'key.store' for the location of your keystore and
#  'key.alias' for the name of the key to use.
# The password will be asked during the build when you use the 'release' target.



================================================
FILE: build.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project name="android-websockets" default="help">

    <!-- The local.properties file is created and updated by the 'android' tool.
         It contains the path to the SDK. It should *NOT* be checked into
         Version Control Systems. -->
    <property file="local.properties" />

    <!-- The ant.properties file can be created by you. It is only edited by the
         'android' tool to add properties to it.
         This is the place to change some Ant specific build properties.
         Here are some properties you may want to change/update:

         source.dir
             The name of the source directory. Default is 'src'.
         out.dir
             The name of the output directory. Default is 'bin'.

         For other overridable properties, look at the beginning of the rules
         files in the SDK, at tools/ant/build.xml

         Properties related to the SDK location or the project target should
         be updated using the 'android' tool with the 'update' action.

         This file is an integral part of the build system for your
         application and should be checked into Version Control Systems.

         -->
    <property file="ant.properties" />

    <!-- if sdk.dir was not set from one of the property file, then
         get it from the ANDROID_HOME env var.
         This must be done before we load project.properties since
         the proguard config can use sdk.dir -->
    <property environment="env" />
    <condition property="sdk.dir" value="${env.ANDROID_HOME}">
        <isset property="env.ANDROID_HOME" />
    </condition>

    <!-- The project.properties file is created and updated by the 'android'
         tool, as well as ADT.

         This contains project specific properties such as project target, and library
         dependencies. Lower level build properties are stored in ant.properties
         (or in .classpath for Eclipse projects).

         This file is an integral part of the build system for your
         application and should be checked into Version Control Systems. -->
    <loadproperties srcFile="project.properties" />

    <!-- quick check on sdk.dir -->
    <fail
            message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
            unless="sdk.dir"
    />

    <!--
        Import per project custom build rules if present at the root of the project.
        This is the place to put custom intermediary targets such as:
            -pre-build
            -pre-compile
            -post-compile (This is typically used for code obfuscation.
                           Compiled code location: ${out.classes.absolute.dir}
                           If this is not done in place, override ${out.dex.input.absolute.dir})
            -post-package
            -post-build
            -pre-clean
    -->
    <import file="custom_rules.xml" optional="true" />

    <!-- Import the actual build file.

         To customize existing targets, there are two options:
         - Customize only one target:
             - copy/paste the target into this file, *before* the
               <import> task.
             - customize it to your needs.
         - Customize the whole content of build.xml
             - copy/paste the content of the rules files (minus the top node)
               into this file, replacing the <import> task.
             - customize to your needs.

         ***********************
         ****** IMPORTANT ******
         ***********************
         In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
         in order to avoid having your file be overridden by tools such as "android update project"
    -->
    <!-- version-tag: 1 -->
    <import file="${sdk.dir}/tools/ant/build.xml" />

</project>


================================================
FILE: proguard-project.txt
================================================
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}


================================================
FILE: src/com/codebutler/android_websockets/HybiParser.java
================================================
//
// HybiParser.java: draft-ietf-hybi-thewebsocketprotocol-13 parser
//
// Based on code from the faye project.
// https://github.com/faye/faye-websocket-node
// Copyright (c) 2009-2012 James Coglan
//
// Ported from Javascript to Java by Eric Butler <eric@codebutler.com>
//
// (The MIT License)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

package com.codebutler.android_websockets;

import android.util.Log;

import java.io.*;
import java.util.Arrays;
import java.util.List;

public class HybiParser {
    private static final String TAG = "HybiParser";

    private WebSocketClient mClient;

    private boolean mMasking = true;

    private int     mStage;

    private boolean mFinal;
    private boolean mMasked;
    private int     mOpcode;
    private int     mLengthSize;
    private int     mLength;
    private int     mMode;

    private byte[] mMask    = new byte[0];
    private byte[] mPayload = new byte[0];

    private boolean mClosed = false;

    private ByteArrayOutputStream mBuffer = new ByteArrayOutputStream();

    private static final int BYTE   = 255;
    private static final int FIN    = 128;
    private static final int MASK   = 128;
    private static final int RSV1   =  64;
    private static final int RSV2   =  32;
    private static final int RSV3   =  16;
    private static final int OPCODE =  15;
    private static final int LENGTH = 127;

    private static final int MODE_TEXT   = 1;
    private static final int MODE_BINARY = 2;

    private static final int OP_CONTINUATION =  0;
    private static final int OP_TEXT         =  1;
    private static final int OP_BINARY       =  2;
    private static final int OP_CLOSE        =  8;
    private static final int OP_PING         =  9;
    private static final int OP_PONG         = 10;

    private static final List<Integer> OPCODES = Arrays.asList(
        OP_CONTINUATION,
        OP_TEXT,
        OP_BINARY,
        OP_CLOSE,
        OP_PING,
        OP_PONG
    );

    private static final List<Integer> FRAGMENTED_OPCODES = Arrays.asList(
        OP_CONTINUATION, OP_TEXT, OP_BINARY
    );

    public HybiParser(WebSocketClient client) {
        mClient = client;
    }

    private static byte[] mask(byte[] payload, byte[] mask, int offset) {
        if (mask.length == 0) return payload;

        for (int i = 0; i < payload.length - offset; i++) {
            payload[offset + i] = (byte) (payload[offset + i] ^ mask[i % 4]);
        }
        return payload;
    }

    public void start(HappyDataInputStream stream) throws IOException {
        while (true) {
            if (stream.available() == -1) break;
            switch (mStage) {
                case 0:
                    parseOpcode(stream.readByte());
                    break;
                case 1:
                    parseLength(stream.readByte());
                    break;
                case 2:
                    parseExtendedLength(stream.readBytes(mLengthSize));
                    break;
                case 3:
                    mMask = stream.readBytes(4);
                    mStage = 4;
                    break;
                case 4:
                    mPayload = stream.readBytes(mLength);
                    emitFrame();
                    mStage = 0;
                    break;
            }
        }
        mClient.getListener().onDisconnect(0, "EOF");
    }

    private void parseOpcode(byte data) throws ProtocolError {
        boolean rsv1 = (data & RSV1) == RSV1;
        boolean rsv2 = (data & RSV2) == RSV2;
        boolean rsv3 = (data & RSV3) == RSV3;

        if (rsv1 || rsv2 || rsv3) {
            throw new ProtocolError("RSV not zero");
        }

        mFinal   = (data & FIN) == FIN;
        mOpcode  = (data & OPCODE);
        mMask    = new byte[0];
        mPayload = new byte[0];

        if (!OPCODES.contains(mOpcode)) {
            throw new ProtocolError("Bad opcode");
        }

        if (!FRAGMENTED_OPCODES.contains(mOpcode) && !mFinal) {
            throw new ProtocolError("Expected non-final packet");
        }

        mStage = 1;
    }

    private void parseLength(byte data) {
        mMasked = (data & MASK) == MASK;
        mLength = (data & LENGTH);

        if (mLength >= 0 && mLength <= 125) {
            mStage = mMasked ? 3 : 4;
        } else {
            mLengthSize = (mLength == 126) ? 2 : 8;
            mStage      = 2;
        }
    }

    private void parseExtendedLength(byte[] buffer) throws ProtocolError {
        mLength = getInteger(buffer);
        mStage  = mMasked ? 3 : 4;
    }

    public byte[] frame(String data) {
        return frame(data, OP_TEXT, -1);
    }

    public byte[] frame(byte[] data) {
        return frame(data, OP_BINARY, -1);
    }

    private byte[] frame(byte[] data, int opcode, int errorCode)  {
        return frame((Object)data, opcode, errorCode);
    }

    private byte[] frame(String data, int opcode, int errorCode) {
        return frame((Object)data, opcode, errorCode);
    }

    private byte[] frame(Object data, int opcode, int errorCode) {
        if (mClosed) return null;

        Log.d(TAG, "Creating frame for: " + data + " op: " + opcode + " err: " + errorCode);

        byte[] buffer = (data instanceof String) ? decode((String) data) : (byte[]) data;
        int insert = (errorCode > 0) ? 2 : 0;
        int length = buffer.length + insert;
        int header = (length <= 125) ? 2 : (length <= 65535 ? 4 : 10);
        int offset = header + (mMasking ? 4 : 0);
        int masked = mMasking ? MASK : 0;
        byte[] frame = new byte[length + offset];

        frame[0] = (byte) ((byte)FIN | (byte)opcode);

        if (length <= 125) {
            frame[1] = (byte) (masked | length);
        } else if (length <= 65535) {
            frame[1] = (byte) (masked | 126);
            frame[2] = (byte) Math.floor(length / 256);
            frame[3] = (byte) (length & BYTE);
        } else {
            frame[1] = (byte) (masked | 127);
            frame[2] = (byte) (((int) Math.floor(length / Math.pow(2, 56))) & BYTE);
            frame[3] = (byte) (((int) Math.floor(length / Math.pow(2, 48))) & BYTE);
            frame[4] = (byte) (((int) Math.floor(length / Math.pow(2, 40))) & BYTE);
            frame[5] = (byte) (((int) Math.floor(length / Math.pow(2, 32))) & BYTE);
            frame[6] = (byte) (((int) Math.floor(length / Math.pow(2, 24))) & BYTE);
            frame[7] = (byte) (((int) Math.floor(length / Math.pow(2, 16))) & BYTE);
            frame[8] = (byte) (((int) Math.floor(length / Math.pow(2, 8)))  & BYTE);
            frame[9] = (byte) (length & BYTE);
        }

        if (errorCode > 0) {
            frame[offset] = (byte) (((int) Math.floor(errorCode / 256)) & BYTE);
            frame[offset+1] = (byte) (errorCode & BYTE);
        }
        System.arraycopy(buffer, 0, frame, offset + insert, buffer.length);

        if (mMasking) {
            byte[] mask = {
                (byte) Math.floor(Math.random() * 256), (byte) Math.floor(Math.random() * 256),
                (byte) Math.floor(Math.random() * 256), (byte) Math.floor(Math.random() * 256)
            };
            System.arraycopy(mask, 0, frame, header, mask.length);
            mask(frame, mask, offset);
        }

        return frame;
    }

    public void ping(String message) {
        mClient.send(frame(message, OP_PING, -1));
    }

    public void close(int code, String reason) {
        if (mClosed) return;
        mClient.send(frame(reason, OP_CLOSE, code));
        mClosed = true;
    }

    private void emitFrame() throws IOException {
        byte[] payload = mask(mPayload, mMask, 0);
        int opcode = mOpcode;

        if (opcode == OP_CONTINUATION) {
            if (mMode == 0) {
                throw new ProtocolError("Mode was not set.");
            }
            mBuffer.write(payload);
            if (mFinal) {
                byte[] message = mBuffer.toByteArray();
                if (mMode == MODE_TEXT) {
                    mClient.getListener().onMessage(encode(message));
                } else {
                    mClient.getListener().onMessage(message);
                }
                reset();
            }

        } else if (opcode == OP_TEXT) {
            if (mFinal) {
                String messageText = encode(payload);
                mClient.getListener().onMessage(messageText);
            } else {
                mMode = MODE_TEXT;
                mBuffer.write(payload);
            }

        } else if (opcode == OP_BINARY) {
            if (mFinal) {
                mClient.getListener().onMessage(payload);
            } else {
                mMode = MODE_BINARY;
                mBuffer.write(payload);
            }

        } else if (opcode == OP_CLOSE) {
            int    code   = (payload.length >= 2) ? 256 * payload[0] + payload[1] : 0;
            String reason = (payload.length >  2) ? encode(slice(payload, 2))     : null;
            Log.d(TAG, "Got close op! " + code + " " + reason);
            mClient.getListener().onDisconnect(code, reason);

        } else if (opcode == OP_PING) {
            if (payload.length > 125) { throw new ProtocolError("Ping payload too large"); }
            Log.d(TAG, "Sending pong!!");
            mClient.sendFrame(frame(payload, OP_PONG, -1));

        } else if (opcode == OP_PONG) {
            String message = encode(payload);
            // FIXME: Fire callback...
            Log.d(TAG, "Got pong! " + message);
        }
    }

    private void reset() {
        mMode = 0;
        mBuffer.reset();
    }

    private String encode(byte[] buffer) {
        try {
            return new String(buffer, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    private byte[] decode(String string) {
        try {
            return (string).getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    private int getInteger(byte[] bytes) throws ProtocolError {
        long i = byteArrayToLong(bytes, 0, bytes.length);
        if (i < 0 || i > Integer.MAX_VALUE) {
            throw new ProtocolError("Bad integer: " + i);
        }
        return (int) i;
    }
    
    /**
     * Copied from AOSP Arrays.java.
     */
    /**
     * Copies elements from {@code original} into a new array, from indexes start (inclusive) to
     * end (exclusive). The original order of elements is preserved.
     * If {@code end} is greater than {@code original.length}, the result is padded
     * with the value {@code (byte) 0}.
     *
     * @param original the original array
     * @param start the start index, inclusive
     * @param end the end index, exclusive
     * @return the new array
     * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
     * @throws IllegalArgumentException if {@code start > end}
     * @throws NullPointerException if {@code original == null}
     * @since 1.6
     */
    private static byte[] copyOfRange(byte[] original, int start, int end) {
        if (start > end) {
            throw new IllegalArgumentException();
        }
        int originalLength = original.length;
        if (start < 0 || start > originalLength) {
            throw new ArrayIndexOutOfBoundsException();
        }
        int resultLength = end - start;
        int copyLength = Math.min(resultLength, originalLength - start);
        byte[] result = new byte[resultLength];
        System.arraycopy(original, start, result, 0, copyLength);
        return result;
    }

    private byte[] slice(byte[] array, int start) {
        return copyOfRange(array, start, array.length);
    }

    public static class ProtocolError extends IOException {
        public ProtocolError(String detailMessage) {
            super(detailMessage);
        }
    }

    private static long byteArrayToLong(byte[] b, int offset, int length) {
        if (b.length < length)
            throw new IllegalArgumentException("length must be less than or equal to b.length");

        long value = 0;
        for (int i = 0; i < length; i++) {
            int shift = (length - 1 - i) * 8;
            value += (b[i + offset] & 0x000000FF) << shift;
        }
        return value;
    }

    public static class HappyDataInputStream extends DataInputStream {
        public HappyDataInputStream(InputStream in) {
            super(in);
        }

        public byte[] readBytes(int length) throws IOException {
            byte[] buffer = new byte[length];

            int total = 0;

            while (total < length) {
                int count = read(buffer, total, length - total);
                if (count == -1) {
                    break;
                }
                total += count;
            }

            if (total != length) {
                throw new IOException(String.format("Read wrong number of bytes. Got: %s, Expected: %s.", total, length));
            }

            return buffer;
        }
    }
}

================================================
FILE: src/com/codebutler/android_websockets/WebSocketClient.java
================================================
package com.codebutler.android_websockets;

import android.os.Handler;
import android.os.HandlerThread;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
import org.apache.http.*;
import org.apache.http.client.HttpResponseException;
import org.apache.http.message.BasicLineParser;
import org.apache.http.message.BasicNameValuePair;

import javax.net.SocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import java.io.EOFException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.URI;
import java.security.KeyManagementException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;

public class WebSocketClient {
    private static final String TAG = "WebSocketClient";

    private URI                      mURI;
    private Listener                 mListener;
    private Socket                   mSocket;
    private Thread                   mThread;
    private HandlerThread            mHandlerThread;
    private Handler                  mHandler;
    private List<BasicNameValuePair> mExtraHeaders;
    private HybiParser               mParser;
    private boolean                  mConnected;

    private final Object mSendLock = new Object();

    private static TrustManager[] sTrustManagers;

    public static void setTrustManagers(TrustManager[] tm) {
        sTrustManagers = tm;
    }

    public WebSocketClient(URI uri, Listener listener, List<BasicNameValuePair> extraHeaders) {
        mURI          = uri;
        mListener     = listener;
        mExtraHeaders = extraHeaders;
        mConnected    = false;
        mParser       = new HybiParser(this);

        mHandlerThread = new HandlerThread("websocket-thread");
        mHandlerThread.start();
        mHandler = new Handler(mHandlerThread.getLooper());
    }

    public Listener getListener() {
        return mListener;
    }

    public void connect() {
        if (mThread != null && mThread.isAlive()) {
            return;
        }

        mThread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    int port = (mURI.getPort() != -1) ? mURI.getPort() : ((mURI.getScheme().equals("wss") || mURI.getScheme().equals("https")) ? 443 : 80);

                    String path = TextUtils.isEmpty(mURI.getPath()) ? "/" : mURI.getPath();
                    if (!TextUtils.isEmpty(mURI.getQuery())) {
                        path += "?" + mURI.getQuery();
                    }

                    String originScheme = mURI.getScheme().equals("wss") ? "https" : "http";
                    URI origin = new URI(originScheme, "//" + mURI.getHost(), null);

                    SocketFactory factory = (mURI.getScheme().equals("wss") || mURI.getScheme().equals("https")) ? getSSLSocketFactory() : SocketFactory.getDefault();
                    mSocket = factory.createSocket(mURI.getHost(), port);

                    PrintWriter out = new PrintWriter(mSocket.getOutputStream());
                    String secretKey = createSecret();
                    out.print("GET " + path + " HTTP/1.1\r\n");
                    out.print("Upgrade: websocket\r\n");
                    out.print("Connection: Upgrade\r\n");
                    out.print("Host: " + mURI.getHost() + "\r\n");
                    out.print("Origin: " + origin.toString() + "\r\n");
                    out.print("Sec-WebSocket-Key: " + secretKey + "\r\n");
                    out.print("Sec-WebSocket-Version: 13\r\n");
                    if (mExtraHeaders != null) {
                        for (NameValuePair pair : mExtraHeaders) {
                            out.print(String.format("%s: %s\r\n", pair.getName(), pair.getValue()));
                        }
                    }
                    out.print("\r\n");
                    out.flush();

                    HybiParser.HappyDataInputStream stream = new HybiParser.HappyDataInputStream(mSocket.getInputStream());

                    // Read HTTP response status line.
                    StatusLine statusLine = parseStatusLine(readLine(stream));
                    if (statusLine == null) {
                        throw new HttpException("Received no reply from server.");
                    } else if (statusLine.getStatusCode() != HttpStatus.SC_SWITCHING_PROTOCOLS) {
                        throw new HttpResponseException(statusLine.getStatusCode(), statusLine.getReasonPhrase());
                    }

                    // Read HTTP response headers.
                    String line;
                    while (!TextUtils.isEmpty(line = readLine(stream))) {
                        Header header = parseHeader(line);
                        if (header.getName().equals("Sec-WebSocket-Accept")) {
                            String expected = expectedKey(secretKey);
                            if (expected == null) {
                                throw new Exception("SHA-1 algorithm not found");
                            } else if (!expected.equals(header.getValue())) {
                                throw new Exception("Invalid Sec-WebSocket-Accept, expected: " + expected + ", got: " + header.getValue());
                            }
                        }
                    }

                    mListener.onConnect();

                    mConnected = true;

                    // Now decode websocket frames.
                    mParser.start(stream);

                } catch (EOFException ex) {
                    Log.d(TAG, "WebSocket EOF!", ex);
                    mListener.onDisconnect(0, "EOF");
                    mConnected = false;

                } catch (SSLException ex) {
                    // Connection reset by peer
                    Log.d(TAG, "Websocket SSL error!", ex);
                    mListener.onDisconnect(0, "SSL");
                    mConnected = false;

                } catch (Exception ex) {
                    mListener.onError(ex);
                }
            }
        });
        mThread.start();
    }

    public void disconnect() {
        if (mSocket != null) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    if (mSocket != null) {
                        try {
                            mSocket.close();
                        } catch (IOException ex) {
                            Log.d(TAG, "Error while disconnecting", ex);
                            mListener.onError(ex);
                        }
                        mSocket = null;
                    }
                    mConnected = false;
                }
            });
        }
    }

    public void send(String data) {
        sendFrame(mParser.frame(data));
    }

    public void send(byte[] data) {
        sendFrame(mParser.frame(data));
    }

    public boolean isConnected() {
        return mConnected;
    }

    private StatusLine parseStatusLine(String line) {
        if (TextUtils.isEmpty(line)) {
            return null;
        }
        return BasicLineParser.parseStatusLine(line, new BasicLineParser());
    }

    private Header parseHeader(String line) {
        return BasicLineParser.parseHeader(line, new BasicLineParser());
    }

    // Can't use BufferedReader because it buffers past the HTTP data.
    private String readLine(HybiParser.HappyDataInputStream reader) throws IOException {
        int readChar = reader.read();
        if (readChar == -1) {
            return null;
        }
        StringBuilder string = new StringBuilder("");
        while (readChar != '\n') {
            if (readChar != '\r') {
                string.append((char) readChar);
            }

            readChar = reader.read();
            if (readChar == -1) {
                return null;
            }
        }
        return string.toString();
    }

    private String expectedKey(String secret) {
        //concatenate, SHA1-hash, base64-encode
        try {
            final String GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
            final String secretGUID = secret + GUID;
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            byte[] digest = md.digest(secretGUID.getBytes());
            return Base64.encodeToString(digest, Base64.DEFAULT).trim();
        } catch (NoSuchAlgorithmException e) {
            return null;
        }
    }

    private String createSecret() {
        byte[] nonce = new byte[16];
        for (int i = 0; i < 16; i++) {
            nonce[i] = (byte) (Math.random() * 256);
        }
        return Base64.encodeToString(nonce, Base64.DEFAULT).trim();
    }

    void sendFrame(final byte[] frame) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                try {
                    synchronized (mSendLock) {
                        OutputStream outputStream = mSocket.getOutputStream();
                        outputStream.write(frame);
                        outputStream.flush();
                    }
                } catch (IOException e) {
                    mListener.onError(e);
                }
            }
        });
    }

    public interface Listener {
        public void onConnect();
        public void onMessage(String message);
        public void onMessage(byte[] data);
        public void onDisconnect(int code, String reason);
        public void onError(Exception error);
    }

    private SSLSocketFactory getSSLSocketFactory() throws NoSuchAlgorithmException, KeyManagementException {
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, sTrustManagers, null);
        return context.getSocketFactory();
    }
}

================================================
FILE: src/com/koushikdutta/async/http/socketio/Acknowledge.java
================================================
package com.koushikdutta.async.http.socketio;

import org.json.JSONArray;

public interface Acknowledge {
    void acknowledge(JSONArray arguments);
}


================================================
FILE: src/com/koushikdutta/async/http/socketio/ConnectCallback.java
================================================
package com.koushikdutta.async.http.socketio;

public interface ConnectCallback {
    public void onConnectCompleted(Exception ex, SocketIOClient client);
}

================================================
FILE: src/com/koushikdutta/async/http/socketio/DisconnectCallback.java
================================================
package com.koushikdutta.async.http.socketio;

/**
 * Created by koush on 7/2/13.
 */
public interface DisconnectCallback {
    void onDisconnect(Exception e);
}


================================================
FILE: src/com/koushikdutta/async/http/socketio/ErrorCallback.java
================================================
package com.koushikdutta.async.http.socketio;

/**
 * Created by koush on 7/2/13.
 */
public interface ErrorCallback {
    void onError(String error);
}


================================================
FILE: src/com/koushikdutta/async/http/socketio/EventCallback.java
================================================
package com.koushikdutta.async.http.socketio;

import org.json.JSONArray;

public interface EventCallback {
    public void onEvent(String event, JSONArray argument, Acknowledge acknowledge);
}

================================================
FILE: src/com/koushikdutta/async/http/socketio/EventEmitter.java
================================================
package com.koushikdutta.async.http.socketio;

import com.koushikdutta.async.util.HashList;

import org.json.JSONArray;

import java.util.Iterator;
import java.util.List;

/**
 * Created by koush on 7/1/13.
 */
public class EventEmitter {
    interface OnceCallback extends EventCallback {
    }

    HashList<EventCallback> callbacks = new HashList<EventCallback>();
    
    void onEvent(String event, JSONArray arguments, Acknowledge acknowledge) {
        List<EventCallback> list = callbacks.get(event);
        if (list == null)
            return;
        Iterator<EventCallback> iter = list.iterator();
        while (iter.hasNext()) {
            EventCallback cb = iter.next();
            cb.onEvent(event, arguments, acknowledge);
            if (cb instanceof OnceCallback)
                iter.remove();
        }
    }

    public void addListener(String event, EventCallback callback) {
        on(event, callback);
    }

    public void once(final String event, final EventCallback callback) {
        on(event, new OnceCallback() {
            @Override
            public void onEvent(String event, JSONArray arguments, Acknowledge acknowledge) {
                callback.onEvent(event, arguments, acknowledge);
            }
        });
    }

    public void on(String event, EventCallback callback) {
        callbacks.add(event, callback);
    }

    public void removeListener(String event, EventCallback callback) {
        List<EventCallback> list = callbacks.get(event);
        if (list == null)
            return;
        list.remove(callback);
    }
}


================================================
FILE: src/com/koushikdutta/async/http/socketio/JSONCallback.java
================================================
package com.koushikdutta.async.http.socketio;

import org.json.JSONObject;

public interface JSONCallback {
    public void onJSON(JSONObject json, Acknowledge acknowledge);
}
    


================================================
FILE: src/com/koushikdutta/async/http/socketio/ReconnectCallback.java
================================================
package com.koushikdutta.async.http.socketio;

public interface ReconnectCallback {
    public void onReconnect();
}

================================================
FILE: src/com/koushikdutta/async/http/socketio/SocketIOClient.java
================================================
package com.koushikdutta.async.http.socketio;

import org.json.JSONArray;
import org.json.JSONObject;

import android.os.Handler;
import android.text.TextUtils;

import com.codebutler.android_websockets.WebSocketClient;
import com.koushikdutta.http.AsyncHttpClient;
import com.koushikdutta.http.AsyncHttpClient.SocketIORequest;

public class SocketIOClient extends EventEmitter {

    boolean connected;
    boolean disconnected;
    Handler handler;

    private void emitRaw(int type, String message, Acknowledge acknowledge) {
        connection.emitRaw(type, this, message, acknowledge);
    }

    public void emit(String name, JSONArray args) {
        emit(name, args, null);
    }

    public void emit(final String message) {
        emit(message, (Acknowledge) null);
    }

    public void emit(final JSONObject jsonMessage) {
        emit(jsonMessage, null);
    }

    public void emit(String name, JSONArray args, Acknowledge acknowledge) {
        final JSONObject event = new JSONObject();
        try {
            event.put("name", name);
            event.put("args", args);
            emitRaw(5, event.toString(), acknowledge);
        } catch (Exception e) {
        }
    }

    public void emit(final String message, Acknowledge acknowledge) {
        emitRaw(3, message, acknowledge);
    }

    public void emit(final JSONObject jsonMessage, Acknowledge acknowledge) {
        emitRaw(4, jsonMessage.toString(), acknowledge);
    }

    public static void connect(String uri, final ConnectCallback callback, final Handler handler) {
        connect(new SocketIORequest(uri), callback, handler);
    }

    ConnectCallback connectCallback;

    public static void connect(final SocketIORequest request, final ConnectCallback callback, final Handler handler) {

        final SocketIOConnection connection = new SocketIOConnection(handler, new AsyncHttpClient(), request);

        final ConnectCallback wrappedCallback = new ConnectCallback() {
            @Override
            public void onConnectCompleted(Exception ex, SocketIOClient client) {
                if (ex != null || TextUtils.isEmpty(request.getEndpoint())) {

                    client.handler = handler;
                    if (callback != null) {
                        callback.onConnectCompleted(ex, client);
                    }

                    return;
                }

                // remove the root client since that's not actually being used.
                connection.clients.remove(client);

                // connect to the endpoint we want
                client.of(request.getEndpoint(), new ConnectCallback() {
                    @Override
                    public void onConnectCompleted(Exception ex, SocketIOClient client) {
                        if (callback != null) {
                            callback.onConnectCompleted(ex, client);
                        }
                    }
                });
            }
        };

        connection.clients.add(new SocketIOClient(connection, "", wrappedCallback));
        connection.reconnect();

    }

    ErrorCallback errorCallback;

    public void setErrorCallback(ErrorCallback callback) {
        errorCallback = callback;
    }

    public ErrorCallback getErrorCallback() {
        return errorCallback;
    }

    DisconnectCallback disconnectCallback;

    public void setDisconnectCallback(DisconnectCallback callback) {
        disconnectCallback = callback;
    }

    public DisconnectCallback getDisconnectCallback() {
        return disconnectCallback;
    }

    ReconnectCallback reconnectCallback;

    public void setReconnectCallback(ReconnectCallback callback) {
        reconnectCallback = callback;
    }

    public ReconnectCallback getReconnectCallback() {
        return reconnectCallback;
    }

    JSONCallback jsonCallback;

    public void setJSONCallback(JSONCallback callback) {
        jsonCallback = callback;
    }

    public JSONCallback getJSONCallback() {
        return jsonCallback;
    }

    StringCallback stringCallback;

    public void setStringCallback(StringCallback callback) {
        stringCallback = callback;
    }

    public StringCallback getStringCallback() {
        return stringCallback;
    }

    SocketIOConnection connection;
    String endpoint;

    private SocketIOClient(SocketIOConnection connection, String endpoint,
            ConnectCallback callback) {
        this.endpoint = endpoint;
        this.connection = connection;
        this.connectCallback = callback;
    }

    public boolean isConnected() {
        return connected && !disconnected && connection.isConnected();
    }

    public void disconnect() {
        connection.disconnect(this);
        final DisconnectCallback disconnectCallback = this.disconnectCallback;
        if (disconnectCallback != null) {
            handler.post(new Runnable() {

                @Override
                public void run() {
                    disconnectCallback.onDisconnect(null);

                }
            });

        }
    }

    public void of(String endpoint, ConnectCallback connectCallback) {
        connection.connect(new SocketIOClient(connection, endpoint, connectCallback));
    }

    public WebSocketClient getWebSocket() {
        return connection.webSocketClient;
    }

}


================================================
FILE: src/com/koushikdutta/async/http/socketio/SocketIOConnection.java
================================================
package com.koushikdutta.async.http.socketio;

import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Hashtable;

import org.json.JSONArray;
import org.json.JSONObject;

import android.net.Uri;
import android.os.Handler;
import android.text.TextUtils;

import com.codebutler.android_websockets.WebSocketClient;
import com.codebutler.android_websockets.WebSocketClient.Listener;
import com.koushikdutta.http.AsyncHttpClient;
import com.koushikdutta.http.AsyncHttpClient.SocketIORequest;

/**
 * Created by koush on 7/1/13.
 */
class SocketIOConnection {

    private Handler mHandler;
    AsyncHttpClient httpClient;
    int heartbeat;
    ArrayList<SocketIOClient> clients = new ArrayList<SocketIOClient>();
    WebSocketClient webSocketClient;
    SocketIORequest request;

    public SocketIOConnection(Handler handler, AsyncHttpClient httpClient,
            SocketIORequest request) {
        mHandler = handler;
        this.httpClient = httpClient;
        this.request = request;
    }

    public boolean isConnected() {
        return webSocketClient != null && webSocketClient.isConnected();
    }

    Hashtable<String, Acknowledge> acknowledges = new Hashtable<String, Acknowledge>();
    int ackCount;

    public void emitRaw(int type, SocketIOClient client, String message, Acknowledge acknowledge) {
        String ack = "";
        if (acknowledge != null) {
            String id = "" + ackCount++;
            ack = id + "+";
            acknowledges.put(id, acknowledge);
        }
        webSocketClient.send(String.format("%d:%s:%s:%s", type, ack, client.endpoint, message));
    }

    public void connect(SocketIOClient client) {
        clients.add(client);
        webSocketClient.send(String.format("1::%s", client.endpoint));
    }

    public void disconnect(SocketIOClient client) {
        clients.remove(client);

        // see if we can leave this endpoint completely
        boolean needsEndpointDisconnect = true;
        for (SocketIOClient other : clients) {
            // if this is the default endpoint (which disconnects everything),
            // or another client is using this endpoint,
            // we can't disconnect
            if (TextUtils.equals(other.endpoint, client.endpoint)
                    || TextUtils.isEmpty(client.endpoint)) {
                needsEndpointDisconnect = false;
                break;
            }
        }

        if (needsEndpointDisconnect)
            webSocketClient.send(String.format("0::%s", client.endpoint));

        // and see if we can disconnect the socket completely
        if (clients.size() > 0)
            return;

        webSocketClient.disconnect();
        webSocketClient = null;
    }

    void reconnect() {
        if (isConnected()) {
            return;
        }

        // initiate a session
        httpClient.executeString(request, new AsyncHttpClient.StringCallback() {
            @Override
            public void onCompleted(final Exception e, String result) {
                if (e != null) {
                    reportDisconnect(e);
                    return;
                }

                try {
                    String[] parts = result.split(":");
                    String session = parts[0];
                    if (!"".equals(parts[1]))
                        heartbeat = Integer.parseInt(parts[1]) / 2 * 1000;
                    else
                        heartbeat = 0;

                    String transportsLine = parts[3];
                    String[] transports = transportsLine.split(",");
                    HashSet<String> set = new HashSet<String>(Arrays.asList(transports));
                    if (!set.contains("websocket"))
                        throw new Exception("websocket not supported");

                    final String sessionUrl = Uri.parse(request.getUri()).buildUpon()
                    		.appendPath("websocket").appendPath(session)
                    		.build().toString();
                    
                    SocketIOConnection.this.webSocketClient =  new WebSocketClient(URI.create(sessionUrl), new Listener() {
                        
                        @Override
                        public void onMessage(byte[] data) {
                            //Do nothing
                            
                        }
                        
                        @Override
                        public void onMessage(String message) {
                            try {
                                // Log.d(TAG, "Message: " + message);
                                String[] parts = message.split(":", 4);
                                int code = Integer.parseInt(parts[0]);
                                switch (code) {
                                case 0:
                                    // disconnect
                                    webSocketClient.disconnect();
                                    reportDisconnect(null);
                                    break;
                                case 1:
                                    // connect
                                    reportConnect(parts[2]);
                                    break;
                                case 2:
                                    // heartbeat
                                    webSocketClient.send("2::");
                                    break;
                                case 3: {
                                    // message
                                    reportString(parts[2], parts[3], acknowledge(parts[1]));
                                    break;
                                }
                                case 4: {
                                    // json message
                                    final String dataString = parts[3];
                                    final JSONObject jsonMessage = new JSONObject(dataString);
                                    reportJson(parts[2], jsonMessage, acknowledge(parts[1]));
                                    break;
                                }
                                case 5: {
                                    final String dataString = parts[3];
                                    final JSONObject data = new JSONObject(dataString);
                                    final String event = data.getString("name");
                                    final JSONArray args = data.optJSONArray("args");
                                    reportEvent(parts[2], event, args, acknowledge(parts[1]));
                                    break;
                                }
                                case 6:
                                    // ACK
                                    final String[] ackParts = parts[3].split("\\+", 2);
                                    Acknowledge ack = acknowledges.remove(ackParts[0]);
                                    if (ack == null)
                                        return;
                                    JSONArray arguments = null;
                                    if (ackParts.length == 2)
                                        arguments = new JSONArray(ackParts[1]);
                                    ack.acknowledge(arguments);
                                    break;
                                case 7:
                                    // error
                                    reportError(parts[2], parts[3]);
                                    break;
                                case 8:
                                    // noop
                                    break;
                                default:
                                    throw new Exception("unknown code");
                                }
                            } catch (Exception ex) {
                                webSocketClient.disconnect();
                                webSocketClient = null;
                                reportDisconnect(ex);
                            }
                        
                            
                        }
                        
                        @Override
                        public void onError(Exception error) {
                            reportDisconnect(error);
                        }
                        
                        @Override
                        public void onDisconnect(int code, String reason) {
                            
                            reportDisconnect(new IOException(String.format("Disconnected code %d for reason %s", code, reason)));
                        }
                        
                        @Override
                        public void onConnect() {
                            reconnectDelay = 1000L;
                            setupHeartbeat();
                            
                        }
                    }, null);
                    SocketIOConnection.this.webSocketClient.connect();

                } catch (Exception ex) {
                    reportDisconnect(ex);
                }
            }
        });

    }

    void setupHeartbeat() {
        final WebSocketClient ws = webSocketClient;
        Runnable heartbeatRunner = new Runnable() {
            @Override
            public void run() {
                if (heartbeat <= 0 || ws != webSocketClient || ws == null
                        || !ws.isConnected())
                    return;
                webSocketClient.send("2:::");

                mHandler.postDelayed(this, heartbeat);
            }
        };
        heartbeatRunner.run();
    }

    private interface SelectCallback {
        void onSelect(SocketIOClient client);
    }

    private void select(String endpoint, SelectCallback callback) {
        for (SocketIOClient client : clients) {
            if (endpoint == null || TextUtils.equals(client.endpoint, endpoint)) {
                callback.onSelect(client);
            }
        }
    }

    private void delayReconnect() {
        if (webSocketClient != null || clients.size() == 0)
            return;

        // see if any client has disconnected,
        // and that we need a reconnect
        boolean disconnected = false;
        for (SocketIOClient client : clients) {
            if (client.disconnected) {
                disconnected = true;
                break;
            }
        }

        if (!disconnected)
            return;

        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                reconnect();
            }
        }, reconnectDelay);
        reconnectDelay *= 2;
    }

    long reconnectDelay = 1000L;

    private void reportDisconnect(final Exception ex) {
        select(null, new SelectCallback() {
            @Override
            public void onSelect(final SocketIOClient client) {
                if (client.connected) {
                    client.disconnected = true;
                    final DisconnectCallback closed = client.getDisconnectCallback();
                    if (closed != null) {
                        mHandler.post(new Runnable() {

                            @Override
                            public void run() {
                                closed.onDisconnect(ex);

                            }
                        });

                    }
                } else {
                    // client has never connected, this is a initial connect
                    // failure
                    final ConnectCallback callback = client.connectCallback;
                    if (callback != null) {
                        mHandler.post(new Runnable() {

                            @Override
                            public void run() {
                                callback.onConnectCompleted(ex, client);

                            }
                        });

                    }
                }
            }
        });

        delayReconnect();
    }

    private void reportConnect(String endpoint) {
        select(endpoint, new SelectCallback() {
            @Override
            public void onSelect(SocketIOClient client) {
                if (client.isConnected())
                    return;
                if (!client.connected) {
                    // normal connect
                    client.connected = true;
                    ConnectCallback callback = client.connectCallback;
                    if (callback != null)
                        callback.onConnectCompleted(null, client);
                } else if (client.disconnected) {
                    // reconnect
                    client.disconnected = false;
                    ReconnectCallback callback = client.reconnectCallback;
                    if (callback != null)
                        callback.onReconnect();
                } else {
                    // double connect?
                    // assert false;
                }
            }
        });
    }

    private void reportJson(String endpoint, final JSONObject jsonMessage, final Acknowledge acknowledge) {
        select(endpoint, new SelectCallback() {
            @Override
            public void onSelect(SocketIOClient client) {
                final JSONCallback callback = client.jsonCallback;
                if (callback != null) {
                    mHandler.post(new Runnable() {

                        @Override
                        public void run() {
                            callback.onJSON(jsonMessage, acknowledge);

                        }
                    });
                }

            }
        });
    }

    private void reportString(String endpoint, final String string, final Acknowledge acknowledge) {
        select(endpoint, new SelectCallback() {
            @Override
            public void onSelect(SocketIOClient client) {
                final StringCallback callback = client.stringCallback;
                if (callback != null) {
                    mHandler.post(new Runnable() {

                        @Override
                        public void run() {
                            callback.onString(string, acknowledge);

                        }
                    });

                }
            }
        });
    }

    private void reportEvent(String endpoint, final String event, final JSONArray arguments, final Acknowledge acknowledge) {
        select(endpoint, new SelectCallback() {
            @Override
            public void onSelect(final SocketIOClient client) {
                mHandler.post(new Runnable() {

                    @Override
                    public void run() {
                        client.onEvent(event, arguments, acknowledge);

                    }
                });

            }
        });
    }

    private void reportError(String endpoint, final String error) {
        select(endpoint, new SelectCallback() {
            @Override
            public void onSelect(SocketIOClient client) {
                final ErrorCallback callback = client.errorCallback;
                if (callback != null) {

                    mHandler.post(new Runnable() {

                        @Override
                        public void run() {
                            callback.onError(error);

                        }
                    });

                }
            }
        });
    }

    private Acknowledge acknowledge(final String messageId) {
        if (TextUtils.isEmpty(messageId))
            return null;

        return new Acknowledge() {
            @Override
            public void acknowledge(JSONArray arguments) {
                String data = "";
                if (arguments != null)
                    data += "+" + arguments.toString();
                webSocketClient.send(String.format("6:::%s%s", messageId, data));
            }
        };
    }

    

}


================================================
FILE: src/com/koushikdutta/async/http/socketio/StringCallback.java
================================================
package com.koushikdutta.async.http.socketio;

public interface StringCallback {
    public void onString(String string, Acknowledge acknowledge);
}

================================================
FILE: src/com/koushikdutta/async/util/HashList.java
================================================
package com.koushikdutta.async.util;

import java.util.ArrayList;
import java.util.Hashtable;

/**
 * Created by koush on 5/27/13.
 */
public class HashList<T> extends Hashtable<String, ArrayList<T>> {
   
    private static final long serialVersionUID = 1L;

    public HashList() {
    }

    public boolean contains(String key) {
        ArrayList<T> check = get(key);
        return check != null && check.size() > 0;
    }

    public void add(String key, T value) {
        ArrayList<T> ret = get(key);
        if (ret == null) {
            ret = new ArrayList<T>();
            put(key, ret);
        }
        ret.add(value);
    }
}


================================================
FILE: src/com/koushikdutta/http/AsyncHttpClient.java
================================================
package com.koushikdutta.http;

import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.message.BasicNameValuePair;

import android.net.Uri;
import android.net.http.AndroidHttpClient;
import android.os.AsyncTask;

import com.codebutler.android_websockets.WebSocketClient;

/**
 * 
 * Created by Vinay S Shenoy on 07/09/2013
 */
public class AsyncHttpClient {

    public AsyncHttpClient() {

    }

    public static class SocketIORequest {

        private String mUri;
        private String mEndpoint;
        private List<BasicNameValuePair> mHeaders;

        public SocketIORequest(String uri) {
            this(uri, null);
        }

        public SocketIORequest(String uri, String endpoint) {
            this(uri, endpoint, null);
        }

        public SocketIORequest(String uri, String endpoint, List<BasicNameValuePair> headers) {
            mUri = Uri.parse(uri).buildUpon().encodedPath("/socket.io/1/").build().toString();
            mEndpoint = endpoint;
            mHeaders = headers;
        }

        public String getUri() {
            return mUri;
        }

        public String getEndpoint() {
            return mEndpoint;
        }

        public List<BasicNameValuePair> getHeaders() {
            return mHeaders; 
        }
    }

    public static interface StringCallback {
        public void onCompleted(final Exception e, String result);
    }

    public static interface WebSocketConnectCallback {
        public void onCompleted(Exception ex, WebSocketClient webSocket);
    }

    public void executeString(final SocketIORequest socketIORequest, final StringCallback stringCallback) {

        new AsyncTask<Void, Void, Void>() {

            @Override
            protected Void doInBackground(Void... params) {

                AndroidHttpClient httpClient = AndroidHttpClient.newInstance("android-websockets-2.0");
                HttpPost post = new HttpPost(socketIORequest.getUri());
                addHeadersToRequest(post, socketIORequest.getHeaders());

                try {
                    HttpResponse res = httpClient.execute(post);
                    String responseString = readToEnd(res.getEntity().getContent());

                    if (stringCallback != null) {
                        stringCallback.onCompleted(null, responseString);
                    }

                } catch (IOException e) {

                    if (stringCallback != null) {
                        stringCallback.onCompleted(e, null);
                    }
                } finally {
                    httpClient.close();
                    httpClient = null;
                }
                return null;
            }

            private void addHeadersToRequest(HttpRequest request, List<BasicNameValuePair> headers) {
                if (headers != null) {
                    Iterator<BasicNameValuePair> it = headers.iterator();
                    while (it.hasNext()) {
                        BasicNameValuePair header = it.next();
                        request.addHeader(header.getName(), header.getValue());
                    }
                }
            }
        }.execute();
    }

    private byte[] readToEndAsArray(InputStream input) throws IOException {
        DataInputStream dis = new DataInputStream(input);
        byte[] stuff = new byte[1024];
        ByteArrayOutputStream buff = new ByteArrayOutputStream();
        int read = 0;
        while ((read = dis.read(stuff)) != -1) {
            buff.write(stuff, 0, read);
        }

        return buff.toByteArray();
    }

    private String readToEnd(InputStream input) throws IOException {
        return new String(readToEndAsArray(input));
    }

}
Download .txt
gitextract_fsf22rvj/

├── .gitignore
├── AndroidManifest.xml
├── README.md
├── android-websockets.iml
├── ant.properties
├── build.xml
├── proguard-project.txt
└── src/
    └── com/
        ├── codebutler/
        │   └── android_websockets/
        │       ├── HybiParser.java
        │       └── WebSocketClient.java
        └── koushikdutta/
            ├── async/
            │   ├── http/
            │   │   └── socketio/
            │   │       ├── Acknowledge.java
            │   │       ├── ConnectCallback.java
            │   │       ├── DisconnectCallback.java
            │   │       ├── ErrorCallback.java
            │   │       ├── EventCallback.java
            │   │       ├── EventEmitter.java
            │   │       ├── JSONCallback.java
            │   │       ├── ReconnectCallback.java
            │   │       ├── SocketIOClient.java
            │   │       ├── SocketIOConnection.java
            │   │       └── StringCallback.java
            │   └── util/
            │       └── HashList.java
            └── http/
                └── AsyncHttpClient.java
Download .txt
SYMBOL INDEX (136 symbols across 15 files)

FILE: src/com/codebutler/android_websockets/HybiParser.java
  class HybiParser (line 39) | public class HybiParser {
    method HybiParser (line 94) | public HybiParser(WebSocketClient client) {
    method mask (line 98) | private static byte[] mask(byte[] payload, byte[] mask, int offset) {
    method start (line 107) | public void start(HappyDataInputStream stream) throws IOException {
    method parseOpcode (line 134) | private void parseOpcode(byte data) throws ProtocolError {
    method parseLength (line 159) | private void parseLength(byte data) {
    method parseExtendedLength (line 171) | private void parseExtendedLength(byte[] buffer) throws ProtocolError {
    method frame (line 176) | public byte[] frame(String data) {
    method frame (line 180) | public byte[] frame(byte[] data) {
    method frame (line 184) | private byte[] frame(byte[] data, int opcode, int errorCode)  {
    method frame (line 188) | private byte[] frame(String data, int opcode, int errorCode) {
    method frame (line 192) | private byte[] frame(Object data, int opcode, int errorCode) {
    method ping (line 243) | public void ping(String message) {
    method close (line 247) | public void close(int code, String reason) {
    method emitFrame (line 253) | private void emitFrame() throws IOException {
    method reset (line 307) | private void reset() {
    method encode (line 312) | private String encode(byte[] buffer) {
    method decode (line 320) | private byte[] decode(String string) {
    method getInteger (line 328) | private int getInteger(byte[] bytes) throws ProtocolError {
    method copyOfRange (line 354) | private static byte[] copyOfRange(byte[] original, int start, int end) {
    method slice (line 369) | private byte[] slice(byte[] array, int start) {
    class ProtocolError (line 373) | public static class ProtocolError extends IOException {
      method ProtocolError (line 374) | public ProtocolError(String detailMessage) {
    method byteArrayToLong (line 379) | private static long byteArrayToLong(byte[] b, int offset, int length) {
    class HappyDataInputStream (line 391) | public static class HappyDataInputStream extends DataInputStream {
      method HappyDataInputStream (line 392) | public HappyDataInputStream(InputStream in) {
      method readBytes (line 396) | public byte[] readBytes(int length) throws IOException {

FILE: src/com/codebutler/android_websockets/WebSocketClient.java
  class WebSocketClient (line 29) | public class WebSocketClient {
    method setTrustManagers (line 46) | public static void setTrustManagers(TrustManager[] tm) {
    method WebSocketClient (line 50) | public WebSocketClient(URI uri, Listener listener, List<BasicNameValue...
    method getListener (line 62) | public Listener getListener() {
    method connect (line 66) | public void connect() {
    method disconnect (line 155) | public void disconnect() {
    method send (line 175) | public void send(String data) {
    method send (line 179) | public void send(byte[] data) {
    method isConnected (line 183) | public boolean isConnected() {
    method parseStatusLine (line 187) | private StatusLine parseStatusLine(String line) {
    method parseHeader (line 194) | private Header parseHeader(String line) {
    method readLine (line 199) | private String readLine(HybiParser.HappyDataInputStream reader) throws...
    method expectedKey (line 218) | private String expectedKey(String secret) {
    method createSecret (line 231) | private String createSecret() {
    method sendFrame (line 239) | void sendFrame(final byte[] frame) {
    type Listener (line 256) | public interface Listener {
      method onConnect (line 257) | public void onConnect();
      method onMessage (line 258) | public void onMessage(String message);
      method onMessage (line 259) | public void onMessage(byte[] data);
      method onDisconnect (line 260) | public void onDisconnect(int code, String reason);
      method onError (line 261) | public void onError(Exception error);
    method getSSLSocketFactory (line 264) | private SSLSocketFactory getSSLSocketFactory() throws NoSuchAlgorithmE...

FILE: src/com/koushikdutta/async/http/socketio/Acknowledge.java
  type Acknowledge (line 5) | public interface Acknowledge {
    method acknowledge (line 6) | void acknowledge(JSONArray arguments);

FILE: src/com/koushikdutta/async/http/socketio/ConnectCallback.java
  type ConnectCallback (line 3) | public interface ConnectCallback {
    method onConnectCompleted (line 4) | public void onConnectCompleted(Exception ex, SocketIOClient client);

FILE: src/com/koushikdutta/async/http/socketio/DisconnectCallback.java
  type DisconnectCallback (line 6) | public interface DisconnectCallback {
    method onDisconnect (line 7) | void onDisconnect(Exception e);

FILE: src/com/koushikdutta/async/http/socketio/ErrorCallback.java
  type ErrorCallback (line 6) | public interface ErrorCallback {
    method onError (line 7) | void onError(String error);

FILE: src/com/koushikdutta/async/http/socketio/EventCallback.java
  type EventCallback (line 5) | public interface EventCallback {
    method onEvent (line 6) | public void onEvent(String event, JSONArray argument, Acknowledge ackn...

FILE: src/com/koushikdutta/async/http/socketio/EventEmitter.java
  class EventEmitter (line 13) | public class EventEmitter {
    type OnceCallback (line 14) | interface OnceCallback extends EventCallback {
    method onEvent (line 19) | void onEvent(String event, JSONArray arguments, Acknowledge acknowledg...
    method addListener (line 32) | public void addListener(String event, EventCallback callback) {
    method once (line 36) | public void once(final String event, final EventCallback callback) {
    method on (line 45) | public void on(String event, EventCallback callback) {
    method removeListener (line 49) | public void removeListener(String event, EventCallback callback) {

FILE: src/com/koushikdutta/async/http/socketio/JSONCallback.java
  type JSONCallback (line 5) | public interface JSONCallback {
    method onJSON (line 6) | public void onJSON(JSONObject json, Acknowledge acknowledge);

FILE: src/com/koushikdutta/async/http/socketio/ReconnectCallback.java
  type ReconnectCallback (line 3) | public interface ReconnectCallback {
    method onReconnect (line 4) | public void onReconnect();

FILE: src/com/koushikdutta/async/http/socketio/SocketIOClient.java
  class SocketIOClient (line 13) | public class SocketIOClient extends EventEmitter {
    method emitRaw (line 19) | private void emitRaw(int type, String message, Acknowledge acknowledge) {
    method emit (line 23) | public void emit(String name, JSONArray args) {
    method emit (line 27) | public void emit(final String message) {
    method emit (line 31) | public void emit(final JSONObject jsonMessage) {
    method emit (line 35) | public void emit(String name, JSONArray args, Acknowledge acknowledge) {
    method emit (line 45) | public void emit(final String message, Acknowledge acknowledge) {
    method emit (line 49) | public void emit(final JSONObject jsonMessage, Acknowledge acknowledge) {
    method connect (line 53) | public static void connect(String uri, final ConnectCallback callback,...
    method connect (line 59) | public static void connect(final SocketIORequest request, final Connec...
    method setErrorCallback (line 98) | public void setErrorCallback(ErrorCallback callback) {
    method getErrorCallback (line 102) | public ErrorCallback getErrorCallback() {
    method setDisconnectCallback (line 108) | public void setDisconnectCallback(DisconnectCallback callback) {
    method getDisconnectCallback (line 112) | public DisconnectCallback getDisconnectCallback() {
    method setReconnectCallback (line 118) | public void setReconnectCallback(ReconnectCallback callback) {
    method getReconnectCallback (line 122) | public ReconnectCallback getReconnectCallback() {
    method setJSONCallback (line 128) | public void setJSONCallback(JSONCallback callback) {
    method getJSONCallback (line 132) | public JSONCallback getJSONCallback() {
    method setStringCallback (line 138) | public void setStringCallback(StringCallback callback) {
    method getStringCallback (line 142) | public StringCallback getStringCallback() {
    method SocketIOClient (line 149) | private SocketIOClient(SocketIOConnection connection, String endpoint,
    method isConnected (line 156) | public boolean isConnected() {
    method disconnect (line 160) | public void disconnect() {
    method of (line 176) | public void of(String endpoint, ConnectCallback connectCallback) {
    method getWebSocket (line 180) | public WebSocketClient getWebSocket() {

FILE: src/com/koushikdutta/async/http/socketio/SocketIOConnection.java
  class SocketIOConnection (line 25) | class SocketIOConnection {
    method SocketIOConnection (line 34) | public SocketIOConnection(Handler handler, AsyncHttpClient httpClient,
    method isConnected (line 41) | public boolean isConnected() {
    method emitRaw (line 48) | public void emitRaw(int type, SocketIOClient client, String message, A...
    method connect (line 58) | public void connect(SocketIOClient client) {
    method disconnect (line 63) | public void disconnect(SocketIOClient client) {
    method reconnect (line 90) | void reconnect() {
    method setupHeartbeat (line 228) | void setupHeartbeat() {
    type SelectCallback (line 244) | private interface SelectCallback {
      method onSelect (line 245) | void onSelect(SocketIOClient client);
    method select (line 248) | private void select(String endpoint, SelectCallback callback) {
    method delayReconnect (line 256) | private void delayReconnect() {
    method reportDisconnect (line 284) | private void reportDisconnect(final Exception ex) {
    method reportConnect (line 324) | private void reportConnect(String endpoint) {
    method reportJson (line 350) | private void reportJson(String endpoint, final JSONObject jsonMessage,...
    method reportString (line 370) | private void reportString(String endpoint, final String string, final ...
    method reportEvent (line 390) | private void reportEvent(String endpoint, final String event, final JS...
    method reportError (line 407) | private void reportError(String endpoint, final String error) {
    method acknowledge (line 428) | private Acknowledge acknowledge(final String messageId) {

FILE: src/com/koushikdutta/async/http/socketio/StringCallback.java
  type StringCallback (line 3) | public interface StringCallback {
    method onString (line 4) | public void onString(String string, Acknowledge acknowledge);

FILE: src/com/koushikdutta/async/util/HashList.java
  class HashList (line 9) | public class HashList<T> extends Hashtable<String, ArrayList<T>> {
    method HashList (line 13) | public HashList() {
    method contains (line 16) | public boolean contains(String key) {
    method add (line 21) | public void add(String key, T value) {

FILE: src/com/koushikdutta/http/AsyncHttpClient.java
  class AsyncHttpClient (line 27) | public class AsyncHttpClient {
    method AsyncHttpClient (line 29) | public AsyncHttpClient() {
    class SocketIORequest (line 33) | public static class SocketIORequest {
      method SocketIORequest (line 39) | public SocketIORequest(String uri) {
      method SocketIORequest (line 43) | public SocketIORequest(String uri, String endpoint) {
      method SocketIORequest (line 47) | public SocketIORequest(String uri, String endpoint, List<BasicNameVa...
      method getUri (line 53) | public String getUri() {
      method getEndpoint (line 57) | public String getEndpoint() {
      method getHeaders (line 61) | public List<BasicNameValuePair> getHeaders() {
    type StringCallback (line 66) | public static interface StringCallback {
      method onCompleted (line 67) | public void onCompleted(final Exception e, String result);
    type WebSocketConnectCallback (line 70) | public static interface WebSocketConnectCallback {
      method onCompleted (line 71) | public void onCompleted(Exception ex, WebSocketClient webSocket);
    method executeString (line 74) | public void executeString(final SocketIORequest socketIORequest, final...
    method readToEndAsArray (line 117) | private byte[] readToEndAsArray(InputStream input) throws IOException {
    method readToEnd (line 129) | private String readToEnd(InputStream input) throws IOException {
Condensed preview — 22 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (70K chars).
[
  {
    "path": ".gitignore",
    "chars": 75,
    "preview": "bin\ngen\n.classpath\n.project\nlocal.properties\n/.settings\nproject.properties\n"
  },
  {
    "path": "AndroidManifest.xml",
    "chars": 325,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    pack"
  },
  {
    "path": "README.md",
    "chars": 5550,
    "preview": "# THIS LIBRARY IS DEPRECATED IN FAVOR OF:\n\n[AndroidAsync](https://github.com/koush/AndroidAsync)\n\n\n\n\n\n\n\n\n# WebSocket and"
  },
  {
    "path": "android-websockets.iml",
    "chars": 2056,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module type=\"JAVA_MODULE\" version=\"4\">\n  <component name=\"FacetManager\">\n    <fa"
  },
  {
    "path": "ant.properties",
    "chars": 698,
    "preview": "# This file is used to override default values used by the Ant build system.\n#\n# This file must be checked into Version "
  },
  {
    "path": "build.xml",
    "chars": 3930,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project name=\"android-websockets\" default=\"help\">\n\n    <!-- The local.properties"
  },
  {
    "path": "proguard-project.txt",
    "chars": 781,
    "preview": "# To enable ProGuard in your project, edit project.properties\n# to define the proguard.config property as described in t"
  },
  {
    "path": "src/com/codebutler/android_websockets/HybiParser.java",
    "chars": 14099,
    "preview": "//\n// HybiParser.java: draft-ietf-hybi-thewebsocketprotocol-13 parser\n//\n// Based on code from the faye project.\n// http"
  },
  {
    "path": "src/com/codebutler/android_websockets/WebSocketClient.java",
    "chars": 9934,
    "preview": "package com.codebutler.android_websockets;\n\nimport android.os.Handler;\nimport android.os.HandlerThread;\nimport android.t"
  },
  {
    "path": "src/com/koushikdutta/async/http/socketio/Acknowledge.java",
    "chars": 151,
    "preview": "package com.koushikdutta.async.http.socketio;\n\nimport org.json.JSONArray;\n\npublic interface Acknowledge {\n    void ackno"
  },
  {
    "path": "src/com/koushikdutta/async/http/socketio/ConnectCallback.java",
    "chars": 156,
    "preview": "package com.koushikdutta.async.http.socketio;\n\npublic interface ConnectCallback {\n    public void onConnectCompleted(Exc"
  },
  {
    "path": "src/com/koushikdutta/async/http/socketio/DisconnectCallback.java",
    "chars": 162,
    "preview": "package com.koushikdutta.async.http.socketio;\n\n/**\n * Created by koush on 7/2/13.\n */\npublic interface DisconnectCallbac"
  },
  {
    "path": "src/com/koushikdutta/async/http/socketio/ErrorCallback.java",
    "chars": 153,
    "preview": "package com.koushikdutta.async.http.socketio;\n\n/**\n * Created by koush on 7/2/13.\n */\npublic interface ErrorCallback {\n "
  },
  {
    "path": "src/com/koushikdutta/async/http/socketio/EventCallback.java",
    "chars": 193,
    "preview": "package com.koushikdutta.async.http.socketio;\n\nimport org.json.JSONArray;\n\npublic interface EventCallback {\n    public v"
  },
  {
    "path": "src/com/koushikdutta/async/http/socketio/EventEmitter.java",
    "chars": 1584,
    "preview": "package com.koushikdutta.async.http.socketio;\n\nimport com.koushikdutta.async.util.HashList;\n\nimport org.json.JSONArray;\n"
  },
  {
    "path": "src/com/koushikdutta/async/http/socketio/JSONCallback.java",
    "chars": 181,
    "preview": "package com.koushikdutta.async.http.socketio;\n\nimport org.json.JSONObject;\n\npublic interface JSONCallback {\n    public v"
  },
  {
    "path": "src/com/koushikdutta/async/http/socketio/ReconnectCallback.java",
    "chars": 116,
    "preview": "package com.koushikdutta.async.http.socketio;\n\npublic interface ReconnectCallback {\n    public void onReconnect();\n}"
  },
  {
    "path": "src/com/koushikdutta/async/http/socketio/SocketIOClient.java",
    "chars": 5319,
    "preview": "package com.koushikdutta.async.http.socketio;\n\nimport org.json.JSONArray;\nimport org.json.JSONObject;\n\nimport android.os"
  },
  {
    "path": "src/com/koushikdutta/async/http/socketio/SocketIOConnection.java",
    "chars": 15983,
    "preview": "package com.koushikdutta.async.http.socketio;\n\nimport java.io.IOException;\nimport java.net.URI;\nimport java.util.ArrayLi"
  },
  {
    "path": "src/com/koushikdutta/async/http/socketio/StringCallback.java",
    "chars": 148,
    "preview": "package com.koushikdutta.async.http.socketio;\n\npublic interface StringCallback {\n    public void onString(String string,"
  },
  {
    "path": "src/com/koushikdutta/async/util/HashList.java",
    "chars": 643,
    "preview": "package com.koushikdutta.async.util;\n\nimport java.util.ArrayList;\nimport java.util.Hashtable;\n\n/**\n * Created by koush o"
  },
  {
    "path": "src/com/koushikdutta/http/AsyncHttpClient.java",
    "chars": 4010,
    "preview": "package com.koushikdutta.http;\n\nimport java.io.ByteArrayOutputStream;\nimport java.io.DataInputStream;\nimport java.io.IOE"
  }
]

About this extraction

This page contains the full source code of the koush/android-websockets GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 22 files (64.7 KB), approximately 14.2k tokens, and a symbol index with 136 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!