NSIS-ka
A free C++ implementation of NSIS protocols

root/natfw-nslp/trunk/src/gistka_mapper.cpp @ 2273

Revision 2273, 8.7 KB (checked in by stud-matfried, 7 years ago)

Renamed the benchmark class to benchmark_journal.
We will need the name "benchmark" later.

  • Property svn:keywords set to Id HeadURL
Line 
1/*
2 * Utilities for mapping between GISTka/protlib and NATFW.
3 *
4 * $Id$
5 * $HeadURL$
6 */
7#include "timer_module.h"
8#include "logfile.h"
9
10#include "apimessage.h"         // from NTLP
11
12#include "natfw_config.h"
13#include "msg/natfw_ie.h"
14#include "events.h"
15#include "gistka_mapper.h"
16#include "benchmark_journal.h"
17
18
19using namespace natfw;
20using namespace natfw::msg;
21using namespace protlib::log;
22
23
24#define LogError(msg) ERRLog("gistka_mapper", msg)
25#define LogWarn(msg) WLog("gistka_mapper", msg)
26#define LogInfo(msg) ILog("gistka_mapper", msg)
27#define LogDebug(msg) DLog("gistka_mapper", msg)
28
29#define LogUnimp(msg) Log(ERROR_LOG, LOG_UNIMP, "gistka_mapper", \
30        msg << " at " << __FILE__ << ":" << __LINE__)
31
32#ifdef BENCHMARK
33  extern benchmark_journal journal;
34#endif
35
36
37/*
38 * Create an NTLP APIMsg from our ntlp_msg.
39 */
40ntlp::APIMsg *gistka_mapper::create_api_msg(msg::ntlp_msg *msg) const throw () {
41        using ntlp::nslpdata;
42
43        MP(benchmark_journal::PRE_SERIALIZE);
44
45        /*
46         * Construct the NSLP payload (the NTLP's body).
47         */
48        const natfw_msg *m = msg->get_natfw_msg();
49        NetMsg payload( m->get_serialized_size(IE::protocol_v1) );
50
51        try {
52                uint32 bytes_written;
53                m->serialize(payload, IE::protocol_v1, bytes_written);
54        }
55        catch ( IEError &e ) {
56                LogError("serializing NATFW message failed");
57                assert( false ); // this would be a programming error
58        }
59
60        // Note: The nslpdata constructor copies the buffer.
61        nslpdata *data = new nslpdata(payload.get_buffer(), payload.get_size());
62
63
64        /*
65         * Gather all data the NTLP needs for sending our message.
66         */
67        uint32 msg_handle = 0;          // NSLP message handle
68        uint32 nslp_id = natfw_config::NSLP_ID;
69
70        ntlp::sessionid *sid = create_ntlp_session_id(msg->get_session_id());
71
72        ntlp::mri *nslp_mri = msg->get_mri()->copy();
73        assert( nslp_mri != NULL );
74
75        uint32 sii_handle = msg->get_sii_handle();
76
77        // reliable, but not secure; final hop flag is irrelevant
78        ntlp::tx_attr_t attr = { true, false, true };
79        uint32 timeout = 5;             // which unit?
80        uint16 ip_ttl = 100;            // IP Time to Live
81        uint32 ntlp_hop_count = 10;     // maximum hop count?
82
83        /*
84         * Now construct a message from the data above and hand it off to the
85         * NTLP.
86         */
87        ntlp::APIMsg *apimsg = new ntlp::APIMsg();
88        apimsg->set_source(natfw_config::INPUT_QUEUE_ADDRESS);
89        apimsg->set_sendmessage(data, msg_handle, nslp_id, sid, nslp_mri,
90                sii_handle, attr, timeout, ip_ttl, ntlp_hop_count);
91
92        MP(benchmark_journal::POST_SERIALIZE);
93
94        return apimsg;
95}
96
97
98/**
99 * Map APIMsg objects to event objects.
100 */
101event *gistka_mapper::map_to_event(const protlib::message *msg) const {
102        using ntlp::APIMsg;
103
104        event *ret = NULL;
105
106        assert( msg != NULL );
107
108        MP(benchmark_journal::PRE_MAPPING);
109
110        if ( dynamic_cast<const APIMsg *>(msg) != NULL )
111                ret = map_api_message(dynamic_cast<const APIMsg *>(msg));
112        else if ( dynamic_cast<const NatFwTimerMsg *>(msg) != NULL )
113                ret = map_timer_message(
114                        dynamic_cast<const NatFwTimerMsg *>(msg));
115        else if ( dynamic_cast<const NatFwEventMsg *>(msg) != NULL ) {
116                const NatFwEventMsg *em
117                        = dynamic_cast<const NatFwEventMsg *>(msg);
118                ret = em->get_event();
119        }
120        else
121                LogError("received unknown protlib::message of type "
122                        << msg->get_type_name() << " from "
123                        << msg->get_qaddr_name());
124
125        if ( ret == NULL )
126                LogWarn("map_to_event(): mapping not possible");
127
128        MP(benchmark_journal::POST_MAPPING);
129
130        return ret;
131}
132
133
134event *gistka_mapper::map_api_message(const ntlp::APIMsg *msg) const {
135        using ntlp::APIMsg;
136
137        switch ( msg->get_subtype() ) {
138                case APIMsg::RecvMessage:
139                        return map_api_receive_message(msg);
140                        break;
141
142                case APIMsg::NetworkNotification:
143                        return map_api_network_notification(msg);
144                        break;
145
146                case APIMsg::MessageStatus:
147                        return map_api_message_status(msg);
148                        break;
149
150                default:
151                        LogError("map_to_event(): can't handle type "
152                                        << msg->get_subtype_name());
153                        break;
154        }
155
156
157        return NULL;
158}
159
160
161/**
162 * Create a msg_event from the given APIMsg.
163 *
164 * This is called each time the NTLP gets a NATFW message from the network.
165 */
166event *gistka_mapper::map_api_receive_message(
167                const ntlp::APIMsg *apimsg) const {
168
169        using namespace protlib;
170        using ntlp::APIMsg;
171        using ntlp::nslpdata;
172
173        assert( apimsg->get_subtype() == APIMsg::RecvMessage );
174
175
176        // Convert the NTLP session ID to our local session_id.
177        session_id *sid = create_natfw_session_id(apimsg->get_sessionid());
178
179
180        /*
181         * The initial Query (a UDP datagram) does not contain a payload,
182         * because we requested reliable mode. So data can be NULL.
183         */
184        nslpdata *data = apimsg->get_data();
185
186        if ( data == NULL ) {
187                LogInfo("received message contains no NSLP payload");
188
189                // The NTLP instance asks us if we want to setup routing state.
190                if ( apimsg->get_adjacency_check() == true ) {
191                        LogInfo("routing state check flag set");
192                        return new routing_state_check_event(
193                                sid, apimsg->get_mri()->copy());
194                }
195                else {
196                        // This could be triggered by GIST-Confirm in C-Mode
197                        // I don't think we have to do anything here.
198                        LogInfo("routing state check flag NOT set");
199                        LogDebug("SII-Handle " << apimsg->get_sii_handle());
200                        delete sid;
201                        return NULL;
202                }
203        }
204
205
206        /*
207         * Parse the NSLP payload (the NTLP's body).
208         */
209        MP(benchmark_journal::PRE_DESERIALIZE);
210        NetMsg payload(data->get_buffer(), data->get_size()); // copies the data
211        NATFW_IEManager *mgr = NATFW_IEManager::instance();
212
213        IEErrorList errlist;
214        uint32 num_read;
215
216        IE *ie = mgr->deserialize(payload, cat_natfw_msg, IE::protocol_v1,
217                errlist, num_read, false);
218
219        if ( ie == NULL ) {
220                assert( ! errlist.is_empty() );
221                LogError("deserializing NATFW message failed: "
222                                << *(errlist.get()) );
223                LogDebug("nslp-data (the NATFW message) payload: " << payload);
224        }
225
226        /*
227         * With the deserialize() call above, the NATFW_IEManager can only
228         * create subclasses of natfw_msg. If it doesn't something has gone
229         * wrong with the IE registration, which would be a programming error.
230         */
231        natfw_msg *m = NULL;
232
233        if ( ie != NULL ) {
234                m = dynamic_cast<natfw_msg *>(ie);
235                assert( m != NULL );
236        }
237
238        uint32 sii = apimsg->get_sii_handle();
239        bool final_hop = apimsg->get_tx_attr().final_hop;
240
241        // Note that m may be NULL if deserialize() failed!
242        ntlp_msg *ret = new ntlp_msg(*sid, m, apimsg->get_mri()->copy(), sii);
243        msg_event *evt = new msg_event(sid, ret, final_hop);
244
245        MP(benchmark_journal::POST_DESERIALIZE);
246
247        return evt;
248}
249
250
251event *gistka_mapper::map_api_network_notification(
252                const ntlp::APIMsg *msg) const {
253
254        using ntlp::APIMsg;
255
256        assert( msg->get_subtype() == APIMsg::NetworkNotification );
257
258        APIMsg::error_t status = msg->get_msgstatus();
259
260        LogDebug("NetworkNotification: NSLPID " << msg->get_nslpid());
261        LogDebug("NetworkNotification: SessionID " << *msg->get_sessionid());
262        LogDebug("NetworkNotification: MRI " << *msg->get_mri());
263        LogDebug("NetworkNotification: SII-Handle " << msg->get_sii_handle());
264        LogDebug("NetworkNotification: notify value "
265                << status << " (" << msg->get_error_str(status) << ")");
266
267        switch ( status ) {
268          case APIMsg::route_changed_status_bad:
269                return new route_changed_bad_event(
270                        create_natfw_session_id(msg->get_sessionid()) );
271                break;
272
273          default:
274                LogUnimp("unhandled NetworkNotification, status "
275                        << status << " (" << msg->get_error_str(status) << ")");
276        }
277
278        return NULL;
279}
280
281
282/*
283 * Using this message, we could discover problems like unreachable hosts
284 * earlier. But we can as well resend a few times and give up then.
285 */
286event *gistka_mapper::map_api_message_status(const ntlp::APIMsg *msg) const {
287        using ntlp::APIMsg;
288
289        assert( msg->get_subtype() == APIMsg::MessageStatus );
290
291        APIMsg::error_t status = msg->get_msgstatus();
292
293        LogDebug("MessageStatus:"
294                << " NSLP-Message-Handle=" << msg->get_nslpmsghandle()
295                //<< " Transfer-Attributes=" << msg->get_tx_attr()
296                << " Error-Type=" << msg->get_error_str(status));
297
298        // If no session ID is available, we don't create an event.
299        if ( msg->get_sessionid() == NULL ) {
300                LogDebug("MessageStatus has no SessionID");
301                return NULL;
302        }
303
304        if ( status == APIMsg::error_msg_node_not_found )
305                return new no_next_node_found_event(
306                        create_natfw_session_id(msg->get_sessionid()) );
307
308        LogError("MessageStatus error code unknown");
309
310        return NULL;
311}
312
313
314event *gistka_mapper::map_timer_message(const NatFwTimerMsg *msg) const {
315        assert( msg != NULL );
316
317        timer_event *e = new timer_event(
318                new session_id(msg->get_session_id()), msg->get_id());
319
320        return e;
321}
322
323
324/**
325 * Convert our local session_id to an ntlp::sessionid.
326 */
327ntlp::sessionid *gistka_mapper::create_ntlp_session_id(
328                const session_id &s) const {
329
330        uint128 raw = s.get_id();
331        return  new ntlp::sessionid(raw.w1, raw.w2, raw.w3, raw.w4);
332}
333
334
335/**
336 * Convert an ntlp::sessionid to our local session_id.
337 */
338session_id *gistka_mapper::create_natfw_session_id(ntlp::sessionid *sid) const {
339        assert( sid != NULL );
340
341        uint128 raw_sid;
342        sid->get_sessionid(raw_sid.w1, raw_sid.w2, raw_sid.w3, raw_sid.w4);
343
344        return new session_id(raw_sid);
345}
346
347// EOF
Note: See TracBrowser for help on using the browser.