From cb97ce6f728e051f2fb2b69690fa53a01e339663 Mon Sep 17 00:00:00 2001
From: csoler <csoler@users.sourceforge.net>
Date: Wed, 18 Nov 2015 23:56:35 -0500
Subject: [PATCH] half-way through GxsTunnel service

---
 libretroshare/src/gxstunnel/p3gxstunnel.cc    | 173 +++++---
 libretroshare/src/gxstunnel/p3gxstunnel.h     |   3 +-
 .../src/gxstunnel/rsgxstunnelitems.h          | 385 +++---------------
 libretroshare/src/serialiser/rsserviceids.h   |  39 +-
 4 files changed, 191 insertions(+), 409 deletions(-)

diff --git a/libretroshare/src/gxstunnel/p3gxstunnel.cc b/libretroshare/src/gxstunnel/p3gxstunnel.cc
index a62e8e5b2..b43aa7ff8 100644
--- a/libretroshare/src/gxstunnel/p3gxstunnel.cc
+++ b/libretroshare/src/gxstunnel/p3gxstunnel.cc
@@ -51,6 +51,13 @@ static const uint32_t RS_GXS_TUNNEL_DH_STATUS_UNINITIALIZED = 0x0000 ;
 static const uint32_t RS_GXS_TUNNEL_DH_STATUS_HALF_KEY_DONE = 0x0001 ;
 static const uint32_t RS_GXS_TUNNEL_DH_STATUS_KEY_AVAILABLE = 0x0002 ;
 
+static const uint32_t RS_GXS_TUNNEL_STATUS_UNKNOWN    = 0x00 ;
+static const uint32_t RS_GXS_TUNNEL_STATUS_CAN_TALK   = 0x01 ;
+static const uint32_t RS_GXS_TUNNEL_STATUS_TUNNEL_DN  = 0x02 ;
+
+static const uint32_t GXS_TUNNEL_HMAC_SIZE    = SHA_DIGEST_LENGTH ;
+static const uint32_t GXS_TUNNEL_IV_SIZE      = 8 ;
+
 void p3GxsTunnelService::connectToTurtleRouter(p3turtle *tr)
 {
 	mTurtle = tr ;
@@ -93,7 +100,7 @@ void p3GxsTunnelService::flush()
         }
         if(it->second.last_keep_alive_sent + GXS_TUNNEL_KEEP_ALIVE_TIMEOUT < now && it->second.status == RS_GXS_TUNNEL_STATUS_CAN_TALK)
         {
-            RsChatStatusItem *cs = new RsChatStatusItem ;
+            RsGxsTunnelStatusItem *cs = new RsGxsTunnelStatusItem ;
 
 #warning should we send that unencrypted??
             cs->status_string.clear() ;
@@ -112,21 +119,26 @@ void p3GxsTunnelService::flush()
     }
 }
 
-bool p3GxsTunnelService::handleRecvItem(RsChatItem *item)
+bool p3GxsTunnelService::handleRecvItem(RsGxsTunnelItem *item)
 {
 	if(item == NULL)
 		return false ;
 
 	switch(item->PacketSubType())
 	{
-	case RS_PKT_SUBTYPE_GXS_TUNNEL_DH_PUBLIC_KEY: handleRecvDHPublicKey(dynamic_cast<RsGxsTunnelDHPublicKeyItem*>(item)) ; break ;
-		return true ;
+	case RS_PKT_SUBTYPE_GXS_TUNNEL_DH_PUBLIC_KEY:	handleRecvDHPublicKey(dynamic_cast<RsGxsTunnelDHPublicKeyItem*>(item)) ; break ;
+							return true ;
 
-	case RS_PKT_SUBTYPE_GXS_TUNNEL_STATUS:
-	{
-		// Keep alive packets should not be forwarded to the GUI. It's just for keeping the tunnel up.
-
-		return true ;
+#warning need to implement tunnel data handling here
+	case RS_PKT_SUBTYPE_GXS_TUNNEL_DATA:
+        	return true ;
+            
+#warning need to implement tunnel data ACK handling here
+	case RS_PKT_SUBTYPE_GXS_TUNNEL_DATA_ACK:
+        	return true ;
+            
+	case RS_PKT_SUBTYPE_GXS_TUNNEL_STATUS:		handleRecvStatusItem(dynamic_cast<RsGxsTunnelStatusItem*>(item)) ;
+	    						return true ;
 	}
 
 	default:
@@ -135,7 +147,9 @@ bool p3GxsTunnelService::handleRecvItem(RsChatItem *item)
 
 	return false ;
 }
-bool p3GxsTunnelService::handleOutgoingItem(RsChatItem *item)
+
+#warning is this function still used??
+bool p3GxsTunnelService::handleOutgoingItem(RsGxsTunnelItem *item)
 {
     {
         RS_STACK_MUTEX(mGxsTunnelMtx) ;
@@ -147,7 +161,7 @@ bool p3GxsTunnelService::handleOutgoingItem(RsChatItem *item)
     }
 
 #ifdef CHAT_DEBUG
-    std::cerr << "p3ChatService::handleOutgoingItem(): sending to " << item->PeerId() << ": interpreted as a distant chat virtual peer id." << std::endl;
+    std::cerr << "p3GxsTunnelService::handleOutgoingItem(): sending to " << item->PeerId() << ": interpreted as a distant chat virtual peer id." << std::endl;
 #endif
     sendTurtleData(item) ;
     return true;
@@ -161,7 +175,7 @@ void p3GxsTunnelService::handleRecvStatusItem(RsGxsTunnelStatusItem *cs)
     // nothing more to do, because the decryption routing will update the last_contact time when decrypting.
 
     if(cs->flags & RS_GXS_TUNNEL_FLAG_KEEP_ALIVE)
-        std::cerr << "GxsTunnelService::handleRecvChatStatusItem(): received keep alive packet for inactive tunnel! peerId=" << cs->PeerId() << std::endl;
+        std::cerr << "GxsTunnelService::handleRecvGxsTunnelStatusItem(): received keep alive packet for inactive tunnel! peerId=" << cs->PeerId() << std::endl;
 }
 
 bool p3GxsTunnelService::handleTunnelRequest(const RsFileHash& hash,const RsPeerId& /*peer_id*/)
@@ -192,64 +206,64 @@ bool p3GxsTunnelService::handleTunnelRequest(const RsFileHash& hash,const RsPeer
 void p3GxsTunnelService::addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction dir)
 {
 #ifdef DEBUG_GXS_TUNNEL
-    std::cerr << "GxsTunnelService:: received new virtual peer " << virtual_peer_id << " for hash " << hash << ", dir=" << dir << std::endl;
+	std::cerr << "GxsTunnelService:: received new virtual peer " << virtual_peer_id << " for hash " << hash << ", dir=" << dir << std::endl;
 #endif
-    RsGxsId own_gxs_id ;
+	RsGxsId own_gxs_id ;
 
-    {
-        RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/
+	{
+		RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/
 
-        GxsTunnelDHInfo& dhinfo( _gxs_tunnel_virtual_peer_ids[virtual_peer_id] ) ;
-    dhinfo.gxs_id.clear() ;
+		GxsTunnelDHInfo& dhinfo( _gxs_tunnel_virtual_peer_ids[virtual_peer_id] ) ;
+		dhinfo.gxs_id.clear() ;
 
-    if(dhinfo.dh != NULL)
-        DH_free(dhinfo.dh) ;
+		if(dhinfo.dh != NULL)
+			DH_free(dhinfo.dh) ;
 
-    dhinfo.dh = NULL ;
-    dhinfo.direction = dir ;
-    dhinfo.hash = hash ;
-    dhinfo.status = RS_GXS_TUNNEL_DH_STATUS_UNINITIALIZED ;
+		dhinfo.dh = NULL ;
+		dhinfo.direction = dir ;
+		dhinfo.hash = hash ;
+		dhinfo.status = RS_GXS_TUNNEL_DH_STATUS_UNINITIALIZED ;
 
-        if(dir == RsTurtleGenericTunnelItem::DIRECTION_CLIENT)
-        {
-            // check that a tunnel is not already working for this hash. If so, give up.
+		if(dir == RsTurtleGenericTunnelItem::DIRECTION_CLIENT)
+		{
+			// check that a tunnel is not already working for this hash. If so, give up.
 
-            own_gxs_id = gxsIdFromHash(hash) ;
-        }
-        else	// client side
-        {
-            RsGxsId to_gxs_id = gxsIdFromHash(hash) ;
-            std::map<RsGxsId,GxsTunnelPeerInfo>::const_iterator it = _gxs_tunnel_contacts.find(to_gxs_id) ;
+			own_gxs_id = gxsIdFromHash(hash) ;
+		}
+		else	// client side
+		{
+			RsGxsId to_gxs_id = gxsIdFromHash(hash) ;
+			std::map<RsGxsId,GxsTunnelPeerInfo>::const_iterator it = _gxs_tunnel_contacts.find(to_gxs_id) ;
 
-            if(it == _gxs_tunnel_contacts.end())
-            {
-                std::cerr << "(EE) no pre-registered peer for hash " << hash << " on client side. This is a bug." << std::endl;
-                return ;
-            }
+			if(it == _gxs_tunnel_contacts.end())
+			{
+				std::cerr << "(EE) no pre-registered peer for hash " << hash << " on client side. This is a bug." << std::endl;
+				return ;
+			}
 
-				if(it->second.status == RS_GXS_TUNNEL_STATUS_CAN_TALK)
-				{
-					std::cerr << "  virtual peer is for a distant chat session that is already openned and alive. Giving it up." << std::endl;
-					return ;
-				}
+			if(it->second.status == RS_GXS_TUNNEL_STATUS_CAN_TALK)
+			{
+				std::cerr << "  virtual peer is for a distant chat session that is already openned and alive. Giving it up." << std::endl;
+				return ;
+			}
 
-            own_gxs_id = it->second.own_gxs_id ;
-        }
+			own_gxs_id = it->second.own_gxs_id ;
+		}
 
 #ifdef DEBUG_GXS_TUNNEL
-          std::cerr << "  Creating new virtual peer ID entry and empty DH session key." << std::endl;
+		std::cerr << "  Creating new virtual peer ID entry and empty DH session key." << std::endl;
 #endif
 
-    }
+	}
 
 #ifdef DEBUG_GXS_TUNNEL
-    std::cerr << "  Adding virtual peer " << virtual_peer_id << " for chat hash " << hash << std::endl;
+	std::cerr << "  Adding virtual peer " << virtual_peer_id << " for chat hash " << hash << std::endl;
 #endif
 
-    // Start a new DH session for this tunnel
-    RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/
+	// Start a new DH session for this tunnel
+	RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/
 
-    locked_restartDHSession(virtual_peer_id,own_gxs_id) ;
+	locked_restartDHSession(virtual_peer_id,own_gxs_id) ;
 }
 
 void p3GxsTunnelService::locked_restartDHSession(const RsPeerId& virtual_peer_id,const RsGxsId& own_gxs_id)
@@ -350,8 +364,6 @@ void p3GxsTunnelService::receiveTurtleData(RsTurtleGenericTunnelItem *gitem,cons
         std::cerr << "(EE) item encrypted data stream is too small: size = " << item->data_size << std::endl;
         return ;
     }
-#warning use flags here!!
-#warning add a MAC to make sure the data is not forged
     if(*((uint64_t*)item->data_bytes) != 0)	// WTF?? we should use flags
     {
 #ifdef DEBUG_GXS_TUNNEL
@@ -392,6 +404,7 @@ void p3GxsTunnelService::receiveTurtleData(RsTurtleGenericTunnelItem *gitem,cons
     }
 }
 
+// This function encrypts the given data and adds a MAC and an IV into a serialised memory chunk that is then sent through the tunnel.
 
 bool p3GxsTunnelService::handleEncryptedData(const uint8_t *data_bytes,uint32_t data_size,const TurtleFileHash& hash,const RsPeerId& virtual_peer_id)
 {
@@ -409,7 +422,9 @@ bool p3GxsTunnelService::handleEncryptedData(const uint8_t *data_bytes,uint32_t
     {
         RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/
 
-        uint32_t decrypted_size = RsAES::get_buffer_size(data_size-8);
+        uint32_t encrypted_size = data_size - GXS_TUNNEL_IV_SIZE - GXS_TUNNEL_HMAC_SIZE;
+        uint32_t decrypted_size = RsAES::get_buffer_size(encrypted_size);
+        uint8_t *encrypted_data = (uint8_t*)data_bytes+GXS_TUNNEL_IV_SIZE+GXS_TUNNEL_HMAC_SIZE;
         uint8_t *decrypted_data = new uint8_t[decrypted_size];
         uint8_t aes_key[GXS_TUNNEL_AES_KEY_SIZE] ;
 
@@ -434,11 +449,27 @@ bool p3GxsTunnelService::handleEncryptedData(const uint8_t *data_bytes,uint32_t
 #ifdef DEBUG_GXS_TUNNEL
         std::cerr << "   Using IV: " << std::hex << *(uint64_t*)data_bytes << std::dec << std::endl;
         std::cerr << "   Decrypted buffer size: " << decrypted_size << std::endl;
-        std::cerr << "   key  : " << Bin2Hex(aes_key,16) << ; std::cerr << std::endl;
+        std::cerr << "   key  : " << Bin2Hex(aes_key,GXS_TUNNEL_AES_KEY_SIZE) << ; std::cerr << std::endl;
+        std::cerr << "   hmac : " << Bin2Hex((uint8_t*)data_bytes+GXS_TUNNEL_IV_SIZE,GXS_TUNNEL_HMAC_SIZE) << ; std::cerr << std::endl;
         std::cerr << "   data : " << Bin2Hex((uint8_t*)data_bytes,data_size) << ; std::cerr << std::endl;
 #endif
+        // first, check the HMAC
+        
+        unsigned char *hm = HMAC(EVP_sha1(),aes_key,GXS_TUNNEL_AES_KEY_SIZE,encrypted_data,encrypted_size,NULL,NULL) ;
+        
+        if(memcmp(hm,&data_bytes[GXS_TUNNEL_IV_SIZE],GXS_TUNNEL_HMAC_SIZE))
+        {
+            std::cerr << "(EE) packet HMAC does not match. Computed HMAC=" << Bin2Hex(md,GXS_TUNNEL_HMAC_SIZE) << std::endl;
+            std::cerr << "(EE) resetting new DH session." << std::endl;
 
-        if(!RsAES::aes_decrypt_8_16((uint8_t*)data_bytes+8,data_size-8,aes_key,(uint8_t*)data_bytes,decrypted_data,decrypted_size))
+            delete[] decrypted_data ;
+
+            locked_restartDHSession(virtual_peer_id,it2->second.own_gxs_id) ;
+
+            return false ;
+        }
+
+        if(!RsAES::aes_decrypt_8_16(encrypted_data,encrypted_size, aes_key,(uint8_t*)data_bytes,decrypted_data,decrypted_size))
         {
             std::cerr << "(EE) packet decryption failed." << std::endl;
             std::cerr << "(EE) resetting new DH session." << std::endl;
@@ -750,7 +781,9 @@ bool GxsTunnelService::locked_initDHSessionKey(DH *& dh)
     return true ;
 }
 
-void p3GxsTunnelService::sendTurtleData(RsChatItem *item)
+// Encrypts and sends the item.
+
+void p3GxsTunnelService::sendTurtleData(RsGxsTunnelItem *item)
 {
 #ifdef DEBUG_GXS_TUNNEL
     std::cerr << "GxsTunnelService::sendTurtleData(): try sending item " << (void*)item << " to peer " << item->PeerId() << std::endl;
@@ -767,6 +800,7 @@ void p3GxsTunnelService::sendTurtleData(RsChatItem *item)
         gitem->data_size  = rssize + 8 ;
         gitem->data_bytes = malloc(rssize+8) ;
 
+        // by convention, we use a IV of 0 for unencrypted data.
         memset(gitem->data_bytes,0,8) ;
 
         if(!item->serialise(&((uint8_t*)gitem->data_bytes)[8],rssize))
@@ -842,10 +876,6 @@ void p3GxsTunnelService::sendEncryptedTurtleData(const uint8_t *buff,uint32_t rs
     uint8_t *encrypted_data = new uint8_t[RsAES::get_buffer_size(rssize)];
     uint32_t encrypted_size = RsAES::get_buffer_size(rssize);
 
-#ifdef DEBUG_GXS_TUNNEL
-    std::cerr << "   Using  IV: " << std::hex << IV << std::dec << std::endl;
-    std::cerr << "   Using Key: " << Bin2Hex(aes_key,16) ; std::cerr << std::endl;
-#endif
     if(!RsAES::aes_crypt_8_16(buff,rssize,aes_key,(uint8_t*)&IV,encrypted_data,encrypted_size))
     {
         std::cerr << "(EE) packet encryption failed." << std::endl;
@@ -857,18 +887,27 @@ void p3GxsTunnelService::sendEncryptedTurtleData(const uint8_t *buff,uint32_t rs
     //
     RsTurtleGenericDataItem *gitem = new RsTurtleGenericDataItem ;
 
-    gitem->data_size  = encrypted_size + 8 ;
+    gitem->data_size  = encrypted_size + GXS_TUNNEL_ENCRYPTION_IV_SIZE + GXS_TUNNEL_HMAC_SIZE ;
     gitem->data_bytes = malloc(gitem->data_size) ;
 
-    memcpy(gitem->data_bytes  ,&IV,8) ;
-    memcpy(& (((uint8_t*)gitem->data_bytes)[8]),encrypted_data,encrypted_size) ;
+    memcpy(& (((uint8_t*)gitem->data_bytes)[0]                                       ,&IV,8) ;
 
+    unsigned int md_len = GXS_TUNNEL_HMAC_SIZE ;
+    HMAC(EVP_sha1(),aes_key,GXS_TUNNEL_AES_KEY_SIZE,encrypted_data,encrypted_size,&(((uint8_t*)gitem->data_bytes)[GXS_TUNNEL_IV_SIZE]),&md_len) ;
+    
+    memcpy(& (((uint8_t*)gitem->data_bytes)[GXS_TUNNEL_HMAC_SIZE+GXS_TUNNEL_IV_SIZE]),encrypted_data,encrypted_size) ;
+    
     delete[] encrypted_data ;
 
+#ifdef DEBUG_GXS_TUNNEL
+    std::cerr << "   Using  IV: " << std::hex << IV << std::dec << std::endl;
+    std::cerr << "   Using Key: " << Bin2Hex(aes_key,GXS_TUNNEL_AES_KEY_SIZE) ; std::cerr << std::endl;
+    std::cerr << "        hmac: " << Bin2Hex(gitem->data_bytes,GXS_TUNNEL_HMAC_SIZE) ;
+#endif
 #ifdef DEBUG_GXS_TUNNEL
     std::cerr << "GxsTunnelService::sendTurtleData(): Sending encrypted data to virtual peer: " << virtual_peer_id << std::endl;
     std::cerr << "   gitem->data_size = " << gitem->data_size << std::endl;
-    std::cerr << "   data = " << Bin2Hex(gitem->data_bytes,gitem->data_size) ;
+    std::cerr << "    serialised data = " << Bin2Hex(gitem->data_bytes,gitem->data_size) ;
     std::cerr << std::endl;
 #endif
 
@@ -946,11 +985,11 @@ void p3GxsTunnelService::startClientGxsTunnelConnection(const RsGxsId& to_gxs_id
 #warning check that this code should go.
 #ifdef TO_BE_REMOVED
     // spawn a status item so as to open the chat window.
-    RsChatMsgItem *item = new RsChatMsgItem;
+    RsGxsTunnelMsgItem *item = new RsGxsTunnelMsgItem;
     item->message = "[Starting distant chat. Please wait for secure tunnel to be established]" ;
     item->chatFlags = RS_CHAT_FLAG_PRIVATE ;
     item->PeerId(RsPeerId(to_gxs_id)) ;
-    handleRecvChatMsgItem(item) ;
+    handleRecvGxsTunnelMsgItem(item) ;
 #endif
 }
 
diff --git a/libretroshare/src/gxstunnel/p3gxstunnel.h b/libretroshare/src/gxstunnel/p3gxstunnel.h
index c08c57690..a26ef6019 100644
--- a/libretroshare/src/gxstunnel/p3gxstunnel.h
+++ b/libretroshare/src/gxstunnel/p3gxstunnel.h
@@ -27,6 +27,7 @@
 
 #include <turtle/turtleclientservice.h>
 #include <retroshare/rsgxstunnel.h>
+#include <gxstunnel/rsgxstunnelitems.h>
 
 class RsGixs ;
 
@@ -120,7 +121,7 @@ private:
     bool locked_sendDHPublicKey(const DH *dh, const RsGxsId& own_gxs_id, const RsPeerId& virtual_peer_id) ;
     bool locked_initDHSessionKey(DH *&dh);
     
-    GxsTunnelPeerId virtualPeerIdFromHash(const TurtleFileHash& hash) ;	// ... and to a hash for p3turtle
+    TurtleVirtualPeerId virtualPeerIdFromHash(const TurtleFileHash& hash) ;	// ... and to a hash for p3turtle
 
     // Comunication with Turtle service
 
diff --git a/libretroshare/src/gxstunnel/rsgxstunnelitems.h b/libretroshare/src/gxstunnel/rsgxstunnelitems.h
index 34c960d95..f2f4c0ef5 100644
--- a/libretroshare/src/gxstunnel/rsgxstunnelitems.h
+++ b/libretroshare/src/gxstunnel/rsgxstunnelitems.h
@@ -25,7 +25,6 @@
 
 #pragma once
 
-#include "openssl/bn.h"
 #include "retroshare/rstypes.h"
 #include "serialiser/rstlvkeys.h"
 #include "serialiser/rsserviceids.h"
@@ -35,60 +34,26 @@
 #include "serialiser/rstlvfileitem.h"
 
 /* chat Flags */
-const uint32_t RS_CHAT_FLAG_PRIVATE                    = 0x0001;
-const uint32_t RS_CHAT_FLAG_REQUESTS_AVATAR            = 0x0002;
-const uint32_t RS_CHAT_FLAG_CONTAINS_AVATAR            = 0x0004;
-const uint32_t RS_CHAT_FLAG_AVATAR_AVAILABLE           = 0x0008;
-const uint32_t RS_CHAT_FLAG_CUSTOM_STATE               = 0x0010;  // used for transmitting peer status string
-const uint32_t RS_CHAT_FLAG_PUBLIC                     = 0x0020;
-const uint32_t RS_CHAT_FLAG_REQUEST_CUSTOM_STATE       = 0x0040;
-const uint32_t RS_CHAT_FLAG_CUSTOM_STATE_AVAILABLE     = 0x0080;
-const uint32_t RS_CHAT_FLAG_PARTIAL_MESSAGE            = 0x0100;
-const uint32_t RS_CHAT_FLAG_LOBBY                      = 0x0200;
-const uint32_t RS_CHAT_FLAG_CLOSING_DISTANT_CONNECTION = 0x0400;
-const uint32_t RS_CHAT_FLAG_ACK_DISTANT_CONNECTION     = 0x0800;
-const uint32_t RS_CHAT_FLAG_KEEP_ALIVE                 = 0x1000;
+const uint32_t RS_GXS_TUNNEL_FLAG_CLOSING_DISTANT_CONNECTION = 0x0400;
+const uint32_t RS_GXS_TUNNEL_FLAG_ACK_DISTANT_CONNECTION     = 0x0800;
+const uint32_t RS_GXS_TUNNEL_FLAG_KEEP_ALIVE                 = 0x1000;
 
-const uint32_t RS_CHATMSG_CONFIGFLAG_INCOMING 		= 0x0001;
+const uint8_t RS_PKT_SUBTYPE_GXS_TUNNEL_DATA           = 0x01 ;	
+const uint8_t RS_PKT_SUBTYPE_GXS_TUNNEL_DH_PUBLIC_KEY  = 0x02 ;
+const uint8_t RS_PKT_SUBTYPE_GXS_TUNNEL_STATUS         = 0x03 ;
+const uint8_t RS_PKT_SUBTYPE_GXS_TUNNEL_DATA_ACK       = 0x04 ;
 
-const uint8_t RS_PKT_SUBTYPE_CHAT_AVATAR           	  = 0x03 ;
-const uint8_t RS_PKT_SUBTYPE_CHAT_STATUS           	  = 0x04 ;	
-const uint8_t RS_PKT_SUBTYPE_PRIVATECHATMSG_CONFIG 	  = 0x05 ;	
-const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_MSG_DEPRECATED    = 0x06 ;	// don't use ! Deprecated
-const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE_DEPREC     = 0x07 ;	// don't use ! Deprecated
-const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_ACCEPT     	  = 0x08 ;
-const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_CHALLENGE  	  = 0x09 ;
-const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_UNSUBSCRIBE	  = 0x0A ;
-const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_EVENT_DEPREC      = 0x0B ;	// don't use ! Deprecated
-const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_MSG        	  = 0x0C ;	// will be deprecated when only signed messages are accepted (02/2015)
-const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_LIST_REQUEST 	  = 0x0D ;
-const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_LIST_deprecated   = 0x0E ;	// to be removed
-const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE_deprecated = 0x0F ;	// to be removed
-const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_EVENT       	  = 0x10 ;
-const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_LIST_deprecated2  = 0x11 ;	// to be removed (deprecated since 02 Dec. 2012)
-const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_LIST_deprecated3  = 0x12 ;
-const uint8_t RS_PKT_SUBTYPE_DISTANT_INVITE_CONFIG   	  = 0x13 ;
-const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_CONFIG      	  = 0x15 ;
-const uint8_t RS_PKT_SUBTYPE_DISTANT_CHAT_DH_PUBLIC_KEY   = 0x16 ;
-const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_SIGNED_MSG     	  = 0x17 ;
-const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_SIGNED_EVENT      = 0x18 ;
-const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_LIST              = 0x19 ;
-const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE       	  = 0x1A ;
+typedef uint64_t		GxsTunnelDHSessionId ;
 
-typedef uint64_t 		ChatLobbyId ;
-typedef uint64_t 		ChatLobbyMsgId ;
-typedef std::string 		ChatLobbyNickName ;
-typedef uint64_t		DistantChatDHSessionId ;
-
-class RsChatItem: public RsItem
+class RsGxsTunnelItem: public RsItem
 {
 	public:
-		RsChatItem(uint8_t chat_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_CHAT,chat_subtype) 
+		RsGxsTunnelItem(uint8_t item_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_GXS_TUNNEL,item_subtype) 
 		{
 			setPriorityLevel(QOS_PRIORITY_RS_CHAT_ITEM) ;
 		}
 
-		virtual ~RsChatItem() {}
+		virtual ~RsGxsTunnelItem() {}
 		virtual void clear() {}
 		virtual std::ostream& print(std::ostream &out, uint16_t indent = 0) = 0 ;
 
@@ -96,305 +61,80 @@ class RsChatItem: public RsItem
 		virtual uint32_t serial_size() = 0 ; 							// deserialise is handled using a constructor
 };
 
-/*!
- * For sending chat msgs
- * @see p3ChatService
- */
-class RsChatMsgItem: public RsChatItem
-{
-public:
-    RsChatMsgItem() :RsChatItem(RS_PKT_SUBTYPE_DEFAULT) {}
-    RsChatMsgItem(uint8_t subtype) :RsChatItem(subtype) {}
+//  /*!
+//   * For sending distant communication data. The item is not encrypted after being serialised, but the data it.
+//   * The MAC is computed over encrypted data using the PFS key. All other items (except DH keys) are serialised, encrypted, and
+//   * sent as data in a RsGxsTunnelDataItem.
+//   * 
+//   * @see p3GxsTunnelService
+//   */
+//  class RsGxsTunnelDataItem: public RsGxsTunnelItem
+//  {
+//  public:
+//      RsGxsTunnelDataItem() :RsGxsTunnelItem(RS_PKT_SUBTYPE_GXS_TUNNEL_DATA) {}
+//      RsGxsTunnelDataItem(uint8_t subtype) :RsGxsTunnelItem(subtype) {}
+//  
+//      virtual ~RsGxsTunnelDataItem() {}
+//      virtual void clear() {}
+//      virtual std::ostream& print(std::ostream &out, uint16_t indent = 0);
+//  
+//      virtual bool serialise(void *data,uint32_t& size) ;	// Isn't it better that items can serialize themselves ?
+//      virtual uint32_t serial_size() ;				// deserialise is handled using a constructor
+//  
+//      uint32_t sendTime;
+//      uint32_t flags;						// mainly NEEDS_HACK?
+//      unsigned char *data ;					// encrypted data
+//      uint32_t data_size ;					// encrypted data size
+//      unsigned char IV[IV_LENGTH] ;				// IV for the encrypted data
+//      unsigned char encrypted_data_mac[SHA_DIGEST_LENGTH] ;	// mac of the encrypted data, in order to avoid 
+//  };
 
-    RsChatMsgItem(void *data,uint32_t size,uint8_t subtype = RS_PKT_SUBTYPE_DEFAULT) ; // deserialization
+// Used to send status of connection. This can be closing orders, flushing orders, etc.
+// These items are always sent encrypted.
 
-    virtual ~RsChatMsgItem() {}
-    virtual void clear() {}
-    virtual std::ostream& print(std::ostream &out, uint16_t indent = 0);
-
-    virtual bool serialise(void *data,uint32_t& size) ;	// Isn't it better that items can serialize themselves ?
-    virtual uint32_t serial_size() ; 							// deserialise is handled using a constructor
-
-    uint32_t chatFlags;
-    uint32_t sendTime;
-    std::string message;
-
-    /* not serialised */
-    uint32_t recvTime;
-};
-
-// This class contains the info to bounce an object throughout a lobby, while
-// maintaining cache info to avoid duplicates.
-//
-class RsChatLobbyBouncingObject
-{
-public:
-    ChatLobbyId lobby_id ;
-    ChatLobbyMsgId msg_id ;
-    ChatLobbyNickName nick ;	// Nickname of sender
-
-    RsTlvKeySignature signature ;
-
-    virtual RsChatLobbyBouncingObject *duplicate() const = 0 ;
-    virtual std::ostream& print(std::ostream &out, uint16_t indent = 0);
-
-    // returns the size in bytes of the data chunk to sign.
-
-    virtual uint32_t signed_serial_size() =0;
-    virtual bool serialise_signed_part(void *data,uint32_t& size) = 0;
-
-protected:
-    // The functions below handle the serialisation of data that is specific to the bouncing object level.
-    // They are called by serial_size() and serialise() from children, but should not overload the serial_size() and
-    // serialise() methods, otherwise the wrong method will be called when serialising from this top level class.
-
-    uint32_t serialized_size(bool include_signature) ;
-    bool serialise_to_memory(void *data,uint32_t tlvsize,uint32_t& offset,bool include_signature) ;
-    bool deserialise_from_memory(void *data,uint32_t rssize,uint32_t& offset) ;
-};
-
-class RsChatLobbyMsgItem: public RsChatMsgItem, public RsChatLobbyBouncingObject
-{
-public:
-    RsChatLobbyMsgItem() :RsChatMsgItem(RS_PKT_SUBTYPE_CHAT_LOBBY_SIGNED_MSG) {}
-
-    RsChatLobbyMsgItem(void *data,uint32_t size) ; // deserialization /// TODO!!!
-
-    virtual ~RsChatLobbyMsgItem() {}
-    virtual std::ostream& print(std::ostream &out, uint16_t indent = 0);
-    virtual RsChatLobbyBouncingObject *duplicate() const { return new RsChatLobbyMsgItem(*this) ; }
-
-    virtual bool serialise(void *data,uint32_t& size) ;	// Isn't it better that items can serialize themselves ?
-    virtual uint32_t serial_size() ;			// deserialise is handled using a constructor
-
-    virtual uint32_t signed_serial_size() ;
-    virtual bool serialise_signed_part(void *data,uint32_t& size) ;// Isn't it better that items can serialize themselves ?
-
-    ChatLobbyMsgId parent_msg_id ;				// Used for threaded chat.
-};
-
-class RsChatLobbyEventItem: public RsChatItem, public RsChatLobbyBouncingObject
-{
-    public:
-        RsChatLobbyEventItem() :RsChatItem(RS_PKT_SUBTYPE_CHAT_LOBBY_SIGNED_EVENT) {}
-        RsChatLobbyEventItem(void *data,uint32_t size) ; // deserialization /// TODO!!!
-
-        virtual ~RsChatLobbyEventItem() {}
-        virtual std::ostream& print(std::ostream &out, uint16_t indent = 0);
-        virtual RsChatLobbyBouncingObject *duplicate() const { return new RsChatLobbyEventItem(*this) ; }
-        //
-        virtual bool serialise(void *data,uint32_t& size) ;
-        virtual uint32_t serial_size() ;
-
-        virtual uint32_t signed_serial_size() ;
-    virtual bool serialise_signed_part(void *data,uint32_t& size) ;
-
-        // members.
-        //
-        uint8_t event_type ;		// used for defining the type of event.
-        std::string string1;		// used for any string
-        uint32_t sendTime;		// used to check for old looping messages
-};
-
-class RsChatLobbyListRequestItem: public RsChatItem
+class RsGxsTunnelStatusItem: public RsGxsTunnelItem
 {
 	public:
-		RsChatLobbyListRequestItem() : RsChatItem(RS_PKT_SUBTYPE_CHAT_LOBBY_LIST_REQUEST) {}
-		RsChatLobbyListRequestItem(void *data,uint32_t size) ; 
-		virtual ~RsChatLobbyListRequestItem() {}
+		RsGxsTunnelStatusItem() :RsGxsTunnelItem(RS_PKT_SUBTYPE_GXS_TUNNEL_STATUS) {}
+		RsGxsTunnelStatusItem(void *data,uint32_t size) ; // deserialization
 
-		virtual bool serialise(void *data,uint32_t& size) ;	
-		virtual uint32_t serial_size() ;				 			
-
-        virtual std::ostream& print(std::ostream &out, uint16_t indent = 0);
-};
-
-struct VisibleChatLobbyInfo
-{
-    ChatLobbyId id ;
-    std::string name ;
-    std::string topic ;
-    uint32_t    count ;
-    ChatLobbyFlags flags ;
-};
-
-class RsChatLobbyListItem: public RsChatItem
-{
-	public:
-		RsChatLobbyListItem() : RsChatItem(RS_PKT_SUBTYPE_CHAT_LOBBY_LIST) {}
-		RsChatLobbyListItem(void *data,uint32_t size) ; 
-		virtual ~RsChatLobbyListItem() {}
-
-		virtual std::ostream& print(std::ostream &out, uint16_t indent = 0);
-
-		virtual bool serialise(void *data,uint32_t& size) ;	
-		virtual uint32_t serial_size() ;				 			
-
-        std::vector<VisibleChatLobbyInfo> lobbies ;
-};
-
-class RsChatLobbyUnsubscribeItem: public RsChatItem
-{
-	public:
-		RsChatLobbyUnsubscribeItem() :RsChatItem(RS_PKT_SUBTYPE_CHAT_LOBBY_UNSUBSCRIBE) {}
-		RsChatLobbyUnsubscribeItem(void *data,uint32_t size) ; // deserialization 
-
-		virtual ~RsChatLobbyUnsubscribeItem() {} 
-		virtual std::ostream& print(std::ostream &out, uint16_t indent = 0);
-
-		uint64_t lobby_id ;
-
-		virtual bool serialise(void *data,uint32_t& size) ;	// Isn't it better that items can serialize themselves ?
-		virtual uint32_t serial_size() ; 							// deserialise is handled using a constructor
-};
-
-class RsChatLobbyConnectChallengeItem: public RsChatItem
-{
-	public:
-		RsChatLobbyConnectChallengeItem() :RsChatItem(RS_PKT_SUBTYPE_CHAT_LOBBY_CHALLENGE) {}
-		RsChatLobbyConnectChallengeItem(void *data,uint32_t size) ; // deserialization 
-
-		virtual ~RsChatLobbyConnectChallengeItem() {} 
-		virtual std::ostream& print(std::ostream &out, uint16_t indent = 0);
-
-		uint64_t challenge_code ;
-
-		virtual bool serialise(void *data,uint32_t& size) ;	// Isn't it better that items can serialize themselves ?
-		virtual uint32_t serial_size() ; 							// deserialise is handled using a constructor
-};
-
-class RsChatLobbyInviteItem: public RsChatItem
-{
-	public:
-		RsChatLobbyInviteItem() :RsChatItem(RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE) {}
-		RsChatLobbyInviteItem(void *data,uint32_t size) ; // deserialization 
-
-		virtual ~RsChatLobbyInviteItem() {} 
-		virtual std::ostream& print(std::ostream &out, uint16_t indent = 0);
-
-		ChatLobbyId lobby_id ;
-		std::string lobby_name ;
-		std::string lobby_topic ;
-        ChatLobbyFlags lobby_flags ;
-
-		virtual bool serialise(void *data,uint32_t& size) ;	// Isn't it better that items can serialize themselves ?
-		virtual uint32_t serial_size() ; 							// deserialise is handled using a constructor
-};
-
-/*!
- * For saving incoming and outgoing chat msgs
- * @see p3ChatService
- */
-class RsPrivateChatMsgConfigItem: public RsChatItem
-{
-	public:
-		RsPrivateChatMsgConfigItem() :RsChatItem(RS_PKT_SUBTYPE_PRIVATECHATMSG_CONFIG) {}
-		RsPrivateChatMsgConfigItem(void *data,uint32_t size) ; // deserialization
-
-		virtual ~RsPrivateChatMsgConfigItem() {}
-		virtual void clear() {}
+		virtual ~RsGxsTunnelStatusItem() {}
 		virtual std::ostream& print(std::ostream &out, uint16_t indent = 0);
 
 		virtual bool serialise(void *data,uint32_t& size) ;	// Isn't it better that items can serialize themselves ?
-		virtual uint32_t serial_size() ; 							// deserialise is handled using a constructor
+		virtual uint32_t serial_size() ;			// deserialise is handled using a constructor
 
-		/* set data from RsChatMsgItem to RsPrivateChatMsgConfigItem */
-		void set(RsChatMsgItem *ci, const RsPeerId &peerId, uint32_t confFlags);
-		/* get data from RsPrivateChatMsgConfigItem to RsChatMsgItem */
-		void get(RsChatMsgItem *ci);
-
-		RsPeerId configPeerId;
-		uint32_t chatFlags;
-		uint32_t configFlags;
-		uint32_t sendTime;
-		std::string message;
-		uint32_t recvTime;
-};
-class RsPrivateChatDistantInviteConfigItem: public RsChatItem
-{
-	public:
-		RsPrivateChatDistantInviteConfigItem() :RsChatItem(RS_PKT_SUBTYPE_DISTANT_INVITE_CONFIG) {}
-		RsPrivateChatDistantInviteConfigItem(void *data,uint32_t size) ; // deserialization
-
-		virtual ~RsPrivateChatDistantInviteConfigItem() {}
-		virtual void clear() {}
-		virtual std::ostream& print(std::ostream &out, uint16_t indent = 0);
-
-		virtual bool serialise(void *data,uint32_t& size) ;	// Isn't it better that items can serialize themselves ?
-		virtual uint32_t serial_size() ; 							// deserialise is handled using a constructor
-
-		unsigned char aes_key[16] ;
-        RsFileHash hash ;
-		std::string encrypted_radix64_string ;
-		RsPgpId destination_pgp_id ;
-		uint32_t time_of_validity ;
-		uint32_t last_hit_time ;
 		uint32_t flags ;
 };
-class RsChatLobbyConfigItem: public RsChatItem
-{
-public:
-    RsChatLobbyConfigItem() :RsChatItem(RS_PKT_SUBTYPE_CHAT_LOBBY_CONFIG) { lobby_Id = 0; }
-    RsChatLobbyConfigItem(void *data,uint32_t size) ; // deserialization
 
-    virtual ~RsChatLobbyConfigItem() {}
+// Used to confirm reception of an encrypted item. 
 
-    virtual void clear() { lobby_Id = 0; }
-    virtual std::ostream& print(std::ostream &out, uint16_t indent = 0);
-
-    virtual bool serialise(void *data,uint32_t& size) ;	// Isn't it better that items can serialize themselves ?
-    virtual uint32_t serial_size() ; 							// deserialise is handled using a constructor
-
-    uint64_t lobby_Id;
-	 uint32_t flags ;
-};
-
-// This class contains activity info for the sending peer: active, idle, typing, etc.
-//
-class RsChatStatusItem: public RsChatItem
+class RsGxsTunnelDataAckItem: public RsGxsTunnelItem
 {
 	public:
-		RsChatStatusItem() :RsChatItem(RS_PKT_SUBTYPE_CHAT_STATUS) {}
-		RsChatStatusItem(void *data,uint32_t size) ; // deserialization
+		RsGxsTunnelDataAckItem() :RsGxsTunnelItem(RS_PKT_SUBTYPE_GXS_TUNNEL_DATA_ACK) {}
+		RsGxsTunnelDataAckItem(void *data,uint32_t size) ; // deserialization
 
-		virtual ~RsChatStatusItem() {}
+		virtual ~RsGxsTunnelDataAckItem() {}
 		virtual std::ostream& print(std::ostream &out, uint16_t indent = 0);
 
 		virtual bool serialise(void *data,uint32_t& size) ;	// Isn't it better that items can serialize themselves ?
-		virtual uint32_t serial_size() ; 							// deserialise is handled using a constructor
+		virtual uint32_t serial_size() ;			// deserialise is handled using a constructor
 
-		uint32_t flags ;
-		std::string status_string;
+        	Sha1CheckSum data_hash ;
 };
 
-// This class contains avatar images in Qt format.
-//
-class RsChatAvatarItem: public RsChatItem
-{
-	public:
-		RsChatAvatarItem() :RsChatItem(RS_PKT_SUBTYPE_CHAT_AVATAR) {setPriorityLevel(QOS_PRIORITY_RS_CHAT_AVATAR_ITEM) ;}
-		RsChatAvatarItem(void *data,uint32_t size) ; // deserialization
-
-		virtual ~RsChatAvatarItem() ;
-		virtual std::ostream& print(std::ostream &out, uint16_t indent = 0);
-
-		virtual bool serialise(void *data,uint32_t& size) ;	// Isn't it better that items can serialize themselves ?
-		virtual uint32_t serial_size() ; 							// deserialise is handled using a constructor
-
-		uint32_t image_size ;				// size of data in bytes
-		unsigned char *image_data ;		// image
-};
 
 // This class contains the public Diffie-Hellman parameters to be sent
 // when performing a DH agreement over a distant chat tunnel.
 //
-class RsChatDHPublicKeyItem: public RsChatItem
+class RsGxsTunnelDHPublicKeyItem: public RsGxsTunnelItem
 {
 	public:
-		RsChatDHPublicKeyItem() :RsChatItem(RS_PKT_SUBTYPE_DISTANT_CHAT_DH_PUBLIC_KEY) {setPriorityLevel(QOS_PRIORITY_RS_CHAT_ITEM) ;}
-		RsChatDHPublicKeyItem(void *data,uint32_t size) ; // deserialization
+		RsGxsTunnelDHPublicKeyItem() :RsGxsTunnelItem(RS_PKT_SUBTYPE_DISTANT_CHAT_DH_PUBLIC_KEY) {}
+		RsGxsTunnelDHPublicKeyItem(void *data,uint32_t size) ; // deserialization
 
-		virtual ~RsChatDHPublicKeyItem() { BN_free(public_key) ; } 
+		virtual ~RsGxsTunnelDHPublicKeyItem() { BN_free(public_key) ; } 
 		virtual std::ostream& print(std::ostream &out, uint16_t indent = 0);
 
 		virtual bool serialise(void *data,uint32_t& size) ;	// Isn't it better that items can serialize themselves ?
@@ -408,22 +148,23 @@ class RsChatDHPublicKeyItem: public RsChatItem
 		RsTlvSecurityKey  gxs_key ;	// public key of the signer
 
 	private:
-		RsChatDHPublicKeyItem(const RsChatDHPublicKeyItem&) : RsChatItem(RS_PKT_SUBTYPE_DISTANT_CHAT_DH_PUBLIC_KEY) {}						// make the object non copy-able
-		const RsChatDHPublicKeyItem& operator=(const RsChatDHPublicKeyItem&) { return *this ;}
+		// make the object non copy-able
+		RsGxsTunnelDHPublicKeyItem(const RsGxsTunnelDHPublicKeyItem&) : RsGxsTunnelItem(RS_PKT_SUBTYPE_GXS_TUNNEL_DH_PUBLIC_KEY) {}
+		const RsGxsTunnelDHPublicKeyItem& operator=(const RsGxsTunnelDHPublicKeyItem&) { return *this ;}
 };
 
-class RsChatSerialiser: public RsSerialType
+class RsGxsTunnelSerialiser: public RsSerialType
 {
 	public:
-		RsChatSerialiser() :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_CHAT) {}
+		RsGxsTunnelSerialiser() :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_TUNNEL) {}
 
 		virtual uint32_t 	size (RsItem *item) 
 		{ 
-			return static_cast<RsChatItem *>(item)->serial_size() ; 
+			return static_cast<RsGxsTunnelItem *>(item)->serial_size() ; 
 		}
 		virtual bool serialise(RsItem *item, void *data, uint32_t *size) 
 		{ 
-			return static_cast<RsChatItem *>(item)->serialise(data,*size) ; 
+			return static_cast<RsGxsTunnelItem *>(item)->serialise(data,*size) ; 
 		}
 		virtual RsItem *deserialise (void *data, uint32_t *size) ;
 };
diff --git a/libretroshare/src/serialiser/rsserviceids.h b/libretroshare/src/serialiser/rsserviceids.h
index 3460008a8..b7d7b2fa1 100644
--- a/libretroshare/src/serialiser/rsserviceids.h
+++ b/libretroshare/src/serialiser/rsserviceids.h
@@ -38,32 +38,33 @@
  */
 
 /* These are Cache Only */
-const uint16_t RS_SERVICE_TYPE_FILE_INDEX    = 0x0001;
+const uint16_t RS_SERVICE_TYPE_FILE_INDEX     = 0x0001;
 
 /* These are Services only */
-const uint16_t RS_SERVICE_TYPE_DISC          = 0x0011;
-const uint16_t RS_SERVICE_TYPE_CHAT          = 0x0012;
-const uint16_t RS_SERVICE_TYPE_MSG           = 0x0013;
-const uint16_t RS_SERVICE_TYPE_TURTLE        = 0x0014;
-const uint16_t RS_SERVICE_TYPE_TUNNEL        = 0x0015;
-const uint16_t RS_SERVICE_TYPE_HEARTBEAT     = 0x0016;
-const uint16_t RS_SERVICE_TYPE_FILE_TRANSFER = 0x0017;
-const uint16_t RS_SERVICE_TYPE_GROUTER       = 0x0018;
+const uint16_t RS_SERVICE_TYPE_DISC           = 0x0011;
+const uint16_t RS_SERVICE_TYPE_CHAT           = 0x0012;
+const uint16_t RS_SERVICE_TYPE_MSG            = 0x0013;
+const uint16_t RS_SERVICE_TYPE_TURTLE         = 0x0014;
+const uint16_t RS_SERVICE_TYPE_TUNNEL         = 0x0015;
+const uint16_t RS_SERVICE_TYPE_HEARTBEAT      = 0x0016;
+const uint16_t RS_SERVICE_TYPE_FILE_TRANSFER  = 0x0017;
+const uint16_t RS_SERVICE_TYPE_GROUTER        = 0x0018;
 
-const uint16_t RS_SERVICE_TYPE_SERVICEINFO   = 0x0020;
+const uint16_t RS_SERVICE_TYPE_SERVICEINFO    = 0x0020;
 /* Bandwidth Control */
-const uint16_t RS_SERVICE_TYPE_BWCTRL        = 0x0021;
-// New Mail Service (replace old Msg Service)
-const uint16_t RS_SERVICE_TYPE_MAIL          = 0x0022;
-const uint16_t RS_SERVICE_TYPE_DIRECT_MAIL   = 0x0023;
-const uint16_t RS_SERVICE_TYPE_DISTANT_MAIL  = 0x0024;
-const uint16_t RS_SERVICE_TYPE_GWEMAIL_MAIL  = 0x0025;
+const uint16_t RS_SERVICE_TYPE_BWCTRL         = 0x0021;
+// New Mail Service (replace old Msg Service) 
+const uint16_t RS_SERVICE_TYPE_MAIL           = 0x0022;
+const uint16_t RS_SERVICE_TYPE_DIRECT_MAIL    = 0x0023;
+const uint16_t RS_SERVICE_TYPE_DISTANT_MAIL   = 0x0024;
+const uint16_t RS_SERVICE_TYPE_GWEMAIL_MAIL   = 0x0025;
 const uint16_t RS_SERVICE_TYPE_SERVICE_CONTROL= 0x0026;
-const uint16_t RS_SERVICE_TYPE_DISTANT_CHAT  = 0x0027;
+const uint16_t RS_SERVICE_TYPE_DISTANT_CHAT   = 0x0027;
+const uint16_t RS_SERVICE_TYPE_GXS_TUNNEL     = 0x0028;
 
 // Non essential services.
-const uint16_t RS_SERVICE_TYPE_BANLIST       = 0x0101;
-const uint16_t RS_SERVICE_TYPE_STATUS        = 0x0102;
+const uint16_t RS_SERVICE_TYPE_BANLIST        = 0x0101;
+const uint16_t RS_SERVICE_TYPE_STATUS         = 0x0102;
 
  /* New Cache Services  */
 /* Rs Network Exchange Service */