blob: 8fb1f397fb8016fed559410736714f06deca1fb1 [file] [log] [blame]
Andrew Brown3831baf2015-01-19 13:38:52 -08001/*
2 * File name: MockTransport.java
3 *
4 * Purpose: Use the MockTransport to mock sending data over the network.
5 *
6 * © Copyright Intel Corporation. All rights reserved.
7 * Intel Corporation, 2200 Mission College Boulevard,
8 * Santa Clara, CA 95052-8119, USA
9 */
10package com.intel.jndn.mock;
11
12import java.io.IOException;
13import java.util.HashMap;
14import java.util.Map.Entry;
15import net.named_data.jndn.Data;
16import net.named_data.jndn.ForwardingFlags;
17import net.named_data.jndn.Interest;
18import net.named_data.jndn.Name;
19import net.named_data.jndn.Node;
20import net.named_data.jndn.OnData;
21import net.named_data.jndn.OnInterest;
22import net.named_data.jndn.OnRegisterFailed;
23import net.named_data.jndn.OnTimeout;
24import net.named_data.jndn.encoding.EncodingException;
25import net.named_data.jndn.encoding.WireFormat;
26import org.apache.logging.log4j.LogManager;
27import org.apache.logging.log4j.Logger;
28
29/**
30 *
31 * @author Andrew Brown <andrew.brown@intel.com>
32 */
33public class MockFace {
34
35 private static final Logger logger = LogManager.getLogger();
36 private final Node node_;
37 HashMap<String, Data> responseMap = new HashMap<>();
38 HashMap<Long, MockOnInterestHandler> handlerMap = new HashMap<>();
39 long lastRegisteredId = 0;
40
41 /**
42 * Create a new Face to mock communication over the network; all packets are
43 * maintained in memory
44 */
45 public MockFace() {
46 node_ = new Node(new MockTransport(), null);
47 }
48
49 /**
50 * Add a response Data packet to send immediately when an Interest with a
51 * matching name is received; will continue to respond with the same packet
52 * over multiple requests. This will preempt any registered OnInterest
53 * handlers.
54 *
55 * @param name
56 * @param data
57 */
58 public void addResponse(Name name, Data data) {
59 logger.debug("Added response for: " + name.toUri());
60 responseMap.put(name.toUri(), data);
61 }
62
63 /**
64 * Stop sending a response for the given name.
65 *
66 * @param name
67 */
68 public void removeResponse(Name name) {
69 logger.debug("Removed response for: " + name.toUri());
70 responseMap.remove(name);
71 }
72
73 /**
74 * Handle incoming Interest packets; when an Interest is expressed through
75 * expressInterest(), this will run to determine if: 1) any responses have
Andrew Brown8d8535b2015-01-19 15:22:06 -080076 * been registered or 2) if any OnInterest handlers have been registered. If
77 * one of these two succeeds, this method then re-directs the Interest from
Andrew Brown3831baf2015-01-19 13:38:52 -080078 * traveling down the network stack and returns data.
Andrew Brown8d8535b2015-01-19 15:22:06 -080079 *
Andrew Brown3831baf2015-01-19 13:38:52 -080080 * @param interest
81 */
82 protected void handleIncomingRequests(Interest interest) {
83 String interestName = interest.getName().toUri();
84 long registeredPrefixId = findRegisteredHandler(interest);
85 // check if response registered
86 if (responseMap.containsKey(interestName)) {
87 logger.debug("Found response for: " + interestName);
88 Data data = responseMap.get(interestName);
89 ((MockTransport) node_.getTransport()).respondWith(data);
Andrew Brown8d8535b2015-01-19 15:22:06 -080090 } // check if handler registered
Andrew Brown3831baf2015-01-19 13:38:52 -080091 else if (registeredPrefixId != -1) {
92 logger.debug("Found handler for: " + interestName);
93 MockOnInterestHandler handler = handlerMap.get(findRegisteredHandler(interest));
94 handler.onInterest.onInterest(handler.prefix, interest, node_.getTransport(), registeredPrefixId);
Andrew Brown8d8535b2015-01-19 15:22:06 -080095 } // log failure
Andrew Brown3831baf2015-01-19 13:38:52 -080096 else {
97 logger.warn("No response found for interest (aborting): " + interestName);
98 }
99 }
100
101 /**
102 * Find a handler that matches the incoming interest; currently, the only
103 * flags supported are the ChildInherit flags.
Andrew Brown8d8535b2015-01-19 15:22:06 -0800104 *
Andrew Brown3831baf2015-01-19 13:38:52 -0800105 * @param interest
Andrew Brown8d8535b2015-01-19 15:22:06 -0800106 * @return
Andrew Brown3831baf2015-01-19 13:38:52 -0800107 */
108 protected long findRegisteredHandler(Interest interest) {
109 for (Entry<Long, MockOnInterestHandler> entry : handlerMap.entrySet()) {
110 MockOnInterestHandler handler = entry.getValue();
111 if (handler.flags.getChildInherit() && handler.prefix.match(interest.getName())) {
112 return entry.getKey();
113 }
114 if (handler.prefix.equals(interest.getName())) {
115 return entry.getKey();
116 }
117 }
118 return -1;
119 }
120
121 /**
122 * Helper class for holding references to OnInterest handlers
123 */
124 class MockOnInterestHandler {
125
126 Name prefix;
127 OnInterest onInterest;
128 ForwardingFlags flags;
129
130 public MockOnInterestHandler(Name prefix, OnInterest onInterest, ForwardingFlags flags) {
131 this.prefix = prefix;
132 this.onInterest = onInterest;
133 this.flags = flags;
134 }
135 }
136
137 /**
138 * Send the Interest through the transport, read the entire response and call
139 * onData(interest, data).
140 *
141 * @param interest The Interest to send. This copies the Interest.
142 * @param onData When a matching data packet is received, this calls
143 * onData.onData(interest, data) where interest is the interest given to
144 * expressInterest and data is the received Data object. NOTE: You must not
145 * change the interest object - if you need to change it then make a copy.
146 * @param onTimeout If the interest times out according to the interest
147 * lifetime, this calls onTimeout.onTimeout(interest) where interest is the
148 * interest given to expressInterest. If onTimeout is null, this does not use
149 * it.
150 * @param wireFormat A WireFormat object used to encode the message.
151 * @return The pending interest ID which can be used with
152 * removePendingInterest.
153 * @throws IOException For I/O error in sending the interest.
154 */
155 public long expressInterest(Interest interest, OnData onData, OnTimeout onTimeout,
156 WireFormat wireFormat) throws IOException {
157 long id = node_.expressInterest(interest, onData, onTimeout, wireFormat);
158 handleIncomingRequests(interest);
159 return id;
160 }
161
162 /**
163 * Send the Interest through the transport, read the entire response and call
164 * onData(interest, data). This uses the default
165 * WireFormat.getDefaultWireFormat().
166 *
167 * @param interest The Interest to send. This copies the Interest.
168 * @param onData When a matching data packet is received, this calls
169 * onData.onData(interest, data) where interest is the interest given to
170 * expressInterest and data is the received Data object. NOTE: You must not
171 * change the interest object - if you need to change it then make a copy.
172 * @param onTimeout If the interest times out according to the interest
173 * lifetime, this calls onTimeout.onTimeout(interest) where interest is the
174 * interest given to expressInterest. If onTimeout is null, this does not use
175 * it.
176 * @return The pending interest ID which can be used with
177 * removePendingInterest.
178 * @throws IOException For I/O error in sending the interest.
179 */
180 public long expressInterest(Interest interest, OnData onData, OnTimeout onTimeout) throws IOException {
181 return expressInterest(interest, onData, onTimeout, WireFormat.getDefaultWireFormat());
182 }
183
184 /**
185 * Send the Interest through the transport, read the entire response and call
186 * onData(interest, data). Ignore if the interest times out.
187 *
188 * @param interest The Interest to send. This copies the Interest.
189 * @param onData When a matching data packet is received, this calls
190 * onData.onData(interest, data) where interest is the interest given to
191 * expressInterest and data is the received Data object. NOTE: You must not
192 * change the interest object - if you need to change it then make a copy.
193 * @param wireFormat A WireFormat object used to encode the message.
194 * @return The pending interest ID which can be used with
195 * removePendingInterest.
196 * @throws IOException For I/O error in sending the interest.
197 */
198 public long expressInterest(Interest interest, OnData onData, WireFormat wireFormat) throws IOException {
199 return expressInterest(interest, onData, null, wireFormat);
200 }
201
202 /**
203 * Send the Interest through the transport, read the entire response and call
204 * onData(interest, data). Ignore if the interest times out. This uses the
205 * default WireFormat.getDefaultWireFormat().
206 *
207 * @param interest The Interest to send. This copies the Interest.
208 * @param onData When a matching data packet is received, this calls
209 * onData.onData(interest, data) where interest is the interest given to
210 * expressInterest and data is the received Data object. NOTE: You must not
211 * change the interest object - if you need to change it then make a copy.
212 * @return The pending interest ID which can be used with
213 * removePendingInterest.
214 * @throws IOException For I/O error in sending the interest.
215 */
216 public long expressInterest(Interest interest, OnData onData) throws IOException {
217 return expressInterest(interest, onData, null, WireFormat.getDefaultWireFormat());
218 }
219
220 /**
221 * Encode name as an Interest. If interestTemplate is not null, use its
222 * interest selectors. Send the interest through the transport, read the
223 * entire response and call onData(interest, data).
224 *
225 * @param name A Name for the interest. This copies the Name.
226 * @param interestTemplate If not null, copy interest selectors from the
227 * template. This does not keep a pointer to the Interest object.
228 * @param onData When a matching data packet is received, this calls
229 * onData.onData(interest, data) where interest is the interest given to
230 * expressInterest and data is the received Data object. NOTE: You must not
231 * change the interest object - if you need to change it then make a copy.
232 * @param onTimeout If the interest times out according to the interest
233 * lifetime, this calls onTimeout.onTimeout(interest) where interest is the
234 * interest given to expressInterest. If onTimeout is null, this does not use
235 * it.
236 * @param wireFormat A WireFormat object used to encode the message.
237 * @return The pending interest ID which can be used with
238 * removePendingInterest.
239 * @throws IOException For I/O error in sending the interest.
240 */
241 public long expressInterest(Name name, Interest interestTemplate, OnData onData, OnTimeout onTimeout,
242 WireFormat wireFormat) throws IOException {
243 Interest interest = new Interest(name);
244 if (interestTemplate != null) {
245 interest.setMinSuffixComponents(interestTemplate.getMinSuffixComponents());
246 interest.setMaxSuffixComponents(interestTemplate.getMaxSuffixComponents());
247 interest.setKeyLocator(interestTemplate.getKeyLocator());
248 interest.setExclude(interestTemplate.getExclude());
249 interest.setChildSelector(interestTemplate.getChildSelector());
250 interest.setMustBeFresh(interestTemplate.getMustBeFresh());
251 interest.setScope(interestTemplate.getScope());
252 interest.setInterestLifetimeMilliseconds(
253 interestTemplate.getInterestLifetimeMilliseconds());
254 // Don't copy the nonce.
255 } else {
256 interest.setInterestLifetimeMilliseconds(4000.0);
257 }
258
259 return expressInterest(interest, onData, onTimeout, wireFormat);
260 }
261
262 /**
263 * Encode name as an Interest. If interestTemplate is not null, use its
264 * interest selectors. Send the interest through the transport, read the
265 * entire response and call onData(interest, data). Use a default interest
266 * lifetime.
267 *
268 * @param name A Name for the interest. This copies the Name.
269 * @param onData When a matching data packet is received, this calls
270 * onData.onData(interest, data) where interest is the interest given to
271 * expressInterest and data is the received Data object. NOTE: You must not
272 * change the interest object - if you need to change it then make a copy.
273 * @param onTimeout If the interest times out according to the interest
274 * lifetime, this calls onTimeout.onTimeout(interest) where interest is the
275 * interest given to expressInterest. If onTimeout is null, this does not use
276 * it.
277 * @param wireFormat A WireFormat object used to encode the message.
278 * @return The pending interest ID which can be used with
279 * removePendingInterest.
280 * @throws IOException For I/O error in sending the interest.
281 */
282 public long expressInterest(Name name, OnData onData, OnTimeout onTimeout,
283 WireFormat wireFormat) throws IOException {
284 return expressInterest(name, null, onData, onTimeout, wireFormat);
285 }
286
287 /**
288 * Encode name as an Interest. If interestTemplate is not null, use its
289 * interest selectors. Send the interest through the transport, read the
290 * entire response and call onData(interest, data). Ignore if the interest
291 * times out.
292 *
293 * @param name A Name for the interest. This copies the Name.
294 * @param interestTemplate If not null, copy interest selectors from the
295 * template. This does not keep a pointer to the Interest object.
296 * @param onData When a matching data packet is received, this calls
297 * onData.onData(interest, data) where interest is the interest given to
298 * expressInterest and data is the received Data object. NOTE: You must not
299 * change the interest object - if you need to change it then make a copy.
300 * @param wireFormat A WireFormat object used to encode the message.
301 * @return The pending interest ID which can be used with
302 * removePendingInterest.
303 * @throws IOException For I/O error in sending the interest.
304 */
305 public long expressInterest(Name name, Interest interestTemplate, OnData onData,
306 WireFormat wireFormat) throws IOException {
307 return expressInterest(name, interestTemplate, onData, null, wireFormat);
308 }
309
310 /**
311 * Encode name as an Interest. If interestTemplate is not null, use its
312 * interest selectors. Send the interest through the transport, read the
313 * entire response and call onData(interest, data). This uses the default
314 * WireFormat.getDefaultWireFormat().
315 *
316 * @param name A Name for the interest. This copies the Name.
317 * @param interestTemplate If not null, copy interest selectors from the
318 * template. This does not keep a pointer to the Interest object.
319 * @param onData When a matching data packet is received, this calls
320 * onData.onData(interest, data) where interest is the interest given to
321 * expressInterest and data is the received Data object. NOTE: You must not
322 * change the interest object - if you need to change it then make a copy.
323 * @param onTimeout If the interest times out according to the interest
324 * lifetime, this calls onTimeout.onTimeout(interest) where interest is the
325 * interest given to expressInterest. If onTimeout is null, this does not use
326 * it.
327 * @return The pending interest ID which can be used with
328 * removePendingInterest.
329 * @throws IOException For I/O error in sending the interest.
330 */
331 public long expressInterest(Name name, Interest interestTemplate, OnData onData,
332 OnTimeout onTimeout) throws IOException {
333 return expressInterest(name, interestTemplate, onData, onTimeout,
334 WireFormat.getDefaultWireFormat());
335 }
336
337 /**
338 * Encode name as an Interest. If interestTemplate is not null, use its
339 * interest selectors. Send the interest through the transport, read the
340 * entire response and call onData(interest, data). Ignore if the interest
341 * times out. This uses the default WireFormat.getDefaultWireFormat().
342 *
343 * @param name A Name for the interest. This copies the Name.
344 * @param interestTemplate If not null, copy interest selectors from the
345 * template. This does not keep a pointer to the Interest object.
346 * @param onData When a matching data packet is received, this calls
347 * onData.onData(interest, data) where interest is the interest given to
348 * expressInterest and data is the received Data object. NOTE: You must not
349 * change the interest object - if you need to change it then make a copy.
350 * @return The pending interest ID which can be used with
351 * removePendingInterest.
352 * @throws IOException For I/O error in sending the interest.
353 */
354 public long expressInterest(Name name, Interest interestTemplate, OnData onData) throws IOException {
355 return expressInterest(name, interestTemplate, onData, null, WireFormat.getDefaultWireFormat());
356 }
357
358 /**
359 * Encode name as an Interest. If interestTemplate is not null, use its
360 * interest selectors. Send the interest through the transport, read the
361 * entire response and call onData(interest, data). Use a default interest
362 * lifetime. This uses the default WireFormat.getDefaultWireFormat().
363 *
364 * @param name A Name for the interest. This copies the Name.
365 * @param onData When a matching data packet is received, this calls
366 * onData.onData(interest, data) where interest is the interest given to
367 * expressInterest and data is the received Data object. NOTE: You must not
368 * change the interest object - if you need to change it then make a copy.
369 * @param onTimeout If the interest times out according to the interest
370 * lifetime, this calls onTimeout.onTimeout(interest) where interest is the
371 * interest given to expressInterest. If onTimeout is null, this does not use
372 * it.
373 * @return The pending interest ID which can be used with
374 * removePendingInterest.
375 * @throws IOException For I/O error in sending the interest.
376 */
377 public long expressInterest(Name name, OnData onData, OnTimeout onTimeout) throws IOException {
378 return expressInterest(name, null, onData, onTimeout, WireFormat.getDefaultWireFormat());
379 }
380
381 /**
382 * Encode name as an Interest. If interestTemplate is not null, use its
383 * interest selectors. Send the interest through the transport, read the
384 * entire response and call onData(interest, data). Use a default interest
385 * lifetime. Ignore if the interest times out.
386 *
387 * @param name A Name for the interest. This copies the Name.
388 * @param onData When a matching data packet is received, this calls
389 * onData.onData(interest, data) where interest is the interest given to
390 * expressInterest and data is the received Data object. NOTE: You must not
391 * change the interest object - if you need to change it then make a copy.
392 * @param wireFormat A WireFormat object used to encode the message.
393 * @return The pending interest ID which can be used with
394 * removePendingInterest.
395 * @throws IOException For I/O error in sending the interest.
396 */
397 public long expressInterest(Name name, OnData onData, WireFormat wireFormat) throws IOException {
398 return expressInterest(name, null, onData, null, wireFormat);
399 }
400
401 /**
402 * Encode name as an Interest. If interestTemplate is not null, use its
403 * interest selectors. Send the interest through the transport, read the
404 * entire response and call onData(interest, data). Use a default interest
405 * lifetime. Ignore if the interest times out. This uses the default
406 * WireFormat.getDefaultWireFormat().
407 *
408 * @param name A Name for the interest. This copies the Name.
409 * @param onData When a matching data packet is received, this calls
410 * onData.onData(interest, data) where interest is the interest given to
411 * expressInterest and data is the received Data object. NOTE: You must not
412 * change the interest object - if you need to change it then make a copy.
413 * @return The pending interest ID which can be used with
414 * removePendingInterest.
415 * @throws IOException For I/O error in sending the interest.
416 */
417 public long expressInterest(Name name, OnData onData) throws IOException {
418 return expressInterest(name, null, onData, null, WireFormat.getDefaultWireFormat());
419 }
420
421 /**
422 * Remove the pending interest entry with the pendingInterestId from the
423 * pending interest table. This does not affect another pending interest with
424 * a different pendingInterestId, even if it has the same interest name. If
425 * there is no entry with the pendingInterestId, do nothing.
426 *
427 * @param pendingInterestId The ID returned from expressInterest.
428 */
429 public void removePendingInterest(long pendingInterestId) {
430 node_.removePendingInterest(pendingInterestId);
431 }
432
433 /**
434 * Register prefix with the connected NDN hub and call onInterest when a
435 * matching interest is received. If you have not called
436 * setCommandSigningInfo, this assumes you are connecting to NDNx. If you have
437 * called setCommandSigningInfo, this first sends an NFD registration request,
438 * and if that times out then this sends an NDNx registration request. If you
439 * need to register a prefix with NFD, you must first call
440 * setCommandSigningInfo.
441 *
442 * @param prefix A Name for the prefix to register. This copies the Name.
443 * @param onInterest When an interest is received which matches the name
444 * prefix, this calls onInterest.onInterest(prefix, interest, transport,
445 * registeredPrefixId). NOTE: You must not change the prefix object - if you
446 * need to change it then make a copy.
447 * @param onRegisterFailed If register prefix fails for any reason, this calls
448 * onRegisterFailed.onRegisterFailed(prefix).
449 * @param flags The flags for finer control of which interests are forwarded
450 * to the application.
451 * @param wireFormat A WireFormat object used to encode the message.
452 * @return The lastRegisteredId prefix ID which can be used with
453 * removeRegisteredPrefix.
454 * @throws IOException For I/O error in sending the registration request.
455 * @throws SecurityException If signing a command interest for NFD and cannot
456 * find the private key for the certificateName.
457 */
458 public long registerPrefix(Name prefix, OnInterest onInterest, OnRegisterFailed onRegisterFailed,
459 ForwardingFlags flags, WireFormat wireFormat) throws IOException, net.named_data.jndn.security.SecurityException {
460 lastRegisteredId++;
461 handlerMap.put(lastRegisteredId, new MockOnInterestHandler(prefix, onInterest, flags));
462 return lastRegisteredId;
463 }
464
465 /**
466 * Register prefix with the connected NDN hub and call onInterest when a
467 * matching interest is received. This uses the default
468 * WireFormat.getDefaultWireFormat().
469 *
470 * @param prefix A Name for the prefix to register. This copies the Name.
471 * @param onInterest When an interest is received which matches the name
472 * prefix, this calls onInterest.onInterest(prefix, interest, transport,
473 * registeredPrefixId). NOTE: You must not change the prefix object - if you
474 * need to change it then make a copy.
475 * @param onRegisterFailed If register prefix fails for any reason, this calls
476 * onRegisterFailed.onRegisterFailed(prefix).
477 * @param flags The flags for finer control of which interests are forwarded
478 * to the application.
479 * @return The lastRegisteredId prefix ID which can be used with
480 * removeRegisteredPrefix.
481 * @throws IOException For I/O error in sending the registration request.
482 */
483 public long registerPrefix(Name prefix, OnInterest onInterest, OnRegisterFailed onRegisterFailed,
484 ForwardingFlags flags) throws IOException, net.named_data.jndn.security.SecurityException {
485 return registerPrefix(prefix, onInterest, onRegisterFailed, flags,
486 WireFormat.getDefaultWireFormat());
487 }
488
489 /**
490 * Register prefix with the connected NDN hub and call onInterest when a
491 * matching interest is received. Use default ForwardingFlags.
492 *
493 * @param prefix A Name for the prefix to register. This copies the Name.
494 * @param onInterest When an interest is received which matches the name
495 * prefix, this calls onInterest.onInterest(prefix, interest, transport,
496 * registeredPrefixId). NOTE: You must not change the prefix object - if you
497 * need to change it then make a copy.
498 * @param onRegisterFailed If register prefix fails for any reason, this calls
499 * onRegisterFailed.onRegisterFailed(prefix).
500 * @param wireFormat A WireFormat object used to encode the message.
501 * @return The lastRegisteredId prefix ID which can be used with
502 * removeRegisteredPrefix.
503 * @throws IOException For I/O error in sending the registration request.
504 * @throws SecurityException If signing a command interest for NFD and cannot
505 * find the private key for the certificateName.
506 */
507 public long registerPrefix(Name prefix, OnInterest onInterest, OnRegisterFailed onRegisterFailed,
508 WireFormat wireFormat) throws IOException, net.named_data.jndn.security.SecurityException {
509 return registerPrefix(prefix, onInterest, onRegisterFailed, new ForwardingFlags(), wireFormat);
510 }
511
512 /**
513 * Register prefix with the connected NDN hub and call onInterest when a
514 * matching interest is received. This uses the default
515 * WireFormat.getDefaultWireFormat(). Use default ForwardingFlags.
516 *
517 * @param prefix A Name for the prefix to register. This copies the Name.
518 * @param onInterest When an interest is received which matches the name
519 * prefix, this calls onInterest.onInterest(prefix, interest, transport,
520 * registeredPrefixId). NOTE: You must not change the prefix object - if you
521 * need to change it then make a copy.
522 * @param onRegisterFailed If register prefix fails for any reason, this calls
523 * onRegisterFailed.onRegisterFailed(prefix).
524 * @return The lastRegisteredId prefix ID which can be used with
525 * removeRegisteredPrefix.
526 * @throws IOException For I/O error in sending the registration request.
527 * @throws SecurityException If signing a command interest for NFD and cannot
528 * find the private key for the certificateName.
529 */
530 public long registerPrefix(Name prefix, OnInterest onInterest,
531 OnRegisterFailed onRegisterFailed) throws IOException, net.named_data.jndn.security.SecurityException {
532 return registerPrefix(prefix, onInterest, onRegisterFailed, new ForwardingFlags(),
533 WireFormat.getDefaultWireFormat());
534 }
535
536 /**
537 * Remove the lastRegisteredId prefix entry with the registeredPrefixId from
538 * the lastRegisteredId prefix table. This does not affect another
539 * lastRegisteredId prefix with a different registeredPrefixId, even if it has
540 * the same prefix name. If there is no entry with the registeredPrefixId, do
541 * nothing.
542 *
543 * @param registeredPrefixId The ID returned from registerPrefix.
544 */
545 public void removeRegisteredPrefix(long registeredPrefixId) {
546 handlerMap.remove(registeredPrefixId);
547 }
548
549 /**
550 * Process any packets to receive and call callbacks such as onData,
551 * onInterest or onTimeout. This returns immediately if there is no data to
552 * receive. This blocks while calling the callbacks. You should repeatedly
553 * call this from an event loop, with calls to sleep as needed so that the
554 * loop doesn’t use 100% of the CPU. Since processEvents modifies the pending
555 * interest table, your application should make sure that it calls
556 * processEvents in the same thread as expressInterest (which also modifies
557 * the pending interest table). This may throw an exception for reading data
558 * or in the callback for processing the data. If you call this from an main
559 * event loop, you may want to catch and log/disregard all exceptions.
560 */
561 public void processEvents() throws IOException, EncodingException {
562 // Just call Node's processEvents.
563 node_.processEvents();
564 }
565
566 /**
567 * Shut down and disconnect this Face.
568 */
569 public void shutdown() {
570 node_.shutdown();
571 }
572}