Browse Source

server: add new resetpeer command to allow a peer to reset knowledge of another peer

ambrop7 14 years ago
parent
commit
a1c08b8eac
2 changed files with 47 additions and 0 deletions
  1. 12 0
      protocol/scproto.h
  2. 35 0
      server/server.c

+ 12 - 0
protocol/scproto.h

@@ -82,6 +82,7 @@ typedef uint16_t peerid_t;
 #define SCID_ENDCLIENT 4
 #define SCID_OUTMSG 5
 #define SCID_INMSG 6
+#define SCID_RESETPEER 7
 
 /**
  * "clienthello" client packet payload.
@@ -183,4 +184,15 @@ struct sc_server_inmsg {
 
 #define SC_MAX_MSGLEN (_SC_MAX_OUTMSGLEN < _SC_MAX_INMSGLEN ? _SC_MAX_OUTMSGLEN : _SC_MAX_INMSGLEN)
 
+/**
+ * "resetpeer" client packet header.
+ * Packet type is SCID_RESETPEER.
+ */
+struct sc_client_resetpeer {
+    /**
+     * ID of the peer to reset.
+     */
+    peerid_t clientid;
+} __attribute__((packed));
+
 #endif

+ 35 - 0
server/server.c

@@ -218,6 +218,9 @@ static void process_packet_hello (struct client_data *client, uint8_t *data, int
 // processes outmsg packets from clients
 static void process_packet_outmsg (struct client_data *client, uint8_t *data, int data_len);
 
+// processes resetpeer packets from clients
+static void process_packet_resetpeer (struct client_data *client, uint8_t *data, int data_len);
+
 // creates a peer flow
 static struct peer_flow * peer_flow_create (struct client_data *src_client, struct client_data *dest_client);
 
@@ -1383,6 +1386,9 @@ void client_input_handler_send (struct client_data *client, uint8_t *data, int d
         case SCID_OUTMSG:
             process_packet_outmsg(client, data, data_len);
             return;
+        case SCID_RESETPEER:
+            process_packet_resetpeer(client, data, data_len);
+            return;
         default:
             client_log(client, BLOG_NOTICE, "unknown packet type %d, removing", (int)type);
             client_remove(client);
@@ -1520,6 +1526,35 @@ void process_packet_outmsg (struct client_data *client, uint8_t *data, int data_
     peer_flow_end_packet(flow, SCID_INMSG);
 }
 
+void process_packet_resetpeer (struct client_data *client, uint8_t *data, int data_len)
+{
+    if (client->initstatus != INITSTATUS_COMPLETE) {
+        client_log(client, BLOG_NOTICE, "resetpeer: not expected");
+        client_remove(client);
+        return;
+    }
+    
+    if (data_len != sizeof(struct sc_client_resetpeer)) {
+        client_log(client, BLOG_NOTICE, "resetpeer: wrong size");
+        client_remove(client);
+        return;
+    }
+    
+    struct sc_client_resetpeer *msg = (struct sc_client_resetpeer *)data;
+    peerid_t id = ltoh16(msg->clientid);
+    
+    // lookup flow to destination client
+    BAVLNode *node = BAVL_LookupExact(&client->peer_out_flows_tree, &id);
+    if (!node) {
+        client_log(client, BLOG_INFO, "resetpeer: no flow to %d", (int)id);
+        return;
+    }
+    struct peer_flow *flow = UPPER_OBJECT(node, struct peer_flow, src_tree_node);
+    
+    // reset clients
+    reset_clients(flow);
+}
+
 struct peer_flow * peer_flow_create (struct client_data *src_client, struct client_data *dest_client)
 {
     ASSERT(src_client->initstatus == INITSTATUS_COMPLETE)