diff --git a/Cargo.toml b/Cargo.toml
index 22ff7f1bbeba5de5c04a68a8a17d5c38acf6f82f..4b656fb56c80665f7ea141c51e4c8728f83b1219 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "coap"
-version = "0.3.1"
+version = "0.4.0"
 description = "A CoAP library"
 readme = "README.md"
 documentation = "http://covertness.github.io/coap-rs/coap/index.html"
@@ -17,6 +17,7 @@ threadpool = "0.1"
 url = "0.2.36"
 num = "0.1"
 rand = "0.3"
+log = "0.3"
 
 [dev-dependencies]
-quickcheck = "*"
\ No newline at end of file
+quickcheck = "*"
diff --git a/LICENSE b/LICENSE
index 23b5b4099ba4ecb013ed93295c6ffb0cbc059810..970e986dd325b8baa3e808c0b842b6fc2aaf916c 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2014 Sean McArthur
+Copyright (c) 2014-2016 Yang Zhang
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
@@ -16,4 +16,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
\ No newline at end of file
+THE SOFTWARE.
diff --git a/README.md b/README.md
index 025c07f19af1da296f25745bdb9fb34aa87faf2d..a0e628db918409cc72534eef1cbd94ac269b0709 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@ First add this to your `Cargo.toml`:
 
 ```toml
 [dependencies]
-coap = "0.3"
+coap = "0.4"
 ```
 
 Then, add this to your crate root:
@@ -36,8 +36,9 @@ use std::io;
 use coap::packet::*;
 use coap::{CoAPServer, CoAPClient};
 
-fn request_handler(req: Packet, _resp: CoAPClient) {
+fn request_handler(req: Packet) -> Option<Packet> {
 	println!("Receive request: {:?}", req);
+	None
 }
 
 fn main() {
@@ -45,7 +46,7 @@ fn main() {
 
 	let mut server = CoAPServer::new(addr).unwrap();
 	server.handle(request_handler).unwrap();
-		
+
 	println!("Server up on {}", addr);
     println!("Press any key to stop...");
 	io::stdin().read_line(&mut String::new()).unwrap();
diff --git a/src/lib.rs b/src/lib.rs
index 5f4c68774c8ec180335f852f4fbdb904324b2de3..079d5e398233279b9557d23ed68f7315d2c4f7c5 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -74,6 +74,9 @@ extern crate num;
 extern crate rand;
 #[cfg(test)] extern crate quickcheck;
 
+#[macro_use]
+extern crate log;
+
 pub use server::CoAPServer;
 pub use client::CoAPClient;
 
diff --git a/src/server.rs b/src/server.rs
index 79924db59de0c7fadc1f554159cf615a3967b0b1..280fcaed9ea021b1cb7f8677e55a7c9ef63a0984 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -1,8 +1,9 @@
 use std;
+use std::io::{Error, ErrorKind};
 use std::thread;
 use std::net::{ToSocketAddrs, SocketAddr};
 use std::sync::mpsc;
-use mio::*;
+use mio::{EventLoop, PollOpt, EventSet, Handler, Sender, Token};
 use mio::udp::UdpSocket;
 use packet::Packet;
 use threadpool::ThreadPool;
@@ -57,38 +58,56 @@ impl<H: CoAPHandler + 'static> Handler for UdpHandler<H> {
 	type Message = ();
 
 	fn ready(&mut self, _: &mut EventLoop<UdpHandler<H>>, _: Token, events: EventSet) {
-		if events.is_readable() {
-			let coap_handler = self.coap_handler;
-			let mut buf = [0; 1500];
-
-			match self.socket.recv_from(&mut buf) {
-				Ok(Some((nread, src))) => {
-					let response_q = self.tx_sender.clone();
-					self.thread_pool.execute(move || {
-						match Packet::from_bytes(&buf[..nread]) {
-							Ok(packet) => {
-								// Dispatch user handler, if there is a response packet
-								//   send the reply via the TX thread
-								match coap_handler.handle(packet) {
-									Some(response) => {
-										response_q.send(CoAPResponse{
-											address: src,
-											response: response
-										}).unwrap();
-									},
-									None => {}
-								};
-							},
-							Err(_) => return
-						};
-					});
-				},
-				_ => {}, //panic!("unexpected error"),
-			}
+		if !events.is_readable() {
+			warn!("Unreadable Event");
+			return;
 		}
+
+		let coap_handler = self.coap_handler;
+		let mut buf = [0; 1500];
+
+		match self.socket.recv_from(&mut buf) {
+			Ok(Some((nread, src))) => {
+				debug!("Handling request from {}", src);
+				let response_q = self.tx_sender.clone();
+				self.thread_pool.execute(move || {
+
+					match Packet::from_bytes(&buf[..nread]) {
+						Ok(packet) => {
+							// Dispatch user handler, if there is a response packet
+							//   send the reply via the TX thread
+							match coap_handler.handle(packet) {
+								Some(response) => {
+									debug!("Response: {:?}", response);
+									response_q.send(CoAPResponse{
+										address: src,
+										response: response
+									}).unwrap();
+								},
+								None => {
+									debug!("No response");
+								}
+							};
+						},
+						Err(_) => {
+							error!("Failed to parse request");
+							return;
+						}
+					};
+
+
+				});
+			},
+			_ => {
+				error!("Failed to read from socket");
+				panic!("unexpected error");
+			},
+		}
+
 	}
 
 	fn notify(&mut self, event_loop: &mut EventLoop<UdpHandler<H>>, _: ()) {
+		info!("Shutting down request handler");
         event_loop.shutdown();
     }
 }
@@ -115,7 +134,7 @@ impl CoAPServer {
 						worker_num: DEFAULT_WORKER_NUM,
 					}))
 				},
-				None => Err(std::io::Error::new(std::io::ErrorKind::Other, "no address"))
+				None => Err(Error::new(ErrorKind::Other, "no address"))
 			}
 		})
 	}
@@ -126,6 +145,7 @@ impl CoAPServer {
 
 		// Early return error checking
 		if let Some(_) = self.event_sender {
+			error!("Handler already running!");
 			return Err(CoAPServerError::AnotherHandlerIsRunning);
 		}
 		match self.socket.try_clone() {
@@ -133,6 +153,7 @@ impl CoAPServer {
 				socket = good_socket
 			},
 			Err(_) => {
+				error!("Network Error!");
 				return Err(CoAPServerError::NetworkError);
 			},
 		}
@@ -200,12 +221,15 @@ fn transmit_handler(tx_recv: RxQueue, tx_only: UdpSocket) {
 					Ok(bytes) => {
 						let _ = tx_only.send_to(&bytes[..], &q_res.address);
 					},
-					Err(_) => {}
+					Err(_) => {
+						error!("Failed to decode response");
+					}
 				}
 			},
 			// recv error occurs when all transmitters are terminited
 			//   (when all UDP Handlers are closed)
 			Err(_) => {
+				info!("Shutting down Transmit Handler");
 				break;
 			}
 		}