Skip to content

Commit 1646aa7

Browse files
committed
core packet draft
1 parent 7f797c1 commit 1646aa7

File tree

4 files changed

+168
-33
lines changed

4 files changed

+168
-33
lines changed

src/core/core.c

+132-11
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,17 @@
2323
*
2424
*/
2525

26+
#include <ocac/ocp/ocp1.h>
27+
#include <ocac/obj.h>
28+
#include <ocac/occ/datatypes/framework.h>
2629
#include "ocac/core.h"
2730

2831
#include "ocac/session.h"
2932

33+
34+
extern OCAC_OBJ_BASE * ocac_obj_registry_get(OcaONo ono);
35+
36+
3037
void ocac_core_init()
3138
{
3239
ocac_session_init();
@@ -38,7 +45,7 @@ void ocac_core_deinit()
3845
}
3946

4047

41-
void ocac_core_rx_packet(struct ocac_sock * sock, u8_t * inbuf, u16_t inlen, u8_t * outbuf, u16_t maxoutlen)
48+
void ocac_core_rx_packet(struct ocac_sock * sock, u8_t * inbuf, u32_t inlen, u8_t * outbuf, u32_t maxoutlen)
4249
{
4350
OCAC_ASSERT("sock != NULL", sock != NULL);
4451
OCAC_ASSERT("OCAC_NET_TYPE_ISVALID(sock->type)", OCAC_NET_TYPE_ISVALID(sock->type));
@@ -83,12 +90,12 @@ void ocac_core_rx_packet(struct ocac_sock * sock, u8_t * inbuf, u16_t inlen, u8_
8390

8491

8592
// read out PDU header
86-
Ocp1Header header;
93+
Ocp1Header inheader;
8794

88-
ocac_ocp1_header_read(&header, &inbuf[1]);
95+
ocac_ocp1_header_read(&inheader, &inbuf[1]);
8996

9097
// check if actual packet length is equal to inbuffer length (+1 for syn byte)
91-
if (header.pduSize + 1 != inlen){
98+
if (inheader.pduSize + 1 != inlen){
9299

93100
OCAC_DEBUGF(OCAC_DBG_TRACE | OCAC_DBG_LEVEL_WARNING, "Invalid packet length");
94101

@@ -97,18 +104,18 @@ void ocac_core_rx_packet(struct ocac_sock * sock, u8_t * inbuf, u16_t inlen, u8_
97104
}
98105

99106
// messagecount must be at least 1
100-
if (header.messageCount == 0){
107+
if (inheader.messageCount == 0){
101108

102109
OCAC_DEBUGF(OCAC_DBG_TRACE | OCAC_DBG_LEVEL_WARNING, "invalid message count");
103110

104111
// (we could choose not to be so strict about it if the packet length is right)
105112
return;
106113
}
107114

108-
if (header.pduType == OcaMessageType_KeepAlive){
115+
if (inheader.pduType == OcaMessageType_KeepAlive){
109116

110117
// heartbeat messages MUST have a message count of 1 ..
111-
if (header.messageCount != 1){
118+
if (inheader.messageCount != 1){
112119

113120
OCAC_DEBUGF(OCAC_DBG_TRACE | OCAC_DBG_LEVEL_WARNING, "invalid message count");
114121

@@ -151,12 +158,73 @@ void ocac_core_rx_packet(struct ocac_sock * sock, u8_t * inbuf, u16_t inlen, u8_
151158
return;
152159
}
153160

161+
if (inheader.pduType == OcaMessageType_Command || inheader.pduType == OcaMessageType_CommandNR){
162+
163+
u32_t inpos = 1 + sizeof(Ocp1Header); // sync byte + header
164+
u32_t outpos = 1 + sizeof(Ocp1Header);
165+
166+
Ocp1Header outheader;
167+
168+
ocac_memset( &outheader, 0, sizeof(Ocp1Header));
169+
170+
for(u16_t i = 0; i < inheader.messageCount; i++){
171+
172+
// make sure the four first bytes of the message (denoting its total length) are there
173+
if (inpos + 4 > inlen){
174+
OCAC_DEBUGF(OCAC_DBG_TRACE | OCAC_DBG_LEVEL_WARNING, "missing msg size");
175+
return;
176+
}
177+
178+
u32_t len = ocac_ntohl(*(u32_t*)&inbuf[inpos]);
179+
180+
// make sure all bytes of the message are there
181+
if (inpos + len > inlen){
182+
OCAC_DEBUGF(OCAC_DBG_TRACE | OCAC_DBG_LEVEL_WARNING, "missing msg data");
183+
return;
184+
}
185+
186+
Ocp1CommandRef command;
187+
188+
ocac_ocp1_commandref_read(&command, &inbuf[inpos]);
189+
190+
u32_t posbefore = outheader.pduSize;
191+
192+
ocac_core_command_handler(&command, (inheader.pduType == OcaMessageType_Command), &outbuf[outpos], &outpos, maxoutlen, session);
193+
194+
// if the outpos changed, a response was written to outbuf
195+
if (outpos != posbefore){
196+
outheader.messageCount++;
197+
}
198+
199+
inpos += len;
200+
}
201+
202+
// if outpos changed response data was written by the handler
203+
if (outheader.messageCount > 0) {
204+
205+
// finalize header
206+
outheader.pduSize = outpos;
207+
outheader.pduType = OcaMessageType_Response;
208+
outheader.protocolVersion = OCAC_OCA_VERSION;
209+
210+
outbuf[0] = OCP_SYNC_VAL;
211+
212+
//write header to outbuf
213+
ocac_ocp1_header_write(&outbuf[1], &outheader);
214+
215+
// TX of outbuf
216+
ocac_sock_tx(sock, outbuf, outheader.pduSize + 1);
217+
}
218+
219+
return;
220+
}
221+
154222
#if OCAC_USE_RESPONSE_HANDLER == 1
155-
if (header.pduType == OcaMessageType_Response){
223+
if (inheader.pduType == OcaMessageType_Response){
156224

157225
u32_t pos = 1 + sizeof(Ocp1Header);
158226

159-
for(u16_t i = 0; i < header.messageCount; i++){
227+
for(u16_t i = 0; i < inheader.messageCount; i++){
160228

161229
// make sure the four first bytes of the message (denoting its total length) are there
162230
if (pos + 4 > inlen){
@@ -186,11 +254,11 @@ void ocac_core_rx_packet(struct ocac_sock * sock, u8_t * inbuf, u16_t inlen, u8_
186254
#endif //OCAC_USE_RESPONSE_HANDLER == 1
187255

188256
#if OCAC_USE_NOTIFICATION_HANDLER == 1
189-
if (header.pduType == OcaMessageType_Notification){
257+
if (inheader.pduType == OcaMessageType_Notification){
190258

191259
u32_t pos = 1 + sizeof(Ocp1Header);
192260

193-
for(u16_t i = 0; i < header.messageCount; i++){
261+
for(u16_t i = 0; i < inheader.messageCount; i++){
194262

195263
// make sure the four first bytes of the message (denoting its total length) are there
196264
if (pos + 4 > inlen){
@@ -224,6 +292,59 @@ void ocac_core_rx_packet(struct ocac_sock * sock, u8_t * inbuf, u16_t inlen, u8_
224292

225293
}
226294

295+
u8_t ocac_core_command_handler(Ocp1CommandRef * command, u8_t requirersp, u8_t * outbuf, u32_t * outlen, u32_t maxoutlen, struct ocac_session * session)
296+
{
297+
OCAC_ASSERT("command != NULL", command != NULL);
298+
OCAC_ASSERT("outbuf != NULL", outbuf != NULL);
299+
OCAC_ASSERT("outlen != NULL", outlen != NULL);
300+
301+
302+
// if a response is required, make sure there is at least space for response meta data
303+
if (requirersp != 0 && *outlen + sizeof(Ocp1Response) < maxoutlen){
304+
305+
OCAC_DEBUGF(OCAC_DBG_TRACE | OCAC_DBG_LEVEL_WARNING, "not enough space for msg");
306+
307+
return 1;
308+
}
309+
310+
Ocp1ResponseRef response;
311+
312+
response.statusCode = OcaStatus_OK;
313+
314+
// attempt to get the called object
315+
OCAC_OBJ_BASE * obj = ocac_obj_registry_get(command->targetONo);
316+
317+
if (obj == NULL){
318+
response.statusCode = OcaStatus_BadONo;
319+
response.responseSize = 0;
320+
} else {
321+
// note
322+
// developers implementing class methods may intuitively assume that the passed buffer is the starting point
323+
// for writing response data and that the outlen reference thus initially is zero.
324+
// This assumption (which makes developing methods easier in the first place) should be true.
325+
326+
u32_t pos = *outlen + sizeof(Ocp1Response);
327+
u32_t len = 0;
328+
u32_t max = maxoutlen - pos;
329+
330+
// call class method on object
331+
// note: response data is written directly to outbuf
332+
response.statusCode = ocac_obj_exec(obj, command->methodID.DefLevel, command->methodID.MethodIndex, command->parameters.parameters, command->parameters.parameterCount, &outbuf[pos], &len, max, session);
333+
334+
response.responseSize = len;
335+
}
336+
337+
// write response header if either required, there is response data or the command failed
338+
if (requirersp != 0 || response.responseSize > 0 || response.statusCode != OcaStatus_OK){
339+
340+
response.responseSize += sizeof(Ocp1Response);
341+
response.handle = command->handle;
342+
343+
ocac_ocp1_responseref_write(outbuf, &response);
344+
}
345+
346+
return 0;
347+
}
227348

228349
#if OCAC_USE_RESPONSE_HANDLER == 1
229350
__weak void ocac_core_response_handler(Ocp1ResponseRef * response);

src/core/obj.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
#include "ocac/obj.h"
2727

28-
OcaStatus ocac_obj_exec(OCAC_OBJ_BASE * obj, u16_t deflevel, u16_t index, u8_t * req, u16_t reqlen, u8_t * rsp, u16_t * rsplen, u16_t maxrsplen, struct ocac_session * session)
28+
OcaStatus ocac_obj_exec(OCAC_OBJ_BASE * obj, u16_t deflevel, u16_t index, u8_t * req, u32_t reqlen, u8_t * rsp, u32_t * rsplen, u32_t maxrsplen, struct ocac_session * session)
2929
{
3030
OCAC_ASSERT("obj != NULL", obj != NULL);
3131
OCAC_ASSERT("obj->class_ptr != NULL", obj->class_ptr != NULL);

src/include/ocac/core.h

+4-19
Original file line numberDiff line numberDiff line change
@@ -34,31 +34,16 @@
3434
extern "C" {
3535
#endif
3636

37-
//struct ocac_api_buffer {
38-
// Ocp1Header header;
39-
// u16_t maxlen;
40-
// u16_t curlen;
41-
// u8_t * bytes;
42-
//};
43-
//#define OCAC_API_BUFFER_INIT(__bytes__, __maxlen__) {.bytes = __bytes__, .maxlen = __maxlen__, .curlen = 0 }
44-
//
45-
//inline void ocac_api_buffer_init( struct ocac_api_buffer * buf, u8_t * bytes, u16_t maxlen ){
46-
// OCAC_ASSERT("buf != NULL", buf != NULL);
47-
// OCAC_ASSERT("bytes != NULL", bytes != NULL);
48-
// OCAC_ASSERT("maxlen > 0", maxlen > 0);
49-
//
50-
// buf->bytes = bytes;
51-
// buf->maxlen = maxlen;
52-
// buf->curlen = 0;
53-
//}
54-
5537

5638
void ocac_core_init();
5739

5840
void ocac_core_deinit();
5941

6042

61-
void ocac_core_rx_packet(struct ocac_sock *sock, u8_t *inbuf, u16_t inlen, u8_t *outbuf, u16_t maxoutlen);
43+
void ocac_core_rx_packet(struct ocac_sock *sock, u8_t *inbuf, u32_t inlen, u8_t *outbuf, u32_t maxoutlen);
44+
45+
u8_t ocac_core_command_handler(Ocp1CommandRef * command, u8_t requirersp, u8_t * outbuf, u32_t * outlen, u32_t maxoutlen, struct ocac_session * session);
46+
6247

6348
#if OCAC_USE_RESPONSE_HANDLER == 1
6449
void ocac_core_response_handler(Ocp1ResponseRef * response);

src/include/ocac/ocp/ocp1.h

+31-2
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,16 @@ typedef struct {
104104
Ocp1Parameters parameters;
105105
} PACK_STRUCT_STRUCT Ocp1Command;
106106

107+
typedef struct {
108+
OcaUint32 commandSize; // size (in bytes) of complete command segment (incl. commandSize)
109+
OcaUint32 handle; // random command id used for responses
110+
OcaONo targetONo;
111+
OcaMethodID methodID;
112+
struct {
113+
OcaUint8 parameterCount;
114+
OcaUint8 * parameters;
115+
} PACK_STRUCT_STRUCT parameters;
116+
} PACK_STRUCT_STRUCT Ocp1CommandRef;
107117

108118

109119
typedef struct {
@@ -176,13 +186,32 @@ inline void ocac_ocp1_header_read(Ocp1Header * header, u8_t * bytes)
176186
header->messageCount = ocac_ntohs(*(u16_t*)(&bytes[7]));
177187
}
178188

189+
inline void ocac_ocp1_commandref_read(Ocp1CommandRef * cmd, u8_t * bytes)
190+
{
191+
cmd->commandSize = ocac_ntohl(*(u32_t *) (&bytes[0]));
192+
cmd->handle = ocac_ntohl(*(u32_t *) (&bytes[4]));
193+
cmd->targetONo = ocac_ntohl(*(u32_t *) (&bytes[8]));
194+
cmd->methodID.DefLevel = ocac_ntohs(*(u16_t *) (&bytes[12]));
195+
cmd->methodID.DefLevel = ocac_ntohs(*(u16_t *) (&bytes[14]));
196+
cmd->parameters.parameterCount = bytes[15];
197+
cmd->parameters.parameters = &bytes[16];
198+
}
199+
179200
inline void ocac_ocp1_responseref_read(Ocp1ResponseRef * response, u8_t * bytes)
180201
{
181202
response->responseSize = ocac_ntohl(*(u32_t *) (&bytes[0]));
182203
response->handle = ocac_ntohl(*(u32_t *) (&bytes[4]));
183-
response->statusCode = bytes[8];
184-
response->parameters.parameterCount = bytes[9];
204+
response->statusCode = (OcaStatus)bytes[8];
185205
response->parameters.parameterCount = bytes[9];
206+
response->parameters.parameters = &bytes[10];
207+
}
208+
209+
inline void ocac_ocp1_responseref_write(u8_t * bytes, Ocp1ResponseRef * response)
210+
{
211+
*(u32_t *) (&bytes[0]) = response->responseSize;
212+
*(u32_t *) (&bytes[4]) = response->handle;
213+
bytes[8] = (u8_t)response->statusCode;
214+
bytes[9] = response->parameters.parameterCount;
186215
}
187216

188217
inline u8_t ocac_ocp1_notification_read(Ocp1Notification * notification, u8_t * bytes)

0 commit comments

Comments
 (0)