static const char* version =
  "$Id: route-message.cc,v 2.2 1999/09/30 20:34:00 v2kea318 Exp $";

// $Log: route-message.cc,v $
// Revision 2.2  1999/09/30  20:34:00  v2kea318
// Only route messages to users other than the sender.  If a user sends
// a message to itself, it will only get the COPY type.
//
// Revision 2.1  1999/08/06  17:46:20  v2kea318
// Redesigned the code to reflect the new system design.  The router
// will now talk directly to the user's daemon rather than routing a
// message through the server.
//
// Revision 1.1  1999/05/07  19:48:45  v2kea318
// Initial revision
//
//***************************************************************************

#include "route-message.h"
#include "msg_codes.h"
#include "msg_constants.h"
#include "server_name.h"
#include "Socket.h"
#include "action_transfer.h"
#include "string-transfer.h"
#include "get_userid.h"
#include "query_name_server.h"
#include <algorithm>

//***************************************************************************

static void distribute_message(const UserInfoVector& info,
			       const string& name, const string& text,
			       msg_action_code type);

//***************************************************************************

void msg(const string& uid, const string& text)
{
  // get the user's id.
  string sender_uid = get_userid();

  // query the name server for the requested user.
  UserInfoVector recip_info(query_name_server(uid));
  
  // query the name server for the sender info.
  UserInfoVector sender_info;  
  try {
      sender_info = query_name_server(sender_uid);
  } catch (const action_failed& unr) {
    /* If this is a bad_user_id error, the sender isn't registered,
       which is fine.  So eat the exception.  Otherwise, rethrow it. */
    if (unr.failure_code() != bad_user_id) throw;      
  }

  /* Deliver the message to the recipients.  We only ROUTE messages
     to users other than the sender. */
  if (sender_uid != uid) {
    distribute_message(recip_info, sender_uid, text, ROUTE);
  }
  
  // If the sender is registered, deliver a copy.
  if (sender_info) distribute_message(sender_info, uid, text, COPY);
}

//***************************************************************************

struct deliverer_struct 
{
    const string& uid;
    const string& text;
    msg_action_code act;
    deliverer_struct(const string& u, const string& t,
		     msg_action_code c) : uid(u), text(t), act(c) {}
    void operator () (const UserInformation& it);
};

void deliverer_struct::operator () (const UserInformation& it)
{
    // open a socket to the daemon.
    Socket sock(it.machine, it.port);
    
    // send the correct action code.
    send_action(sock, act);
    
    // deliver the message.
    write_string(sock, uid);
    write_string(sock, text);
    eval_response(sock);
}

    
//***************************************************************************

void distribute_message(const UserInfoVector& info,
			const string& name, const string& text,
			msg_action_code type)
{
    for_each(info->begin(), info->end(), deliverer_struct(name, text, type));
}
