Attempting to fulfill remote requests

This commit is contained in:
jmjatlanta 2017-07-31 17:59:51 -05:00
parent fa7a6826b1
commit 836fb5387b
7 changed files with 101 additions and 38 deletions

View file

@ -30,7 +30,7 @@ int ipfs_bitswap_engine_free(struct BitswapEngine* engine) {
} }
/*** /***
* A separate thread that processes the queue * A separate thread that processes the queue of local requests
* @param context the context * @param context the context
*/ */
void* ipfs_bitswap_engine_wantlist_processor_start(void* ctx) { void* ipfs_bitswap_engine_wantlist_processor_start(void* ctx) {
@ -50,7 +50,7 @@ void* ipfs_bitswap_engine_wantlist_processor_start(void* ctx) {
} }
/*** /***
* A separate thread that processes the queue * A separate thread that processes the queue of remote requests
* @param context the context * @param context the context
*/ */
void* ipfs_bitswap_engine_peer_request_processor_start(void* ctx) { void* ipfs_bitswap_engine_peer_request_processor_start(void* ctx) {

View file

@ -682,6 +682,8 @@ int ipfs_bitswap_message_add_blocks(struct BitswapMessage* message, struct Libp2
if (message == NULL) if (message == NULL)
return 0; return 0;
if (blocks == NULL || blocks->total == 0)
return 0;
if (message->payload == NULL) { if (message->payload == NULL) {
message->payload = libp2p_utils_vector_new(blocks->total); message->payload = libp2p_utils_vector_new(blocks->total);
if (message->payload == NULL) if (message->payload == NULL)

View file

@ -43,6 +43,28 @@ int ipfs_bitswap_network_send_message(const struct BitswapContext* context, stru
return 1; return 1;
} }
/***
* Remove a cid from the queue
* @param cids the vector of cids
* @param cid the cid to remove
* @returns true(1) on success, false(0) otherwise
*/
int ipfs_bitswap_network_remove_cid_from_queue(struct Libp2pVector* collection, struct Cid* cid) {
if (collection == NULL || cid == NULL)
return 0;
for(int i = 0; i < collection->total; collection++) {
const struct Cid* current = (const struct Cid*)libp2p_utils_vector_get(collection, i);
if (ipfs_cid_compare(current, cid) == 0) {
libp2p_utils_vector_delete(collection, i);
return 1;
}
}
return 0;
}
/*** /***
* Handle a raw incoming bitswap message from the network * Handle a raw incoming bitswap message from the network
* @param node us * @param node us
@ -116,8 +138,10 @@ int ipfs_bitswap_network_handle_message(const struct IpfsNode* node, const struc
ipfs_cid_free(cid); ipfs_cid_free(cid);
return 0; return 0;
} }
// add the cid to their queue if (entry->cancel)
libp2p_utils_vector_add(queueEntry->current->cids, cid); ipfs_bitswap_network_remove_cid_from_queue(queueEntry->current->cids_they_want, cid);
else
libp2p_utils_vector_add(queueEntry->current->cids_they_want, cid);
} }
} }
return 1; return 1;

View file

@ -15,21 +15,32 @@
* @returns a new PeerRequest struct or NULL if there was a problem * @returns a new PeerRequest struct or NULL if there was a problem
*/ */
struct PeerRequest* ipfs_bitswap_peer_request_new() { struct PeerRequest* ipfs_bitswap_peer_request_new() {
int retVal = 0;
struct PeerRequest* request = (struct PeerRequest*) malloc(sizeof(struct PeerRequest)); struct PeerRequest* request = (struct PeerRequest*) malloc(sizeof(struct PeerRequest));
if (request != NULL) { if (request != NULL) {
request->cids = libp2p_utils_vector_new(1); request->cids_they_want = libp2p_utils_vector_new(1);
if (request->cids == NULL) { if (request->cids_they_want == NULL)
free(request); goto exit;
return NULL; request->cids_we_want = libp2p_utils_vector_new(1);
} if (request->cids_we_want == NULL)
request->blocks = libp2p_utils_vector_new(1); goto exit;
if (request->blocks == NULL) { request->blocks_we_want_to_send = libp2p_utils_vector_new(1);
libp2p_utils_vector_free(request->cids); if (request->blocks_we_want_to_send == NULL)
free(request); goto exit;
return NULL;
}
request->peer = NULL; request->peer = NULL;
} }
retVal = 1;
exit:
if (retVal == 0 && request != NULL) {
if (request->blocks_we_want_to_send != NULL)
libp2p_utils_vector_free(request->blocks_we_want_to_send);
if (request->cids_they_want != NULL)
libp2p_utils_vector_free(request->cids_they_want);
if (request->cids_we_want != NULL)
libp2p_utils_vector_free(request->cids_we_want);
free(request);
request = NULL;
}
return request; return request;
} }
@ -194,9 +205,14 @@ int ipfs_bitswap_peer_request_entry_free(struct PeerRequestEntry* entry) {
* @param block the block * @param block the block
* @returns true(1) on success, otherwise false(0) * @returns true(1) on success, otherwise false(0)
*/ */
int ipfs_bitswap_peer_request_queue_fill(struct PeerRequestQueue* queue, struct SessionContext* who, struct Block* block) { int ipfs_bitswap_peer_request_queue_fill(struct PeerRequestQueue* queue, struct Libp2pPeer* who, struct Block* block) {
// find the right entry // find the right entry
// add to the block array struct PeerRequest* entry = ipfs_peer_request_queue_find_peer(queue, who);
if (entry != NULL)
{
// add to the block array
libp2p_utils_vector_add(entry->blocks_we_want_to_send, block);
}
return 0; return 0;
} }
@ -207,9 +223,19 @@ int ipfs_bitswap_peer_request_queue_fill(struct PeerRequestQueue* queue, struct
* @returns true(1) on succes, otherwise false(0) * @returns true(1) on succes, otherwise false(0)
*/ */
int ipfs_bitswap_peer_request_process_entry(const struct BitswapContext* context, struct PeerRequest* request) { int ipfs_bitswap_peer_request_process_entry(const struct BitswapContext* context, struct PeerRequest* request) {
// determine if we have enough information to continue
if (request == NULL)
return 0;
if (request->peer == NULL)
return 0;
if (!request->peer->is_local) {
if (request->peer->connection_type != CONNECTION_TYPE_CONNECTED)
if (request->peer->addr_head == NULL || request->peer->addr_head->item == NULL)
return 0;
}
// determine if we're connected // determine if we're connected
int connected = request->peer == NULL || request->peer->connection_type == CONNECTION_TYPE_CONNECTED; int connected = request->peer->is_local || request->peer->connection_type == CONNECTION_TYPE_CONNECTED;
int need_to_connect = request->cids != NULL; int need_to_connect = request->cids_we_want->total != 0 || request->cids_they_want->total != 0 || request->blocks_we_want_to_send->total != 0;
// determine if we need to connect // determine if we need to connect
if (need_to_connect) { if (need_to_connect) {
@ -220,10 +246,10 @@ int ipfs_bitswap_peer_request_process_entry(const struct BitswapContext* context
if (connected) { if (connected) {
// build a message // build a message
struct BitswapMessage* msg = ipfs_bitswap_message_new(); struct BitswapMessage* msg = ipfs_bitswap_message_new();
// add requests // see if we can fulfill any of their requests. If so, fill in msg->payload
ipfs_bitswap_message_add_wantlist_items(msg, request->cids); ipfs_bitswap_message_add_blocks(msg, request->blocks_we_want_to_send);
// add blocks // add requests that we would like
ipfs_bitswap_message_add_blocks(msg, request->blocks); ipfs_bitswap_message_add_wantlist_items(msg, request->cids_we_want);
// send message // send message
if (ipfs_bitswap_network_send_message(context, request->peer, msg)) if (ipfs_bitswap_network_send_message(context, request->peer, msg))
return 1; return 1;

View file

@ -197,9 +197,9 @@ int ipfs_bitswap_wantlist_session_compare(const struct WantListSession* a, const
// it's local, there should be only 1 // it's local, there should be only 1
return 0; return 0;
} else { } else {
struct SessionContext* contextA = (struct SessionContext*)a->context; struct Libp2pPeer* contextA = (struct Libp2pPeer*)a->context;
struct SessionContext* contextB = (struct SessionContext*)b->context; struct Libp2pPeer* contextB = (struct Libp2pPeer*)b->context;
return libp2p_session_context_compare(contextA, contextB); return libp2p_peer_compare(contextA, contextB);
} }
} }
@ -250,11 +250,8 @@ int ipfs_bitswap_wantlist_get_block_remote(struct BitswapContext* context, struc
struct Libp2pPeer* current = (struct Libp2pPeer*) libp2p_utils_vector_get(providers, i); struct Libp2pPeer* current = (struct Libp2pPeer*) libp2p_utils_vector_get(providers, i);
// add this to their queue // add this to their queue
struct PeerRequest* queueEntry = ipfs_peer_request_queue_find_peer(context->peerRequestQueue, current); struct PeerRequest* queueEntry = ipfs_peer_request_queue_find_peer(context->peerRequestQueue, current);
libp2p_utils_vector_add(queueEntry->cids, cid); libp2p_utils_vector_add(queueEntry->cids_we_want, cid);
// process this queue // process this queue via bitswap protocol
// NOTE: We need to ask the remotes via bitswap, and wait for a response before returning
// there will need to be some fancy stuff to know when we get it back so that this method
// can return with the block
ipfs_bitswap_peer_request_process_entry(context, queueEntry); ipfs_bitswap_peer_request_process_entry(context, queueEntry);
} }
return 1; return 1;
@ -263,7 +260,10 @@ int ipfs_bitswap_wantlist_get_block_remote(struct BitswapContext* context, struc
} }
/** /**
* Called by the Bitswap engine, this processes an item on the WantListQueue * Called by the Bitswap engine, this processes an item on the WantListQueue. This is called when
* we want a file locally from a remote source. Send a message immediately, adding in stuff that
* perhaps the remote source wanted.
*
* @param context the context * @param context the context
* @param entry the WantListQueueEntry * @param entry the WantListQueueEntry
* @returns true(1) on success, false(0) if not. * @returns true(1) on success, false(0) if not.
@ -293,8 +293,8 @@ int ipfs_bitswap_wantlist_process_entry(struct BitswapContext* context, struct W
if (session->type == WANTLIST_SESSION_TYPE_LOCAL) { if (session->type == WANTLIST_SESSION_TYPE_LOCAL) {
context->ipfsNode->exchange->HasBlock(context->ipfsNode->exchange, entry->block); context->ipfsNode->exchange->HasBlock(context->ipfsNode->exchange, entry->block);
} else { } else {
struct SessionContext* sessionContext = (struct SessionContext*) session->context; struct Libp2pPeer* peer = (struct Libp2pPeer*) session->context;
ipfs_bitswap_peer_request_queue_fill(context->peerRequestQueue, sessionContext, entry->block); ipfs_bitswap_peer_request_queue_fill(context->peerRequestQueue, peer, entry->block);
} }
} }

View file

@ -9,11 +9,22 @@
#include "ipfs/exchange/bitswap/bitswap.h" #include "ipfs/exchange/bitswap/bitswap.h"
#include "ipfs/blocks/block.h" #include "ipfs/blocks/block.h"
struct CidEntry {
struct Cid* cid;
int cancel;
};
struct PeerRequest { struct PeerRequest {
pthread_mutex_t request_mutex; pthread_mutex_t request_mutex;
struct Libp2pPeer* peer; struct Libp2pPeer* peer;
struct Libp2pVector* cids; // Cid collection of cids that they want. Note cancellations are removed immediately
struct Libp2pVector* blocks; struct Libp2pVector* cids_they_want;
// CidEntry collection of cids that we want or are canceling
struct Libp2pVector* cids_we_want;
// blocks to send to them
struct Libp2pVector* blocks_we_want_to_send;
// blocks they sent us are processed immediately, so no queue necessary
// although the cid can go in cids_we_want again, with a cancel flag
}; };
struct PeerRequestEntry { struct PeerRequestEntry {
@ -92,7 +103,7 @@ struct PeerRequestEntry* ipfs_bitswap_peer_request_queue_find_entry(struct PeerR
* @param block the block * @param block the block
* @returns true(1) on success, otherwise false(0) * @returns true(1) on success, otherwise false(0)
*/ */
int ipfs_bitswap_peer_request_queue_fill(struct PeerRequestQueue* queue, struct SessionContext* who, struct Block* block); int ipfs_bitswap_peer_request_queue_fill(struct PeerRequestQueue* queue, struct Libp2pPeer* who, struct Block* block);
/*** /***
* Allocate resources for a PeerRequestEntry struct * Allocate resources for a PeerRequestEntry struct

View file

@ -14,7 +14,7 @@ enum WantListSessionType { WANTLIST_SESSION_TYPE_LOCAL, WANTLIST_SESSION_TYPE_RE
struct WantListSession { struct WantListSession {
enum WantListSessionType type; enum WantListSessionType type;
void* context; // either an IpfsNode (local) or a SessionContext (remote) void* context; // either an IpfsNode (local) or a Libp2pPeer (remote)
}; };
struct WantListQueueEntry { struct WantListQueueEntry {