source: azure_iot_hub/trunk/ntshell/echonet/echonet_udp6_task.c@ 388

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

Azure IoT Hub Device C SDK を使ったサンプルの追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 21.9 KB
Line 
1/*
2 * TOPPERS ECHONET Lite Communication Middleware
3 *
4 * Copyright (C) 2014 Cores Co., Ltd. Japan
5 *
6 * 上記著作権者
7は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
8 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
9 * 変・再é…
10å¸ƒï¼ˆä»¥ä¸‹ï¼Œåˆ©ç”¨ã¨å‘¼ã¶ï¼‰ã™ã‚‹ã“とを無償で許諾する.
11 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
12 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
13 * スコード中に含まれていること.
14 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
15 * 用できる形で再é…
16å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
17å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
18 * 者
19マニュアルなど)に,上記の著作権表示,この利用条件および下記
20 * の無保証規定を掲載すること.
21 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
22 * 用できない形で再é…
23å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®ã„ずれかの条件を満たすこ
24 * と.
25 * (a) 再é…
26å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
27マニュアルなど)に,上記の著
28 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
29 * (b) 再é…
30å¸ƒã®å½¢æ…
31‹ã‚’,別に定める方法によって,TOPPERSプロジェクトに
32 * 報告すること.
33 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
34 * 害からも,上記著作権者
35およびTOPPERSプロジェクトをå…
36è²¬ã™ã‚‹ã“と.
37 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
38 * 由に基づく請求からも,上記著作権者
39およびTOPPERSプロジェクトを
40 * å…
41è²¬ã™ã‚‹ã“と.
42 *
43 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者
44お
45 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
46 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
47 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
48 * の責任を負わない.
49 *
50 * @(#) $Id: echonet_udp6_task.c 388 2019-05-22 11:25:18Z coas-nagasima $
51 */
52
53/*
54 * ECHONET Lite UDP通信処理タスク
55 */
56#if 0 //def SUPPORT_INET6
57
58#include <kernel.h>
59#include <string.h>
60#include <stdio.h>
61#include <stdlib.h>
62#include <t_syslog.h>
63#include <t_stdlib.h>
64#include <sil.h>
65
66#include "syssvc/serial.h"
67#include "syssvc/syslog.h"
68#include "echonet.h"
69
70#include <tinet_config.h>
71#include <tinet_defs.h>
72#include <net/net.h>
73#include <netinet/in.h>
74#include <netinet/in_var.h>
75#include <net/ethernet.h>
76#include <net/if.h>
77#include <net/if_var.h>
78#include <net/if6_var.h>
79#include <netinet/in_itron.h>
80
81#include "echonet_task.h"
82#include "echonet_lcl_task.h"
83#include "echonet_dbg.h"
84
85#ifndef ECHONET_UDP_TASK_GET_TIMER
86#define ECHONET_UDP_TASK_GET_TIMER TMO_FEVR
87#endif /* ECHONET_UDP_TASK_GET_TIMER */
88
89#ifndef ECHONET_UDP_TASK_PROGRESS
90#define ECHONET_UDP_TASK_PROGRESS(timer)
91#endif /* ECHONET_UDP_TASK_PROGRESS */
92
93#ifndef ECHONET_UDP_TASK_TIMEOUT
94#define ECHONET_UDP_TASK_TIMEOUT
95#endif /* ECHONET_UDP_TASK_TIMEOUT */
96
97#ifndef ECHONET_UDP_SEND_TO_MBX
98#define ECHONET_UDP_SEND_TO_MBX
99#endif /* ECHONET_UDP_SEND_TO_MBX */
100
101#ifndef ECHONET_NODE_MATCH
102#define ECHONET_NODE_MATCH(enodcb, edata, ipaddr, portno) is_match(enodcb, edata, ipaddr, portno)
103#endif /* ECHONET_NODE_MATCH */
104
105#define IPV6_ADDR_LOCAL_LOOPBACK_INIT \
106 {{{ UINT_C(0x00), UINT_C(0x00), UINT_C(0x00), UINT_C(0x00), \
107 UINT_C(0x00), UINT_C(0x00), UINT_C(0x00), UINT_C(0x00), \
108 UINT_C(0x00), UINT_C(0x00), UINT_C(0x00), UINT_C(0x00), \
109 UINT_C(0x00), UINT_C(0x00), UINT_C(0x00), UINT_C(0x01) }}}
110
111static ECN_ENOD_ID udp_get_id(T_EDATA *edata, const T_IN6_ADDR ipaddr, uint16_t portno);
112static int udp_get_ip(T_IPV6EP *fp_ipep, ECN_ENOD_ID fa_enodid);
113void _ecn_int_msg(ECN_FBS_ID fbs_id, ECN_FBS_SSIZE_T a_snd_len);
114void _ecn_esv_msg(ECN_FBS_ID fbs_id);
115
116/*
117 * 受信したUDPデータをMAILBOXに送る
118 */
119ER _ecn_udp2dtq(const uint8_t *buffer, size_t fa_len, const T_IPV6EP *dst);
120ER _ecn_udp2dtq(const uint8_t *buffer, size_t fa_len, const T_IPV6EP *dst)
121{
122 ECN_FBS_ID a_fbs_id = { 0 };
123 ER a_ret = E_OK;
124 ECN_ENOD_ID a_enod_id;
125 union
126 {
127 const uint8_t *buffer;
128 const T_ECN_EDT_HDR *t_esv;
129 } a_rcv_pkt;
130
131 a_rcv_pkt.buffer = buffer;
132 if ( a_rcv_pkt.t_esv->ecn_hdr.ehd1 != ECN_EDH1_ECHONET_LITE /* ECHONET Lite規格 */
133 || a_rcv_pkt.t_esv->ecn_hdr.ehd2 != ECN_EDH2_FORMAT_1 /* 電文形式1 */) {
134 ECN_DBG_PUT_2("[UDP ECHO SRV] illegal type (0x%02X,0x%02X)", a_rcv_pkt.t_esv->ecn_hdr.ehd1, a_rcv_pkt.t_esv->ecn_hdr.ehd2);
135 return E_PAR;
136 }
137
138#ifdef ECN_DBG_PUT_ENA
139 _ecn_dbg_bindmp(buffer, fa_len);
140#endif
141
142 a_ret = _ecn_fbs_cre(fa_len, &a_fbs_id);
143 if (a_ret != E_OK) {
144 ECN_DBG_PUT_2("[UDP ECHO SRV] _ecn_fbs_cre() result = %d:%s", a_ret, itron_strerror(a_ret));
145 return a_ret;
146 }
147 a_ret = _ecn_fbs_add_data_ex(a_fbs_id, buffer, fa_len);
148 if (a_ret) {
149 ECN_DBG_PUT_2("[UDP ECHO SRV] _ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
150 goto lb_except;
151 }
152 a_fbs_id.ptr->hdr.type = ECN_MSG_ECHONET;
153 a_fbs_id.ptr->hdr.target.id = ENOD_LOCAL_ID;
154 a_fbs_id.ptr->hdr.sender.id = ENOD_NOT_MATCH_ID;
155
156 /* IPアドレスからリモートECHONETノードへ変換 */
157 a_enod_id = udp_get_id((T_EDATA *)a_fbs_id.ptr, dst->ipaddr, dst->portno);
158 if (a_enod_id < 0 || tnum_enodadr <= a_enod_id) {
159 ECN_DBG_PUT_1("[UDP ECHO SRV] udp src(%s) echonet-node not found.",
160 ipv62str(NULL, &dst->ipaddr));
161 } else {
162 /* 送信å…
163ƒECHONETノードを記録 */
164 a_fbs_id.ptr->hdr.sender.id = a_enod_id;
165 }
166 a_fbs_id.ptr->hdr.reply.id = a_fbs_id.ptr->hdr.sender.id;
167
168 /* echonet_taskに送る */
169 a_ret = snd_dtq(ecn_svc_dataqueueid, (intptr_t)a_fbs_id.ptr);
170 if (a_ret != E_OK) {
171 ECN_DBG_PUT_2("[UDP ECHO SRV] snd_dtq(ecn_svc_dataqueueid) result = %d:%s", a_ret, itron_strerror(a_ret));
172 goto lb_except;
173 }
174 return a_ret;
175lb_except:
176 _ecn_fbs_del(a_fbs_id);
177 return a_ret;
178}
179
180/*
181 * ECHONET UDP通信処理タスク
182 */
183void echonet_udp_task(intptr_t exinf)
184{
185 T_IN6_ADDR a_src;
186 ER a_ret, a_ret2;
187 ID tskid;
188 ECN_FBS_SSIZE_T a_snd_len;
189 union
190 {
191 T_MSG *p_msg;
192 ECN_FBS_ID fbs_id;
193 } a_mdt;
194 SYSTIM a_prev, a_now;
195 int a_timer;
196
197 get_tid(&tskid);
198 memcpy(&a_src, in6_get_ifaddr(0), sizeof(T_IN6_ADDR));
199 ECN_DBG_PUT_4("[UDP TSK:%d,%d] started, IP Address: %s ether_max_len: %u",
200 tskid, exinf,
201 ipv62str(NULL, &a_src),
202 ETHER_MAX_LEN);
203 memcpy(enodadrb_table[ENOD_LOCAL_ID].ipaddr, &a_src, sizeof(T_IN6_ADDR));
204
205 syscall(act_tsk(ecn_svc_taskid));
206
207 a_ret = get_tim(&a_now);
208 if (a_ret != E_OK) {
209 ECN_DBG_PUT_2("get_tim() result = %d:%s", a_ret, itron_strerror(a_ret));
210 return;
211 }
212
213 /* メッセージループ */
214 for (;;) {
215 a_prev = a_now;
216
217 a_timer = ECHONET_UDP_TASK_GET_TIMER;
218
219 a_ret = trcv_dtq(ecn_udp_dataqueueid, (intptr_t *)&a_mdt.p_msg, a_timer);
220 if ((a_ret != E_OK) && (a_ret != E_TMOUT)) {
221 ECN_DBG_PUT_2("trcv_dtq() result = %d:%s", a_ret, itron_strerror(a_ret));
222 break;
223 }
224
225 a_ret2 = get_tim(&a_now);
226 if (a_ret2 != E_OK) {
227 ECN_DBG_PUT_2("get_tim() result = %d:%s", a_ret2, itron_strerror(a_ret2));
228 break;
229 }
230
231 a_timer = a_now - a_prev;
232 ECHONET_UDP_TASK_PROGRESS(a_timer);
233
234 if (a_ret == E_OK) {
235 /* 送信データ長を取得 */
236 a_snd_len = _ecn_fbs_get_datalen(a_mdt.fbs_id);
237
238 ECN_DBG_PUT_1("[UDP TSK] trcv_dtq() dtq recv (%d byte)", _ecn_fbs_get_datalen(a_mdt.fbs_id));
239
240 if (0 < a_snd_len) {
241 switch(a_mdt.fbs_id.ptr->hdr.type){
242 case ECN_MSG_INTERNAL:
243 _ecn_int_msg(a_mdt.fbs_id, a_snd_len);
244 break;
245 case ECN_MSG_ECHONET:
246 _ecn_esv_msg(a_mdt.fbs_id);
247 break;
248 }
249 }
250
251 _ecn_fbs_del(a_mdt.fbs_id);
252 }
253
254 ECHONET_UDP_TASK_TIMEOUT;
255 }
256}
257
258/* 応答電文用fbs設定(sender/targetの設定) */
259static ER _ecn_udp_cre_req_fbs(ID sender, uint8_t cmd, ECN_FBS_ID *pk_req)
260{
261 ER ret;
262 ECN_FBS_ID req;
263
264 ret = _ecn_fbs_cre(1, &req);
265 if (ret != E_OK) {
266 ECN_DBG_PUT_2("_ecn_udp_cre_req_fbs() : _ecn_fbs_cre() result = %d:%s", ret, itron_strerror(ret));
267 return ret;
268 }
269
270 ret = _ecn_fbs_add_data(req, &cmd, sizeof(cmd));
271 if (ret != E_OK) {
272 _ecn_fbs_del(req);
273 ECN_DBG_PUT_2("_ecn_udp_cre_req_fbs() : _ecn_fbs_add_data() result = %d:%s", ret, itron_strerror(ret));
274 return ret;
275 }
276
277 req.ptr->hdr.type = ECN_MSG_INTERNAL;
278 req.ptr->hdr.sender.dtqid = sender;
279 req.ptr->hdr.target.dtqid = ecn_udp_dataqueueid;
280 req.ptr->hdr.reply.dtqid = sender;
281
282 *pk_req = req;
283
284 return E_OK;
285}
286
287/* 応答電文用fbs設定(sender/targetの設定) */
288static ER _ecn_udp_cre_res_fbs(ECN_FBS_ID req, uint8_t cmd, ECN_FBS_ID *pk_res)
289{
290 ER ret;
291 ECN_FBS_ID res;
292
293 ret = _ecn_fbs_cre(1, &res);
294 if (ret != E_OK) {
295 ECN_DBG_PUT_2("_ecn_udp_cre_res_fbs() : _ecn_fbs_cre() result = %d:%s", ret, itron_strerror(ret));
296 return ret;
297 }
298
299 ret = _ecn_fbs_add_data(res, &cmd, sizeof(cmd));
300 if (ret != E_OK) {
301 _ecn_fbs_del(res);
302 ECN_DBG_PUT_2("_ecn_udp_cre_res_fbs() : _ecn_fbs_add_data() result = %d:%s", ret, itron_strerror(ret));
303 return ret;
304 }
305
306 res.ptr->hdr.type = ECN_MSG_INTERNAL;
307 res.ptr->hdr.sender.dtqid = ecn_udp_dataqueueid;
308 res.ptr->hdr.target.dtqid = req.ptr->hdr.reply.dtqid;
309 res.ptr->hdr.reply.dtqid = ecn_udp_dataqueueid;
310
311 *pk_res = res;
312
313 return E_OK;
314}
315
316/*
317 * 内
318部メッセージ受信処理
319 */
320void _ecn_int_msg(ECN_FBS_ID fbs_id, ECN_FBS_SSIZE_T a_snd_len)
321{
322 ER result = E_OK, a_ret;
323 ecn_udp_msg_get_ipaddr_req_t msg;
324 ecn_udp_msg_get_ipaddr_error_t err;
325 ECN_FBS_SSIZE_T len;
326 ECN_FBS_ID buf;
327 uint8_t cmd;
328
329 a_ret = _ecn_fbs_get_data(fbs_id, &cmd, 1, &len);
330 if (a_ret != E_OK) {
331 ECN_DBG_PUT_2("[UDP TSK] _ecn_fbs_get_data() result = %d:%s", a_ret, itron_strerror(a_ret));
332 return;
333 }
334
335 switch(cmd){
336 // IPアドレスを返信
337 case ECN_UDP_MSG_GET_IPADDR_REQ:
338 if (a_snd_len < sizeof(msg)) {
339 result = E_PAR;
340 break;
341 }
342
343 a_snd_len = 0;
344 a_ret = _ecn_fbs_get_data(fbs_id, &msg, sizeof(msg), &a_snd_len);
345 if (a_ret != E_OK) {
346 ECN_DBG_PUT_2("[UDP TSK] _ecn_fbs_get_data() result = %d:%s", a_ret, itron_strerror(a_ret));
347 }
348
349 if ((msg.enodid < 0) && (msg.enodid >= tnum_enodadr)) {
350 result = E_PAR;
351 break;
352 }
353
354 a_ret = _ecn_udp_cre_res_fbs(fbs_id, ECN_UDP_MSG_GET_IPADDR_RES, &buf);
355 if (a_ret != E_OK) {
356 return;
357 }
358
359 a_ret = _ecn_fbs_add_data_ex(buf, &msg.requestid, offsetof(ecn_udp_msg_get_ipaddr_res_t, enodadrb));
360 if (a_ret != E_OK) {
361 _ecn_fbs_del(buf);
362 ECN_DBG_PUT_2("_ecn_int_msg() : _ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
363 return;
364 }
365
366 a_ret = _ecn_fbs_add_data_ex(buf, &enodadrb_table[msg.enodid], sizeof(enodadrb_table[msg.enodid]));
367 if (a_ret != E_OK) {
368 _ecn_fbs_del(buf);
369 ECN_DBG_PUT_2("_ecn_int_msg() : _ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
370 return;
371 }
372
373 a_ret = psnd_dtq(buf.ptr->hdr.target.dtqid, (intptr_t)buf.ptr);
374 if (a_ret != E_OK) {
375 _ecn_fbs_del(buf);
376 ECN_DBG_PUT_2("_ecn_int_msg() : psnd_dtq() result = %d:%s", a_ret, itron_strerror(a_ret));
377 return;
378 }
379 return;
380 }
381
382 a_ret = _ecn_udp_cre_res_fbs(fbs_id, ECN_UDP_MSG_GET_IPADDR_ERROR, &buf);
383 if (a_ret != E_OK) {
384 return;
385 }
386
387 err.requestid = msg.requestid;
388 err.error = result;
389 a_ret = _ecn_fbs_add_data_ex(buf, &err, sizeof(err));
390 if (a_ret != E_OK) {
391 _ecn_fbs_del(buf);
392 ECN_DBG_PUT_2("_ecn_int_msg() : _ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
393 return;
394 }
395
396 a_ret = psnd_dtq(buf.ptr->hdr.target.dtqid, (intptr_t)buf.ptr);
397 if (a_ret != E_OK) {
398 _ecn_fbs_del(buf);
399 ECN_DBG_PUT_2("_ecn_int_msg() : psnd_dtq() result = %d:%s", a_ret, itron_strerror(a_ret));
400 return;
401 }
402}
403
404/*
405 * ECHONET 電文受信処理
406 */
407void _ecn_esv_msg(ECN_FBS_ID fbs_id)
408{
409 const static T_IN6_ADDR locl = IPV6_ADDR_LOCAL_LOOPBACK_INIT;
410 /* UDP出力領域(暫定) */
411 static uint_t buffer[(ETHER_MAX_LEN) / sizeof(uint_t) + 1];
412 T_IPV6EP a_dst;
413 ER a_ret;
414 ECN_FBS_SSIZE_T a_snd_len;
415
416 memset(&a_dst.ipaddr, 0, sizeof(a_dst.ipaddr));
417 a_dst.portno = 0;
418 /* 送信å…
419ˆIPアドレス */
420 a_ret = udp_get_ip(&a_dst, fbs_id.ptr->hdr.target.id);
421 if (!a_ret) {
422 ECN_DBG_PUT_4("[UDP TSK] echonet-node 0x%02X-0x%02X-0x%02X → udp dest(%s)",
423 ((T_EDATA *)fbs_id.ptr)->hdr.edata.deoj.eojx1,
424 ((T_EDATA *)fbs_id.ptr)->hdr.edata.deoj.eojx2,
425 ((T_EDATA *)fbs_id.ptr)->hdr.edata.deoj.eojx3,
426 ipv62str(NULL, &a_dst.ipaddr));
427
428 /* fbsから出力領域にデータを抽出 */
429 a_snd_len = 0;
430 a_ret = _ecn_fbs_get_data(fbs_id, buffer, sizeof(buffer), &a_snd_len);
431 if (a_ret != E_OK) {
432 ECN_DBG_PUT_2("[UDP TSK] _ecn_fbs_get_data() result = %d:%s", a_ret, itron_strerror(a_ret));
433 }
434 else if (memcmp(&a_dst.ipaddr, &locl, sizeof(a_dst.ipaddr)) == 0) {
435 /* 送信å…
436ˆãŒ127.0.0.1 → dtqに転送 */
437 ECN_DBG_PUT_1("redirect ecn_udp_dataqueueid → ecn_svc_dataqueueid (esv:0x%02X)",
438 ((T_EDATA *)fbs_id.ptr)->hdr.edata.esv);
439
440 a_ret = _ecn_udp2dtq((const uint8_t *)buffer, a_snd_len, &a_dst);
441 if (a_ret != E_OK) {
442 syslog(LOG_WARNING, "_ecn_esv_msg() : _ecn_udp2dtq() result = %d:%s", a_ret, itron_strerror(a_ret));
443 }
444 }
445 else {
446 ECN_DBG_PUT_2("[UDP TSK] udp6_snd_dat() to:%s %ubyte(s)",
447 ipv62str(NULL, &a_dst.ipaddr), a_snd_len);
448#ifdef ECN_DBG_PUT_ENA
449 _ecn_dbg_bindmp((const uint8_t *)buffer, a_snd_len);
450#endif
451 /* UDP送信 */
452 a_ret = udp6_snd_dat(ecn_udp_cepid, &a_dst, buffer, a_snd_len, TMO_FEVR);
453 if (a_ret < 0) {
454 ECN_DBG_PUT_1("[UDP TSK] send, error: %s", itron_strerror(a_ret));
455 }
456 }
457
458 /* データが長すぎて1パケットに収まらなかった場合 */
459 if (_ecn_fbs_exist_data(fbs_id)) {
460 ECN_DBG_PUT_1("[UDP TSK] send, data so long: %dbyte(s)", _ecn_fbs_get_datalen(fbs_id));
461 }
462 } else {
463 ECN_DBG_PUT_3("[UDP TSK] echonet-node 0x%02X-0x%02X-0x%02X not found.",
464 ((T_EDATA *)fbs_id.ptr)->hdr.edata.deoj.eojx1,
465 ((T_EDATA *)fbs_id.ptr)->hdr.edata.deoj.eojx2,
466 ((T_EDATA *)fbs_id.ptr)->hdr.edata.deoj.eojx3);
467 }
468}
469
470/*
471 * ノンブロッキングコールのコールバック関数
472 */
473ER callback_nblk_udp(ID cepid, FN fncd, void *p_parblk)
474{
475 ER error = E_OK;
476
477 static uint8_t buffer[(ETHER_MAX_LEN) / sizeof(uint_t) + 1];
478
479 T_IPV6EP dst;
480 int a_len;
481
482 switch (fncd) {
483 case TEV_UDP_RCV_DAT:
484 case TFN_UDP_RCV_DAT:
485 /* ECN_CAP_PUT("[UDP ECHO SRV] callback_nblk_udp() recv: %u", *(int *)p_parblk); */
486 memset(buffer, 0, sizeof(buffer));
487 if ((a_len = udp6_rcv_dat(cepid, &dst, buffer, sizeof(buffer) - 1, 20 * 1000)) < 0) {
488 syslog(LOG_WARNING, "[UDP ECHO SRV] recv, error: %s", itron_strerror(a_len));
489 return a_len;
490 }
491#ifdef _MSC_VER
492 /* (開発用) ECHONET用パケット以外は読み捨てる */
493 if (buffer[0] != 0x10 || buffer[1] != 0x81) {
494 return E_OK;
495 }
496#endif
497 ECN_CAP_PUT_4("[UDP ECHO SRV] recv, addr: %s:%d, len: %d, msg: '%s'",
498 ipv62str(NULL, &dst.ipaddr), dst.portno, a_len, buffer);
499 if ((int)sizeof(buffer) <= a_len)
500 a_len = (int)sizeof(buffer) - 1;
501 if (0 < a_len) {
502 ECHONET_UDP_SEND_TO_MBX;
503
504 _ecn_udp2dtq(buffer, a_len, &dst);
505 }
506
507 return E_OK;
508
509 case TFN_UDP_CRE_CEP:
510 case TFN_UDP_SND_DAT:
511 break;
512 default:
513 ECN_CAP_PUT_2("[UDP ECHO SRV] fncd:0x%04X(%s)", -fncd,
514 (fncd == TEV_UDP_RCV_DAT ? "TEV_UDP_RCV_DAT" :
515 (fncd == TFN_UDP_CRE_CEP ? "TFN_UDP_CRE_CEP" :
516 (fncd == TFN_UDP_RCV_DAT ? "TFN_UDP_RCV_DAT" :
517 (fncd == TFN_UDP_SND_DAT ? "TFN_UDP_SND_DAT" : "undef")))));
518
519 error = E_PAR;
520 break;
521 }
522 return error;
523}
524
525/*
526 * リモートECHONETノードの適合確認
527 */
528bool_t is_match(const EOBJCB *enodcb, T_EDATA *edata, const void *_ipaddr, uint16_t portno)
529{
530 /*T_IN6_ADDR *ipaddr = (T_IN6_ADDR *)_ipaddr;*/
531 ER ret;
532 T_ENUM_EPC enm;
533 uint8_t epc;
534 uint8_t pdc;
535 uint8_t p_edt[256];
536 int i, j, k;
537 int count;
538 const EOBJINIB *p_eobj;
539 bool_t match;
540
541 if (!edata)
542 return false;
543
544 /* ノードスタート時インスタンスリスト通知以外は除外 */
545 if ( edata->hdr.edata.esv != ESV_INF
546 || edata->hdr.edata.deoj.eojx1 != EOJ_X1_PROFILE
547 || edata->hdr.edata.deoj.eojx2 != EOJ_X2_NODE_PROFILE
548 || edata->hdr.edata.deoj.eojx3 != 0x01
549 || edata->hdr.edata.seoj.eojx1 != EOJ_X1_PROFILE
550 || edata->hdr.edata.seoj.eojx2 != EOJ_X2_NODE_PROFILE
551 || ( edata->hdr.edata.seoj.eojx3 != 0x01
552 && edata->hdr.edata.seoj.eojx3 != 0x02)) {
553 return false;
554 }
555
556 ret = ecn_itr_ini(&enm, edata);
557 if (ret) {
558 syslog(LOG_WARNING, "is_match(): ecn_itr_ini() result = %d:%s", ret, itron_strerror(ret));
559 return false;
560 }
561 while ((ret = ecn_itr_nxt(&enm, &epc, &pdc, p_edt)) == E_OK) {
562 if (enm.is_eof) {
563 break;
564 }
565 ECN_DBG_PUT_2("is_match(): ecn_itr_nxt() result: epc=0x%02X, pdc=%d", epc, pdc);
566 /* インスタンスリスト通知または自ノードインスタンスリストS以外は除外 */
567 if ((epc != 0xD5) && (epc != 0xD6)) {
568 continue;
569 }
570
571 /* 2バイト目以降にeojが列挙されている */
572 count = (pdc - 1) / sizeof(T_ECN_EOJ);
573
574 /* ノード内
575の機器オブジェクトを検索 */
576 for (k = 0; k < enodcb->eobjcnt; k++) {
577 p_eobj = enodcb->eobjs[k];
578
579 /* インスタンスリストを確認 */
580 match = false;
581 for (i = 0, j = 1; i < count; i++, j += sizeof(T_ECN_EOJ)) {
582 if (p_eobj->eojx1 != p_edt[j])
583 continue;
584 if (p_eobj->eojx2 != p_edt[j + 1])
585 continue;
586 if (p_eobj->eojx3 != p_edt[j + 2])
587 continue;
588
589 match = true;
590 break;
591 }
592
593 if (!match)
594 return false;
595 }
596
597 /* すべて揃っていたら適合(インスタンスリストの方が多くてもいいこととする) */
598 return true;
599 }
600
601 return false;
602}
603
604/*
605 * IPアドレスからリモートECHONETノードへ変換
606 */
607ECN_ENOD_ID udp_get_id(T_EDATA *edata, const T_IN6_ADDR ipaddr, uint16_t portno)
608{
609 T_ENOD_ADDR *ea;
610 const static T_IN6_ADDR mcst = IPV6_ADDR_LINKLOCAL_ALLNODES_INIT,
611 locl = IPV6_ADDR_LOCAL_LOOPBACK_INIT;
612 int i;
613
614 if (IN6_ARE_ADDR_EQUAL(&ipaddr, &locl))
615 return ENOD_LOCAL_ID;
616 if (IN6_ARE_ADDR_EQUAL(&ipaddr, in6_get_ifaddr(0)))
617 return ENOD_LOCAL_ID;
618 if (IN6_ARE_ADDR_EQUAL(&ipaddr, &mcst))
619 return ENOD_MULTICAST_ID;
620
621 /* IPアドレスの同じものを検索 */
622 for (i = 0, ea = enodadrb_table; i < tnum_enodadr; i++, ea++) {
623 if (!ea->inuse)
624 continue;
625 if (!IN6_ARE_ADDR_EQUAL(&ea->ipaddr, &ipaddr))
626 continue;
627
628 ECN_CAP_PUT_2("udp_get_id(): ip-found remote(%d) = %s",
629 i - ENOD_REMOTE_ID, ipv62str(NULL, &ipaddr));
630 return (ECN_ENOD_ID)i;
631 }
632
633 /* 対応するリモートノードを検索 */
634 for (i = ENOD_REMOTE_ID, ea = &enodadrb_table[ENOD_REMOTE_ID]; i < tnum_enodadr; i++, ea++) {
635 if (!ea->inuse)
636 continue;
637 if ((i - ENOD_REMOTE_ID + 1) >= tnum_enodid)
638 break;
639 if ((((T_IN6_ADDR *)ea->ipaddr)->__u6_addr.__u6_addr32[0] != 0)
640 || (((T_IN6_ADDR *)ea->ipaddr)->__u6_addr.__u6_addr32[1] != 0)
641 || (((T_IN6_ADDR *)ea->ipaddr)->__u6_addr.__u6_addr32[2] != 0)
642 || (((T_IN6_ADDR *)ea->ipaddr)->__u6_addr.__u6_addr32[3] != 0))
643 continue;
644 if (!ECHONET_NODE_MATCH(&eobjcb_table[i - ENOD_REMOTE_ID + 1], edata, &ipaddr, portno))
645 continue;
646
647 /* 対応するリモートノードがあればIPアドレスを設定 */
648 memcpy(&ea->ipaddr, &ipaddr, sizeof(T_IN6_ADDR));
649
650 ECN_CAP_PUT_2("udp_get_id(): enod-found remote(%d) = %s",
651 i - ENOD_REMOTE_ID, ipv62str(NULL, &ipaddr));
652 return (ECN_ENOD_ID)i;
653 }
654
655 /* 空き領域を探して自動登録 */
656 for (i = ENOD_REMOTE_ID, ea = &enodadrb_table[ENOD_REMOTE_ID]; i < tnum_enodadr; i++, ea++) {
657 if (ea->inuse)
658 continue;
659
660 ea->inuse = true;
661 memcpy(&ea->ipaddr, &ipaddr, sizeof(T_IN6_ADDR));
662
663 ECN_CAP_PUT_2("udp_get_id(): empty-found remote(%d) = %s",
664 i - ENOD_REMOTE_ID, ipv62str(NULL, &ipaddr));
665 return (ECN_ENOD_ID)i;
666 }
667
668 return ENOD_NOT_MATCH_ID;
669}
670
671/*
672 * リモートECHONETノードからIPアドレスへ変換
673 */
674int udp_get_ip(T_IPV6EP *fp_ipep, ECN_ENOD_ID fa_enodid)
675{
676 T_ENOD_ADDR *ea;
677 const static T_IN6_ADDR mcst = IPV6_ADDR_LINKLOCAL_ALLNODES_INIT,
678 locl = IPV6_ADDR_LOCAL_LOOPBACK_INIT;
679
680 if (!fp_ipep)
681 return -1; /* NG */
682
683 fp_ipep->portno = 3610;
684
685 if (fa_enodid == ENOD_MULTICAST_ID) {
686 /* targetがENOD_MULTICAST_IDの場合、マルチキャストを行う */
687 memcpy(&fp_ipep->ipaddr, &mcst, sizeof(T_IN6_ADDR));
688 return 0; /* ok */
689 }
690
691 if (fa_enodid < ENOD_REMOTE_ID) {
692 /* targetが未定義・LOCAL・APIの場合、ローカルé…
693é€ã‚’行う */
694 memcpy(&fp_ipep->ipaddr, &locl, sizeof(T_IN6_ADDR));
695 return 0; /* ok */
696 }
697
698 if (fa_enodid >= tnum_enodadr)
699 return -1; /* NG */
700
701 ea = &enodadrb_table[fa_enodid];
702 if (!ea->inuse)
703 return -1; /* NG */
704
705 if ((((T_IN6_ADDR *)ea->ipaddr)->__u6_addr.__u6_addr32[0] == 0)
706 && (((T_IN6_ADDR *)ea->ipaddr)->__u6_addr.__u6_addr32[1] == 0)
707 && (((T_IN6_ADDR *)ea->ipaddr)->__u6_addr.__u6_addr32[2] == 0)
708 && (((T_IN6_ADDR *)ea->ipaddr)->__u6_addr.__u6_addr32[3] == 0))
709 return -1; /* NG */
710
711 memcpy(&fp_ipep->ipaddr, &ea->ipaddr, sizeof(T_IN6_ADDR));
712 return 0; /* ok */
713}
714
715ER ecn_udp_get_ipaddr(ID sender, int requestid, ECN_ENOD_ID enodid, ECN_FBS_ID *pk_req)
716{
717 ER a_ret;
718 ECN_FBS_ID req;
719
720 a_ret = _ecn_udp_cre_req_fbs(sender, ECN_UDP_MSG_GET_IPADDR_REQ, &req);
721 if (a_ret != E_OK) {
722 return a_ret;
723 }
724
725 a_ret = _ecn_fbs_add_data_ex(req, &requestid, sizeof(((ecn_udp_msg_get_ipaddr_res_t *)0)->requestid));
726 if (a_ret != E_OK) {
727 _ecn_fbs_del(req);
728 ECN_DBG_PUT_2("ecn_udp_get_ipaddr() : _ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
729 return a_ret;
730 }
731
732 a_ret = _ecn_fbs_add_data_ex(req, &enodid, sizeof(((ecn_udp_msg_get_ipaddr_res_t *)0)->enodid));
733 if (a_ret != E_OK) {
734 _ecn_fbs_del(req);
735 ECN_DBG_PUT_2("ecn_udp_get_ipaddr() : _ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
736 return a_ret;
737 }
738
739 a_ret = _ecn_fbs_add_data_ex(req, &enodadrb_table[enodid], sizeof(((ecn_udp_msg_get_ipaddr_res_t *)0)->enodadrb));
740 if (a_ret != E_OK) {
741 _ecn_fbs_del(req);
742 ECN_DBG_PUT_2("ecn_udp_get_ipaddr() : _ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
743 return a_ret;
744 }
745
746 *pk_req = req;
747
748 return E_OK;
749}
750
751char *ipaddr2str(char *buf, int bubsz, uint8_t *ipaddr)
752{
753 return ipv62str(buf, (T_IN6_ADDR *)ipaddr);
754}
755
756#endif
Note: See TracBrowser for help on using the repository browser.