2017-07-24 14:09:22 +00:00
|
|
|
/***
|
|
|
|
* A queue for requests from remote peers
|
|
|
|
* NOTE: This should handle multiple threads
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
2017-07-27 13:38:57 +00:00
|
|
|
#include "libp2p/conn/session.h"
|
2017-07-24 14:09:22 +00:00
|
|
|
#include "ipfs/cid/cid.h"
|
|
|
|
#include "ipfs/exchange/bitswap/peer_request_queue.h"
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Allocate resources for a new PeerRequest
|
|
|
|
* @returns a new PeerRequest struct or NULL if there was a problem
|
|
|
|
*/
|
|
|
|
struct PeerRequest* ipfs_bitswap_peer_request_new() {
|
|
|
|
struct PeerRequest* request = (struct PeerRequest*) malloc(sizeof(struct PeerRequest));
|
|
|
|
if (request != NULL) {
|
2017-07-27 13:38:57 +00:00
|
|
|
request->cids = NULL;
|
|
|
|
request->blocks = NULL;
|
|
|
|
request->context = NULL;
|
2017-07-24 14:09:22 +00:00
|
|
|
}
|
|
|
|
return request;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Free resources from a PeerRequest
|
|
|
|
* @param request the request to free
|
|
|
|
* @returns true(1)
|
|
|
|
*/
|
|
|
|
int ipfs_bitswap_peer_request_free(struct PeerRequest* request) {
|
|
|
|
free(request);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Allocate resources for a new queue
|
|
|
|
*/
|
|
|
|
struct PeerRequestQueue* ipfs_bitswap_peer_request_queue_new() {
|
|
|
|
struct PeerRequestQueue* queue = malloc(sizeof(struct PeerRequestQueue));
|
2017-07-24 15:26:07 +00:00
|
|
|
if (queue != NULL) {
|
|
|
|
pthread_mutex_init(&queue->queue_mutex, NULL);
|
|
|
|
queue->first = NULL;
|
|
|
|
queue->last = NULL;
|
|
|
|
}
|
2017-07-24 14:09:22 +00:00
|
|
|
return queue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Free all resources related to the queue
|
|
|
|
* @param queue the queue
|
|
|
|
* @returns true(1)
|
|
|
|
*/
|
|
|
|
int ipfs_bitswap_peer_request_queue_free(struct PeerRequestQueue* queue) {
|
|
|
|
pthread_mutex_lock(&queue->queue_mutex);
|
|
|
|
struct PeerRequestEntry* current = queue->last;
|
|
|
|
while (current != NULL) {
|
2017-07-24 15:26:07 +00:00
|
|
|
struct PeerRequestEntry* prior = current->prior;
|
2017-07-24 14:09:22 +00:00
|
|
|
ipfs_bitswap_peer_request_entry_free(current);
|
2017-07-24 15:26:07 +00:00
|
|
|
current = prior;
|
2017-07-24 14:09:22 +00:00
|
|
|
}
|
|
|
|
pthread_mutex_unlock(&queue->queue_mutex);
|
2017-07-24 15:26:07 +00:00
|
|
|
free(queue);
|
2017-07-24 14:09:22 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds a peer request to the end of the queue
|
|
|
|
* @param queue the queue
|
|
|
|
* @param request the request
|
|
|
|
* @returns true(1) on success, otherwise false
|
|
|
|
*/
|
|
|
|
int ipfs_bitswap_peer_request_queue_add(struct PeerRequestQueue* queue, struct PeerRequest* request) {
|
|
|
|
if (request != NULL) {
|
|
|
|
struct PeerRequestEntry* entry = ipfs_bitswap_peer_request_entry_new();
|
|
|
|
entry->current = request;
|
|
|
|
pthread_mutex_lock(&queue->queue_mutex);
|
|
|
|
entry->prior = queue->last;
|
|
|
|
queue->last = entry;
|
2017-07-24 15:26:07 +00:00
|
|
|
if (queue->first == NULL) {
|
|
|
|
queue->first = entry;
|
|
|
|
}
|
2017-07-24 14:09:22 +00:00
|
|
|
pthread_mutex_unlock(&queue->queue_mutex);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Removes a peer request from the queue, no mather where it is
|
|
|
|
* @param queue the queue
|
|
|
|
* @param request the request
|
|
|
|
* @returns true(1) on success, otherwise false(0)
|
|
|
|
*/
|
|
|
|
int ipfs_bitswap_peer_request_queue_remove(struct PeerRequestQueue* queue, struct PeerRequest* request) {
|
|
|
|
if (request != NULL) {
|
|
|
|
struct PeerRequestEntry* entry = ipfs_bitswap_peer_request_queue_find_entry(queue, request);
|
|
|
|
if (entry != NULL) {
|
|
|
|
pthread_mutex_lock(&queue->queue_mutex);
|
|
|
|
// remove the entry's link, and hook prior and next together
|
|
|
|
entry->prior->next = entry->next;
|
|
|
|
entry->prior = NULL;
|
|
|
|
entry->next = NULL;
|
|
|
|
ipfs_bitswap_peer_request_entry_free(entry);
|
|
|
|
pthread_mutex_unlock(&queue->queue_mutex);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Finds a PeerRequestEntry that contains the specified PeerRequest
|
|
|
|
* @param queue the queue to look through
|
|
|
|
* @param request what we're looking for
|
|
|
|
* @returns the PeerRequestEntry or NULL if not found
|
|
|
|
*/
|
|
|
|
struct PeerRequestEntry* ipfs_bitswap_peer_request_queue_find_entry(struct PeerRequestQueue* queue, struct PeerRequest* request) {
|
|
|
|
if (request != NULL) {
|
|
|
|
struct PeerRequestEntry* current = queue->first;
|
|
|
|
while (current != NULL) {
|
2017-07-27 13:38:57 +00:00
|
|
|
if (libp2p_session_context_compare(current->current->context, request->context) == 0)
|
2017-07-24 14:09:22 +00:00
|
|
|
return current;
|
2017-07-27 13:38:57 +00:00
|
|
|
current = current->next;
|
2017-07-24 14:09:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Pull a PeerRequest off the queue
|
|
|
|
* @param queue the queue
|
|
|
|
* @returns the PeerRequest that should be handled next, or NULL if the queue is empty
|
|
|
|
*/
|
|
|
|
struct PeerRequest* ipfs_bitswap_peer_request_pop(struct PeerRequestQueue* queue) {
|
|
|
|
struct PeerRequest* retVal = NULL;
|
|
|
|
if (queue != NULL) {
|
|
|
|
pthread_mutex_lock(&queue->queue_mutex);
|
|
|
|
struct PeerRequestEntry* entry = queue->first;
|
|
|
|
retVal = entry->current;
|
|
|
|
queue->first = queue->first->next;
|
|
|
|
pthread_mutex_unlock(&queue->queue_mutex);
|
|
|
|
ipfs_bitswap_peer_request_entry_free(entry);
|
|
|
|
}
|
|
|
|
return retVal;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***
|
|
|
|
* Allocate resources for a PeerRequestEntry struct
|
|
|
|
* @returns the allocated struct or NULL if there was a problem
|
|
|
|
*/
|
|
|
|
struct PeerRequestEntry* ipfs_bitswap_peer_request_entry_new() {
|
|
|
|
struct PeerRequestEntry* entry = (struct PeerRequestEntry*) malloc(sizeof(struct PeerRequestEntry));
|
|
|
|
if (entry != NULL) {
|
|
|
|
entry->current = NULL;
|
|
|
|
entry->next = NULL;
|
|
|
|
entry->prior = NULL;
|
|
|
|
}
|
|
|
|
return entry;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Frees resources allocated
|
|
|
|
* @param entry the PeerRequestEntry to free
|
|
|
|
* @returns true(1)
|
|
|
|
*/
|
|
|
|
int ipfs_bitswap_peer_request_entry_free(struct PeerRequestEntry* entry) {
|
|
|
|
entry->next = NULL;
|
|
|
|
entry->prior = NULL;
|
2017-07-24 15:26:07 +00:00
|
|
|
ipfs_bitswap_peer_request_free(entry->current);
|
2017-07-24 14:09:22 +00:00
|
|
|
entry->current = NULL;
|
|
|
|
free(entry);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-07-27 13:38:57 +00:00
|
|
|
/***
|
|
|
|
* Add a block to the appropriate peer's queue
|
|
|
|
* @param queue the queue
|
|
|
|
* @param who the session context that identifies the peer
|
|
|
|
* @param block the block
|
|
|
|
* @returns true(1) on success, otherwise false(0)
|
|
|
|
*/
|
|
|
|
int ipfs_bitswap_peer_request_queue_fill(struct PeerRequestQueue* queue, struct SessionContext* who, struct Block* block) {
|
|
|
|
// find the right entry
|
|
|
|
// add to the block array
|
|
|
|
return 0;
|
|
|
|
}
|