KM3NeT CLB  2.0
KM3NeT CLB v2 Embedded Software
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
msg.c
1 /*
2  * KM3NeT CLB v2 Firmware
3  * ----------------------
4  *
5  * Copyright 2013 National Institute for Subatomic Physics Nikhef
6  *
7  * All Rights Reserved.
8  *
9  *
10  * File : mcflayer.c
11  * Created : 9 jul. 2013
12  * Author : Vincent van Beveren
13  */
14 #include "net/msg.h"
15 
16 #include <stdio.h>
17 #include <assert.h>
18 
19 #include "util/log.h"
20 #include "util/databuffer.h"
21 
22 #include "cfg_msg.h"
23 
24 #include "errorcode.h"
25 
26 LOG_DEF(Msg);
27 
28 // #define DUMP_MESSAGES
29 
30 #ifdef DUMP_MESSAGES
31 #include "dbg/show.h"
32 #endif
33 
34 #define MSG_MAX_SIZE 1024
35 
36 static bool _msgTxHoldOff;
37 static uint8_t _msgBuffer[MSG_MAX_SIZE];
38 static MCFState _msgTxState;
39 static MCFMessage * const _msgTxMsg = &(_msgTxState.msg);
40 static SockAddr _msgTxAddr;
41 static uint16_t _msgId;
42 
43 static SockAddr _msgEvtAddr;
44 
45 // Generate dummy prototypes, such that each command which is not implemented returns
46 // a 'Not implemented' error. Not implemented events are simply ignored.
47 
48 #ifdef KM3SIM
49 // Somehow windows can not handle weak references
50 
51 #define MSG_CMD(CMD_TYPE, CMD_STUB) \
52  bool _msg ## CMD_STUB (MsgId * id, DataBuffer * buf);
54 
55 #undef MSG_CMD
56 
57 #define MSG_EVT(EVT_TYPE, EVT_STUB) \
58  void _evt ## EVT_STUB (MsgId * id, DataBuffer * buf);
60 
61 #undef MSG_EVT
62 
63 
64 #else
65 
66 #define MSG_CMD(CMD_TYPE, CMD_STUB) \
67  bool _msg ## CMD_STUB (MsgId * id, DataBuffer * buf) __attribute__((weak, alias("_msgNotImpl")));
69 
70 #undef MSG_CMD
71 
72 #define MSG_EVT(EVT_TYPE, EVT_STUB) \
73  void _evt ## EVT_STUB (MsgId * id, DataBuffer * buf) __attribute__((weak, alias("_evtNotImpl")));
75 
76 #undef MSG_EVT
77 
78 #endif
79 
80 
81 bool _msgNotImpl(MsgId * id, DataBuffer * buf)
82 {
83  return msgTxError(id, ERROR_CTX(E_NOTIMPLEMENTED));
84 }
85 
86 void _evtNotImpl(MsgId * id, DataBuffer * buf)
87 {
88 }
89 
90 
91 // Generate switch statement for messages
92 #define MSG_CMD(CMD_TYPE, CMD_STUB) \
93  case ( CMD_TYPE ):\
94  if (! _msg ## CMD_STUB(id, buf)) goto failed; \
95  return;
96 
97 
98 
99 static void msgRxCmd(MsgId * id, DataBuffer * buf)
100 {
101 
102 #ifdef DUMP_MESSAGES
103  char msg[32];
104  sprintf(msg, "RX Type=%04x", id->msgType);
105  showHex8(msg, buf->start, (int)(buf->end - buf->start));
106 #endif
107 
108  switch(id->msgType)
109  {
111  default:
112  msgTxError(id, ERROR_CTX(E_MSG_TYPE_UNKNOWN));
113  return;
114  }
115 failed:
116  msgTxError(id, ERROR_CTX(E_MSG_FUNCTION));
117 }
118 
119 #undef MSG_CMD
120 
121 
122 
123 // Generate switch statement for events
124 #define MSG_EVT(EVT_TYPE, EVT_STUB) \
125  case ( EVT_TYPE ):\
126  _evt ## EVT_STUB(id, buf); \
127  return;
128 
129 static void msgRxEvt(MsgId * id, DataBuffer * buf)
130 {
131 
132  switch(id->msgType)
133  {
134  MSG_EVENTS
135  }
136 }
137 
138 #undef MSG_EVT
139 
140 
142 {
143  if (buf->error != DB_ERR_NONE) {
144  logWarn("Could not decode message", buf->error);
145  return false;
146  }
147 
148  if (buf->cur != buf->end) {
149  logWarn("Not all parameters converted", DB_ERR_INVALID_BUFFER);
150  return false;
151  }
152  return true;
153 }
154 
155 static void msgRxMsg(SockAddr * addr, MCFMessage * msg)
156 {
157  MsgId id =
158  {
159  .addr = *addr,
160  .msgType = msg->typ,
161  .msgId = msg->identifier
162  };
163  DataBuffer buf = DB_BUF_INIT(msg->cntPtr, msg->cntLength);
164 
165  switch (msg->clazz)
166  {
167  case MCF_CLASS_CMD:
168  msgRxCmd(&id, &buf);
169  break;
170  case MCF_CLASS_EVENT:
171  msgRxEvt(&id, &buf);
172  break;
173  default:
174  msgTxError(&id, ERROR_CTX(E_MSG_CLASS_UNSUPPORT));
175  break;
176  }
177 }
178 
179 
180 
181 static void msgTxInit(SockAddr * addr)
182 {
183  _msgTxAddr = *addr;
184  mcfInitState(&_msgTxState, _msgBuffer, MSG_MAX_SIZE);
185 }
186 
187 static void msgTxSend()
188 {
189  uint32_t len = mcfEncodeFinish(&_msgTxState);
190  _msgTx(&_msgTxAddr, _msgBuffer, len);
191 }
192 
193 
194 void msgRx(SockAddr * addr, uint8_t * data, int len)
195 {
196  MCFState state;
197  MCFMessage * msg = &(state.msg);
198  msgTxInit(addr);
199  _msgTxHoldOff = true;
200  mcfInitState(&state, data, len);
201  while (mcfDecodeNext(&state))
202  {
203  // printf("Decoding message with class %d, type %d, id %d\n", msg->clazz, msg->typ, msg->identifier);
204  msgRxMsg(addr, msg);
205  }
206  _msgTxHoldOff = false;
207  msgTxSend();
208 }
209 
210 
211 
212 
213 static bool msgTxRespond(MsgId * id, int clazz, DataBuffer * buf)
214 {
215  if (_msgTxHoldOff) {
216  if (buf && dbLength(buf) > mcfEncodeFreeNext(&_msgTxMsg)) {
217  // send previous buffer, cause its full.
218  msgTxSend();
219  msgTxInit(&(id->addr));
220  }
221 
222  } else {
223  msgTxInit(&(id->addr));
224  }
225 
226 
227  mcfEncodeNext(&_msgTxState);
228  _msgTxMsg->clazz = clazz;
229  _msgTxMsg->typ = id->msgType;
230  _msgTxMsg->identifier = id->msgId;
231 
232  // printf("Encoding message with class %d, type %d, id %d\n", clazz, id->msgType, id->msgId);
233 
234  if (buf)
235  {
236  // copy content into MCF.
237  if (!mcfEncodeBuffer(&_msgTxState, buf)) {
238  // TODO if this would EVER occur, it would be serious issue, as the buffer is
239  // already corrupted.... not that it can occur.
240  return false;
241  }
242  } else {
243  _msgTxMsg->cntLength = 0;
244  }
245 
246  if (!_msgTxHoldOff) msgTxSend();
247  return true;
248 }
249 
250 
251 void msgSetEvtTarget(SockAddr * sockAddr)
252 {
253  if (sockAddr == NULL) {
254  _msgEvtAddr.ip = 0;
255  logInfo("Event target cleared");
256  } else {
257  // if it is the same, don't bother.
258  if ( _msgEvtAddr.ip == sockAddr->ip && _msgEvtAddr.port == sockAddr->port ) return;
259  _msgEvtAddr = *sockAddr;
260  logInfo("Event target set to %08x:%u", _msgEvtAddr.ip, _msgEvtAddr.port);
261  }
262 }
263 
264 void msgGetEvtTarget(SockAddr * sockAddr)
265 {
266  *sockAddr = _msgEvtAddr;
267 }
268 
269 bool msgTxEvent(int msgType, DataBuffer * buf)
270 {
271  // Can't emit anything, IP has not been set!
272  if (_msgEvtAddr.ip == 0) return false;
273 
274  MsgId id;
275  id.msgType = msgType;
276  id.msgId = _msgId++;
277  id.addr = _msgEvtAddr;
278 
279 #ifdef MSG_DONTACK_EVENTS
280  return msgTxDontAck(&id, MCF_CLASS_EVENT, buf);
281 #else
282  return msgTxRespond(&id, MCF_CLASS_EVENT, buf);
283 #endif
284 }
285 
286 bool msgTxReply(MsgId * id, DataBuffer * buf)
287 {
288  // printf("Sending reply: %d\n", id->msgType);
289  return msgTxRespond(id, MCF_CLASS_REPLY, buf);
290 }
291 
292 
293 bool msgTxError(MsgId * id, int errCode, const char * errMsg, const char * name)
294 {
295  if (errCode == 0) {
296  errCode = E_UNKNOWN;
297  errMsg = E_UNKNOWN_DESCR;
298  }
299 
300  printf("MSG Error (type=%d, id=%d): %s (0x%08x)\n", id->msgType, id->msgId, errMsg, errCode);
301  uint8_t tmp[80];
302  DataBuffer db = DB_BUF_INIT(tmp, 80);
303  dbWriteI32(&db, errCode);
304  if (errMsg == NULL) {
305  errMsg = "";
306  }
307  dbWriteString(&db, errMsg, 74);
308 
309  return msgTxRespond(id, MCF_CLASS_ERROR, &db);
310 }
311 
uint32_t mcfEncodeFinish(MCFState *state)
Call this after encoding to complete the MCF packet.
Definition: mcf.c:180
void msgGetEvtTarget(SockAddr *sockAddr)
Returns the event target address.
Definition: msg.c:264
#define E_MSG_TYPE_UNKNOWN
Message unknown.
Definition: msg.h:282
void _msgTx(SockAddr *addr, uint8_t *data, int len)
Stub function, invoked by RMT when sending a MCF packet.
Definition: network.c:623
#define E_MSG_FUNCTION
Message function returned false.
Definition: msg.h:284
bool msgTxEvent(int msgType, DataBuffer *buf)
Invoked to send an event.
Definition: msg.c:269
bool dbWriteI32(DataBuffer *buf, int32_t i)
Writes an 32 bits signed integer.
Definition: databuffer.c:213
uint16_t port
Port number.
Definition: net.h:34
uint8_t * end
End Pointer.
Definition: databuffer.h:48
bool mcfEncodeBuffer(MCFState *state, DataBuffer *db)
Encodes the content of a databuffer into the container.
Definition: mcf.c:157
#define DB_ERR_NONE
Indicates no error.
Definition: databuffer.h:34
uint8_t * start
Start Pointer.
Definition: databuffer.h:47
uint32_t ip
IP address.
Definition: net.h:33
bool mcfEncodeNext(MCFState *state)
Creates a new encoding entry.
Definition: mcf.c:170
Defines a DataBuffer structure.
Definition: databuffer.h:45
#define logWarn(MSG,...)
Format a log message with warning level.
Definition: log.h:219
uint16_t msgType
the message type
Definition: msg.h:276
static uint32_t dbLength(DataBuffer *buf)
Returns the lenght of the current buffer.
Definition: databuffer.h:83
Handles MCF packed messages from the higher protocol layer.
int error
Last error.
Definition: databuffer.h:50
void msgSetEvtTarget(SockAddr *sockAddr)
Set the target for all events, or pass NULL to unset.
Definition: msg.c:251
Combination of IP address and port.
Definition: net.h:31
#define MSG_COMMANDS
List containing all commands.
Definition: cfg_msg.h:565
uint32_t mcfEncodeFreeNext()
Returns the number of bytes available for content in the NEXT message.
bool msgTxReply(MsgId *id, DataBuffer *buf)
Invoke to send a reply.
Definition: msg.c:286
#define E_NOTIMPLEMENTED
Generic error: not implemented.
Definition: errorcode.h:118
#define E_MSG_CLASS_UNSUPPORT
Message class received not supported.
Definition: msg.h:286
DataBuffer reads and writes data into a buffer in the same format as defined in the data Java DataOut...
bool msgTxError(MsgId *id, int errCode, const char *errMsg, const char *name)
Invoke to send an error response.
Definition: msg.c:293
void msgRx(SockAddr *addr, uint8_t *data, int len)
Receive a packet with data as a command.
Definition: msg.c:194
bool msgRxBufCheck(DataBuffer *buf)
Checks the received buffer, and logs an error if there is something wrong.
Definition: msg.c:141
#define MSG_EVENTS
List containing all events.
Definition: cfg_msg.h:561
Definition: mcf.h:94
This module is responsible for distributing error codes.
Defines all remote commands.
#define LOG_DEF(NAME,...)
Define a logger for a module.
Definition: log.h:129
void mcfInitState(MCFState *state, uint8_t *bufPtr, uint32_t bufLen)
Initializes the decoding or encoding of a Message Container Formatted message.
Definition: mcf.c:63
SockAddr addr
the address of the sender
Definition: msg.h:275
If defined, events will not require an acknowledge.
Definition: msg.h:274
bool dbWriteString(DataBuffer *buf, const char *s, int max)
Writes a String as &#39;sort of&#39; UTF-8 encoding, as defined in the Java DataOuput and DataInput writeUTF ...
Definition: databuffer.c:74
Definition: mcf.h:104
#define DB_ERR_INVALID_BUFFER
Indicates an invalid buffer.
Definition: databuffer.h:35
bool mcfDecodeNext(MCFState *state)
Decodes the next message.
Definition: mcf.c:82
Implements a generic logger facility.
#define DB_BUF_INIT(PTR, LEN)
Simple buffer initialization.
Definition: databuffer.h:63
uint8_t * cur
Current Pointer.
Definition: databuffer.h:49
uint16_t msgId
the message identifier
Definition: msg.h:277
#define E_UNKNOWN
Generic error: Unknown error.
Definition: errorcode.h:97
#define logInfo(MSG,...)
Write a log message with formatting on info level.
Definition: log.h:202