diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h
index 9ba2e90c710edce89531f09ede54efc5cfd8c212..8c78720841f1c3728990cc2b8efd480538f8dff6 100644
--- a/include/asterisk/res_pjsip.h
+++ b/include/asterisk/res_pjsip.h
@@ -1504,4 +1504,60 @@ int ast_sip_add_global_response_header(const char *name, const char *value, int
 
 int ast_sip_initialize_sorcery_global(struct ast_sorcery *sorcery);
 
+/*!
+ * \brief Retrieves the value associated with the given key.
+ *
+ * \param ht the hash table/dictionary to search
+ * \param key the key to find
+ *
+ * \retval the value associated with the key, NULL otherwise.
+ */
+void *ast_sip_dict_get(void *ht, const char *key);
+
+/*!
+ * \brief Using the dictionary stored in mod_data array at a given id,
+ *        retrieve the value associated with the given key.
+ *
+ * \param mod_data a module data array
+ * \param id the mod_data array index
+ * \param key the key to find
+ *
+ * \retval the value associated with the key, NULL otherwise.
+ */
+#define ast_sip_mod_data_get(mod_data, id, key)		\
+	ast_sip_dict_get(mod_data[id], key)
+
+/*!
+ * \brief Set the value for the given key.
+ *
+ * Note - if the hash table does not exist one is created first, the key/value
+ * pair is set, and the hash table returned.
+ *
+ * \param pool the pool to allocate memory in
+ * \param ht the hash table/dictionary in which to store the key/value pair
+ * \param key the key to associate a value with
+ * \param val the value to associate with a key
+ *
+ * \retval the given, or newly created, hash table.
+ */
+void *ast_sip_dict_set(pj_pool_t* pool, void *ht,
+		       const char *key, void *val);
+
+/*!
+ * \brief Utilizing a mod_data array for a given id, set the value
+ *        associated with the given key.
+ *
+ * For a given structure's mod_data array set the element indexed by id to
+ * be a dictionary containing the key/val pair.
+ *
+ * \param pool a memory allocation pool
+ * \param mod_data a module data array
+ * \param id the mod_data array index
+ * \param key the key to find
+ * \param val the value to associate with a key
+ */
+#define ast_sip_mod_data_set(pool, mod_data, id, key, val)		\
+	mod_data[id] = ast_sip_dict_set(pool, mod_data[id], key, val)
+
+
 #endif /* _RES_PJSIP_H */
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index eab9b14037ede2e538f976832c520a74fbf674ff..c102803a2e444d5c0ddb689984c32eabbac391c1 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -1836,6 +1836,29 @@ int ast_sip_thread_is_servant(void)
 	return *servant_id == SIP_SERVANT_ID;
 }
 
+void *ast_sip_dict_get(void *ht, const char *key)
+{
+	unsigned int hval;
+
+	if (!ht) {
+		return NULL;
+	}
+
+	return pj_hash_get(ht, key, PJ_HASH_KEY_STRING, &hval);
+}
+
+void *ast_sip_dict_set(pj_pool_t* pool, void *ht,
+		       const char *key, void *val)
+{
+	if (!ht) {
+		ht = pj_hash_create(pool, 11);
+	}
+
+	pj_hash_set(pool, ht, key, PJ_HASH_KEY_STRING, 0, val);
+
+	return ht;
+}
+
 static void remove_request_headers(pjsip_endpoint *endpt)
 {
 	const pjsip_hdr *request_headers = pjsip_endpt_get_request_headers(endpt);
diff --git a/res/res_pjsip.exports.in b/res/res_pjsip.exports.in
index d896ee60d0d9a9043ee8c2dca91055b0cd4cfae0..5afafc481ee1b56c5217d0a229520c4f34b5bb67 100644
--- a/res/res_pjsip.exports.in
+++ b/res/res_pjsip.exports.in
@@ -70,6 +70,8 @@
 		LINKER_SYMBOL_PREFIXast_sip_initialize_sorcery_global;
 		LINKER_SYMBOL_PREFIXast_sip_auth_array_init;
 		LINKER_SYMBOL_PREFIXast_sip_auth_array_destroy;
+		LINKER_SYMBOL_PREFIXast_sip_dict_get;
+		LINKER_SYMBOL_PREFIXast_sip_dict_set;
 	local:
 		*;
 };
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index cac4c2fc5876daf4690ac6a6f30e21945aa93f95..54e03f531c52912e744ed4a6e9771e674fb4a5ff 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -45,6 +45,9 @@
 
 #define SDP_HANDLER_BUCKETS 11
 
+#define MOD_DATA_ON_RESPONSE "on_response"
+#define MOD_DATA_NAT_HOOK "nat_hook"
+
 /* Some forward declarations */
 static void handle_incoming_request(struct ast_sip_session *session, pjsip_rx_data *rdata);
 static void handle_incoming_response(struct ast_sip_session *session, pjsip_rx_data *rdata);
@@ -127,7 +130,7 @@ int ast_sip_session_register_sdp_handler(struct ast_sip_session_sdp_handler *han
 			}
 		}
 		AST_LIST_INSERT_TAIL(&handler_list->list, handler, next);
-		ast_debug(1, "Registered SDP stream handler '%s' for stream type '%s'\n", handler->id, stream_type); 
+		ast_debug(1, "Registered SDP stream handler '%s' for stream type '%s'\n", handler->id, stream_type);
 		ast_module_ref(ast_module_info->self);
 		return 0;
 	}
@@ -144,7 +147,7 @@ int ast_sip_session_register_sdp_handler(struct ast_sip_session_sdp_handler *han
 	if (!ao2_link(sdp_handlers, handler_list)) {
 		return -1;
 	}
-	ast_debug(1, "Registered SDP stream handler '%s' for stream type '%s'\n", handler->id, stream_type); 
+	ast_debug(1, "Registered SDP stream handler '%s' for stream type '%s'\n", handler->id, stream_type);
 	ast_module_ref(ast_module_info->self);
 	return 0;
 }
@@ -925,7 +928,9 @@ void ast_sip_session_send_request_with_cb(struct ast_sip_session *session, pjsip
 		return;
 	}
 
-	tdata->mod_data[session_module.id] = on_response;
+	ast_sip_mod_data_set(tdata->pool, tdata->mod_data, session_module.id,
+			     MOD_DATA_ON_RESPONSE, on_response);
+
 	handle_outgoing_request(session, tdata);
 	pjsip_inv_send_msg(session->inv_session, tdata);
 	return;
@@ -1641,7 +1646,7 @@ static void reschedule_reinvite(struct ast_sip_session *session, ast_sip_session
 	pjsip_inv_session *inv = session->inv_session;
 	struct reschedule_reinvite_data *rrd = reschedule_reinvite_data_alloc(session, delay);
 	pj_time_val tv;
-	
+
 	if (!rrd || !delay) {
 		return;
 	}
@@ -1850,6 +1855,7 @@ static void session_inv_on_new_session(pjsip_inv_session *inv, pjsip_event *e)
 
 static void session_inv_on_tsx_state_changed(pjsip_inv_session *inv, pjsip_transaction *tsx, pjsip_event *e)
 {
+	ast_sip_session_response_cb cb;
 	struct ast_sip_session *session = inv->mod_data[session_module.id];
 	print_debug_details(inv, tsx, e);
 	if (!session) {
@@ -1904,8 +1910,8 @@ static void session_inv_on_tsx_state_changed(pjsip_inv_session *inv, pjsip_trans
 				handle_incoming_request(session, e->body.tsx_state.src.rdata);
 			}
 		}
-		if (tsx->mod_data[session_module.id]) {
-			ast_sip_session_response_cb cb = tsx->mod_data[session_module.id];
+		if ((cb = ast_sip_mod_data_get(tsx->mod_data, session_module.id,
+					       MOD_DATA_ON_RESPONSE))) {
 			cb(session, e->body.tsx_state.src.rdata);
 		}
 	case PJSIP_EVENT_TRANSPORT_ERROR:
@@ -2073,7 +2079,8 @@ static pjsip_inv_callback inv_callback = {
 /*! \brief Hook for modifying outgoing messages with SDP to contain the proper address information */
 static void session_outgoing_nat_hook(pjsip_tx_data *tdata, struct ast_sip_transport *transport)
 {
-	struct ast_sip_nat_hook *hook = tdata->mod_data[session_module.id];
+	struct ast_sip_nat_hook *hook = ast_sip_mod_data_get(
+		tdata->mod_data, session_module.id, MOD_DATA_NAT_HOOK);
 	struct pjmedia_sdp_session *sdp;
 	int stream;
 
@@ -2107,7 +2114,7 @@ static void session_outgoing_nat_hook(pjsip_tx_data *tdata, struct ast_sip_trans
 	}
 
 	/* We purposely do this so that the hook will not be invoked multiple times, ie: if a retransmit occurs */
-	tdata->mod_data[session_module.id] = nat_hook;
+	ast_sip_mod_data_set(tdata->pool, tdata->mod_data, session_module.id, MOD_DATA_NAT_HOOK, nat_hook);
 }
 
 static int load_module(void)