diff --git a/net/cpp/src/protocol.cpp b/net/cpp/src/protocol.cpp
deleted file mode 100644
index 27f1146d6977035603ecf309bf1a2a2584fc8f24..0000000000000000000000000000000000000000
--- a/net/cpp/src/protocol.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-#define GLOG_NO_ABBREVIATED_SEVERITIES
-#include <glog/logging.h>
-#include <ftl/net/socket.hpp>
-#include <ftl/net/protocol.hpp>
-#include <functional>
-#include <iostream>
-
-using ftl::net::Socket;
-using ftl::net::Protocol;
-
-std::map<std::string,Protocol*> Protocol::protocols__;
-
-Protocol *Protocol::find(const std::string &id) {
-	if (protocols__.count(id) > 0) return protocols__[id];
-	else return NULL;
-}
-
-Protocol::Protocol(const std::string &id) : id_(id) {
-	protocols__[id] = this;
-}
-
-Protocol::~Protocol() {
-	protocols__.erase(id_);
-	// TODO Make sure all dependent sockets are closed!
-}
-
-void Protocol::bind(int service, std::function<void(uint32_t,Socket&)> func) {
-	if (handlers_.count(service) == 0) {
-		handlers_[service] = func;
-	} else {
-		LOG(ERROR) << "Message service " << service << " already bound";
-	}
-}
-
-void Protocol::dispatchRPC(Socket &s, const std::string &d) {
-	disp_.dispatch(s,d);
-}
-
-void Protocol::dispatchRaw(uint32_t service, Socket &s) {
-	// Lookup raw message handler
-	if (handlers_.count(service) > 0) {
-		handlers_[service](service, s);
-	} else {
-		LOG(ERROR) << "Unrecognised service request (" << service << ") from " << s.getURI();
-	}
-}
-
diff --git a/net/cpp/test/peer_unit.cpp b/net/cpp/test/peer_unit.cpp
index a6507d615fb2b600710e152b0908d485da538fe7..0f7e19855c16896139bd8cd239b5a379b7d123e7 100644
--- a/net/cpp/test/peer_unit.cpp
+++ b/net/cpp/test/peer_unit.cpp
@@ -260,26 +260,6 @@ TEST_CASE("Peer::bind()", "[rpc]") {
 	}
 }
 
-/*TEST_CASE("Socket::operator>>()", "[io]") {
-	MockPeer s;
-	
-	SECTION("stream ints") {
-		int i[2];
-		i[0] = 99;
-		i[1] = 101;
-		fake_send(0, 100, std::string((char*)&i,2*sizeof(int)));
-		
-		i[0] = 0;
-		i[1] = 0;
-		s.mock_data(); // Force a message read, but no protocol...
-		
-		REQUIRE( (s.size() == 2*sizeof(int)) );
-		s >> i;
-		REQUIRE( (i[0] == 99) );
-		REQUIRE( (i[1] == 101) );
-	}
-}*/
-
 TEST_CASE("Socket::send()", "[io]") {
 	MockPeer s;
 	
@@ -293,49 +273,54 @@ TEST_CASE("Socket::send()", "[io]") {
 		REQUIRE( (get<0>(value) == 607) );
 	}
 	
-	/*SECTION("send a string") {
+	SECTION("send a string") {
 		std::string str("hello world");
-		s.send(100,str);
+		s.send("dummy",str);
 		
-		REQUIRE( (get_service(0) == 100) );
-		REQUIRE( (get_size(0) == str.size()) );
-		REQUIRE( (get_value<std::string>(0) == "hello world") );
+		auto [name, value] = readResponse<tuple<std::string>>(0);
+		
+		REQUIRE( (name == "dummy") );
+		REQUIRE( (get<0>(value) == "hello world") );
 	}
 	
 	SECTION("send const char* string") {
-		s.send(100,"hello world");
+		s.send("dummy","hello world");
 		
-		REQUIRE( (get_service(0) == 100) );
-		REQUIRE( (get_size(0) == 11) );
-		REQUIRE( (get_value<std::string>(0) == "hello world") );
+		auto [name, value] = readResponse<tuple<std::string>>(0);
+		
+		REQUIRE( (name == "dummy") );
+		REQUIRE( (get<0>(value) == "hello world") );
 	}
 	
-	SECTION("send const char* array") {
+	/*SECTION("send const char* array") {
 		s.send(100,ftl::net::array{"hello world",10});
 		
 		REQUIRE( (get_service(0) == 100) );
 		REQUIRE( (get_size(0) == 10) );
 		REQUIRE( (get_value<std::string>(0) == "hello worl") );
-	}
+	}*/
 	
 	SECTION("send a tuple") {
 		auto tup = std::make_tuple(55,66,true,6.7);
-		s.send(100,tup);
+		s.send("dummy",tup);
 		
-		REQUIRE( (get_service(0) == 100) );
-		REQUIRE( (get_size(0) == sizeof(tup)) );
-		REQUIRE( (get_value<decltype(tup)>(0) == tup) );
+		auto [name, value] = readResponse<tuple<decltype(tup)>>(0);
+		
+		REQUIRE( (name == "dummy") );
+		REQUIRE( (get<1>(get<0>(value)) == 66) );
 	}
 	
 	SECTION("send multiple strings") {
 		std::string str("hello ");
 		std::string str2("world");
-		s.send(100,str,str2);
+		s.send("dummy2",str,str2);
 		
-		REQUIRE( (get_service(0) == 100) );
-		REQUIRE( (get_size(0) == str.size()+str2.size()) );
-		REQUIRE( (get_value<std::string>(0) == "hello world") );
-	}*/
+		auto [name, value] = readResponse<tuple<std::string,std::string>>(0);
+		
+		REQUIRE( (name == "dummy2") );
+		REQUIRE( (get<0>(value) == "hello") );
+		REQUIRE( (get<1>(value) == "world") );
+	}
 }
 
 /*TEST_CASE("Socket::read()", "[io]") {