Add next_hop field to route update record, filled in locally.
[trust_router.git] / trp / trps.c
index d0e6a31..7a27840 100644 (file)
@@ -1,12 +1,10 @@
 #include <fcntl.h>
-#include <event2/event.h>
 #include <talloc.h>
 #include <errno.h>
 #include <unistd.h>
 
 #include <gsscon.h>
 #include <tr_rp.h>
-#include <tr_event.h>
 #include <tr_debug.h>
 #include <trp_internal.h>
 
@@ -19,6 +17,7 @@ TRPS_INSTANCE *trps_new (TALLOC_CTX *mem_ctx)
     trps->port=0;
     trps->cookie=NULL;
     trps->conn=NULL;
+    trps->trpc=NULL;
     trps->mq=tr_mq_new(trps);
     if (trps->mq==NULL) {
       /* failed to allocate mq */
@@ -35,6 +34,16 @@ void trps_free (TRPS_INSTANCE *trps)
     talloc_free(trps);
 }
 
+TR_MQ_MSG *trps_mq_pop(TRPS_INSTANCE *trps)
+{
+  return tr_mq_pop(trps->mq);
+}
+
+void trps_mq_append(TRPS_INSTANCE *trps, TR_MQ_MSG *msg)
+{
+  tr_mq_append(trps->mq, msg);
+}
+
 /* stand-in for a function that finds the connection for a particular peer */
 #if 0
 static TRP_CONNECTION *trps_find_connection(TRPS_INSTANCE *trps)
@@ -53,23 +62,52 @@ void trps_add_connection(TRPS_INSTANCE *trps, TRP_CONNECTION *new)
   talloc_steal(trps, new);
 }
 
-int trps_send_msg (TRPS_INSTANCE *trps,
-                   int conn,
-                   gss_ctx_id_t gssctx,
-                   const char *msg_content)
+/* ok to call more than once; guarantees connection no longer in the list.
+ * Caller is responsible for freeing the removed element afterwards.  */
+void trps_remove_connection(TRPS_INSTANCE *trps, TRP_CONNECTION *remove)
 {
-  int err=0;
-  int rc=0;
-
-  /* Send the request over the connection */
-  if (err = gsscon_write_encrypted_token (conn,
-                                          gssctx,
-                                          msg_content, 
-                                          strlen(msg_content))) {
-    tr_err( "trps_send_msg: Error sending message over connection.\n");
-    rc = -1;
-  }
+  trps->conn=trp_connection_remove(trps->conn, remove);
+}
+
+void trps_add_trpc(TRPS_INSTANCE *trps, TRPC_INSTANCE *trpc)
+{
+  if (trps->trpc==NULL)
+    trps->trpc=trpc;
+  else
+    trpc_append(trps->trpc, trpc);
+
+  talloc_steal(trps, trpc);
+}
+
+/* ok to call more than once; guarantees trpc no longer in the list.
+ * Caller is responsible for freeing the removed element afterwards.  */
+void trps_remove_trpc(TRPS_INSTANCE *trps, TRPC_INSTANCE *remove)
+{
+  trps->trpc=trpc_remove(trps->trpc, remove);
+}
 
+TRP_RC trps_send_msg (TRPS_INSTANCE *trps, void *peer, const char *msg)
+{
+  TALLOC_CTX *tmp_ctx=talloc_new(NULL);
+  TR_MQ_MSG *mq_msg=NULL;
+  char *msg_dup=NULL;
+  TRP_RC rc=TRP_ERROR;
+
+  /* Currently ignore peer and just send to an open connection.
+   * In reality, need to identify the correct peer and send via that
+   * one.  */
+  if (trps->trpc != NULL) {
+    if (trpc_get_status(trps->trpc)!=TRP_CONNECTION_UP)
+      tr_debug("trps_send_msg: skipping message sent while TRPC connection not up.");
+    else {
+      mq_msg=tr_mq_msg_new(tmp_ctx, "trpc_send");
+      msg_dup=talloc_strdup(mq_msg, msg); /* get local copy in mq_msg context */
+      tr_mq_msg_set_payload(mq_msg, msg_dup, NULL); /* no need for a free() func */
+      trpc_mq_append(trps->trpc, mq_msg);
+      rc=TRP_SUCCESS;
+    }
+  }
+  talloc_free(tmp_ctx);
   return rc;
 }
 
@@ -119,30 +157,38 @@ int trps_auth_cb(gss_name_t clientName, gss_buffer_t displayName, void *data)
   return result;
 }
 
-#if 0
-static int trps_read_message (TRPS_INSTANCE *trps, int conn, gss_ctx_id_t *gssctx, char **msg)
+static TRP_RC trps_read_message(TRPS_INSTANCE *trps, TRP_CONNECTION *conn, TR_MSG **msg)
 {
-  int err;
-  char *buf;
+  int err=0;
+  char *buf=NULL;
   size_t buflen = 0;
 
-  if (err = gsscon_read_encrypted_token(conn, *gssctx, &buf, &buflen)) {
+  tr_debug("trps_read_message: started");
+  if (err = gsscon_read_encrypted_token(trp_connection_get_fd(conn),
+                                       *(trp_connection_get_gssctx(conn)), 
+                                        &buf,
+                                        &buflen)) {
+    tr_debug("trps_read_message: error");
     if (buf)
       free(buf);
-    return -1;
+    return TRP_ERROR;
   }
 
-  tr_debug("trps_read_request(): Request Received, %u bytes.", (unsigned) buflen);
-  tr_debug("trps_read_request(): %.*s", buflen, buf);
+  tr_debug("trps_read_message(): Request Received, %u bytes.", (unsigned) buflen);
+  tr_debug("trps_read_message(): %.*s", buflen, buf);
 
-  *msg=talloc_strndup(NULL, buf, buflen); /* no context owns this! */
+  *msg=tr_msg_decode(buf, buflen);
   free(buf);
-  return buflen;
+  if (*msg==NULL)
+    return TRP_NOPARSE;
+
+  /* fill in the next hop as the peer who just sent this to us */
+  trp_inforec_set_next_hop(*msg, trp_connection_get_peer(conn));
+  return TRP_SUCCESS;
 }
-#endif
 
 int trps_get_listener(TRPS_INSTANCE *trps,
-                      TRP_REQ_FUNC req_handler,
+                      TRPS_MSG_FUNC msg_handler,
                       TRP_AUTH_FUNC auth_handler,
                       const char *hostname,
                       unsigned int port,
@@ -173,7 +219,7 @@ int trps_get_listener(TRPS_INSTANCE *trps,
 
   if (listen > 0) {
     /* store the caller's request handler & cookie */
-    trps->req_handler = req_handler;
+    trps->msg_handler = msg_handler;
     trps->auth_handler = auth_handler;
     trps->hostname = talloc_strdup(trps, hostname);
     trps->port = port;
@@ -183,37 +229,36 @@ int trps_get_listener(TRPS_INSTANCE *trps,
   return listen;
 }
 
-/* old cruft */
-#if 0
-static gss_ctx_id_t trps_establish_gss_context (TRPS_INSTANCE *trps, int conn)
+void trps_handle_connection(TRPS_INSTANCE *trps, TRP_CONNECTION *conn)
 {
   TALLOC_CTX *tmp_ctx=talloc_new(NULL);
-  gss_ctx_id_t gssctx = GSS_C_NO_CONTEXT;
-  char *msg_rec=NULL;
-  int msg_len = 0;
-  int rc=0;
-
-  if (trps_auth_connection(trps, conn, &gssctx))
-    tr_notice("trps_establish_gss_context: Error authorizing TID Server connection.");
-  else:
-    tr_notice("trps_establish_gss_context: Connection authorized!");
-  return gssctx;
-
-  msg_len = trps_read_message(trps, conn, &gssctx, &msg_rec);
-  talloc_steal(tmp_ctx, msg_rec); /* get this in our context */
-  if (0 > msg_len) {
-    tr_debug("trps_handle_connection: Error from trps_read_message()");
-    goto cleanup;
+  TR_MSG *msg=NULL;
+  TRP_RC rc=TRP_ERROR;
+
+  /* try to establish a GSS context */
+  if (0!=trp_connection_auth(conn, trps->auth_handler, trps->cookie)) {
+    tr_notice("tr_trps_conn_thread: failed to authorize connection");
+    pthread_exit(NULL);
   }
+  tr_notice("trps_handle_connection: authorized connection");
   
-  tr_debug("trps_handle_connection: msg_len=%d", msg_len);
-  reply=talloc_asprintf(tmp_ctx, "TRPS heard: %.*s", msg_len, msg_rec);
-  if (0 > (rc = trps_send_msg(trps, conn, gssctx, reply))) {
-    tr_debug("trps_handle_connection: Error from trps_send_message(), rc = %d.", rc);
+  /* loop as long as the connection exists */
+  while (trp_connection_get_status(conn)==TRP_CONNECTION_UP) {
+    rc=trps_read_message(trps, conn, &msg);
+    switch(rc) {
+    case TRP_SUCCESS:
+      trps->msg_handler(trps, conn, msg); /* send the TR_MSG off to the callback */
+      break;
+
+    case TRP_ERROR:
+      trp_connection_close(conn);
+      break;
+
+    default:
+      tr_debug("trps_handle_connection: trps_read_message failed (%d)", rc);
+    }
   }
 
-cleanup:
+  tr_debug("trps_handle_connection: connection closed.");
   talloc_free(tmp_ctx);
-  return conn;
 }
-#endif