KeyStore.java revision 5423e68d5dbe048ec6f042cce52a33f94184e9fb
144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh/* 244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * Copyright (C) 2009 The Android Open Source Project 344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * 444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * Licensed under the Apache License, Version 2.0 (the "License"); 544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * you may not use this file except in compliance with the License. 644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * You may obtain a copy of the License at 744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * 844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * http://www.apache.org/licenses/LICENSE-2.0 944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * 1044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * Unless required by applicable law or agreed to in writing, software 1144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * distributed under the License is distributed on an "AS IS" BASIS, 1244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * See the License for the specific language governing permissions and 1444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * limitations under the License. 1544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh */ 1644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 1744039172627d1c15737ea73836ad375559d76211Chia-chi Yehpackage android.security; 1844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 1944039172627d1c15737ea73836ad375559d76211Chia-chi Yehimport android.net.LocalSocketAddress; 2044039172627d1c15737ea73836ad375559d76211Chia-chi Yehimport android.net.LocalSocket; 2144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 2244039172627d1c15737ea73836ad375559d76211Chia-chi Yehimport java.io.InputStream; 2344039172627d1c15737ea73836ad375559d76211Chia-chi Yehimport java.io.IOException; 2444039172627d1c15737ea73836ad375559d76211Chia-chi Yehimport java.io.OutputStream; 2534c47c855815d731e6deb55748ff690b0ec7b53fNick Kralevichimport java.io.UnsupportedEncodingException; 2646703b099516c383a6882815bcf9cd4df0ec538dBrian Carlstromimport java.nio.charset.Charsets; 2744039172627d1c15737ea73836ad375559d76211Chia-chi Yehimport java.util.ArrayList; 2844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 2944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh/** 3046703b099516c383a6882815bcf9cd4df0ec538dBrian Carlstrom * @hide This should not be made public in its present form because it 3146703b099516c383a6882815bcf9cd4df0ec538dBrian Carlstrom * assumes that private and secret key bytes are available and would 3246703b099516c383a6882815bcf9cd4df0ec538dBrian Carlstrom * preclude the use of hardware crypto. 3344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh */ 3444039172627d1c15737ea73836ad375559d76211Chia-chi Yehpublic class KeyStore { 355cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom 365cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom // ResponseCodes 377e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom public static final int NO_ERROR = 1; 387e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom public static final int LOCKED = 2; 397e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom public static final int UNINITIALIZED = 3; 407e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom public static final int SYSTEM_ERROR = 4; 417e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom public static final int PROTOCOL_ERROR = 5; 427e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom public static final int PERMISSION_DENIED = 6; 437e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom public static final int KEY_NOT_FOUND = 7; 447e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom public static final int VALUE_CORRUPTED = 8; 457e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom public static final int UNDEFINED_ACTION = 9; 467e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom public static final int WRONG_PASSWORD = 10; 475cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom 485cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom // States 495cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom public enum State { UNLOCKED, LOCKED, UNINITIALIZED }; 5044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 5144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh private static final LocalSocketAddress sAddress = new LocalSocketAddress( 5244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh "keystore", LocalSocketAddress.Namespace.RESERVED); 5344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 5444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh private int mError = NO_ERROR; 5544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 5644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh private KeyStore() {} 5744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 5844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh public static KeyStore getInstance() { 5944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh return new KeyStore(); 6044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 6144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 625cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom public State state() { 6344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh execute('t'); 645cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom switch (mError) { 655cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom case NO_ERROR: return State.UNLOCKED; 665cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom case LOCKED: return State.LOCKED; 675cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom case UNINITIALIZED: return State.UNINITIALIZED; 685cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom default: throw new AssertionError(mError); 695cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom } 7044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 7144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 725cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom private byte[] get(byte[] key) { 73d12feb97667498378a472c5a7895a9fcd8056ec5Chia-chi Yeh ArrayList<byte[]> values = execute('g', key); 7434c47c855815d731e6deb55748ff690b0ec7b53fNick Kralevich return (values == null || values.isEmpty()) ? null : values.get(0); 7544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 7644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 775cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom public byte[] get(String key) { 785cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom return get(getBytes(key)); 7944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 8044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 815cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom private boolean put(byte[] key, byte[] value) { 8244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh execute('i', key, value); 8344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh return mError == NO_ERROR; 8444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 8544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 865cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom public boolean put(String key, byte[] value) { 875cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom return put(getBytes(key), value); 8844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 8944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 905cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom private boolean delete(byte[] key) { 9144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh execute('d', key); 9244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh return mError == NO_ERROR; 9344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 9444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 9544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh public boolean delete(String key) { 9634c47c855815d731e6deb55748ff690b0ec7b53fNick Kralevich return delete(getBytes(key)); 9744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 9844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 995cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom private boolean contains(byte[] key) { 10044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh execute('e', key); 10144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh return mError == NO_ERROR; 10244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 10344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 10444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh public boolean contains(String key) { 10534c47c855815d731e6deb55748ff690b0ec7b53fNick Kralevich return contains(getBytes(key)); 10644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 10744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 108613fcc850686dfe71cec9809c3694be9cf02cdc7Chia-chi Yeh public byte[][] saw(byte[] prefix) { 109d12feb97667498378a472c5a7895a9fcd8056ec5Chia-chi Yeh ArrayList<byte[]> values = execute('s', prefix); 110d12feb97667498378a472c5a7895a9fcd8056ec5Chia-chi Yeh return (values == null) ? null : values.toArray(new byte[values.size()][]); 11144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 11244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 113613fcc850686dfe71cec9809c3694be9cf02cdc7Chia-chi Yeh public String[] saw(String prefix) { 11434c47c855815d731e6deb55748ff690b0ec7b53fNick Kralevich byte[][] values = saw(getBytes(prefix)); 11544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh if (values == null) { 11644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh return null; 11744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 11844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh String[] strings = new String[values.length]; 11944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh for (int i = 0; i < values.length; ++i) { 12034c47c855815d731e6deb55748ff690b0ec7b53fNick Kralevich strings[i] = toString(values[i]); 12144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 12244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh return strings; 12344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 12444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 12544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh public boolean reset() { 12644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh execute('r'); 12744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh return mError == NO_ERROR; 12844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 12944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 1305cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom private boolean password(byte[] password) { 1315cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom execute('p', password); 13244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh return mError == NO_ERROR; 13344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 13444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 13544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh public boolean password(String password) { 13634c47c855815d731e6deb55748ff690b0ec7b53fNick Kralevich return password(getBytes(password)); 13744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 13844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 13944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh public boolean lock() { 14044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh execute('l'); 14144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh return mError == NO_ERROR; 14244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 14344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 1445cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom private boolean unlock(byte[] password) { 14544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh execute('u', password); 14644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh return mError == NO_ERROR; 14744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 14844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 14944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh public boolean unlock(String password) { 15034c47c855815d731e6deb55748ff690b0ec7b53fNick Kralevich return unlock(getBytes(password)); 15144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 15244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 1535cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom public boolean isEmpty() { 1545cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom execute('z'); 1555cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom return mError == KEY_NOT_FOUND; 1565cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom } 1575cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom 1585423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root private boolean generate(byte[] key) { 1595423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root execute('a', key); 1605423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root return mError == NO_ERROR; 1615423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root } 1625423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root 1635423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root public boolean generate(String key) { 1645423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root return generate(getBytes(key)); 1655423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root } 1665423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root 1675423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root private boolean importKey(byte[] keyName, byte[] key) { 1685423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root execute('m', keyName, key); 1695423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root return mError == NO_ERROR; 1705423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root } 1715423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root 1725423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root public boolean importKey(String keyName, byte[] key) { 1735423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root return importKey(getBytes(keyName), key); 1745423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root } 1755423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root 1765423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root private byte[] getPubkey(byte[] key) { 1775423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root ArrayList<byte[]> values = execute('b', key); 1785423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root return (values == null || values.isEmpty()) ? null : values.get(0); 1795423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root } 1805423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root 1815423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root public byte[] getPubkey(String key) { 1825423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root return getPubkey(getBytes(key)); 1835423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root } 1845423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root 1855423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root private boolean delKey(byte[] key) { 1865423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root execute('k', key); 1875423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root return mError == NO_ERROR; 1885423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root } 1895423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root 1905423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root public boolean delKey(String key) { 1915423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root return delKey(getBytes(key)); 1925423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root } 1935423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root 1945423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root private byte[] sign(byte[] keyName, byte[] data) { 1955423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root final ArrayList<byte[]> values = execute('n', keyName, data); 1965423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root return (values == null || values.isEmpty()) ? null : values.get(0); 1975423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root } 1985423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root 1995423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root public byte[] sign(String key, byte[] data) { 2005423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root return sign(getBytes(key), data); 2015423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root } 2025423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root 2035423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root private boolean verify(byte[] keyName, byte[] data, byte[] signature) { 2045423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root execute('v', keyName, data, signature); 2055423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root return mError == NO_ERROR; 2065423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root } 2075423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root 2085423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root public boolean verify(String key, byte[] data, byte[] signature) { 2095423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root return verify(getBytes(key), data, signature); 2105423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root } 2115423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root 2125423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root private boolean grant(byte[] key, byte[] uid) { 2135423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root execute('x', key, uid); 2145423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root return mError == NO_ERROR; 2155423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root } 2165423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root 2175423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root public boolean grant(String key, int uid) { 2185423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root return grant(getBytes(key), Integer.toString(uid).getBytes()); 2195423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root } 2205423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root 2215423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root private boolean ungrant(byte[] key, byte[] uid) { 2225423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root execute('y', key, uid); 2235423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root return mError == NO_ERROR; 2245423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root } 2255423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root 2265423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root public boolean ungrant(String key, int uid) { 2275423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root return ungrant(getBytes(key), Integer.toString(uid).getBytes()); 2285423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root } 2295423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root 23044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh public int getLastError() { 23144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh return mError; 23244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 23344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 234d12feb97667498378a472c5a7895a9fcd8056ec5Chia-chi Yeh private ArrayList<byte[]> execute(int code, byte[]... parameters) { 23544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh mError = PROTOCOL_ERROR; 23644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 23744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh for (byte[] parameter : parameters) { 23844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh if (parameter == null || parameter.length > 65535) { 23944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh return null; 24044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 24144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 24244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 24344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh LocalSocket socket = new LocalSocket(); 24444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh try { 24544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh socket.connect(sAddress); 24644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 24744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh OutputStream out = socket.getOutputStream(); 24844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh out.write(code); 24944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh for (byte[] parameter : parameters) { 25044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh out.write(parameter.length >> 8); 25144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh out.write(parameter.length); 25244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh out.write(parameter); 25344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 25444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh out.flush(); 25544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh socket.shutdownOutput(); 25644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 25744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh InputStream in = socket.getInputStream(); 258f1ece5d0c16fa3e79390e41ad9bec020c77d7720Chia-chi Yeh if ((code = in.read()) != NO_ERROR) { 259f1ece5d0c16fa3e79390e41ad9bec020c77d7720Chia-chi Yeh if (code != -1) { 260f1ece5d0c16fa3e79390e41ad9bec020c77d7720Chia-chi Yeh mError = code; 261f1ece5d0c16fa3e79390e41ad9bec020c77d7720Chia-chi Yeh } 26244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh return null; 26344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 26444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh 265d12feb97667498378a472c5a7895a9fcd8056ec5Chia-chi Yeh ArrayList<byte[]> values = new ArrayList<byte[]>(); 26644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh while (true) { 26744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh int i, j; 26844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh if ((i = in.read()) == -1) { 26944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh break; 27044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 27144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh if ((j = in.read()) == -1) { 27244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh return null; 27344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 274d12feb97667498378a472c5a7895a9fcd8056ec5Chia-chi Yeh byte[] value = new byte[i << 8 | j]; 275d12feb97667498378a472c5a7895a9fcd8056ec5Chia-chi Yeh for (i = 0; i < value.length; i += j) { 276d12feb97667498378a472c5a7895a9fcd8056ec5Chia-chi Yeh if ((j = in.read(value, i, value.length - i)) == -1) { 27744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh return null; 27844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 27944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 280d12feb97667498378a472c5a7895a9fcd8056ec5Chia-chi Yeh values.add(value); 28144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 282f1ece5d0c16fa3e79390e41ad9bec020c77d7720Chia-chi Yeh mError = NO_ERROR; 283d12feb97667498378a472c5a7895a9fcd8056ec5Chia-chi Yeh return values; 28444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } catch (IOException e) { 28544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh // ignore 28644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } finally { 28744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh try { 28844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh socket.close(); 28944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } catch (IOException e) {} 29044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 29144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh return null; 29244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh } 29334c47c855815d731e6deb55748ff690b0ec7b53fNick Kralevich 29434c47c855815d731e6deb55748ff690b0ec7b53fNick Kralevich private static byte[] getBytes(String string) { 29546703b099516c383a6882815bcf9cd4df0ec538dBrian Carlstrom return string.getBytes(Charsets.UTF_8); 29634c47c855815d731e6deb55748ff690b0ec7b53fNick Kralevich } 29734c47c855815d731e6deb55748ff690b0ec7b53fNick Kralevich 29834c47c855815d731e6deb55748ff690b0ec7b53fNick Kralevich private static String toString(byte[] bytes) { 29946703b099516c383a6882815bcf9cd4df0ec538dBrian Carlstrom return new String(bytes, Charsets.UTF_8); 30034c47c855815d731e6deb55748ff690b0ec7b53fNick Kralevich } 30144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh} 302