source: uKadecot/trunk/ecnl_ssp/echonet_uip_task.c@ 108

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

MIMEプロパティの変更

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