paulo@0: /* paulo@0: * $Id: gt_share_state.c,v 1.2 2004/03/31 08:58:24 hipnod Exp $ paulo@0: * paulo@0: * Copyright (C) 2004 giFT project (gift.sourceforge.net) paulo@0: * paulo@0: * This program is free software; you can redistribute it and/or modify it paulo@0: * under the terms of the GNU General Public License as published by the paulo@0: * Free Software Foundation; either version 2, or (at your option) any paulo@0: * later version. paulo@0: * paulo@0: * This program is distributed in the hope that it will be useful, but paulo@0: * WITHOUT ANY WARRANTY; without even the implied warranty of paulo@0: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU paulo@0: * General Public License for more details. paulo@0: */ paulo@0: paulo@0: #include "gt_gnutella.h" paulo@0: #include "gt_node.h" paulo@0: #include "gt_node_list.h" paulo@0: #include "gt_packet.h" paulo@0: #include "gt_share_state.h" paulo@0: paulo@0: /*****************************************************************************/ paulo@0: paulo@0: /* whether giftd has disabled shares */ paulo@0: static BOOL giftd_hidden = FALSE; paulo@0: paulo@0: /*****************************************************************************/ paulo@0: paulo@0: struct gt_share_state *gt_share_state_new (void) paulo@0: { paulo@0: struct gt_share_state *state; paulo@0: paulo@0: if (!(state = malloc (sizeof(struct gt_share_state)))) paulo@0: return NULL; paulo@0: paulo@0: /* paulo@0: * Sharing may be disabled now globally, but it isn't for this paulo@0: * gt_share_state until gt_share_state_update() is called. paulo@0: */ paulo@0: state->hidden = FALSE; paulo@0: state->plugin_hidden = FALSE; paulo@0: paulo@0: return state; paulo@0: } paulo@0: paulo@0: void gt_share_state_free (struct gt_share_state *state) paulo@0: { paulo@0: free (state); paulo@0: } paulo@0: paulo@0: static GtPacket *hops_flow_message (uint8_t ttl) paulo@0: { paulo@0: GtPacket *pkt; paulo@0: paulo@0: if (!(pkt = gt_packet_vendor (GT_VMSG_HOPS_FLOW))) paulo@0: return NULL; paulo@0: paulo@0: gt_packet_put_uint8 (pkt, ttl); paulo@0: paulo@0: if (gt_packet_error (pkt)) paulo@0: { paulo@0: gt_packet_free (pkt); paulo@0: return NULL; paulo@0: } paulo@0: paulo@0: return pkt; paulo@0: } paulo@0: paulo@0: static void toggle_sharing (GtNode *node, struct gt_share_state *state, paulo@0: BOOL hidden) paulo@0: { paulo@0: GtPacket *hops_disable; paulo@0: uint8_t max_hops; paulo@0: paulo@0: /* regardless of whether the node receives our HospFlow, record whether paulo@0: * sharing _should_ be disabled */ paulo@0: state->hidden = hidden; paulo@0: paulo@0: if (hidden) paulo@0: max_hops = 0; paulo@0: else paulo@0: max_hops = 8; paulo@0: paulo@0: if (!(hops_disable = hops_flow_message (max_hops))) paulo@0: return; paulo@0: paulo@0: if (!dataset_lookupstr (node->hdr, "vendor-message")) paulo@0: { paulo@0: gt_packet_free (hops_disable); paulo@0: return; paulo@0: } paulo@0: paulo@0: GT->DBGSOCK (GT, GT_CONN(node), "sending HopsFlow(%d)", max_hops); paulo@0: paulo@0: gt_node_send (node, hops_disable); paulo@0: gt_packet_free (hops_disable); paulo@0: } paulo@0: paulo@0: void gt_share_state_update (GtNode *node) paulo@0: { paulo@0: struct gt_share_state *state; paulo@0: paulo@0: assert (node->state == GT_NODE_CONNECTED); paulo@0: state = node->share_state; paulo@0: paulo@0: if (state->hidden) paulo@0: { paulo@0: /* sharing disable, reenable it */ paulo@0: if (!giftd_hidden && !state->plugin_hidden) paulo@0: toggle_sharing (node, state, FALSE); paulo@0: } paulo@0: else paulo@0: { paulo@0: /* sharing enabled, disable it */ paulo@0: if (giftd_hidden || state->plugin_hidden) paulo@0: toggle_sharing (node, state, TRUE); paulo@0: } paulo@0: } paulo@0: paulo@0: /*****************************************************************************/ paulo@0: paulo@0: /* paulo@0: * gt_share_state_update() must have been called before calling either of paulo@0: * these. paulo@0: */ paulo@0: paulo@0: void gt_share_state_hide (GtNode *node) paulo@0: { paulo@0: node->share_state->plugin_hidden = TRUE; paulo@0: gt_share_state_update (node); paulo@0: } paulo@0: paulo@0: void gt_share_state_show (GtNode *node) paulo@0: { paulo@0: node->share_state->plugin_hidden = FALSE; paulo@0: gt_share_state_update (node); paulo@0: } paulo@0: paulo@0: /*****************************************************************************/ paulo@0: paulo@0: static GtNode *foreach_state (TCPC *c, GtNode *node, void *udata) paulo@0: { paulo@0: gt_share_state_update (node); paulo@0: return NULL; paulo@0: } paulo@0: paulo@0: static void update_share_state (BOOL hidden) paulo@0: { paulo@0: giftd_hidden = hidden; paulo@0: paulo@0: /* paulo@0: * Ignore the command from giftd for ultrapeers. XXX: this isn't actually paulo@0: * right, if we change status inbetween two of these message, we're paulo@0: * screwed. paulo@0: */ paulo@0: if (GT_SELF->klass & GT_NODE_ULTRA) paulo@0: return; paulo@0: paulo@0: gt_conn_foreach (foreach_state, NULL, paulo@0: GT_NODE_ULTRA, GT_NODE_CONNECTED, 0); paulo@0: } paulo@0: paulo@0: void gnutella_share_hide (Protocol *p) paulo@0: { paulo@0: if (giftd_hidden) paulo@0: return; paulo@0: paulo@0: update_share_state (TRUE); paulo@0: } paulo@0: paulo@0: void gnutella_share_show (Protocol *p) paulo@0: { paulo@0: if (!giftd_hidden) paulo@0: return; paulo@0: paulo@0: update_share_state (FALSE); paulo@0: } paulo@0: paulo@0: /*****************************************************************************/ paulo@0: paulo@0: void gt_share_state_local_init (void) paulo@0: { paulo@0: giftd_hidden = FALSE; paulo@0: } paulo@0: paulo@0: void gt_share_state_local_cleanup (void) paulo@0: { paulo@0: giftd_hidden = FALSE; paulo@0: }