/** * Attach meta information to supplied message block, returning a possibly * new message block to use. */ static pmsg_t * mq_udp_attach_metadata(pmsg_t *mb, const gnet_host_t *to) { pmsg_t *result; if (pmsg_is_extended(mb)) { struct mq_udp_info_extended *mi; WALLOC(mi); gnet_host_copy(&mi->to, to); result = mb; /* * Replace original free routine with the new one, saving the original * metadata and its free routine in the new metadata for later * transparent dispatching at free time. */ mi->orig_free = pmsg_replace_ext(mb, mq_udp_pmsg_free_extended, mi, &mi->orig_arg); } else { struct mq_udp_info *mi; WALLOC(mi); gnet_host_copy(&mi->to, to); result = pmsg_clone_extend(mb, mq_udp_pmsg_free, mi); pmsg_free(mb); } g_assert(pmsg_is_extended(result)); return result; }
/** * Prepare reception of query hit data by building an appropriate RX stack. * * @return TRUE if we may continue with the download, FALSE if the search * was already closed in the GUI. */ gboolean browse_host_dl_receive( struct browse_ctx *bc, gnet_host_t *host, wrap_io_t *wio, const char *vendor, guint32 flags) { g_assert(bc != NULL); if (bc->closed) return FALSE; gnet_host_copy(&bc->host, host); bc->vendor = atom_str_get(vendor); /* * Freeing of the RX stack must be asynchronous: each time we establish * a new connection, dismantle the previous stack. Otherwise the RX * stack will be freed when the corresponding download structure is * reclaimed. */ if (bc->rx != NULL) { rx_free(bc->rx); bc->rx = NULL; } { struct rx_link_args args; args.cb = &browse_rx_link_cb; args.bws = bsched_in_select_by_addr(gnet_host_get_addr(&bc->host)); args.wio = wio; bc->rx = rx_make(bc, &bc->host, rx_link_get_ops(), &args); } if (flags & BH_DL_CHUNKED) { struct rx_chunk_args args; args.cb = &browse_rx_chunk_cb; bc->rx = rx_make_above(bc->rx, rx_chunk_get_ops(), &args); } if (flags & BH_DL_INFLATE) { struct rx_inflate_args args; args.cb = &browse_rx_inflate_cb; bc->rx = rx_make_above(bc->rx, rx_inflate_get_ops(), &args); } rx_set_data_ind(bc->rx, browse_data_ind); rx_enable(bc->rx); return TRUE; }
/** * Initialize the browse host context. */ struct browse_ctx * browse_host_dl_create(gpointer owner, gnet_host_t *host, gnet_search_t sh) { struct browse_ctx *bc; WALLOC0(bc); bc->owner = owner; gnet_host_copy(&bc->host, host); bc->sh = sh; return bc; }
/** * Initialize the THEX download context. */ struct thex_download * thex_download_create(void *owner, gnet_host_t *host, const struct sha1 *sha1, const struct tth *tth, filesize_t filesize) { static const struct thex_download zero_ctx; struct thex_download *ctx; g_return_val_if_fail(host, NULL); g_return_val_if_fail(sha1, NULL); g_return_val_if_fail(tth, NULL); WALLOC(ctx); *ctx = zero_ctx; ctx->owner = owner; gnet_host_copy(&ctx->host, host); ctx->sha1 = atom_sha1_get(sha1); ctx->tth = atom_tth_get(tth); ctx->filesize = filesize; return ctx; }
/** * Upon reception of an UDP pong, check whether we had a matching registered * ping bearing the given MUID. * * If there was a callback atttached to the reception of a reply, invoke it * before returning UDP_PONG_HANDLED. * * The ``host'' paramaeter MUST be a stack or static pointer to a gnet_host_t, * and NOT the address of a dynamically allocated host because gnet_host_copy() * is going to be used on it. * * @param n the gnutella node replying * @param host if non-NULL, filled with the host to whom we sent the ping * * @return TRUE if indeed this was a reply for a ping we sent. */ enum udp_pong_status udp_ping_is_registered(const struct gnutella_node *n, gnet_host_t *host) { const struct guid *muid = gnutella_header_get_muid(&n->header); if (udp_pings) { struct udp_ping *ping; ping = hash_list_remove(udp_pings, muid); if (ping != NULL) { if (host != NULL) { /* * Let caller know the exact IP:port of the host we contacted, * since the replying party can use a different port (which * we may not be able to contact, whereas we know the targeted * port did cause a reply). */ gnet_host_copy(host, ping->host); } if (ping->callback) { (*ping->callback->cb)(UDP_PING_REPLY, n, ping->callback->data); if (ping->callback->multiple) { ping->callback->got_reply = TRUE; ping->added = tm_time(); /* Delay expiration */ hash_list_append(udp_pings, ping); } else { udp_ping_free(ping); } return UDP_PONG_HANDLED; } udp_ping_free(ping); return UDP_PONG_SOLICITED; } } return UDP_PONG_UNSOLICITED; }
/** * Createion routine for a driver to be stacked above specified lower `ltx'. * * @return NULL if there is an initialization problem. */ txdrv_t * tx_make_above(txdrv_t *ltx, const struct txdrv_ops *ops, void *args) { txdrv_t *tx; tx_check(ltx); g_assert(ltx->upper == NULL); /* Nothing above yet */ g_assert(ops); WALLOC0(tx); tx->magic = TXDRV_MAGIC; tx->owner = ltx->owner; gnet_host_copy(&tx->host, <x->host); tx->ops = ops; tx->upper = NULL; tx->lower = ltx; if (NULL == TX_INIT(tx, args)) /* Let the heir class initialize */ return NULL; tx_attached(tx->lower, tx); return tx; }
/** * Prepare reception of THEX data by building an appropriate RX stack. * * @return TRUE if we may continue with the download. */ bool thex_download_receive(struct thex_download *ctx, filesize_t content_length, gnet_host_t *host, struct wrap_io *wio, uint32 flags) { g_assert(ctx != NULL); gnet_host_copy(&ctx->host, host); /* * Freeing of the RX stack must be asynchronous: each time we establish * a new connection, dismantle the previous stack. Otherwise the RX * stack will be freed when the corresponding download structure is * reclaimed. */ if (ctx->rx != NULL) { rx_free(ctx->rx); ctx->rx = NULL; } /* * If there is a Content-Length indication in the HTTP reply, it is * supplied here and will be used as a limit of the data we'll read. * * If there was none (for instance if the output is chunked), then 0 * is given and we'll use a hardwired maximum. */ if (content_length > MAX_INT_VAL(size_t)) return FALSE; ctx->max_size = content_length ? (size_t) content_length : THEX_DOWNLOAD_MAX_SIZE; { struct rx_link_args args; args.cb = &thex_rx_link_cb; args.bws = bsched_in_select_by_addr(gnet_host_get_addr(&ctx->host)); args.wio = wio; ctx->rx = rx_make(ctx, &ctx->host, rx_link_get_ops(), &args); } if (flags & THEX_DOWNLOAD_F_CHUNKED) { struct rx_chunk_args args; args.cb = &thex_rx_chunk_cb; ctx->rx = rx_make_above(ctx->rx, rx_chunk_get_ops(), &args); } if (flags & THEX_DOWNLOAD_F_INFLATE) { struct rx_inflate_args args; args.cb = &thex_rx_inflate_cb; ctx->rx = rx_make_above(ctx->rx, rx_inflate_get_ops(), &args); } rx_set_data_ind(ctx->rx, thex_download_data_ind); rx_enable(ctx->rx); return TRUE; }