source: EcnlProtoTool/trunk/mrbgems/mruby-ecnl/src/echonet_lcl_task.c@ 321

Last change on this file since 321 was 321, checked in by coas-nagasima, 7 years ago

文字コードを設定

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 18.2 KB
Line 
1/*
2 * TOPPERS ECHONET Lite Communication Middleware
3 *
4 * Copyright (C) 2014-2016 Cores Co., Ltd. Japan
5 *
6 * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
7 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
8 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
9 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
10 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
11 * スコード中に含まれていること.
12 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
13 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
14 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
15 * の無保証規定を掲載すること.
16 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
17 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
18 * と.
19 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
20 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
21 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
22 * 報告すること.
23 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
24 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
25 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
26 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
27 * 免責すること.
28 *
29 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
30 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
31 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
32 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
33 * の責任を負わない.
34 *
35 */
36
37/*
38 * ECHONET Lite LCL通信処理タスク
39 */
40
41#include <mruby.h>
42#include <mruby/data.h>
43#include <mruby/string.h>
44#include <string.h>
45#include <stdio.h>
46#include <stdlib.h>
47
48#include "echonet.h"
49
50#include "echonet_task.h"
51#include "echonet_lcl_task.h"
52#include "echonet_dbg.h"
53#include "mrb_ecnl.h"
54
55#ifndef ECHONET_LCL_TASK_GET_TIMER
56#define ECHONET_LCL_TASK_GET_TIMER TMO_FEVR
57#endif /* ECHONET_LCL_TASK_GET_TIMER */
58
59#ifndef ECHONET_LCL_TASK_PROGRESS
60#define ECHONET_LCL_TASK_PROGRESS(timer)
61#endif /* ECHONET_LCL_TASK_PROGRESS */
62
63#ifndef ECHONET_LCL_TASK_TIMEOUT
64#define ECHONET_LCL_TASK_TIMEOUT
65#endif /* ECHONET_LCL_TASK_TIMEOUT */
66
67#ifndef ECHONET_LCL_SEND_TO_MBX
68#define ECHONET_LCL_SEND_TO_MBX
69#endif /* ECHONET_LCL_SEND_TO_MBX */
70
71static ECN_ENOD_ID lcl_get_id(ecnl_svc_task_t *svc, T_EDATA *edata, const mrb_value ep);
72static mrb_value lcl_get_addr(ecnl_svc_task_t *svc, ECN_ENOD_ID fa_enodid);
73void _ecn_int_msg(ecnl_svc_task_t *svc, ECN_FBS_ID fbs_id, ECN_FBS_SSIZE_T a_snd_len);
74void _ecn_esv_msg(ecnl_svc_task_t *svc, ECN_FBS_ID fbs_id);
75
76/*
77 * 受信したLCLデータをMAILBOXに送る
78 */
79ER _ecn_lcl2mbx(ecnl_svc_task_t *svc, const uint8_t *buffer, size_t fa_len, const mrb_value dst);
80ER _ecn_lcl2mbx(ecnl_svc_task_t *svc, const uint8_t *buffer, size_t fa_len, const mrb_value dst)
81{
82 mrb_state *mrb = svc->mrb;
83 ECN_FBS_ID a_fbs_id = { 0 };
84 ER a_ret = E_OK;
85 ECN_ENOD_ID a_enod_id;
86 union
87 {
88 const uint8_t *buffer;
89 const T_ECN_EDT_HDR *t_esv;
90 } a_rcv_pkt;
91
92 a_rcv_pkt.buffer = buffer;
93 if ( a_rcv_pkt.t_esv->ecn_hdr.ehd1 != ECN_EDH1_ECHONET_LITE /* ECHONET Lite規格 */
94 || a_rcv_pkt.t_esv->ecn_hdr.ehd2 != ECN_EDH2_FORMAT_1 /* 電文形式1 */) {
95 ECN_DBG_PUT_2("[LCL ECHO SRV] illegal type (0x%02X,0x%02X)", a_rcv_pkt.t_esv->ecn_hdr.ehd1, a_rcv_pkt.t_esv->ecn_hdr.ehd2);
96 return E_PAR;
97 }
98
99#ifdef ECN_DBG_PUT_ENA
100 _ecn_dbg_bindmp(buffer, fa_len);
101#endif
102
103 a_ret = _ecn_fbs_cre(mrb, fa_len, &a_fbs_id);
104 if (a_ret != E_OK) {
105 ECN_DBG_PUT_2("[LCL ECHO SRV] _ecn_fbs_cre() result = %d:%s", a_ret, itron_strerror(a_ret));
106 return a_ret;
107 }
108 a_ret = _ecn_fbs_add_data_ex(mrb, a_fbs_id, buffer, fa_len);
109 if (a_ret) {
110 ECN_DBG_PUT_2("[LCL ECHO SRV] _ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
111 goto lb_except;
112 }
113 a_fbs_id.ptr->hdr.type = ECN_MSG_ECHONET;
114 a_fbs_id.ptr->hdr.target.id = ENOD_LOCAL_ID;
115 a_fbs_id.ptr->hdr.sender.id = ENOD_NOT_MATCH_ID;
116
117 /* 通信レイヤーアドレスからリモートECHONETノードへ変換 */
118 a_enod_id = lcl_get_id(svc, (T_EDATA *)a_fbs_id.ptr, dst);
119 if (!lcl_is_valid_addrid(svc, a_enod_id)) {
120 ECN_DBG_PUT_1("[LCL ECHO SRV] lcl src(%s) echonet-node not found.",
121 ip2str(NULL, &dst->lcladdr));
122 } else {
123 /* 送信元ECHONETノードを記録 */
124 a_fbs_id.ptr->hdr.sender.id = a_enod_id;
125 }
126 a_fbs_id.ptr->hdr.reply.id = a_fbs_id.ptr->hdr.sender.id;
127
128 /* echonet_taskに送る */
129 a_ret = ecn_fbs_enqueue(&svc->svc_mbxid, a_fbs_id.ptr);
130 if (a_ret != E_OK) {
131 ECN_DBG_PUT_2("[LCL ECHO SRV] snd_mbx(svc->svc_mbxid) result = %d:%s", a_ret, itron_strerror(a_ret));
132 goto lb_except;
133 }
134 return a_ret;
135lb_except:
136 _ecn_fbs_del(mrb, a_fbs_id);
137 return a_ret;
138}
139
140/*
141* ECHONET Lite 通信レイヤータスク タイマー値取得
142*/
143TMO echonet_lcltask_get_timer(ecnl_svc_task_t *svc)
144{
145 TMO a_timer;
146
147 a_timer = ECHONET_LCL_TASK_GET_TIMER;
148
149 return a_timer;
150}
151
152
153/*
154* ECHONET Lite 通信レイヤータスク 時間経過処理
155*/
156void echonet_lcltask_progress(ecnl_svc_task_t *svc, TMO a_timer)
157{
158 ECHONET_LCL_TASK_PROGRESS(a_timer);
159}
160
161/*
162* ECHONET Lite 通信レイヤータスク メッセージ受信処理
163*/
164void echonet_lcltask_recv_msg(ecnl_svc_task_t *svc, T_ECN_FST_BLK *p_msg)
165{
166 ECN_FBS_ID a_fbs_id;
167 ECN_FBS_SSIZE_T a_snd_len;
168
169 a_fbs_id.ptr = p_msg;
170
171 /* 送信データ長を取得 */
172 a_snd_len = _ecn_fbs_get_datalen(a_fbs_id);
173
174 ECN_DBG_PUT_1("trcv_dtq() mbx recv (%d byte)", a_snd_len);
175
176 switch (a_fbs_id.ptr->hdr.type) {
177 /* 内部使用メッセージ */
178 case ECN_MSG_INTERNAL:
179 _ecn_int_msg(svc, a_fbs_id, a_snd_len);
180 break;
181
182 /* ECHONET用メッセージ */
183 case ECN_MSG_ECHONET:
184 _ecn_esv_msg(svc, a_fbs_id);
185 break;
186
187 default:
188 ECN_DBG_PUT_1("echonet_task() a_fbs_id.ptr->k.hdr.k.t_edt.type:0x%02X undefined.", a_fbs_id.ptr->hdr.type);
189 }
190
191 /* 領域解放 */
192 _ecn_fbs_del(svc->mrb, a_fbs_id);
193}
194
195/*
196* ECHONET Lite 通信レイヤータスク タイムアウト処理
197*/
198void echonet_lcltask_timeout(ecnl_svc_task_t *svc)
199{
200 ECHONET_LCL_TASK_TIMEOUT;
201}
202
203/* 応答電文用fbs設定(sender/targetの設定) */
204static ER _ecn_lcl_cre_req_fbs(ecnl_svc_task_t *svc, T_ECN_FBS_QUEUE *sender, uint8_t cmd, ECN_FBS_ID *pk_req)
205{
206 mrb_state *mrb = svc->mrb;
207 ER ret;
208 ECN_FBS_ID req;
209
210 ret = _ecn_fbs_cre(mrb, 1, &req);
211 if (ret != E_OK) {
212 ECN_DBG_PUT_2("_ecn_lcl_cre_req_fbs() : _ecn_fbs_cre() result = %d:%s", ret, itron_strerror(ret));
213 return ret;
214 }
215
216 ret = _ecn_fbs_add_data(mrb, req, &cmd, sizeof(cmd));
217 if (ret != E_OK) {
218 _ecn_fbs_del(mrb, req);
219 ECN_DBG_PUT_2("_ecn_lcl_cre_req_fbs() : _ecn_fbs_add_data() result = %d:%s", ret, itron_strerror(ret));
220 return ret;
221 }
222
223 req.ptr->hdr.type = ECN_MSG_INTERNAL;
224 req.ptr->hdr.sender.mbxid = sender;
225 req.ptr->hdr.target.mbxid = &svc->lcl_mbxid;
226 req.ptr->hdr.reply.mbxid = sender;
227
228 *pk_req = req;
229
230 return E_OK;
231}
232
233/* 応答電文用fbs設定(sender/targetの設定) */
234static ER _ecn_lcl_cre_res_fbs(ecnl_svc_task_t *svc, ECN_FBS_ID req, uint8_t cmd, ECN_FBS_ID *pk_res)
235{
236 mrb_state *mrb = svc->mrb;
237 ER ret;
238 ECN_FBS_ID res;
239
240 ret = _ecn_fbs_cre(mrb, 1, &res);
241 if (ret != E_OK) {
242 ECN_DBG_PUT_2("_ecn_lcl_cre_res_fbs() : _ecn_fbs_cre() result = %d:%s", ret, itron_strerror(ret));
243 return ret;
244 }
245
246 ret = _ecn_fbs_add_data(mrb, res, &cmd, sizeof(cmd));
247 if (ret != E_OK) {
248 _ecn_fbs_del(mrb, res);
249 ECN_DBG_PUT_2("_ecn_lcl_cre_res_fbs() : _ecn_fbs_add_data() result = %d:%s", ret, itron_strerror(ret));
250 return ret;
251 }
252
253 res.ptr->hdr.type = ECN_MSG_INTERNAL;
254 res.ptr->hdr.sender.mbxid = &svc->lcl_mbxid;
255 res.ptr->hdr.target.mbxid = req.ptr->hdr.reply.mbxid;
256 res.ptr->hdr.reply.mbxid = &svc->lcl_mbxid;
257
258 *pk_res = res;
259
260 return E_OK;
261}
262
263/*
264 * 内部メッセージ受信処理
265 */
266void _ecn_int_msg(ecnl_svc_task_t *svc, ECN_FBS_ID fbs_id, ECN_FBS_SSIZE_T a_snd_len)
267{
268 mrb_state *mrb = svc->mrb;
269 ER result = E_OK, a_ret;
270 ecn_lcl_msg_get_lcladdr_req_t msg;
271 ecn_lcl_msg_get_lcladdr_error_t err;
272 ECN_FBS_SSIZE_T len;
273 ECN_FBS_ID buf;
274 uint8_t cmd;
275 mrb_value addr;
276
277 a_ret = _ecn_fbs_get_data(mrb, fbs_id, &cmd, 1, &len);
278 if (a_ret != E_OK) {
279 ECN_DBG_PUT_2("[LCL TSK] _ecn_fbs_get_data() result = %d:%s", a_ret, itron_strerror(a_ret));
280 return;
281 }
282
283 switch(cmd){
284 // 通信レイヤーアドレスを返信
285 case ECN_LCL_MSG_GET_LCLADDR_REQ:
286 if (a_snd_len < sizeof(msg)) {
287 result = E_PAR;
288 break;
289 }
290
291 a_snd_len = 0;
292 a_ret = _ecn_fbs_get_data(mrb, fbs_id, &msg, sizeof(msg), &a_snd_len);
293 if (a_ret != E_OK) {
294 ECN_DBG_PUT_2("[LCL TSK] _ecn_fbs_get_data() result = %d:%s", a_ret, itron_strerror(a_ret));
295 }
296
297 if (!lcl_is_valid_addrid(svc, msg.enodid)) {
298 result = E_PAR;
299 break;
300 }
301
302 a_ret = _ecn_lcl_cre_res_fbs(svc, fbs_id, ECN_LCL_MSG_GET_LCLADDR_RES, &buf);
303 if (a_ret != E_OK) {
304 return;
305 }
306
307 a_ret = _ecn_fbs_add_data_ex(mrb, buf, &msg.requestid, offsetof(ecn_lcl_msg_get_lcladdr_res_t, enodadrb));
308 if (a_ret != E_OK) {
309 _ecn_fbs_del(mrb, buf);
310 ECN_DBG_PUT_2("_ecn_int_msg() : _ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
311 return;
312 }
313
314 addr = lcl_get_remote_addr(svc, msg.enodid);
315 a_ret = _ecn_fbs_add_data_ex(mrb, buf, &addr, sizeof(addr));
316 if (a_ret != E_OK) {
317 _ecn_fbs_del(mrb, buf);
318 ECN_DBG_PUT_2("_ecn_int_msg() : _ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
319 return;
320 }
321
322 a_ret = ecn_fbs_enqueue(buf.ptr->hdr.target.mbxid, buf.ptr);
323 if (a_ret != E_OK) {
324 _ecn_fbs_del(mrb, buf);
325 ECN_DBG_PUT_2("_ecn_int_msg() : psnd_dtq() result = %d:%s", a_ret, itron_strerror(a_ret));
326 return;
327 }
328 return;
329 }
330
331 a_ret = _ecn_lcl_cre_res_fbs(svc, fbs_id, ECN_LCL_MSG_GET_LCLADDR_ERROR, &buf);
332 if (a_ret != E_OK) {
333 return;
334 }
335
336 err.requestid = msg.requestid;
337 err.error = result;
338 a_ret = _ecn_fbs_add_data_ex(mrb, buf, &err, sizeof(err));
339 if (a_ret != E_OK) {
340 _ecn_fbs_del(mrb, buf);
341 ECN_DBG_PUT_2("_ecn_int_msg() : _ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
342 return;
343 }
344
345 a_ret = ecn_fbs_enqueue(buf.ptr->hdr.target.mbxid, buf.ptr);
346 if (a_ret != E_OK) {
347 _ecn_fbs_del(mrb, buf);
348 ECN_DBG_PUT_2("_ecn_int_msg() : psnd_dtq() result = %d:%s", a_ret, itron_strerror(a_ret));
349 return;
350 }
351}
352
353/*
354 * ECHONET 電文受信処理
355 */
356void _ecn_esv_msg(ecnl_svc_task_t *svc, ECN_FBS_ID fbs_id)
357{
358 mrb_state *mrb = svc->mrb;
359 size_t a_len = _ecn_fbs_get_datalen(fbs_id);
360 mrb_value a_msg;
361 mrb_value a_dst;
362 ER a_ret;
363 ECN_FBS_SSIZE_T a_snd_len;
364
365 /* 送信先通信レイヤーアドレス */
366 a_dst = lcl_get_addr(svc, fbs_id.ptr->hdr.target.id);
367 if (mrb_type(a_dst) != MRB_TT_FALSE/*nil*/) {
368 ECN_DBG_PUT_4("[LCL TSK] echonet-node 0x%02X-0x%02X-0x%02X → lcl dest(%s)",
369 ((T_EDATA *)fbs_id.ptr)->hdr.edata.deoj.eojx1,
370 ((T_EDATA *)fbs_id.ptr)->hdr.edata.deoj.eojx2,
371 ((T_EDATA *)fbs_id.ptr)->hdr.edata.deoj.eojx3,
372 ip2str(NULL, &a_dst.lcladdr));
373
374 a_msg = mrb_str_buf_new(mrb, a_len);
375
376 /* fbsから出力領域にデータを抽出 */
377 a_snd_len = 0;
378 a_ret = _ecn_fbs_get_data(mrb, fbs_id, RSTRING_PTR(a_msg), a_len, &a_snd_len);
379 if (a_ret != E_OK) {
380 ECN_DBG_PUT_2("[UDP TSK] _ecn_fbs_get_data() result = %d:%s", a_ret, itron_strerror(a_ret));
381 }
382 else if (lcl_is_local_addr(svc, a_dst)) {
383 RSTR_SET_LEN(RSTRING(a_msg), a_snd_len);
384
385 /* 送信先が127.0.0.1 → mbxに転送 */
386 ECN_DBG_PUT_1("redirect svc->lcl_mbxid → svc->svc_mbxid (esv:0x%02X)",
387 ((T_EDATA *)fbs_id.ptr)->hdr.edata.esv);
388
389 a_ret = _ecn_lcl2mbx(svc, (const uint8_t *)RSTRING_PTR(a_msg), RSTRING_LEN(a_msg), a_dst);
390 if (a_ret != E_OK) {
391 ECN_DBG_PUT_2("_ecn_esv_msg() : _ecn_lcl2mbx() result = %d:%s", a_ret, itron_strerror(a_ret));
392 }
393 }
394 else {
395 RSTR_SET_LEN(RSTRING(a_msg), a_snd_len);
396
397 ECN_DBG_PUT_2("[LCL TSK] lcl_snd_dat() to:%s %ubyte(s)",
398 ip2str(NULL, &a_dst.lcladdr), a_snd_len);
399#ifdef ECN_DBG_PUT_ENA
400 _ecn_dbg_bindmp(RSTRING_PTR(a_msg), a_snd_len);
401#endif
402 /* 通信レイヤーへ送信 */
403 a_ret = lcl_snd_msg(svc, a_dst, a_msg);
404 if (a_ret < 0) {
405 ECN_DBG_PUT_1("[LCL TSK] send, error: %s", itron_strerror(a_ret));
406 }
407 }
408
409 /* データが長すぎて1パケットに収まらなかった場合 */
410 if (_ecn_fbs_exist_data(fbs_id)) {
411 ECN_DBG_PUT_1("[LCL TSK] send, data so long: %dbyte(s)", _ecn_fbs_get_datalen(fbs_id));
412 }
413 } else {
414 ECN_DBG_PUT_3("[LCL TSK] echonet-node 0x%02X-0x%02X-0x%02X not found.",
415 ((T_EDATA *)fbs_id.ptr)->hdr.edata.deoj.eojx1,
416 ((T_EDATA *)fbs_id.ptr)->hdr.edata.deoj.eojx2,
417 ((T_EDATA *)fbs_id.ptr)->hdr.edata.deoj.eojx3);
418 }
419}
420
421/*
422 * ノンブロッキングコールのコールバック関数
423 */
424ER echonet_lcl_input_msg(ecnl_svc_task_t *svc, mrb_value ep, mrb_value data)
425{
426 ECHONET_LCL_SEND_TO_MBX;
427
428 _ecn_lcl2mbx(svc, (const uint8_t *)RSTRING_PTR(data), RSTRING_LEN(data), ep);
429
430 return E_OK;
431}
432
433/*
434 * リモートECHONETノードの適合確認
435 */
436bool_t ecn_is_match(ecnl_svc_task_t *svc, const EOBJCB *enodcb, T_EDATA *edata, mrb_value ep)
437{
438 mrb_state *mrb = svc->mrb;
439 ER ret;
440 T_ENUM_EPC enm;
441 uint8_t epc;
442 uint8_t pdc;
443 uint8_t p_edt[256];
444 int i, j, k;
445 int count;
446 const EOBJINIB *p_eobj;
447 bool_t match;
448
449 if (!edata)
450 return false;
451
452 /* ノードスタート時インスタンスリスト通知以外は除外 */
453 if ( edata->hdr.edata.esv != ESV_INF
454 || edata->hdr.edata.deoj.eojx1 != EOJ_X1_PROFILE
455 || edata->hdr.edata.deoj.eojx2 != EOJ_X2_NODE_PROFILE
456 || edata->hdr.edata.deoj.eojx3 != 0x01
457 || edata->hdr.edata.seoj.eojx1 != EOJ_X1_PROFILE
458 || edata->hdr.edata.seoj.eojx2 != EOJ_X2_NODE_PROFILE
459 || ( edata->hdr.edata.seoj.eojx3 != 0x01
460 && edata->hdr.edata.seoj.eojx3 != 0x02)) {
461 return false;
462 }
463
464 ret = ecn_itr_ini(&enm, edata);
465 if (ret) {
466 ECN_DBG_PUT_2("ecn_is_match(): ecn_itr_ini() result = %d:%s", ret, itron_strerror(ret));
467 return false;
468 }
469 while ((ret = ecn_itr_nxt(mrb, &enm, &epc, &pdc, p_edt)) == E_OK) {
470 if (enm.is_eof) {
471 break;
472 }
473 ECN_DBG_PUT_2("ecn_is_match(): ecn_itr_nxt() result: epc=0x%02X, pdc=%d", epc, pdc);
474 /* インスタンスリスト通知または自ノードインスタンスリストS以外は除外 */
475 if ((epc != 0xD5) && (epc != 0xD6)) {
476 continue;
477 }
478
479 /* 2バイト目以降にeojが列挙されている */
480 count = (pdc - 1) / sizeof(T_ECN_EOJ);
481
482 /* ノード内の機器オブジェクトを検索 */
483 for (k = 0; k < enodcb->eobjcnt; k++) {
484 p_eobj = enodcb->eobjs[k];
485
486 /* インスタンスリストを確認 */
487 match = false;
488 for (i = 0, j = 1; i < count; i++, j += sizeof(T_ECN_EOJ)) {
489 if (p_eobj->eojx1 != p_edt[j])
490 continue;
491 if (p_eobj->eojx2 != p_edt[j + 1])
492 continue;
493 if (p_eobj->eojx3 != p_edt[j + 2])
494 continue;
495
496 match = true;
497 break;
498 }
499
500 if (!match)
501 return false;
502 }
503
504 /* すべて揃っていたら適合(インスタンスリストの方が多くてもいいこととする) */
505 return true;
506 }
507
508 return false;
509}
510
511/*
512 * 通信レイヤーアドレスからリモートECHONETノードへ変換
513 */
514ECN_ENOD_ID lcl_get_id(ecnl_svc_task_t *svc, T_EDATA *edata, const mrb_value ep)
515{
516 ECN_ENOD_ID id;
517
518 if (lcl_is_local_addr(svc, ep))
519 return ENOD_LOCAL_ID;
520 if (lcl_is_multicast_addr(svc, ep))
521 return ENOD_MULTICAST_ID;
522
523 /* 通信レイヤーアドレスの同じものを検索 */
524 if ((id = lcl_get_remote_id(svc, ep)) != ENOD_NOT_MATCH_ID) {
525 ECN_CAP_PUT_2("lcl_get_id(): ip-found remote(%d) = %s",
526 id - ENOD_REMOTE_ID, ip2str(NULL, &lcladdr));
527 return id;
528 }
529
530 /* 対応するリモートノードがあれば通信レイヤーアドレスを設定 */
531 if ((id = lcl_set_remote_addr(svc, edata, ep)) != ENOD_NOT_MATCH_ID) {
532 ECN_CAP_PUT_2("lcl_get_id(): enod-found remote(%d) = %s",
533 id - ENOD_REMOTE_ID, ip2str(NULL, &lcladdr));
534 return id;
535 }
536
537 /* 空き領域を探して自動登録 */
538 if ((id = lcl_add_remote_addr(svc, edata, ep)) != ENOD_NOT_MATCH_ID) {
539 ECN_CAP_PUT_2("lcl_get_id(): empty-found remote(%d) = %s",
540 id - ENOD_REMOTE_ID, ip2str(NULL, &lcladdr));
541 return id;
542 }
543
544 return ENOD_NOT_MATCH_ID;
545}
546
547/*
548 * リモートECHONETノードから通信レイヤーアドレスへ変換
549 */
550mrb_value lcl_get_addr(ecnl_svc_task_t *svc, ECN_ENOD_ID fa_enodid)
551{
552 if (fa_enodid == ENOD_MULTICAST_ID) {
553 /* targetがENOD_MULTICAST_IDの場合、マルチキャストを行う */
554 return lcl_get_multicast_addr(svc);
555 }
556
557 if (fa_enodid < ENOD_REMOTE_ID) {
558 /* targetが未定義・LOCAL・APIの場合、ローカル配送を行う */
559 return lcl_get_local_addr(svc);
560 }
561
562 return lcl_get_remote_addr(svc, fa_enodid);
563}
564
565ER ecn_lcl_get_lcladdr(ecnl_svc_task_t *svc, T_ECN_FBS_QUEUE *sender, int requestid, ECN_ENOD_ID enodid, ECN_FBS_ID *pk_req)
566{
567 mrb_state *mrb = svc->mrb;
568 ER a_ret;
569 ECN_FBS_ID req;
570 mrb_value addr;
571
572 a_ret = _ecn_lcl_cre_req_fbs(svc, sender, ECN_LCL_MSG_GET_LCLADDR_REQ, &req);
573 if (a_ret != E_OK) {
574 return a_ret;
575 }
576
577 a_ret = _ecn_fbs_add_data_ex(mrb, req, &requestid, sizeof(((ecn_lcl_msg_get_lcladdr_res_t *)0)->requestid));
578 if (a_ret != E_OK) {
579 _ecn_fbs_del(mrb, req);
580 ECN_DBG_PUT_2("ecn_lcl_get_lcladdr() : _ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
581 return a_ret;
582 }
583
584 a_ret = _ecn_fbs_add_data_ex(mrb, req, &enodid, sizeof(((ecn_lcl_msg_get_lcladdr_res_t *)0)->enodid));
585 if (a_ret != E_OK) {
586 _ecn_fbs_del(mrb, req);
587 ECN_DBG_PUT_2("ecn_lcl_get_lcladdr() : _ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
588 return a_ret;
589 }
590
591 addr = lcl_get_remote_addr(svc, enodid);
592 a_ret = _ecn_fbs_add_data_ex(mrb, req, &addr, sizeof(addr));
593 if (a_ret != E_OK) {
594 _ecn_fbs_del(mrb, req);
595 ECN_DBG_PUT_2("ecn_lcl_get_lcladdr() : _ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
596 return a_ret;
597 }
598
599 *pk_req = req;
600
601 return E_OK;
602}
Note: See TracBrowser for help on using the repository browser.