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