You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by dr...@apache.org on 2015/03/29 16:19:34 UTC

[2/2] directory-kerby git commit: DIRKRB-199. Support both blocking and event based network transport

DIRKRB-199. Support both blocking and event based network transport


Project: http://git-wip-us.apache.org/repos/asf/directory-kerby/repo
Commit: http://git-wip-us.apache.org/repos/asf/directory-kerby/commit/ff0200f8
Tree: http://git-wip-us.apache.org/repos/asf/directory-kerby/tree/ff0200f8
Diff: http://git-wip-us.apache.org/repos/asf/directory-kerby/diff/ff0200f8

Branch: refs/heads/master
Commit: ff0200f8bb71a9e265e1339589aa773508371f21
Parents: bf116de
Author: Drankye <dr...@gmail.com>
Authored: Sun Mar 29 22:19:14 2015 +0800
Committer: Drankye <dr...@gmail.com>
Committed: Sun Mar 29 22:19:14 2015 +0800

----------------------------------------------------------------------
 README.md                                       |  30 --
 ...kinit-1.0-SNAPSHOT-jar-with-dependencies.jar | Bin 3510337 -> 0 bytes
 .../org/apache/kerby/kerberos/kdc/KdcTest.java  |  15 +-
 .../kerby/kerberos/kdc/WithCertKdcTest.java     |   4 +-
 .../kerby/kerberos/kdc/WithTokenKdcTest.java    |   4 +-
 .../kerby/kerberos/kerb/client/KOption.java     |  41 --
 .../kerby/kerberos/kerb/client/KOptionType.java |  33 --
 .../kerby/kerberos/kerb/client/KOptions.java    | 104 -----
 .../kerby/kerberos/kerb/client/KrbClient.java   | 378 +++++--------------
 .../kerby/kerberos/kerb/client/KrbHandler.java  |  99 -----
 .../kerby/kerberos/kerb/client/KrbOption.java   |  33 +-
 .../kerb/client/event/KrbClientEvent.java       |  43 ---
 .../kerb/client/event/KrbClientEventType.java   |  29 --
 .../client/impl/AbstractInternalKrbClient.java  | 181 +++++++++
 .../kerb/client/impl/InternalKrbClient.java     |  62 +++
 .../impl/blocking/BlockModeKrbClient.java       |  80 ++++
 .../impl/blocking/BlockingKrbHandler.java       |  72 ++++
 .../impl/blocking/KrbCombinedTransport.java     |  74 ++++
 .../client/impl/blocking/KrbTcpTransport.java   |  91 +++++
 .../client/impl/blocking/KrbUdpTransport.java   |  57 +++
 .../client/impl/event/EventBasedKrbClient.java  | 142 +++++++
 .../kerb/client/impl/event/EventKrbHandler.java |  97 +++++
 .../kerb/client/impl/event/KrbClientEvent.java  |  43 +++
 .../client/impl/event/KrbClientEventType.java   |  29 ++
 .../client/preauth/AbstractPreauthPlugin.java   |   2 +-
 .../kerb/client/preauth/KrbPreauth.java         |   2 +-
 .../kerb/client/preauth/PreauthHandle.java      |   2 +-
 .../kerb/client/preauth/PreauthHandler.java     |   2 +-
 .../client/preauth/pkinit/PkinitPreauth.java    |   2 +-
 .../kerb/client/preauth/token/TokenPreauth.java |   4 +-
 .../kerb/client/request/ArmoredAsRequest.java   |   2 +-
 .../kerb/client/request/AsRequestWithCert.java  |   2 +-
 .../client/request/AsRequestWithKeytab.java     |  13 +-
 .../kerb/client/request/AsRequestWithToken.java |   4 +-
 .../kerb/client/request/KdcRequest.java         |  12 +-
 .../kerb/client/request/TgsRequest.java         |   4 +
 .../client/request/TgsRequestWithToken.java     |  36 ++
 .../kerby/kerberos/kerb/common/KrbUtil.java     |  34 +-
 .../kerb/transport/AbstractKrbTransport.java    |  38 ++
 .../kerberos/kerb/transport/KrbTransport.java   |  53 +++
 .../kerby/kerberos/kerb/server/KdcTest.java     |  15 +-
 .../kerby/kerberos/kerb/server/KdcHandler.java  |   4 +-
 .../apache/kerby/kerberos/tool/ToolUtil.java    |   6 +-
 .../apache/kerby/kerberos/tool/kinit/Kinit.java |  32 +-
 .../kerby/kerberos/tool/kinit/KinitOption.java  |   6 +-
 .../src/main/java/org/apache/kerby/KOption.java |  41 ++
 .../main/java/org/apache/kerby/KOptionType.java |  34 ++
 .../main/java/org/apache/kerby/KOptions.java    | 122 ++++++
 48 files changed, 1468 insertions(+), 745 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/ff0200f8/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index 253cc3c..3ef35f5 100644
--- a/README.md
+++ b/README.md
@@ -17,36 +17,6 @@ Apache Kerby is a Java Kerberos binding. It provides a rich, intuitive and inter
 + Provides support for JAAS, GSSAPI and SASL frameworks that applications can leverage.
 + Minimal dependencies, the core part is ensured to depend only on JRE and SLF4J, for easy use and maintenance.
 
-### KrbClient APIs
-* Initiate a KrbClient
-<pre>
-KrbClient krbClient = new KrbClient(kdcHost, kdcPort);
-</pre>
-* Request a TGT with user plain password credential
-<pre>
-krbClient.requestTgtTicket(principal, password);
-</pre>
-* Request a TGT with a keytab file
-<pre>
-krbClient.requestTgtTicket(principal, keytab);
-</pre>
-* Request a TGT with user x509 certificate credential
-<pre>
-krbClient.requestTgtTicket(principal, certificate);
-</pre>
-* Request a TGT with user token credential
-<pre>
-krbClient.requestTgtTicket(principal, kerbToken);
-</pre>
-* Request a service ticket with user TGT credential for a server
-<pre>
-krbClient.requestServiceTicket(tgt, serverPrincipal);
-</pre>
-* Request a service ticket with user AccessToken credential for a server
-<pre>
-krbClient.requestServiceTicket(accessToken, serverPrincipal);
-</pre>
-
 ### ASN-1 support
 Please look at [kerby-asn1](kerby-asn1/) for details.
 

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/ff0200f8/kdc-tool/kinit/kinit-dist/kinit/kinit-1.0-SNAPSHOT-jar-with-dependencies.jar
----------------------------------------------------------------------
diff --git a/kdc-tool/kinit/kinit-dist/kinit/kinit-1.0-SNAPSHOT-jar-with-dependencies.jar b/kdc-tool/kinit/kinit-dist/kinit/kinit-1.0-SNAPSHOT-jar-with-dependencies.jar
deleted file mode 100644
index ff44e4f..0000000
Binary files a/kdc-tool/kinit/kinit-dist/kinit/kinit-1.0-SNAPSHOT-jar-with-dependencies.jar and /dev/null differ

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/ff0200f8/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/KdcTest.java
----------------------------------------------------------------------
diff --git a/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/KdcTest.java b/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/KdcTest.java
index 56e4a92..559b785 100644
--- a/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/KdcTest.java
+++ b/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/KdcTest.java
@@ -52,10 +52,10 @@ public abstract class KdcTest extends KdcTestBase {
 
         // With good password
         try {
-            tgt = krbClnt.requestTgtTicket(clientPrincipal, password, null);
+            tgt = krbClnt.requestTgtWithPassword(clientPrincipal, password);
             assertThat(tgt).isNotNull();
 
-            tkt = krbClnt.requestServiceTicket(tgt, serverPrincipal, null);
+            tkt = krbClnt.requestServiceTicketWithTgt(tgt, serverPrincipal);
             assertThat(tkt).isNotNull();
         } catch (Exception e) {
             System.out.println("Exception occurred with good password");
@@ -65,23 +65,22 @@ public abstract class KdcTest extends KdcTestBase {
 
         // With bad password
         try {
-            tgt = krbClnt.requestTgtTicket(clientPrincipal, "badpassword", null);
+            tgt = krbClnt.requestTgtWithPassword(clientPrincipal, "badpassword");
         } catch (Exception e) {
             System.out.println("Exception occurred with bad password");
         }
 
-        // TODO: With good password again. This will fail, to be investigated.
-        /*
+        // With good password again
         try {
-            tgt = krbClnt.requestTgtTicket(clientPrincipal, password, null);
+            tgt = krbClnt.requestTgtWithPassword(clientPrincipal, password);
             assertThat(tgt).isNotNull();
 
-            tkt = krbClnt.requestServiceTicket(tgt, serverPrincipal, null);
+            tkt = krbClnt.requestServiceTicketWithTgt(tgt, serverPrincipal);
             assertThat(tkt).isNotNull();
         } catch (Exception e) {
             System.out.println("Exception occurred with good password again");
             e.printStackTrace();
             Assert.fail();
-        }*/
+        }
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/ff0200f8/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithCertKdcTest.java
----------------------------------------------------------------------
diff --git a/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithCertKdcTest.java b/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithCertKdcTest.java
index 5df9495..b211f68 100644
--- a/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithCertKdcTest.java
+++ b/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithCertKdcTest.java
@@ -80,14 +80,14 @@ public class WithCertKdcTest extends KdcTestBase {
 
         TgtTicket tgt = null;
         try {
-            tgt = krbClnt.requestTgtTicket(clientPrincipal, userCert, userKey, null);
+            tgt = krbClnt.requestTgtWithCert(clientPrincipal, userCert, userKey);
         } catch (KrbException te) {
             assertThat(te.getMessage().contains("timeout")).isTrue();
             return;
         }
         assertThat(tgt).isNull();
 
-        ServiceTicket tkt = krbClnt.requestServiceTicket(tgt, serverPrincipal, null);
+        ServiceTicket tkt = krbClnt.requestServiceTicketWithTgt(tgt, serverPrincipal);
         assertThat(tkt).isNull();
     }
 

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/ff0200f8/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithTokenKdcTest.java
----------------------------------------------------------------------
diff --git a/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithTokenKdcTest.java b/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithTokenKdcTest.java
index e8f6a5a..6442323 100644
--- a/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithTokenKdcTest.java
+++ b/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithTokenKdcTest.java
@@ -94,14 +94,14 @@ public class WithTokenKdcTest extends KdcTestBase {
 
         TgtTicket tgt;
         try {
-            tgt = krbClnt.requestTgtTicket(clientPrincipal, authToken, null);
+            tgt = krbClnt.requestTgtWithToken(authToken);
         } catch (KrbException te) {
             assertThat(te.getMessage().contains("timeout")).isTrue();
             return;
         }
         assertThat(tgt).isNull();
 
-        ServiceTicket tkt = krbClnt.requestServiceTicket(tgt, serverPrincipal, null);
+        ServiceTicket tkt = krbClnt.requestServiceTicketWithTgt(tgt, serverPrincipal);
         assertThat(tkt).isNull();
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/ff0200f8/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KOption.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KOption.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KOption.java
deleted file mode 100644
index 6a85ad6..0000000
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KOption.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/**
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *  
- *    http://www.apache.org/licenses/LICENSE-2.0
- *  
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License. 
- *  
- */
-package org.apache.kerby.kerberos.kerb.client;
-
-public interface KOption {
-
-    public void setType(KOptionType type);
-
-    public KOptionType getType();
-
-    public String getOptionName();
-
-    public void setName(String name);
-
-    public String getName();
-
-    public void setDescription(String description);
-
-    public String getDescription();
-
-    public void setValue(Object value);
-
-    public Object getValue();
-}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/ff0200f8/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KOptionType.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KOptionType.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KOptionType.java
deleted file mode 100644
index fd83aeb..0000000
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KOptionType.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *  
- *    http://www.apache.org/licenses/LICENSE-2.0
- *  
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License. 
- *  
- */
-package org.apache.kerby.kerberos.kerb.client;
-
-/**
- * Option type.
- */
-public enum KOptionType {
-    NONE,
-    NOV, // no value, a control flag
-    STR, // string value
-    INT, // integer value
-    BOOL, // boolean value
-    FILE, // file path value
-    DIR // dir path value
-}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/ff0200f8/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KOptions.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KOptions.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KOptions.java
deleted file mode 100644
index c196065..0000000
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KOptions.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/**
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *  
- *    http://www.apache.org/licenses/LICENSE-2.0
- *  
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License. 
- *  
- */
-package org.apache.kerby.kerberos.kerb.client;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * A KOption container.
- */
-public class KOptions {
-
-    private final Map<KOption, KOption> options =
-            new HashMap<KOption, KOption>();
-
-    public void add(KOption option) {
-        if (option != null) {
-            options.put(option, option);
-        }
-    }
-
-    public void add(KOption option, Object optionValue) {
-        if (option != null) {
-            option.setValue(optionValue);
-            add(option);
-        }
-    }
-
-    public boolean contains(KOption option) {
-        return options.containsKey(option);
-    }
-
-    public List<KOption> getOptions() {
-        return new ArrayList<>(options.keySet());
-    }
-
-    public KOption getOption(KOption option) {
-        if (! options.containsKey(option)) {
-            return null;
-        }
-
-        return options.get(option);
-    }
-
-    public Object getOptionValue(KOption option) {
-        if (! contains(option)) {
-            return null;
-        }
-        return options.get(option).getValue();
-    }
-
-    public String getStringOption(KOption option) {
-        Object value = getOptionValue(option);
-        if (value instanceof String) {
-            return (String) value;
-        }
-        return null;
-    }
-
-    public boolean getBooleanOption(KOption option) {
-        Object value = getOptionValue(option);
-        if (value instanceof String) {
-            String strVal = (String) value;
-            if (strVal.equalsIgnoreCase("true") ||
-                strVal.equalsIgnoreCase("yes") ||
-                strVal.equals("1")) {
-                return true;
-            }
-        } else if (value instanceof Boolean) {
-            return (Boolean) value;
-        }
-        return false;
-    }
-
-    public int getIntegerOption(KOption option) {
-        Object value = getOptionValue(option);
-        if (value instanceof String) {
-            String strVal = (String) value;
-            return Integer.valueOf(strVal);
-        } else if (value instanceof Integer) {
-            return (Integer) value;
-        }
-        return -1;
-    }
-}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/ff0200f8/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbClient.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbClient.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbClient.java
index 29c4815..67bc7d7 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbClient.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbClient.java
@@ -19,51 +19,27 @@
  */
 package org.apache.kerby.kerberos.kerb.client;
 
-import org.apache.kerby.event.Event;
-import org.apache.kerby.event.EventHub;
-import org.apache.kerby.event.EventWaiter;
-import org.apache.kerby.kerberos.kerb.KrbErrorCode;
-import org.apache.kerby.kerberos.kerb.KrbErrorException;
+import org.apache.kerby.KOptions;
 import org.apache.kerby.kerberos.kerb.KrbException;
-import org.apache.kerby.kerberos.kerb.client.event.KrbClientEvent;
-import org.apache.kerby.kerberos.kerb.client.event.KrbClientEventType;
-import org.apache.kerby.kerberos.kerb.client.request.*;
-import org.apache.kerby.kerberos.kerb.common.KrbErrorUtil;
-import org.apache.kerby.kerberos.kerb.common.KrbStreamingDecoder;
-import org.apache.kerby.kerberos.kerb.spec.base.KrbError;
-import org.apache.kerby.kerberos.kerb.spec.base.PrincipalName;
+import org.apache.kerby.kerberos.kerb.client.impl.blocking.BlockModeKrbClient;
+import org.apache.kerby.kerberos.kerb.client.impl.event.EventBasedKrbClient;
+import org.apache.kerby.kerberos.kerb.client.impl.InternalKrbClient;
+import org.apache.kerby.kerberos.kerb.spec.base.AuthToken;
 import org.apache.kerby.kerberos.kerb.spec.ticket.ServiceTicket;
 import org.apache.kerby.kerberos.kerb.spec.ticket.TgtTicket;
-import org.apache.kerby.kerberos.kerb.spec.base.AuthToken;
-import org.apache.kerby.transport.Network;
-import org.apache.kerby.transport.Transport;
-import org.apache.kerby.transport.event.TransportEvent;
-import org.apache.kerby.transport.event.TransportEventType;
 
 import java.io.File;
 import java.io.IOException;
 import java.security.PrivateKey;
 import java.security.cert.Certificate;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
 
 /**
- * A krb client API for applications to interact with KDC
+ * A Krb client API for applications to interact with KDC
  */
 public class KrbClient {
 
-    private EventHub eventHub;
-    private EventWaiter eventWaiter;
-    private Transport transport;
-
-    private KrbHandler krbHandler;
-    private KrbContext context;
-    private String kdcHost;
-    private int kdcTcpPort;
-    private Boolean allowUdp;
-    private int kdcUdpPort;
-    private KrbConfig krbConfig;
-    private File confDir;
+    private KOptions commonOptions;
+    private InternalKrbClient innerClient;
 
     /**
      * Default constructor.
@@ -73,45 +49,12 @@ public class KrbClient {
     }
 
     /**
-     * Construct a KrbClient with host and port. The port can be TCP, UDP or
-     * both, but TCP will try first.
-     * @param kdcHost
-     * @param kdcPort
-     */
-    public KrbClient(String kdcHost, int kdcPort) {
-        this(new KrbConfig());
-
-        setKdcHost(kdcHost);
-        setKdcTcpPort(kdcPort);
-        setKdcUdpPort(kdcPort);
-    }
-
-    /**
-     * Construct with prepared KrbConfig
+     * Construct with prepared KrbConfig.
      * @param krbConfig
      */
     public KrbClient(KrbConfig krbConfig) {
-        this.krbConfig = krbConfig;
-        this.context = new KrbContext();
-        context.init(krbConfig);
-    }
-
-    /**
-     * Prepare krb config, loading krb5.conf.
-     * It can be override to add more configuration resources.
-     *
-     * @throws IOException
-     */
-    protected void initConfig() throws IOException {
-        if (confDir == null) {
-            confDir = new File("/etc/"); // for Linux. TODO: fix for Win etc.
-        }
-        if (confDir != null && confDir.exists()) {
-            File kdcConfFile = new File(confDir, "krb5.conf");
-            if (kdcConfFile.exists()) {
-                krbConfig.addIniConfig(kdcConfFile);
-            }
-        }
+        commonOptions = new KOptions();
+        commonOptions.add(KrbOption.KRB_CONFIG, krbConfig);
     }
 
     /**
@@ -119,7 +62,7 @@ public class KrbClient {
      * @param file
      */
     public void setConfDir(File file) throws IOException {
-        confDir = file;
+        commonOptions.add(KrbOption.CONF_DIR, file);
     }
 
     /**
@@ -127,35 +70,7 @@ public class KrbClient {
      * @param realm
      */
     public void setKdcRealm(String realm) {
-        context.setKdcRealm(realm);
-    }
-
-    private String getKdcHost() {
-        if (kdcHost != null) {
-            return kdcHost;
-        }
-        return krbConfig.getKdcHost();
-    }
-
-    private int getKdcTcpPort() {
-        if (kdcTcpPort > 0) {
-            return kdcTcpPort;
-        }
-        return krbConfig.getKdcTcpPort();
-    }
-
-    private boolean allowUdp() {
-        if (allowUdp != null) {
-            return allowUdp;
-        }
-        return krbConfig.allowKdcUdp();
-    }
-
-    private int getKdcUdpPort() {
-        if (kdcUdpPort > 0) {
-            return kdcUdpPort;
-        }
-        return krbConfig.getKdcUdpPort();
+        commonOptions.add(KrbOption.KDC_REALM, realm);
     }
 
     /**
@@ -163,7 +78,7 @@ public class KrbClient {
      * @param kdcHost
      */
     public void setKdcHost(String kdcHost) {
-        this.kdcHost = kdcHost;
+        commonOptions.add(KrbOption.KDC_HOST, kdcHost);
     }
 
     /**
@@ -171,7 +86,7 @@ public class KrbClient {
      * @param kdcTcpPort
      */
     public void setKdcTcpPort(int kdcTcpPort) {
-        this.kdcTcpPort = kdcTcpPort;
+        commonOptions.add(KrbOption.KDC_TCP_PORT, kdcTcpPort);
     }
 
     /**
@@ -179,7 +94,7 @@ public class KrbClient {
      * @param allowUdp
      */
     public void setAllowUdp(boolean allowUdp) {
-        this.allowUdp = allowUdp;
+        commonOptions.add(KrbOption.ALLOW_UDP, allowUdp);
     }
 
     /**
@@ -187,92 +102,69 @@ public class KrbClient {
      * @param kdcUdpPort
      */
     public void setKdcUdpPort(int kdcUdpPort) {
-        this.kdcUdpPort = kdcUdpPort;
+        commonOptions.add(KrbOption.KDC_UDP_PORT, kdcUdpPort);
     }
 
     /**
      * Set time out for connection
      * @param timeout in seconds
      */
-    public void setTimeout(long timeout) {
-        context.setTimeout(timeout);
+    public void setTimeout(int timeout) {
+        commonOptions.add(KrbOption.CONN_TIMEOUT, timeout);
     }
 
-    public void init() {
-        try {
-            initConfig();
-        } catch (IOException e) {
-            throw new RuntimeException("Failed to load config", e);
-        }
-
-        this.krbHandler = new KrbHandler();
-        krbHandler.init(context);
-
-        this.eventHub = new EventHub();
-        eventHub.register(krbHandler);
-
-        Network network = new Network();
-        network.setStreamingDecoder(new KrbStreamingDecoder());
-        eventHub.register(network);
-
-        eventWaiter = eventHub.waitEvent(
-                TransportEventType.NEW_TRANSPORT,
-                KrbClientEventType.TGT_RESULT,
-                KrbClientEventType.TKT_RESULT
-        );
-
-        eventHub.start();
-
-        network.tcpConnect(getKdcHost(), getKdcTcpPort());
-        if (allowUdp()) {
-            network.udpConnect(getKdcHost(), getKdcUdpPort());
-        }
-        Event event = eventWaiter.waitEvent(TransportEventType.NEW_TRANSPORT);
-        transport = ((TransportEvent) event).getTransport();
+    /**
+     * Use event model. By default blocking model is used.
+     */
+    public void useEventModel() {
+        commonOptions.add(KrbOption.USE_EVENT_MODEL);
     }
 
     /**
-     * Attempt to request a TGT and you'll be prompted to input a credential.
-     * Whatever credential requested to provide depends on KDC admin configuration.
-     * @param options
-     * @return
+     * Init the client.
      * @throws KrbException
      */
-    public TgtTicket requestTgtTicket(String principal,
-                                      KOptions options) throws KrbException {
-        if (options == null) {
-            options = new KOptions();
-        }
-
-        AsRequest asRequest;
-        if (options.contains(KrbOption.USE_KEYTAB)) {
-            asRequest = new AsRequestWithKeytab(context);
+    public void init() throws KrbException {
+        if (commonOptions.contains(KrbOption.USE_EVENT_MODEL)) {
+            innerClient = new EventBasedKrbClient();
         } else {
-            asRequest = new AsRequest(context);
+            innerClient = new BlockModeKrbClient();
         }
-
-        asRequest.setKrbOptions(options);
-        return requestTgtTicket(principal, asRequest);
+        innerClient.init(commonOptions);
     }
 
     /**
      * Request a TGT with user plain credential
      * @param principal
      * @param password
-     * @param options
      * @return
      * @throws KrbException
      */
-    public TgtTicket requestTgtTicket(String principal, String password,
-                                      KOptions options) throws KrbException {
-        if (options == null) {
-            options = new KOptions();
-        }
+    public TgtTicket requestTgtWithPassword(String principal,
+                                      String password) throws KrbException {
 
-        AsRequest asRequest = new AsRequestWithPasswd(context);
-        options.add(KrbOption.USER_PASSWD, password);
-        asRequest.setKrbOptions(options);
-        return requestTgtTicket(principal, asRequest);
+        KOptions requestOptions = new KOptions();
+        requestOptions.add(KrbOption.CLIENT_PRINCIPAL, principal);
+        requestOptions.add(KrbOption.USE_PASSWD, true);
+        requestOptions.add(KrbOption.USER_PASSWD, password);
+        return requestTgtWithOptions(requestOptions);
+    }
+
+    /**
+     * Request a TGT with user plain credential
+     * @param principal
+     * @param keytabFile
+     * @return TGT
+     * @throws KrbException
+     */
+    public TgtTicket requestTgtWithKeytab(String principal,
+                                      String keytabFile) throws KrbException {
+
+        KOptions requestOptions = new KOptions();
+        requestOptions.add(KrbOption.CLIENT_PRINCIPAL, principal);
+        requestOptions.add(KrbOption.USE_KEYTAB, true);
+        requestOptions.add(KrbOption.KEYTAB_FILE, keytabFile);
+        return requestTgtWithOptions(requestOptions);
     }
 
     /**
@@ -280,167 +172,81 @@ public class KrbClient {
      * @param principal
      * @param certificate
      * @param privateKey
-     * @param options
-     * @return
+     * @return TGT
      * @throws KrbException
      */
-    public TgtTicket requestTgtTicket(
-            String principal, Certificate certificate, PrivateKey privateKey,
-            KOptions options) throws KrbException {
-        if (options == null) {
-            options = new KOptions();
-        }
-
-        AsRequestWithCert asRequest = new AsRequestWithCert(context);
-        options.add(KrbOption.PKINIT_X509_CERTIFICATE, certificate);
-        options.add(KrbOption.PKINIT_X509_PRIVATE_KEY, privateKey);
-        asRequest.setKrbOptions(options);
-        return requestTgtTicket(principal, asRequest);
+    public TgtTicket requestTgtWithCert(String principal, Certificate certificate,
+                                        PrivateKey privateKey) throws KrbException {
+        KOptions requestOptions = new KOptions();
+        requestOptions.add(KrbOption.PKINIT_X509_CERTIFICATE, certificate);
+        requestOptions.add(KrbOption.PKINIT_X509_PRIVATE_KEY, privateKey);
+        return requestTgtWithOptions(requestOptions);
     }
 
     /**
      * Request a TGT with using Anonymous PKINIT
-     * @param options
-     * @return
+     * @return TGT
      * @throws KrbException
      */
-    public TgtTicket requestTgtTicket(KOptions options) throws KrbException {
-        if (options == null) {
-            options = new KOptions();
-        }
-
-        AsRequestWithCert asRequest = new AsRequestWithCert(context);
-        options.add(KrbOption.PKINIT_X509_ANONYMOUS);
-        asRequest.setKrbOptions(options);
-
-        String principal = AsRequestWithCert.ANONYMOUS_PRINCIPAL;
-        return requestTgtTicket(principal, asRequest);
+    public TgtTicket requestTgtWithPkintAnonymous() throws KrbException {
+        KOptions requestOptions = new KOptions();
+        requestOptions.add(KrbOption.USE_PKINIT_ANONYMOUS);
+        return requestTgtWithOptions(requestOptions);
     }
 
     /**
      * Request a TGT with user token credential
-     * @param principal
      * @param token
-     * @param options
-     * @return
+     * @return TGT
      * @throws KrbException
      */
-    public TgtTicket requestTgtTicket(String principal, AuthToken token,
-                                      KOptions options) throws KrbException {
-        if (options == null) {
-            options = new KOptions();
+    public TgtTicket requestTgtWithToken(AuthToken token) throws KrbException {
+        if (! token.isIdToken()) {
+            throw new IllegalArgumentException("Identity token is expected");
         }
 
-        AsRequestWithToken asRequest = new AsRequestWithToken(context);
-        options.add(KrbOption.TOKEN_USER_ID_TOKEN, token);
-        asRequest.setKrbOptions(options);
-        return requestTgtTicket(principal, asRequest);
+        KOptions requestOptions = new KOptions();
+        requestOptions.add(KrbOption.TOKEN_USER_ID_TOKEN, token);
+        return requestTgtWithOptions(requestOptions);
     }
 
     /**
-     * Request a service ticket targeting for a server with user plain credentials
-     * @param clientPrincipal
-     * @param password
-     * @param serverPrincipal
-     * @param options
-     * @return
+     * Request a TGT with using well prepared requestOptions.
+     * @param requestOptions
+     * @return TGT
      * @throws KrbException
      */
-    public ServiceTicket requestServiceTicket(
-            String clientPrincipal, String password, String serverPrincipal,
-            KOptions options) throws KrbException {
-        if (options == null) {
-            options = new KOptions();
+    public TgtTicket requestTgtWithOptions(KOptions requestOptions) throws KrbException {
+        if (requestOptions == null) {
+            throw new IllegalArgumentException("Null KrbOptions specified");
         }
 
-        TgtTicket tgt = requestTgtTicket(clientPrincipal, password, options);
-        return requestServiceTicket(tgt, serverPrincipal, options);
+        return innerClient.requestTgtTicket(requestOptions);
     }
 
     /**
-     * Request a service ticket targeting for a server with an user Access Token
-     * @param clientPrincipal
-     * @param token
+     * Request a service ticket with a TGT targeting for a server
+     * @param tgt
      * @param serverPrincipal
-     * @param options
      * @return
      * @throws KrbException
      */
-    public ServiceTicket requestServiceTicket(
-            String clientPrincipal, AuthToken token, String serverPrincipal,
-            KOptions options) throws KrbException {
-        if (options == null) {
-            options = new KOptions();
-        }
-
-        TgtTicket tgt = requestTgtTicket(clientPrincipal, token, options);
-        return requestServiceTicket(tgt, serverPrincipal, options);
-    }
-
-    private TgtTicket requestTgtTicket(String clientPrincipal,
-                                       AsRequest tgtTktReq) throws KrbException {
-        tgtTktReq.setClientPrincipal(new PrincipalName(clientPrincipal));
-        tgtTktReq.setTransport(transport);
-
-        try {
-            return doRequestTgtTicket(tgtTktReq);
-        } catch(KrbErrorException e) {
-            KrbError krbError = e.getKrbError();
-            if (krbError.getErrorCode() == KrbErrorCode.KDC_ERR_PREAUTH_REQUIRED) {
-                try {
-                    tgtTktReq.setEncryptionTypes(KrbErrorUtil.getEtypes(krbError));
-                } catch (IOException ioe) {
-                    throw new KrbException("Failed to decode and get etypes from krbError", ioe);
-                }
-                tgtTktReq.getPreauthContext().setPreauthRequired(true);
-                return requestTgtTicket(clientPrincipal, tgtTktReq);
-            }
-            throw e;
-        }
-    }
-
-    private TgtTicket doRequestTgtTicket(AsRequest tgtTktReq) throws KrbException {
-        eventHub.dispatch(KrbClientEvent.createTgtIntentEvent(tgtTktReq));
-        Event resultEvent;
-        try {
-            resultEvent = eventWaiter.waitEvent(KrbClientEventType.TGT_RESULT,
-                    context.getTimeout(), TimeUnit.SECONDS);
-        } catch (TimeoutException e) {
-            throw new KrbException("Network timeout", e);
-        }
-        AsRequest asResponse = (AsRequest) resultEvent.getEventData();
-
-        return asResponse.getTicket();
+    public ServiceTicket requestServiceTicketWithTgt(
+            TgtTicket tgt, String serverPrincipal) throws KrbException {
+        return innerClient.requestServiceTicketWithTgt(tgt, serverPrincipal);
     }
 
     /**
-     * Request a service ticket with a TGT targeting for a server
-     * @param tgt
-     * @param serverPrincipal
-     * @return
+     * Request a service ticket using an Access Token.
+     * @return service ticket
      * @throws KrbException
      */
-    public ServiceTicket requestServiceTicket(TgtTicket tgt, String serverPrincipal,
-                                              KOptions options) throws KrbException {
-        if (options == null) {
-            options = new KOptions();
+    public ServiceTicket requestServiceTicketWithAccessToken(
+            AuthToken token, String serverPrincipal) throws KrbException {
+        if (! token.isAcToken()) {
+            throw new IllegalArgumentException("Access token is expected");
         }
-
-        TgsRequest ticketReq = new TgsRequest(context, tgt);
-        ticketReq.setServerPrincipal(new PrincipalName(serverPrincipal));
-        ticketReq.setTransport(transport);
-
-        eventHub.dispatch(KrbClientEvent.createTktIntentEvent(ticketReq));
-        Event resultEvent;
-        try {
-            resultEvent = eventWaiter.waitEvent(KrbClientEventType.TKT_RESULT,
-                    context.getTimeout(), TimeUnit.SECONDS);
-        } catch (TimeoutException e) {
-            throw new KrbException("Network timeout", e);
-        }
-        TgsRequest tgsResponse = (TgsRequest) resultEvent.getEventData();
-
-        return tgsResponse.getServiceTicket();
+        return innerClient.requestServiceTicketWithAccessToken(token, serverPrincipal);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/ff0200f8/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbHandler.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbHandler.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbHandler.java
deleted file mode 100644
index 2037f76..0000000
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbHandler.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/**
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *  
- *    http://www.apache.org/licenses/LICENSE-2.0
- *  
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License. 
- *  
- */
-package org.apache.kerby.kerberos.kerb.client;
-
-import org.apache.kerby.event.AbstractEventHandler;
-import org.apache.kerby.event.Event;
-import org.apache.kerby.event.EventType;
-import org.apache.kerby.kerberos.kerb.client.event.KrbClientEvent;
-import org.apache.kerby.kerberos.kerb.client.event.KrbClientEventType;
-import org.apache.kerby.kerberos.kerb.client.preauth.PreauthHandler;
-import org.apache.kerby.kerberos.kerb.client.request.AsRequest;
-import org.apache.kerby.kerberos.kerb.client.request.KdcRequest;
-import org.apache.kerby.kerberos.kerb.client.request.TgsRequest;
-import org.apache.kerby.kerberos.kerb.common.KrbUtil;
-import org.apache.kerby.kerberos.kerb.KrbException;
-import org.apache.kerby.kerberos.kerb.spec.base.KrbMessage;
-import org.apache.kerby.kerberos.kerb.spec.base.KrbMessageType;
-import org.apache.kerby.kerberos.kerb.spec.kdc.KdcRep;
-import org.apache.kerby.kerberos.kerb.spec.kdc.KdcReq;
-import org.apache.kerby.transport.Transport;
-import org.apache.kerby.transport.event.MessageEvent;
-import org.apache.kerby.transport.event.TransportEventType;
-
-import java.nio.ByteBuffer;
-
-public class KrbHandler extends AbstractEventHandler {
-
-    private KrbContext context;
-    private PreauthHandler preauthHandler;
-
-    public void init(KrbContext context) {
-        this.context = context;
-        preauthHandler = new PreauthHandler();
-        preauthHandler.init(context);
-    }
-
-    @Override
-    public EventType[] getInterestedEvents() {
-        return new EventType[] {
-                TransportEventType.INBOUND_MESSAGE,
-                KrbClientEventType.TGT_INTENT,
-                KrbClientEventType.TKT_INTENT
-        };
-    }
-
-    @Override
-    protected void doHandle(Event event) throws Exception {
-        EventType eventType = event.getEventType();
-
-        if (eventType == KrbClientEventType.TGT_INTENT ||
-                eventType == KrbClientEventType.TKT_INTENT) {
-            KdcRequest kdcRequest = (KdcRequest) event.getEventData();
-            handleKdcRequest(kdcRequest);
-        } else if (event.getEventType() == TransportEventType.INBOUND_MESSAGE) {
-            handleMessage((MessageEvent) event);
-        }
-    }
-
-    protected void handleKdcRequest(KdcRequest kdcRequest) throws KrbException {
-        kdcRequest.process();
-        KdcReq kdcReq = kdcRequest.getKdcReq();
-        Transport transport = kdcRequest.getTransport();
-        transport.setAttachment(kdcRequest);
-        KrbUtil.sendMessage(kdcReq, transport);
-    }
-
-    protected void handleMessage(MessageEvent event) throws Exception {
-        ByteBuffer message = event.getMessage();
-        KrbMessage kdcRep = KrbUtil.decodeMessage(message);
-
-        KrbMessageType messageType = kdcRep.getMsgType();
-        if (messageType == KrbMessageType.AS_REP) {
-            KdcRequest kdcRequest = (KdcRequest) event.getTransport().getAttachment();
-            kdcRequest.processResponse((KdcRep) kdcRep);
-            dispatch(KrbClientEvent.createTgtResultEvent((AsRequest) kdcRequest));
-        } else if (messageType == KrbMessageType.TGS_REP) {
-            KdcRequest kdcRequest = (KdcRequest) event.getTransport().getAttachment();
-            kdcRequest.processResponse((KdcRep) kdcRep);
-            dispatch(KrbClientEvent.createTktResultEvent((TgsRequest) kdcRequest));
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/ff0200f8/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbOption.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbOption.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbOption.java
index 3e6740b..2eb5ad3 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbOption.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbOption.java
@@ -19,8 +19,21 @@
  */
 package org.apache.kerby.kerberos.kerb.client;
 
+import org.apache.kerby.KOption;
+import org.apache.kerby.KOptionType;
+
 public enum KrbOption implements KOption {
     NONE("NONE"),
+    USE_EVENT_MODEL("use event model", KOptionType.NOV),
+    CLIENT_PRINCIPAL("client-principal", "Client principal", KOptionType.STR),
+    KRB_CONFIG("krb config", KOptionType.OBJ),
+    CONF_DIR("conf dir", KOptionType.DIR),
+    KDC_REALM("kdc realm", KOptionType.STR),
+    KDC_HOST("kdc host", KOptionType.STR),
+    KDC_TCP_PORT("kdc tcp port", KOptionType.INT),
+    ALLOW_UDP("allow udp", KOptionType.BOOL),
+    KDC_UDP_PORT("kdc udp port", KOptionType.INT),
+    CONN_TIMEOUT("connection timeout", KOptionType.INT),
     LIFE_TIME("life time", KOptionType.INT),
     START_TIME("start time", KOptionType.INT),
     RENEWABLE_TIME("renewable lifetime", KOptionType.INT),
@@ -35,24 +48,28 @@ public enum KrbOption implements KOption {
     RENEW("renew"),
     CANONICALIZE("canonicalize"),
     AS_ENTERPRISE_PN("as-enterprise-pn", "client is enterprise principal name"),
+
+    USE_PASSWD("using password", "using password"),
+    USER_PASSWD("user-passwd", "User plain password"),
+
     USE_KEYTAB("use-keytab", "use keytab"),
-    USE_DFT_KEYTAB("user-default-keytab", "use default client keytab"),
-    USER_KEYTAB_FILE("user-keytab-file", "filename of keytab to use", KOptionType.FILE),
+    USE_DFT_KEYTAB("-i", "use default client keytab (with -k)"),
+    KEYTAB_FILE("keytab-file", "filename of keytab to use", KOptionType.FILE),
+
     KRB5_CACHE("krb5-cache", "K5 cache name", KOptionType.FILE),
-    SERVICE("service", KOptionType.STR),
+    SERVICE_PRINCIPAL("service-principal", "service principal", KOptionType.STR),
     ARMOR_CACHE("armor-cache", "armor credential cache", KOptionType.STR),
 
-    CONF_DIR("conf dir", KOptionType.DIR),
-    USER_PASSWD("user-passwd", "User plain password"),
-
+    USE_PKINIT("use-pkinit", "using pkinit"),
     PKINIT_X509_IDENTITY("x509-identities", "X509 user private key and cert", KOptionType.STR),
     PKINIT_X509_PRIVATE_KEY("x509-privatekey", "X509 user private key", KOptionType.STR),
     PKINIT_X509_CERTIFICATE("x509-cert", "X509 user certificate", KOptionType.STR),
     PKINIT_X509_ANCHORS("x509-anchors", "X509 anchors", KOptionType.STR),
-    PKINIT_X509_ANONYMOUS("x509-anonymous", "X509 anonymous"),
     PKINIT_USING_RSA("using-rsa-or-dh", "Using RSA or DH"),
 
-    TOKEN_USING_IDTOKEN("using-id-token", "Using identity token"),
+    USE_PKINIT_ANONYMOUS("use-pkinit-anonymous", "X509 anonymous"),
+
+    USE_TOKEN("use-id-token", "Using identity token"),
     TOKEN_USER_ID_TOKEN("user-id-token", "User identity token", KOptionType.STR),
     TOKEN_USER_AC_TOKEN("user-ac-token", "User access token", KOptionType.STR),
 

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/ff0200f8/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/event/KrbClientEvent.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/event/KrbClientEvent.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/event/KrbClientEvent.java
deleted file mode 100644
index 291b33e..0000000
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/event/KrbClientEvent.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *  
- *    http://www.apache.org/licenses/LICENSE-2.0
- *  
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License. 
- *  
- */
-package org.apache.kerby.kerberos.kerb.client.event;
-
-import org.apache.kerby.event.Event;
-import org.apache.kerby.kerberos.kerb.client.request.AsRequest;
-import org.apache.kerby.kerberos.kerb.client.request.TgsRequest;
-
-public class KrbClientEvent {
-
-    public static Event createTgtIntentEvent(AsRequest asRequest) {
-        return new Event(KrbClientEventType.TGT_INTENT, asRequest);
-    }
-
-    public static Event createTktIntentEvent(TgsRequest tgsRequest) {
-        return new Event(KrbClientEventType.TKT_INTENT, tgsRequest);
-    }
-
-    public static Event createTgtResultEvent(AsRequest asRequest) {
-        return new Event(KrbClientEventType.TGT_RESULT, asRequest);
-    }
-
-    public static Event createTktResultEvent(TgsRequest tgsRequest) {
-        return new Event(KrbClientEventType.TKT_RESULT, tgsRequest);
-    }
-}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/ff0200f8/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/event/KrbClientEventType.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/event/KrbClientEventType.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/event/KrbClientEventType.java
deleted file mode 100644
index 78fd424..0000000
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/event/KrbClientEventType.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *  
- *    http://www.apache.org/licenses/LICENSE-2.0
- *  
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License. 
- *  
- */
-package org.apache.kerby.kerberos.kerb.client.event;
-
-import org.apache.kerby.event.EventType;
-
-public enum KrbClientEventType implements EventType {
-    TGT_INTENT,
-    TGT_RESULT,
-    TKT_INTENT,
-    TKT_RESULT
-}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/ff0200f8/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/AbstractInternalKrbClient.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/AbstractInternalKrbClient.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/AbstractInternalKrbClient.java
new file mode 100644
index 0000000..c316b15
--- /dev/null
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/AbstractInternalKrbClient.java
@@ -0,0 +1,181 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.kerby.kerberos.kerb.client.impl;
+
+import org.apache.kerby.KOptions;
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.client.KrbConfig;
+import org.apache.kerby.kerberos.kerb.client.KrbContext;
+import org.apache.kerby.kerberos.kerb.client.KrbOption;
+import org.apache.kerby.kerberos.kerb.client.request.*;
+import org.apache.kerby.kerberos.kerb.spec.base.AuthToken;
+import org.apache.kerby.kerberos.kerb.spec.base.PrincipalName;
+import org.apache.kerby.kerberos.kerb.spec.ticket.ServiceTicket;
+import org.apache.kerby.kerberos.kerb.spec.ticket.TgtTicket;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * A krb client API for applications to interact with KDC
+ */
+public abstract class AbstractInternalKrbClient implements InternalKrbClient {
+    private KrbContext context;
+    private KrbConfig krbConfig;
+    private KOptions commonOptions;
+
+    protected KrbContext getContext() {
+        return context;
+    }
+
+    /**
+     * Prepare krb config, loading krb5.conf.
+     * It can be override to add more configuration resources.
+     *
+     * @throws java.io.IOException
+     */
+    protected void initConfig() throws IOException {
+        this.krbConfig = (KrbConfig) commonOptions.getOptionValue(KrbOption.KRB_CONFIG);
+        if (krbConfig == null) {
+            krbConfig = new KrbConfig();
+        }
+
+        File confDir = getConfDir();
+        if (confDir == null) {
+            confDir = new File("/etc/"); // for Linux. TODO: fix for Win etc.
+        }
+        if (confDir != null && confDir.exists()) {
+            File kdcConfFile = new File(confDir, "krb5.conf");
+            if (kdcConfFile.exists()) {
+                krbConfig.addIniConfig(kdcConfFile);
+            }
+        }
+    }
+
+    protected File getConfDir() {
+        return  commonOptions.getDirOption(KrbOption.CONF_DIR);
+    }
+
+    protected String getKdcHost() {
+        String kdcHost = commonOptions.getStringOption(KrbOption.KDC_HOST);
+        if (kdcHost == null) {
+            return krbConfig.getKdcHost();
+        }
+        return kdcHost;
+    }
+
+    protected int getKdcTcpPort() {
+        int tcpPort = commonOptions.getIntegerOption(KrbOption.KDC_TCP_PORT);
+        if (tcpPort > 0) {
+            return tcpPort;
+        }
+        return krbConfig.getKdcTcpPort();
+    }
+
+    protected boolean allowUdp() {
+        Boolean allowUdp = commonOptions.getBooleanOption(KrbOption.ALLOW_UDP);
+        if (allowUdp != null) {
+            return allowUdp;
+        }
+        return krbConfig.allowKdcUdp();
+    }
+
+    protected int getKdcUdpPort() {
+        int udpPort = commonOptions.getIntegerOption(KrbOption.KDC_UDP_PORT);
+        if (udpPort > 0) {
+            return udpPort;
+        }
+        return krbConfig.getKdcUdpPort();
+    }
+
+    protected int getTimeout() {
+        int timeout = commonOptions.getIntegerOption(KrbOption.CONN_TIMEOUT);
+        if (timeout > 0) {
+            return timeout;
+        }
+        return 1000; // by default
+    }
+
+    @Override
+    public void init(KOptions commonOptions) throws KrbException {
+        this.commonOptions = commonOptions;
+
+        try {
+            initConfig();
+        } catch (IOException e) {
+            throw new RuntimeException("Failed to load config", e);
+        }
+
+        this.context = new KrbContext();
+        context.init(krbConfig);
+    }
+
+    @Override
+    public TgtTicket requestTgtTicket(KOptions requestOptions) throws KrbException {
+        AsRequest asRequest = null;
+
+        if (requestOptions.contains(KrbOption.USE_PASSWD)) {
+            asRequest = new AsRequestWithPasswd(context);
+        } else if (requestOptions.contains(KrbOption.USE_KEYTAB)) {
+            asRequest = new AsRequestWithKeytab(context);
+        } else if (requestOptions.contains(KrbOption.USE_PKINIT_ANONYMOUS)) {
+            asRequest = new AsRequestWithCert(context);
+        } else if (requestOptions.contains(KrbOption.USE_PKINIT)) {
+            asRequest = new AsRequestWithCert(context);
+        } else if (requestOptions.contains(KrbOption.USE_TOKEN)) {
+            asRequest = new AsRequestWithToken(context);
+        }
+
+        if (asRequest == null) {
+            throw new IllegalArgumentException(
+                    "No valid krb client request option found");
+        }
+        if (requestOptions.contains(KrbOption.CLIENT_PRINCIPAL)) {
+            String principal = requestOptions.getStringOption(
+                    KrbOption.CLIENT_PRINCIPAL);
+            asRequest.setClientPrincipal(new PrincipalName(principal));
+        }
+        asRequest.setKrbOptions(requestOptions);
+
+        return doRequestTgtTicket(asRequest);
+    }
+
+    @Override
+    public ServiceTicket requestServiceTicketWithTgt(
+            TgtTicket tgt, String serverPrincipal) throws KrbException {
+
+        TgsRequest ticketReq = new TgsRequest(context, tgt);
+        ticketReq.setServerPrincipal(new PrincipalName(serverPrincipal));
+        return doRequestServiceTicket(ticketReq);
+    }
+
+    @Override
+    public ServiceTicket requestServiceTicketWithAccessToken(
+            AuthToken token, String serverPrincipal) throws KrbException {
+        TgsRequest tgsRequest = new TgsRequestWithToken(context);
+        return doRequestServiceTicket(tgsRequest);
+    }
+
+    protected abstract TgtTicket doRequestTgtTicket(
+            AsRequest tgtTktReq) throws KrbException;
+
+    protected abstract ServiceTicket doRequestServiceTicket(
+            TgsRequest tgsRequest) throws KrbException;
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/ff0200f8/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/InternalKrbClient.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/InternalKrbClient.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/InternalKrbClient.java
new file mode 100644
index 0000000..89ef8ac
--- /dev/null
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/InternalKrbClient.java
@@ -0,0 +1,62 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.kerby.kerberos.kerb.client.impl;
+
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.KOptions;
+import org.apache.kerby.kerberos.kerb.spec.base.AuthToken;
+import org.apache.kerby.kerberos.kerb.spec.ticket.ServiceTicket;
+import org.apache.kerby.kerberos.kerb.spec.ticket.TgtTicket;
+
+/**
+ * An internal krb client interface.
+ */
+public interface InternalKrbClient {
+
+    /**
+     * Init with all the necessary options.
+     * @param options
+     */
+    public void init(KOptions options) throws KrbException;
+
+    /**
+     * Request a Ticket Granting Ticket.
+     * @param requestOptions
+     * @return a TGT
+     * @throws KrbException
+     */
+    public TgtTicket requestTgtTicket(KOptions requestOptions) throws KrbException;
+
+    /**
+     * Request a service ticket using a TGT.
+     * @return service ticket
+     * @throws KrbException
+     */
+    public ServiceTicket requestServiceTicketWithTgt(TgtTicket tgt,
+                                              String serverPrincipal) throws KrbException;
+
+    /**
+     * Request a service ticket using an Access Token.
+     * @return service ticket
+     * @throws KrbException
+     */
+    public ServiceTicket requestServiceTicketWithAccessToken(AuthToken token,
+                                              String serverPrincipal) throws KrbException;
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/ff0200f8/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/blocking/BlockModeKrbClient.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/blocking/BlockModeKrbClient.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/blocking/BlockModeKrbClient.java
new file mode 100644
index 0000000..db32186
--- /dev/null
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/blocking/BlockModeKrbClient.java
@@ -0,0 +1,80 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.kerby.kerberos.kerb.client.impl.blocking;
+
+import org.apache.kerby.KOptions;
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.client.KrbConfig;
+import org.apache.kerby.kerberos.kerb.client.impl.AbstractInternalKrbClient;
+import org.apache.kerby.kerberos.kerb.client.request.AsRequest;
+import org.apache.kerby.kerberos.kerb.client.request.TgsRequest;
+import org.apache.kerby.kerberos.kerb.spec.ticket.ServiceTicket;
+import org.apache.kerby.kerberos.kerb.spec.ticket.TgtTicket;
+import org.apache.kerby.kerberos.kerb.transport.KrbTransport;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+
+/**
+ * An event based krb client implementation.
+ */
+public class BlockModeKrbClient extends AbstractInternalKrbClient {
+
+    private BlockingKrbHandler krbHandler;
+    private KrbTransport transport;
+
+    @Override
+    public void init(KOptions commonOptions) throws KrbException {
+        super.init(commonOptions);
+
+        this.krbHandler = new BlockingKrbHandler();
+        krbHandler.init(getContext());
+
+        InetSocketAddress tcpAddress, udpAddress = null;
+        tcpAddress=  new InetSocketAddress(getKdcHost(), getKdcTcpPort());
+        if (allowUdp()) {
+            udpAddress = new InetSocketAddress(getKdcHost(), getKdcUdpPort());
+        }
+        try {
+            transport = new KrbCombinedTransport(tcpAddress, udpAddress);
+        } catch (IOException e) {
+            throw new KrbException("Failed to create transport", e);
+        }
+    }
+
+    @Override
+    protected TgtTicket doRequestTgtTicket(AsRequest tgtTktReq) throws KrbException {
+        tgtTktReq.setTransport(transport);
+
+        krbHandler.handleRequest(tgtTktReq);
+
+        return tgtTktReq.getTicket();
+    }
+
+    @Override
+    protected ServiceTicket doRequestServiceTicket(TgsRequest ticketReq) throws KrbException {
+        ticketReq.setTransport(transport);
+
+        krbHandler.handleRequest(ticketReq);
+
+        return ticketReq.getServiceTicket();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/ff0200f8/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/blocking/BlockingKrbHandler.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/blocking/BlockingKrbHandler.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/blocking/BlockingKrbHandler.java
new file mode 100644
index 0000000..2e9287b
--- /dev/null
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/blocking/BlockingKrbHandler.java
@@ -0,0 +1,72 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.kerby.kerberos.kerb.client.impl.blocking;
+
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.client.KrbContext;
+import org.apache.kerby.kerberos.kerb.client.preauth.PreauthHandler;
+import org.apache.kerby.kerberos.kerb.client.request.KdcRequest;
+import org.apache.kerby.kerberos.kerb.common.KrbUtil;
+import org.apache.kerby.kerberos.kerb.spec.base.KrbMessage;
+import org.apache.kerby.kerberos.kerb.spec.base.KrbMessageType;
+import org.apache.kerby.kerberos.kerb.spec.kdc.KdcRep;
+import org.apache.kerby.kerberos.kerb.spec.kdc.KdcReq;
+import org.apache.kerby.kerberos.kerb.transport.KrbTransport;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+public class BlockingKrbHandler {
+
+    private PreauthHandler preauthHandler;
+
+    public void init(KrbContext context) {
+        preauthHandler = new PreauthHandler();
+        preauthHandler.init(context);
+    }
+
+    public void handleRequest(KdcRequest kdcRequest) throws KrbException {
+        kdcRequest.process();
+        KdcReq kdcReq = kdcRequest.getKdcReq();
+        KrbTransport transport = kdcRequest.getTransport();
+        transport.setAttachment(kdcRequest);
+        KrbMessage kdcRep = null;
+
+        try {
+            KrbUtil.sendMessage(kdcReq, transport);
+
+            ByteBuffer message = transport.receiveMessage();
+            if (message != null) {
+                kdcRep = KrbUtil.decodeMessage(message);
+            } else {
+                throw new KrbException("No valid response recved");
+            }
+        } catch (IOException e) {
+            throw new KrbException("Transport or decoding error occurred", e);
+        }
+
+        KrbMessageType messageType = kdcRep.getMsgType();
+        if (messageType == KrbMessageType.AS_REP) {
+            kdcRequest.processResponse((KdcRep) kdcRep);
+        } else if (messageType == KrbMessageType.TGS_REP) {
+            kdcRequest.processResponse((KdcRep) kdcRep);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/ff0200f8/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/blocking/KrbCombinedTransport.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/blocking/KrbCombinedTransport.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/blocking/KrbCombinedTransport.java
new file mode 100644
index 0000000..3e882fa
--- /dev/null
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/blocking/KrbCombinedTransport.java
@@ -0,0 +1,74 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *
+ */
+package org.apache.kerby.kerberos.kerb.client.impl.blocking;
+
+import org.apache.kerby.kerberos.kerb.transport.AbstractKrbTransport;
+import org.apache.kerby.kerberos.kerb.transport.KrbTransport;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+
+/**
+ * Default implementation of {@Link KrbTransport} combining TCP and UDP.
+ */
+public class KrbCombinedTransport
+        extends AbstractKrbTransport implements KrbTransport {
+    private KrbTransport tcpTransport;
+    private KrbTransport udpTransport;
+
+    private InetSocketAddress tcpAddress;
+    private InetSocketAddress udpAddress;
+
+    public KrbCombinedTransport(InetSocketAddress tcpAddress,
+                                InetSocketAddress udpAddress) throws IOException {
+        this.tcpAddress = tcpAddress;
+        this.udpAddress = udpAddress;
+
+        /**
+         * Try TCP first.
+         */
+        try {
+            this.tcpTransport = new KrbTcpTransport(tcpAddress);
+        } catch (IOException e) {
+            this.tcpTransport = null;
+            this.udpTransport = new KrbUdpTransport(udpAddress);
+        }
+    }
+
+    @Override
+    public void sendMessage(ByteBuffer message) throws IOException {
+        if (tcpTransport != null) {
+            tcpTransport.sendMessage(message);
+        } else if (udpTransport != null) {
+            udpTransport.sendMessage(message);
+        }
+    }
+
+    @Override
+    public ByteBuffer receiveMessage() throws IOException {
+        if (tcpTransport != null) {
+            return tcpTransport.receiveMessage();
+        } else if (udpTransport != null) {
+            return udpTransport.receiveMessage();
+        }
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/ff0200f8/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/blocking/KrbTcpTransport.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/blocking/KrbTcpTransport.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/blocking/KrbTcpTransport.java
new file mode 100644
index 0000000..4fb76ad
--- /dev/null
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/blocking/KrbTcpTransport.java
@@ -0,0 +1,91 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.kerby.kerberos.kerb.client.impl.blocking;
+
+import org.apache.kerby.kerberos.kerb.transport.AbstractKrbTransport;
+import org.apache.kerby.kerberos.kerb.transport.KrbTransport;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.SocketChannel;
+
+/**
+ * Default implementation of {@Link KrbTransport} using TCP in block mode.
+ */
+public class KrbTcpTransport
+        extends AbstractKrbTransport implements KrbTransport {
+    private SocketChannel socketChannel;
+    private ReadableByteChannel wrappedChannel; // for timeout stuff.
+    private InetSocketAddress remoteAddress;
+    private ByteBuffer headerBuffer; // for message length
+    private ByteBuffer messageBuffer; // for message body
+
+    public KrbTcpTransport(InetSocketAddress remoteAddress) throws IOException {
+        this.remoteAddress = remoteAddress;
+        this.headerBuffer = ByteBuffer.allocate(4);
+        this.messageBuffer = ByteBuffer.allocate(1024 * 1024); // TODO.
+        doConnect();
+    }
+
+    private void doConnect() throws IOException {
+        socketChannel = SocketChannel.open();
+        socketChannel.configureBlocking(true);
+        socketChannel.socket().setSoTimeout(100); // TODO.
+        socketChannel.connect(remoteAddress);
+
+        InputStream inStream = socketChannel.socket().getInputStream();
+        wrappedChannel = Channels.newChannel(inStream);
+    }
+
+    @Override
+    public void sendMessage(ByteBuffer message) throws IOException {
+        socketChannel.write(message);
+    }
+
+    @Override
+    public ByteBuffer receiveMessage() {
+        try {
+            headerBuffer.clear();
+            headerBuffer.position(0);
+            headerBuffer.limit(4);
+            wrappedChannel.read(headerBuffer);
+            headerBuffer.flip();
+
+            int msgLen = headerBuffer.getInt();
+            if (msgLen > 0) {
+                messageBuffer.clear();
+                messageBuffer.position(0);
+                messageBuffer.limit(msgLen);
+                wrappedChannel.read(messageBuffer);
+                messageBuffer.flip();
+
+                return messageBuffer;
+            }
+        } catch (IOException e) {
+            return null;
+        }
+
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/ff0200f8/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/blocking/KrbUdpTransport.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/blocking/KrbUdpTransport.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/blocking/KrbUdpTransport.java
new file mode 100644
index 0000000..8ef7a94
--- /dev/null
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/blocking/KrbUdpTransport.java
@@ -0,0 +1,57 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.kerby.kerberos.kerb.client.impl.blocking;
+
+import org.apache.kerby.kerberos.kerb.transport.AbstractKrbTransport;
+import org.apache.kerby.kerberos.kerb.transport.KrbTransport;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.DatagramChannel;
+
+/**
+ * Default implementation of {@Link KrbTransport} using UDP.
+ */
+public class KrbUdpTransport
+        extends AbstractKrbTransport implements KrbTransport {
+    private DatagramChannel channel;
+    private InetSocketAddress remoteAddress;
+    private ByteBuffer recvBuffer;
+
+    public KrbUdpTransport(InetSocketAddress remoteAddress) throws IOException {
+        this.remoteAddress = remoteAddress;
+        this.channel = DatagramChannel.open();
+        this.recvBuffer = ByteBuffer.allocate(1024 * 1024); // TODO.
+        channel.connect(remoteAddress);
+    }
+
+    @Override
+    public void sendMessage(ByteBuffer message) throws IOException {
+        channel.send(message, remoteAddress);
+    }
+
+    @Override
+    public ByteBuffer receiveMessage() throws IOException {
+        recvBuffer.reset();
+        channel.receive(recvBuffer);
+        return recvBuffer;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/ff0200f8/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/event/EventBasedKrbClient.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/event/EventBasedKrbClient.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/event/EventBasedKrbClient.java
new file mode 100644
index 0000000..8c3cdbd
--- /dev/null
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/event/EventBasedKrbClient.java
@@ -0,0 +1,142 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.kerby.kerberos.kerb.client.impl.event;
+
+import org.apache.kerby.KOptions;
+import org.apache.kerby.event.Event;
+import org.apache.kerby.event.EventHub;
+import org.apache.kerby.event.EventWaiter;
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.client.KrbConfig;
+import org.apache.kerby.kerberos.kerb.client.impl.AbstractInternalKrbClient;
+import org.apache.kerby.kerberos.kerb.client.request.AsRequest;
+import org.apache.kerby.kerberos.kerb.client.request.TgsRequest;
+import org.apache.kerby.kerberos.kerb.common.KrbStreamingDecoder;
+import org.apache.kerby.kerberos.kerb.spec.ticket.ServiceTicket;
+import org.apache.kerby.kerberos.kerb.spec.ticket.TgtTicket;
+import org.apache.kerby.kerberos.kerb.transport.KrbTransport;
+import org.apache.kerby.transport.Network;
+import org.apache.kerby.transport.Transport;
+import org.apache.kerby.transport.event.TransportEvent;
+import org.apache.kerby.transport.event.TransportEventType;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * An event based krb client implementation.
+ */
+public class EventBasedKrbClient extends AbstractInternalKrbClient {
+
+    private EventKrbHandler krbHandler;
+    private EventHub eventHub;
+    private EventWaiter eventWaiter;
+    private Transport eventTransport;
+    private KrbTransport transport;
+
+    @Override
+    public void init(KOptions commonOptions) throws KrbException {
+        super.init(commonOptions);
+
+        this.krbHandler = new EventKrbHandler();
+        krbHandler.init(getContext());
+
+        this.eventHub = new EventHub();
+        eventHub.register(krbHandler);
+
+        Network network = new Network();
+        network.setStreamingDecoder(new KrbStreamingDecoder());
+        eventHub.register(network);
+
+        eventWaiter = eventHub.waitEvent(
+                TransportEventType.NEW_TRANSPORT,
+                KrbClientEventType.TGT_RESULT,
+                KrbClientEventType.TKT_RESULT
+        );
+
+        eventHub.start();
+
+        network.tcpConnect(getKdcHost(), getKdcTcpPort());
+        if (allowUdp()) {
+            network.udpConnect(getKdcHost(), getKdcUdpPort());
+        }
+        final Event event = eventWaiter.waitEvent(TransportEventType.NEW_TRANSPORT);
+        eventTransport = ((TransportEvent) event).getTransport();
+
+        transport = new KrbTransport() {
+            @Override
+            public void sendMessage(ByteBuffer message) throws IOException {
+                eventTransport.sendMessage(message);
+            }
+
+            @Override
+            public ByteBuffer receiveMessage() throws IOException {
+                return null; // NOOP, should not be here, since event based.
+            }
+
+            @Override
+            public void setAttachment(Object attachment) {
+                eventTransport.setAttachment(attachment);
+            }
+
+            @Override
+            public Object getAttachment() {
+                return eventTransport.getAttachment();
+            }
+        };
+    }
+
+    @Override
+    protected TgtTicket doRequestTgtTicket(AsRequest tgtTktReq) throws KrbException {
+        tgtTktReq.setTransport(transport);
+
+        eventHub.dispatch(KrbClientEvent.createTgtIntentEvent(tgtTktReq));
+        Event resultEvent;
+        try {
+            resultEvent = eventWaiter.waitEvent(KrbClientEventType.TGT_RESULT,
+                    getTimeout(), TimeUnit.SECONDS);
+        } catch (TimeoutException e) {
+            throw new KrbException("Network timeout", e);
+        }
+        AsRequest asResponse = (AsRequest) resultEvent.getEventData();
+
+        return asResponse.getTicket();
+    }
+
+    @Override
+    protected ServiceTicket doRequestServiceTicket(TgsRequest ticketReq) throws KrbException {
+        ticketReq.setTransport(transport);
+
+        eventHub.dispatch(KrbClientEvent.createTktIntentEvent(ticketReq));
+        Event resultEvent;
+        try {
+            resultEvent = eventWaiter.waitEvent(KrbClientEventType.TKT_RESULT,
+                    getTimeout(), TimeUnit.SECONDS);
+        } catch (TimeoutException e) {
+            throw new KrbException("Network timeout", e);
+        }
+        TgsRequest tgsResponse = (TgsRequest) resultEvent.getEventData();
+
+        return tgsResponse.getServiceTicket();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/ff0200f8/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/event/EventKrbHandler.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/event/EventKrbHandler.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/event/EventKrbHandler.java
new file mode 100644
index 0000000..f7c7642
--- /dev/null
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/event/EventKrbHandler.java
@@ -0,0 +1,97 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.kerby.kerberos.kerb.client.impl.event;
+
+import org.apache.kerby.event.AbstractEventHandler;
+import org.apache.kerby.event.Event;
+import org.apache.kerby.event.EventType;
+import org.apache.kerby.kerberos.kerb.client.KrbContext;
+import org.apache.kerby.kerberos.kerb.client.preauth.PreauthHandler;
+import org.apache.kerby.kerberos.kerb.client.request.AsRequest;
+import org.apache.kerby.kerberos.kerb.client.request.KdcRequest;
+import org.apache.kerby.kerberos.kerb.client.request.TgsRequest;
+import org.apache.kerby.kerberos.kerb.common.KrbUtil;
+import org.apache.kerby.kerberos.kerb.spec.base.KrbMessage;
+import org.apache.kerby.kerberos.kerb.spec.base.KrbMessageType;
+import org.apache.kerby.kerberos.kerb.spec.kdc.KdcRep;
+import org.apache.kerby.kerberos.kerb.spec.kdc.KdcReq;
+import org.apache.kerby.kerberos.kerb.transport.KrbTransport;
+import org.apache.kerby.transport.event.MessageEvent;
+import org.apache.kerby.transport.event.TransportEventType;
+
+import java.nio.ByteBuffer;
+
+public class EventKrbHandler extends AbstractEventHandler {
+
+    private KrbContext context;
+    private PreauthHandler preauthHandler;
+
+    public void init(KrbContext context) {
+        this.context = context;
+        preauthHandler = new PreauthHandler();
+        preauthHandler.init(context);
+    }
+
+    @Override
+    public EventType[] getInterestedEvents() {
+        return new EventType[] {
+                TransportEventType.INBOUND_MESSAGE,
+                KrbClientEventType.TGT_INTENT,
+                KrbClientEventType.TKT_INTENT
+        };
+    }
+
+    @Override
+    protected void doHandle(Event event) throws Exception {
+        EventType eventType = event.getEventType();
+
+        if (eventType == KrbClientEventType.TGT_INTENT ||
+                eventType == KrbClientEventType.TKT_INTENT) {
+            KdcRequest kdcRequest = (KdcRequest) event.getEventData();
+            handleKdcRequest(kdcRequest);
+        } else if (event.getEventType() == TransportEventType.INBOUND_MESSAGE) {
+            handleMessage((MessageEvent) event);
+        }
+    }
+
+    protected void handleKdcRequest(KdcRequest kdcRequest) throws Exception {
+        kdcRequest.process();
+        KdcReq kdcReq = kdcRequest.getKdcReq();
+        KrbTransport transport = kdcRequest.getTransport();
+        transport.setAttachment(kdcRequest);
+        KrbUtil.sendMessage(kdcReq, transport);
+    }
+
+    protected void handleMessage(MessageEvent event) throws Exception {
+        ByteBuffer message = event.getMessage();
+        KrbMessage kdcRep = KrbUtil.decodeMessageOld(message);
+
+        KrbMessageType messageType = kdcRep.getMsgType();
+        if (messageType == KrbMessageType.AS_REP) {
+            KdcRequest kdcRequest = (KdcRequest) event.getTransport().getAttachment();
+            kdcRequest.processResponse((KdcRep) kdcRep);
+            dispatch(KrbClientEvent.createTgtResultEvent((AsRequest) kdcRequest));
+        } else if (messageType == KrbMessageType.TGS_REP) {
+            KdcRequest kdcRequest = (KdcRequest) event.getTransport().getAttachment();
+            kdcRequest.processResponse((KdcRep) kdcRep);
+            dispatch(KrbClientEvent.createTktResultEvent((TgsRequest) kdcRequest));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/ff0200f8/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/event/KrbClientEvent.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/event/KrbClientEvent.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/event/KrbClientEvent.java
new file mode 100644
index 0000000..574e2d0
--- /dev/null
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/event/KrbClientEvent.java
@@ -0,0 +1,43 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.kerby.kerberos.kerb.client.impl.event;
+
+import org.apache.kerby.event.Event;
+import org.apache.kerby.kerberos.kerb.client.request.AsRequest;
+import org.apache.kerby.kerberos.kerb.client.request.TgsRequest;
+
+public class KrbClientEvent {
+
+    public static Event createTgtIntentEvent(AsRequest asRequest) {
+        return new Event(KrbClientEventType.TGT_INTENT, asRequest);
+    }
+
+    public static Event createTktIntentEvent(TgsRequest tgsRequest) {
+        return new Event(KrbClientEventType.TKT_INTENT, tgsRequest);
+    }
+
+    public static Event createTgtResultEvent(AsRequest asRequest) {
+        return new Event(KrbClientEventType.TGT_RESULT, asRequest);
+    }
+
+    public static Event createTktResultEvent(TgsRequest tgsRequest) {
+        return new Event(KrbClientEventType.TKT_RESULT, tgsRequest);
+    }
+}