Statistics
| Branch: | Revision:

grapes / som / ChunkTrading / chunk_signaling.c @ 8268c97a

History | View | Annotate | Download (5.73 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
int chunkSignalingInit(struct nodeID *myID)
71
{
72
    if(!myID)
73
        return -1;
74
    localID = myID;
75
    return 1;
76
}
77

    
78
int parseSignaling(uint8_t *buff, int buff_len, struct nodeID **owner_id,
79
                   struct chunkID_set **cset, int *max_deliver, int *trans_id,
80
                   enum signaling_type *sig_type)
81
{
82
    struct sig_nal *signal;
83
    int ret, third_peer, meta_len;
84
    void *meta;
85

    
86
    third_peer = meta_len = 0;
87
    *cset = decodeChunkSignaling(&meta, &meta_len, buff, buff_len);
88
    if (meta_len) {
89
        signal = (struct sig_nal *) meta;
90
        switch (signal->type) {
91
            case MSG_SIG_OFF:
92
                *sig_type = sig_offer;
93
                break;
94
            case MSG_SIG_ACC:
95
                *sig_type = sig_accept;
96
                break;
97
            case MSG_SIG_REQ:
98
                *sig_type = sig_request;
99
                break;
100
            case MSG_SIG_DEL:
101
                *sig_type = sig_deliver;
102
                break;
103
            case MSG_SIG_BMOFF:
104
                *sig_type = sig_send_buffermap;
105
                break;
106
            case MSG_SIG_BMREQ:
107
                *sig_type = sig_request_buffermap;
108
                break;
109
            default:
110
                fprintf(stderr, "Error invalid signaling message\n");                
111
                return -1;
112
        }
113
        *max_deliver = signal->max_deliver;
114
        *trans_id = signal->trans_id;
115
        *owner_id = (signal->third_peer ? nodeid_undump(&(signal->third_peer), &third_peer) : NULL);
116
        free(meta);
117
    }
118
    ret = (!*cset || !meta_len) ? -1 : 1;
119
    if (ret < 0) {
120
        fprintf(stderr, "Error parsing invalid signaling message\n");
121
    }
122
    return ret;
123
}
124

    
125
static int sendSignaling(int type, struct nodeID *to_id,
126
                         const struct nodeID *owner_id,
127
                         const struct chunkID_set *cset, int max_deliver,
128
                         int trans_id)
129
{
130
    int buff_len, meta_len, msg_len, ret;
131
    uint8_t *buff;
132
    struct sig_nal *sigmex;
133
    uint8_t *meta;
134
    ret = 1;
135
    meta = malloc(1024);
136
    if (!meta) {
137
        fprintf(stderr, "Error allocating meta-buffer\n");
138
        return -1;
139
    }
140
    sigmex = (struct sig_nal*) meta;
141
    sigmex->type = type;
142
    sigmex->max_deliver = max_deliver;    
143
    sigmex->trans_id = trans_id;
144
    sigmex->third_peer = 0;
145
    meta_len = sizeof(*sigmex) - 1;
146
    if (owner_id) {
147
        meta_len += nodeid_dump(&sigmex->third_peer, owner_id);
148
    }
149
    buff_len = 1 + (cset ? chunkID_set_size(cset):0) * 4 + 12 + meta_len; // this should be enough
150
    buff = malloc(buff_len);
151
    if (!buff) {
152
        fprintf(stderr, "Error allocating buffer\n");
153
        free(meta);
154
        return -1;
155
    }
156

    
157
    buff[0] = MSG_TYPE_SIGNALLING;
158
    msg_len = 1 + encodeChunkSignaling(cset, meta, meta_len, buff+1, buff_len-1);
159
    free(meta);
160
    if (msg_len <= 0) {
161
      fprintf(stderr, "Error in encoding chunk set for sending a buffermap\n");
162
      ret = -1;
163
    } else {
164
      send_to_peer(localID, to_id, buff, msg_len);
165
    }    
166
    free(buff);
167
    return ret;
168
}
169

    
170
int requestChunks(struct nodeID *to, const ChunkIDSet *cset,
171
                  int max_deliver, int trans_id)
172
{
173
    return sendSignaling(MSG_SIG_REQ, to, NULL, cset, max_deliver, trans_id);
174
}
175

    
176
int deliverChunks(struct nodeID *to, ChunkIDSet *cset, int trans_id)
177
{
178
    return sendSignaling(MSG_SIG_DEL, to, NULL, cset, 0, trans_id);
179
}
180

    
181
int offerChunks(struct nodeID *to, struct chunkID_set *cset,
182
                int max_deliver, int trans_id)
183
{
184
    return sendSignaling(MSG_SIG_OFF, to, NULL, cset, max_deliver, trans_id);
185
}
186

    
187
int acceptChunks(struct nodeID *to, struct chunkID_set *cset, int trans_id)
188
{
189
    return sendSignaling(MSG_SIG_ACC, to, NULL, cset, 0, trans_id);
190
}
191

    
192
int sendBufferMap(struct nodeID *to, const struct nodeID *owner,
193
                  struct chunkID_set *bmap, int trans_id)
194
{
195
    return sendSignaling(MSG_SIG_BMOFF, to, (!owner ? localID : owner), bmap,
196
                         0, trans_id);
197
}
198

    
199
int requestBufferMap(struct nodeID *to, const struct nodeID *owner,
200
                     int trans_id)
201
{
202
    return sendSignaling(MSG_SIG_BMREQ, to, (!owner?localID:owner), NULL,
203
                         0, trans_id);
204
}