Changeset - 22ee38bf8490
[Not reviewed]
default
0 4 0
Nathan Brink (binki) - 15 years ago 2010-06-30 00:42:59
ohnobinki@ohnopublishing.net
Implement some ways for the server to force clients to disconnect.
4 files changed with 118 insertions and 2 deletions:
0 comments (0 inline, 0 general)
src/common/protocol.h
Show inline comments
 
@@ -47,6 +47,11 @@ enum distren_request_type
 
    DISTREN_REQUEST_VERSION = 1,
 
    DISTREN_REQUEST_PING = 2,
 
    DISTREN_REQUEST_PONG = 3,
 
    /**
 
       The data is the a reason describing why the one end is
 
       disconnecting. The other end should respectfully close()
 
       the socket or the sender will timeout shortly.
 
     */
 
    DISTREN_REQUEST_DISCONNECT = 4,
 

	
 
    /**
src/server/distrend.c
Show inline comments
 
@@ -85,6 +85,7 @@ int distrend_do_config(int argc, char *a
 
int distrend_config_free(struct distrend_config *config);
 
int distrend_handle_request(struct distrend_client *client, struct distren_request *req, void *reqdata, struct general_info *geninfo);
 

	
 

	
 
/* **************XML Functions**************** */
 
void update_general_info(struct general_info *geninfo);
 
int import_general_info(struct general_info *general_info);
 
@@ -210,6 +211,8 @@ int main(int argc, char *argv[])
 
int distrend_handle_request(struct distrend_client *client, struct distren_request *req, void *reqdata, struct general_info *geninfo)
 
{
 
  size_t counter;
 
  char *tmp_str;
 
  char fixedbuf[32];
 

	
 
  /* for response requests... if that makes any less sense ;-) */
 
  struct distren_request *newreq;
 
@@ -222,6 +225,30 @@ int distrend_handle_request(struct distr
 
  switch(req->type)
 
    {
 
    case DISTREN_REQUEST_VERSION:
 
      if(strlen(PACKAGE_STRING) == req->len
 
	 && !strncmp(PACKAGE_STRING, reqdata, req->len))
 
	{
 
	  /**
 
	     The client and I claim to be of the same version of distren :-D
 
	     Now we will mark the client as valid.
 
	   */
 
	  
 
	}
 
      else
 
	{
 
	  /**
 
	     The client claims to be of a different version of distren.
 
	     Now we will just send a disconnect packet and disconnect the client.
 
	   */
 
	  strncpy(fixedbuf, reqdata, 31);
 
	  fixedbuf[31] = '\0';
 
	  if(req->len < 31)
 
	    fixedbuf[req->len] = '\0';
 

	
 
	  _distren_asprintf(&tmp_str, "You have tried to connect to a %s server when your client claims to be running %s. Bye ;-)\n", PACKAGE_STRING, fixedbuf);
 
	  distrend_send_disconnect(client, tmp_str);
 
	}
 

	
 
      distren_request_new(&newreq, strlen(VERSION), DISTREN_REQUEST_VERSION);
 
      distrend_client_write_request(client, newreq, VERSION);
 
      distren_request_free(newreq);
src/server/listen.c
Show inline comments
 
@@ -304,6 +304,7 @@ struct distrend_accept_client_proc_data
 
  distrend_handle_request_t handlereq;
 
  void *handlereqdata;
 
  enum {DISTREND_ACCEPT_CLIENT_READ, DISTREND_ACCEPT_CLIENT_WRITE} mode;
 
  time_t current_time;
 
};
 
int distrend_accept_client_proc(struct distrend_accept_client_proc_data *data,
 
				struct distrend_client *client)
 
@@ -314,6 +315,25 @@ int distrend_accept_client_proc(struct d
 
  if(client->state == DISTREND_CLIENT_DEAD)
 
    return TRUE;
 

	
 
  if(data->current_time > client->cleanup_time)
 
    switch(client->state)
 
      {
 
      case DISTREND_CLIENT_PREAUTH:
 
	distrend_send_disconnect(client, "You have failed to present authentication information in a timely manner. Cya ;-)");
 
	break;
 

	
 
      case DISTREND_CLIENT_GOOD:
 
	distrend_send_disconnect(client, "Ping timeout :-p");
 
	break;
 

	
 
      case DISTREND_CLIENT_BAD:
 
	client->state = DISTREND_CLIENT_DEAD;
 
	return TRUE;
 

	
 
      default:
 
	break;
 
      }
 

	
 
  if(!FD_ISSET(client->sock, data->fdset))
 
    /** continue iteration through the list */
 
    return TRUE;
 
@@ -403,6 +423,7 @@ int distrend_accept(struct distrend_conf
 
  travinfo.handlereq = handlereq;
 
  travinfo.handlereqdata = handlereqdata;
 
  travinfo.mode = DISTREND_ACCEPT_CLIENT_WRITE;
 
  travinfo.current_time = time(NULL); /*< cache the time */
 
  list_traverse(clients->clients, &travinfo, (list_traverse_func_t)&distrend_accept_client_proc, LIST_FRNT | LIST_ALTR);
 

	
 
  travinfo.fdset = &fdsets.readfds;
 
@@ -484,6 +505,7 @@ int distrend_client_new(struct distrend_
 
    }
 
  (*client)->sock = sock;
 
  (*client)->state = state;
 
  (*client)->cleanup_time = time(NULL) + DISTREND_LISTEN_AUTHTIME;
 
  (*client)->inlen = 0;
 
  (*client)->expectlen = 0;
 
  (*client)->inmsgs = q_init();
 
@@ -646,3 +668,18 @@ int distrend_packets_collapse(QUEUE *que
 

	
 
  return 0;
 
}
 

	
 

	
 
int distrend_send_disconnect(struct distrend_client *client, char *quit_msg)
 
{
 
  struct distren_request *req;
 

	
 
  distren_request_new(&req, strlen(quit_msg), DISTREN_REQUEST_DISCONNECT);
 
  distrend_client_write_request(client, req, quit_msg);
 
  distren_request_free(req);
 

	
 
  client->state = DISTREND_CLIENT_BAD;
 
  client->cleanup_time = time(NULL) + DISTREND_LISTEN_DISCONNECT_GRACE;
 

	
 
  return 0;
 
}
src/server/listen.h
Show inline comments
 
@@ -28,12 +28,44 @@ struct distrend_client;
 
#include "common/protocol.h"
 

	
 
#include <queue.h>
 
#include <time.h>
 

	
 
/**
 
   How long a client has after connecting to send
 
   authentication information before his connection is cleaned
 
   up.
 
 */
 
#define DISTREND_LISTEN_AUTHTIME 32
 

	
 
/**
 
   How long a client has when in DISTREND_CLIENT_BAD before
 
   his connection is dropped. This grace time is intended so that
 
   the client will actually see his disconnect message instead of
 
   just having his connection reset.
 
 */
 
#define DISTREND_LISTEN_DISCONNECT_GRACE 8
 

	
 
enum distrend_client_state
 
  {
 
    /**
 
       We don't yet know the client. It may only use authentication
 
       commands.
 
     */
 
    DISTREND_CLIENT_PREAUTH,
 
    DISTREND_CLIENT_GOODDOGGY,
 
    DISTREND_CLIENT_BADBOY,
 
    /**
 
       The client is authenticated, etc.
 
     */
 
    DISTREND_CLIENT_GOOD,
 
    /**
 
       The client is queued to be disconnected. (This state exists
 
       so that the client at least has a chance to recieve its
 
       disconnect message/error before being dumped).
 
     */
 
    DISTREND_CLIENT_BAD,
 
    /**
 
       The socket used to communicate with the client is closed. Its entry
 
       in the client list should be removed on the next garbage clean-up round.
 
     */
 
    DISTREND_CLIENT_DEAD
 
  };
 

	
 
@@ -48,6 +80,14 @@ struct distrend_client
 
  int sock;
 
  enum distrend_client_state state;
 

	
 
  /**
 
     The absolute time at which this client's entry in the client list will be
 
     expired, closed, and marked as dead so that it may be cleaned up. This is
 
     used to implement ping timeouts (if state == DISTREND_CLIENT_GOOD) and 
 
     disconnect message grace time (if state == DISTREND_CLIENT_BAD).
 
   */
 
  time_t cleanup_time;
 

	
 
  size_t inlen; /*< number of bytes waiting to be processed */
 
  size_t expectlen; /*< number of bytes that inlen has to be for a complete request to be had, 0 when waiting on header */
 
  QUEUE *inmsgs;
 
@@ -100,4 +140,11 @@ int distrend_client_write_request(struct
 
*/
 
void remotio_send_to_client();
 

	
 
/**
 
   Queue a DISTREN_REQUEST_DISCONNECT and prepare a client
 
   to be disconnected.
 
 */
 
int distrend_send_disconnect(struct distrend_client *client, char *quit_msg);
 

	
 

	
 
#endif
0 comments (0 inline, 0 general)