Statistics
| Branch: | Revision:

grapes / som / ChunkTrading / chunk_signaling.c @ 4a0208c3

History | View | Annotate | Download (9.04 KB)

1
/*
2
 *  Copyright (c) 2009 Alessandro Russo.
3
 *
4
 *  This is free software;
5
 *  see lgpl-2.1.txt
6
 *
7
 * Chunk Signaling API - Higher Abstraction
8
 *
9
 * The Chunk Signaling HA provides a set of primitives for chunks signaling negotiation with other peers, in order to collect information for the effective chunk exchange with other peers. <br>
10
 * This is a part of the Data Exchange Protocol which provides high level abstraction for chunks' negotiations, like requesting and proposing chunks.
11
 *
12
 */
13

    
14
#include <stdio.h>
15
#include <stdint.h>
16
#include <string.h>
17
#include <stdlib.h>
18
#include <arpa/inet.h>
19

    
20
#include "chunk.h"
21
#include "msg_types.h"
22
#include "chunkidset.h"
23
#include "trade_sig_la.h"
24
#include "trade_sig_ha.h"
25

    
26
//Type of signaling message
27
//Request a ChunkIDSet
28
#define MSG_SIG_REQ 1
29
//Diliver a ChunkIDSet (reply to a request)
30
#define MSG_SIG_DEL 2
31
//Offer a ChunkIDSet
32
#define MSG_SIG_OFF 4
33
//Accept a ChunkIDSet (reply to an offer)
34
#define MSG_SIG_ACC 6
35
//Receive the BufferMap
36
#define MSG_SIG_BMOFF 10
37
//Request the BufferMap
38
#define MSG_SIG_BMREQ 12
39

    
40
struct sig_nal {
41
    uint8_t type;//type of signal.
42
    uint8_t max_deliver;//Max number of chunks to deliver.
43
    //uint16_t cb_size;//size of the buffer map to send
44
    uint16_t trans_id;//future use...
45
    uint8_t third_peer;//for buffer map exchange from other peers, just the first byte!
46
} __attribute__((packed));
47

    
48
//set the local node ID
49
static struct nodeID *localID;
50

    
51

    
52
static inline void int_cpy(uint8_t *p, int v)
53
{
54
  int tmp;
55

    
56
  tmp = htonl(v);
57
  memcpy(p, &tmp, 4);
58
}
59

    
60
static inline int int_rcpy(const uint8_t *p)
61
{
62
  int tmp;
63

    
64
  memcpy(&tmp, p, 4);
65
  tmp = ntohl(tmp);
66

    
67
  return tmp;
68
}
69

    
70
/**
71
 * @brief Set current node identifier.
72
 *
73
 * Initialize the node identifier of the peer
74
 *
75
 * @param[in] current node indentifier.
76
 * @return 1 on success, <0 on error.
77
 */
78
int chunkSignalingInit(struct nodeID *myID) {
79
    if(!myID)
80
        return -1;
81
    localID = myID;
82
    return 1;
83
}
84

    
85
/**
86
 * @brief Parse an incoming signaling message, providing the signal type and the information of the signaling message.
87
 *
88
 * Parse an incoming signaling message provided in the buffer, giving the information of the message received.
89
 *
90
 * @param[in] buffer containing the incoming message.
91
 * @param[in] buff_len length of the buffer.
92
 * @param[out] owner_id identifier of the node on which refer the message just received.
93
 * @param[out] cset array of chunkIDs.
94
 * @param[out] max_deliver deliver at most this number of Chunks.
95
 * @param[out] trans_id transaction number associated with this message.
96
 * @param[out] sig_type Type of signaling message.
97
 * @return 1 on success, <0 on error.
98
 */
99
int parseSignaling(uint8_t *buff, int buff_len, struct nodeID **owner_id, struct chunkID_set **cset,
100
        int *max_deliver, int *trans_id, int *sig_type) {
101
    struct sig_nal *signal;
102
    int ret, third_peer, meta_len;
103
    void *meta;
104

    
105
    third_peer = meta_len = 0;
106
    *cset = decodeChunkSignaling(&meta, &meta_len, buff, buff_len);
107
    if (meta_len) {
108
        signal = (struct sig_nal *) meta;
109
        switch (signal->type) {
110
            case MSG_SIG_OFF:
111
                *sig_type = sig_offer;
112
                break;
113
            case MSG_SIG_ACC:
114
                *sig_type = sig_accept;
115
                break;
116
            case MSG_SIG_REQ:
117
                *sig_type = sig_request;
118
                break;
119
            case MSG_SIG_DEL:
120
                *sig_type = sig_deliver;
121
                break;
122
            case MSG_SIG_BMOFF:
123
                *sig_type = sig_send_buffermap;
124
                break;
125
            case MSG_SIG_BMREQ:
126
                *sig_type = sig_request_buffermap;
127
                break;
128
            default:
129
                fprintf(stderr, "Error invalid signaling message\n");                
130
                return -1;
131
        }
132
        *max_deliver = signal->max_deliver;
133
        *trans_id = signal->trans_id;
134
        *owner_id = (signal->third_peer ? nodeid_undump(&(signal->third_peer), &third_peer) : NULL);
135
        free(meta);
136
    }
137
    ret = (!*cset || !meta_len) ? -1 : 1;
138
    if (ret < 0) {
139
        fprintf(stderr, "Error parsing invalid signaling message\n");
140
    }
141
    return ret;
142
}
143

    
144

    
145
static int sendSignaling(int type, struct nodeID *to_id, const struct nodeID *owner_id, const struct chunkID_set *cset, int max_deliver, int trans_id)
146
{
147
    int buff_len, meta_len, msg_len, ret;
148
    uint8_t *buff;
149
    struct sig_nal *sigmex;
150
    uint8_t *meta;
151
    ret = 1;
152
    meta = malloc(1024);
153
    if (!meta) {
154
        fprintf(stderr, "Error allocating meta-buffer\n");
155
        return -1;
156
    }
157
    sigmex = (struct sig_nal*) meta;
158
    sigmex->type = type;
159
    sigmex->max_deliver = max_deliver;    
160
    sigmex->trans_id = trans_id;
161
    sigmex->third_peer = 0;
162
    meta_len = sizeof(*sigmex) - 1;
163
    if (owner_id) {
164
        meta_len += nodeid_dump(&sigmex->third_peer, owner_id);
165
    }
166
    buff_len = 1 + (cset ? chunkID_set_size(cset):0) * 4 + 12 + meta_len; // this should be enough
167
    buff = malloc(buff_len);
168
    if (!buff) {
169
        fprintf(stderr, "Error allocating buffer\n");
170
        free(meta);
171
        return -1;
172
    }
173

    
174
    buff[0] = MSG_TYPE_SIGNALLING;
175
    msg_len = 1 + encodeChunkSignaling(cset, meta, meta_len, buff+1, buff_len-1);
176
    free(meta);
177
    if (msg_len <= 0) {
178
      fprintf(stderr, "Error in encoding chunk set for sending a buffermap\n");
179
      ret = -1;
180
    } else {
181
      send_to_peer(localID, to_id, buff, msg_len);
182
    }    
183
    free(buff);
184
    return ret;
185
}
186

    
187
/**
188
 * @brief Request a set of chunks from a Peer.
189
 *
190
 * Request a set of Chunks towards a Peer, and specify the  maximum number of Chunks attempted to receive
191
 * (i.e., the number of chunks the destination peer would like to receive among those requested).
192
 *
193
 * @param[in] to target peer to request the ChunkIDs from.
194
 * @param[in] cset array of ChunkIDs.
195
 * @param[in] max_deliver deliver at most this number of Chunks.
196
 * @param[in] trans_id transaction number associated with this request.
197
 * @return 1 on success, <0 on error.
198
 */
199
int requestChunks(struct nodeID *to, const ChunkIDSet *cset, int max_deliver, int trans_id) {
200
    return sendSignaling(MSG_SIG_REQ, to, NULL, cset, max_deliver, trans_id);
201
}
202

    
203

    
204
/**
205
 * @brief Deliver a set of Chunks to a Peer as a reply of its previous request of Chunks.
206
 *
207
 * Announce to the Peer which sent a request of a set of Chunks, that we have these chunks (sub)set available
208
 * among all those requested and willing to deliver them.
209
 *
210
 * @param[in] to target peer to which deliver the ChunkIDs.
211
 * @param[in] cset array of ChunkIDs.
212
 * @param[in] trans_id transaction number associated with this request.
213
 * @return 1 on success, <0 on error.
214
 */
215
int deliverChunks(struct nodeID *to, ChunkIDSet *cset, int trans_id) {
216
    return sendSignaling(MSG_SIG_DEL, to, NULL, cset, 0, trans_id);
217
}
218

    
219
/**
220
 * @brief Offer a (sub)set of chunks to a Peer.
221
 *
222
 * Initiate a offer for a set of Chunks towards a Peer, and specify the  maximum number of Chunks attempted to deliver
223
 * (attempted to deliver: i.e., the sender peer should try to send at most this number of Chunks from the set).
224
 *
225
 * @param[in] to target peer to offer the ChunkIDs.
226
 * @param[in] cset array of ChunkIDs.
227
 * @param[in] max_deliver deliver at most this number of Chunks.
228
 * @param[in] trans_id transaction number associated with this request.
229
 * @return 1 on success, <0 on error.
230
 */
231
int offerChunks(struct nodeID *to, struct chunkID_set *cset, int max_deliver, int trans_id){
232
  return sendSignaling(MSG_SIG_OFF, to, NULL, cset, max_deliver, trans_id);
233
}
234

    
235
/**
236
 * @brief Accept a (sub)set of chunks from a Peer.
237
 *
238
 * Announce to accept a (sub)set of Chunks from a Peer which sent a offer before, and specify the  maximum number of Chunks attempted to receive
239
 * (attempted to receive: i.e., the receiver peer would like to receive at most this number of Chunks from the set offered before).
240
 *
241
 * @param[in] to target peer to accept the ChunkIDs.
242
 * @param[in] cset array of ChunkIDs. 
243
 * @param[in] trans_id transaction number associated with this request.
244
 * @return 1 on success, <0 on error.
245
 */
246
int acceptChunks(struct nodeID *to, struct chunkID_set *cset, int trans_id) {
247
  return sendSignaling(MSG_SIG_ACC, to, NULL, cset, 0, trans_id);
248
}
249

    
250
/**
251
 * @brief Send a BufferMap to a Peer.
252
 *
253
 * Send (our own or some other peer's) BufferMap to a third Peer.
254
 *
255
 * @param[in] to PeerID.
256
 * @param[in] owner Owner of the BufferMap to send.
257
 * @param[in] bmap the BufferMap to send.
258
 * @param[in] trans_id transaction number associated with this send.
259
 * @return 1 Success, <0 on error.
260
 */
261

    
262
int sendBufferMap(struct nodeID *to, const struct nodeID *owner, struct chunkID_set *bmap, int trans_id) {
263
  return sendSignaling(MSG_SIG_BMOFF, to, (!owner?localID:owner), bmap, 0, trans_id);
264
}
265

    
266
/**
267
 * @brief Request a BufferMap to a Peer.
268
 *
269
 * Request (target peer or some other peer's) BufferMap to target Peer.
270
 *
271
 * @param[in] to PeerID.
272
 * @param[in] owner Owner of the BufferMap to request.
273
 * @param[in] trans_id transaction number associated with this request.
274
 * @return 1 Success, <0 on error.
275
 */
276

    
277
int requestBufferMap(struct nodeID *to, const struct nodeID *owner, int trans_id) {
278
    return sendSignaling(MSG_SIG_BMREQ, to, (!owner?localID:owner), NULL, 0, trans_id);
279
}