Contiki 2.5
agent.c
Go to the documentation of this file.
1 /**
2  * \addtogroup bprocess
3  * @{
4  */
5 
6 /**
7  * \file
8  * \author Georg von Zengen <vonzeng@ibr.cs.tu-bs.de>
9  * \author Daniel Willmann <daniel@totalueberwachung.de>
10  * \author Wolf-Bastian Poettner <poettner@ibr.cs.tu-bs.de>
11  */
12 
13 #include <stdlib.h>
14 #include <string.h>
15 
16 #include "clock.h"
17 #include "timer.h"
18 #include "net/netstack.h"
19 #include "net/rime/rimeaddr.h"
20 #include "mmem.h"
21 #include "lib/memb.h"
22 #include "logging.h"
23 #include "node-id.h"
24 
25 #include "api.h"
26 #include "registration.h"
27 #include "bundle.h"
28 #include "storage.h"
29 #include "sdnv.h"
30 #include "redundancy.h"
31 #include "dispatching.h"
32 #include "routing.h"
33 #include "dtn_network.h"
34 #include "custody.h"
35 #include "discovery.h"
36 #include "statistics.h"
37 #include "convergence_layer.h"
38 #include "hash.h"
39 
40 #include "agent.h"
41 
42 uint32_t dtn_node_id;
43 uint32_t dtn_seq_nr;
44 PROCESS(agent_process, "AGENT process");
45 AUTOSTART_PROCESSES(&agent_process);
46 
47 void agent_init(void) {
48  // if the agent process is already running, to nothing
49  if( process_is_running(&agent_process) ) {
50  return;
51  }
52 
53  // Otherwise start the agent process
54  process_start(&agent_process, NULL);
55 }
56 
57 /* Bundle Protocol Prozess */
58 PROCESS_THREAD(agent_process, ev, data)
59 {
60  uint32_t * bundle_number_ptr = NULL;
61  struct registration_api * reg;
62 
63  PROCESS_BEGIN();
64 
65  /* We obtain our dtn_node_id from the RIME address of the node */
67  dtn_seq_nr = 0;
68 
69  /* We are initialized quite early - give Contiki some time to do its stuff */
70  process_poll(&agent_process);
71  PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
72 
73  mmem_init();
74  convergence_layer_init();
75  BUNDLE_STORAGE.init();
76  REDUNDANCE.init();
77  CUSTODY.init();
78  ROUTING.init();
79  DISCOVERY.init();
81 
85  dtn_receive_bundle_event = process_alloc_event();
88  dtn_beacon_event = process_alloc_event();
89  dtn_send_admin_record_event = process_alloc_event();
90  dtn_bundle_in_storage_event = process_alloc_event();
91  dtn_send_bundle_to_node_event = process_alloc_event();
94 
95  // We use printf here, to make this message visible in every case!
96  printf("Starting DTN Bundle Protocol Agent with EID ipn:%lu\n", dtn_node_id);
97 
98  while(1) {
100 
102  reg = (struct registration_api *) data;
103 
104  registration_new_application(reg->app_id, reg->application_process, reg->node_id);
105  LOG(LOGD_DTN, LOG_AGENT, LOGL_INF, "New Service registration for endpoint %lu", reg->app_id);
106  continue;
107  }
108 
109  if(ev == dtn_application_status_event) {
110  int status;
111  reg = (struct registration_api *) data;
112  LOG(LOGD_DTN, LOG_AGENT, LOGL_DBG, "Service switching status to %i", reg->status);
113  if(reg->status == APP_ACTIVE)
114  status = registration_set_active(reg->app_id, reg->node_id);
115  else if(reg->status == APP_PASSIVE)
116  status = registration_set_passive(reg->app_id, reg->node_id);
117 
118  if(status == -1) {
119  LOG(LOGD_DTN, LOG_AGENT, LOGL_ERR, "no registration found to switch");
120  }
121 
122  continue;
123  }
124 
125  if(ev == dtn_application_remove_event) {
126  reg = (struct registration_api *) data;
127  LOG(LOGD_DTN, LOG_AGENT, LOGL_DBG, "Unregistering service for endpoint %lu", reg->app_id);
128  registration_remove_application(reg->app_id, reg->node_id);
129  continue;
130  }
131 
132  if(ev == dtn_send_bundle_event) {
133  uint8_t n = 0;
134  struct bundle_t * bundle = NULL;
135  struct process * source_process = NULL;
136  struct mmem * bundleptr;
137  uint32_t bundle_flags = 0;
138 
139  bundleptr = (struct mmem *) data;
140  if( bundleptr == NULL ) {
141  LOG(LOGD_DTN, LOG_AGENT, LOGL_ERR, "dtn_send_bundle_event with invalid pointer");
142  process_post(source_process, dtn_bundle_store_failed, NULL);
143  continue;
144  }
145 
146  bundle = (struct bundle_t *) MMEM_PTR(bundleptr);
147  if( bundle == NULL ) {
148  LOG(LOGD_DTN, LOG_AGENT, LOGL_ERR, "dtn_send_bundle_event with invalid MMEM structure");
149  process_post(source_process, dtn_bundle_store_failed, NULL);
150  continue;
151  }
152 
153  /* Go and find the process from which the bundle has been sent */
154  uint32_t app_id = registration_get_application_id(bundle->source_process);
155  if( app_id == 0xFFFF && bundle->source_process != &agent_process) {
156  LOG(LOGD_DTN, LOG_AGENT, LOGL_ERR, "Unregistered process %s tries to send a bundle", PROCESS_NAME_STRING(bundle->source_process));
157  process_post(source_process, dtn_bundle_store_failed, NULL);
158  bundle_decrement(bundleptr);
159  continue;
160  }
161 
162  /* Find out, if the source process has set an app id */
163  uint32_t service_app_id;
164  bundle_get_attr(bundleptr, SRC_SERV, &service_app_id);
165 
166  /* If the service did not set an app id, do it now */
167  if( service_app_id == 0 ) {
168  bundle_set_attr(bundleptr, SRC_SERV, &app_id);
169  }
170 
171  /* Set the source node */
172  bundle_set_attr(bundleptr, SRC_NODE, &dtn_node_id);
173 
174  /* Check for report-to and set node and service accordingly */
175  bundle_get_attr(bundleptr, FLAGS, &bundle_flags);
176  if( bundle_flags & BUNDLE_FLAG_REPORT ) {
177  uint32_t report_to_node = 0;
178  bundle_get_attr(bundleptr, REP_NODE, &report_to_node);
179 
180  if( report_to_node == 0 ) {
181  bundle_set_attr(bundleptr, REP_NODE, &dtn_node_id);
182  }
183 
184  uint32_t report_to_service = 0;
185  bundle_get_attr(bundleptr, REP_SERV, &report_to_service);
186 
187  if( report_to_service ) {
188  bundle_set_attr(bundleptr, REP_SERV, &app_id);
189  }
190  }
191 
192  LOG(LOGD_DTN, LOG_AGENT, LOGL_DBG, "dtn_send_bundle_event(%p) with seqNo %lu", bundleptr, dtn_seq_nr);
193 
194  // Set the outgoing sequence number
195  bundle_set_attr(bundleptr, TIME_STAMP_SEQ_NR, &dtn_seq_nr);
196  dtn_seq_nr++;
197 
198  // Copy the sending process, because 'bundle' will not be accessible anymore afterwards
199  source_process = bundle->source_process;
200 
201  // Calculate the bundle number
202  bundle->bundle_num = HASH.hash_convenience(bundle->tstamp_seq, bundle->tstamp, bundle->src_node, bundle->frag_offs, bundle->app_len);
203 
204  // Save the bundle in storage
205  n = BUNDLE_STORAGE.save_bundle(bundleptr, &bundle_number_ptr);
206 
207  /* Saving the bundle failed... */
208  if( !n ) {
209  /* Decrement the sequence number */
210  dtn_seq_nr--;
211  }
212 
213  // Reset our pointers to avoid using invalid ones
214  bundle = NULL;
215  bundleptr = NULL;
216 
217  // Notify the sender process
218  if( n ) {
219  /* Bundle has been successfully saved, send event to service */
220  process_post(source_process, dtn_bundle_stored, NULL);
221  } else {
222  /* Bundle could not be saved, notify service */
223  process_post(source_process, dtn_bundle_store_failed, NULL);
224  }
225 
226  // Now emulate the event to our agent
227  if( n ) {
228  data = (void *) bundle_number_ptr;
229  ev = dtn_bundle_in_storage_event;
230  } else {
231  continue;
232  }
233  }
234 
235  if(ev == dtn_send_admin_record_event) {
236  LOG(LOGD_DTN, LOG_AGENT, LOGL_ERR, "Send admin record currently not implemented");
237  continue;
238  }
239 
240  if(ev == dtn_beacon_event){
241  rimeaddr_t* src =(rimeaddr_t*) data;
242  ROUTING.new_neighbor(src);
243  LOG(LOGD_DTN, LOG_AGENT, LOGL_DBG, "dtn_beacon_event for %u.%u", src->u8[0], src->u8[1]);
244  continue;
245  }
246 
247  if(ev == dtn_bundle_in_storage_event){
248  uint32_t * bundle_number = (uint32_t *) data;
249 
250  LOG(LOGD_DTN, LOG_AGENT, LOGL_DBG, "bundle %lu in storage", *bundle_number);
251 
252  if(ROUTING.new_bundle(bundle_number) < 0){
253  LOG(LOGD_DTN, LOG_AGENT, LOGL_ERR, "routing reports error when announcing new bundle %lu", *bundle_number);
254  continue;
255  }
256 
257  continue;
258  }
259 
260  if(ev == dtn_processing_finished) {
261  // data should contain the bundlemem ptr
262  struct mmem * bundlemem = NULL;
263  struct bundle_t * bundle = NULL;
264 
265  bundlemem = (struct mmem *) data;
266  if( bundlemem == NULL ) {
267  LOG(LOGD_DTN, LOG_AGENT, LOGL_ERR, "dtn_processing_finished with invalid pointer");
268  continue;
269  }
270 
271  bundle = (struct bundle_t *) MMEM_PTR(bundlemem);
272  if( bundle == NULL ) {
273  LOG(LOGD_DTN, LOG_AGENT, LOGL_ERR, "dtn_send_bundle_event with invalid MMEM structure");
274  continue;
275  }
276 
277  LOG(LOGD_DTN, LOG_AGENT, LOGL_DBG, "service has processed bundle %lu", bundle->bundle_num);
278 
279  // Notify routing, that service has finished processing a bundle
280  ROUTING.locally_delivered(bundlemem);
281 
282  continue;
283  }
284  }
285 
286  PROCESS_END();
287 }
288 
289 void agent_delete_bundle(uint32_t bundle_number){
290  LOG(LOGD_DTN, LOG_AGENT, LOGL_DBG, "Agent deleting bundle no %lu", bundle_number);
291 
292  convergence_layer_delete_bundle(bundle_number);
293  ROUTING.del_bundle(bundle_number);
294  CUSTODY.del_from_list(bundle_number);
295 }
296 /** @} */