source: UsbWattMeter/trunk/ecnl_lwip/echonet_udp_task.c@ 164

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

TOPPERS/ECNLサンプルアプリ「USB充電器電力計」を追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 20.8 KB
Line 
1/*
2 * TOPPERS ECHONET Lite Communication Middleware
3 *
4 * Copyright (C) 2014-2016 Cores Co., Ltd. Japan
5 *
6 * ã‹L’˜ìŒ ŽÒ‚́CˆÈ‰º‚Ì(1)`(4)‚ÌðŒ‚ð–ž‚½‚·ê‡‚ÉŒÀ‚èC–{ƒ\ƒtƒgƒEƒF
7 * ƒAi–{ƒ\ƒtƒgƒEƒFƒA‚ð‰ü•Ï‚µ‚½‚à‚Ì‚ðŠÜ‚ށDˆÈ‰º“¯‚¶j‚ðŽg—pE•¡»E‰ü
8 * •ÏEÄ”z•ziˆÈ‰ºC—˜—p‚ƌĂԁj‚·‚邱‚Ƃ𖳏ž‚Å‹–‘ø‚·‚éD
9 * (1) –{ƒ\ƒtƒgƒEƒFƒA‚ðƒ\[ƒXƒR[ƒh‚ÌŒ`‚Å—˜—p‚·‚éê‡‚ɂ́Cã‹L‚Ì’˜ì
10 * Œ •\Ž¦C‚±‚Ì—˜—pðŒ‚¨‚æ‚щº‹L‚Ì–³•ÛØ‹K’肪C‚»‚Ì‚Ü‚Ü‚ÌŒ`‚Ń\[
11 * ƒXƒR[ƒh’†‚ÉŠÜ‚Ü‚ê‚Ä‚¢‚邱‚ƁD
12 * (2) –{ƒ\ƒtƒgƒEƒFƒA‚ðCƒ‰ƒCƒuƒ‰ƒŠŒ`Ž®‚ȂǁC‘¼‚̃\ƒtƒgƒEƒFƒAŠJ”­‚ÉŽg
13 * —p‚Å‚«‚éŒ`‚ōĔz•z‚·‚éê‡‚ɂ́CÄ”z•z‚É”º‚¤ƒhƒLƒ…
14ƒƒ“ƒgi—˜—p
15 * ŽÒƒ}ƒjƒ…
16ƒAƒ‹‚Ȃǁj‚ɁCã‹L‚Ì’˜ìŒ •\Ž¦C‚±‚Ì—˜—pðŒ‚¨‚æ‚щº‹L
17 * ‚Ì–³•ÛØ‹K’è‚ðŒfÚ‚·‚邱‚ƁD
18 * (3) –{ƒ\ƒtƒgƒEƒFƒA‚ðC‹@Ší‚É‘g‚ݍž‚ނȂǁC‘¼‚̃\ƒtƒgƒEƒFƒAŠJ”­‚ÉŽg
19 * —p‚Å‚«‚È‚¢Œ`‚ōĔz•z‚·‚éê‡‚ɂ́CŽŸ‚Ì‚¢‚¸‚ê‚©‚ÌðŒ‚ð–ž‚½‚·‚±
20 * ‚ƁD
21 * (a) Ä”z•z‚É”º‚¤ƒhƒLƒ…
22ƒƒ“ƒgi—˜—pŽÒƒ}ƒjƒ…
23ƒAƒ‹‚Ȃǁj‚ɁCã‹L‚Ì’˜
24 * ìŒ •\Ž¦C‚±‚Ì—˜—pðŒ‚¨‚æ‚щº‹L‚Ì–³•ÛØ‹K’è‚ðŒfÚ‚·‚邱‚ƁD
25 * (b) Ä”z•z‚ÌŒ`‘Ô‚ðC•Ê‚É’è‚ß‚é•û–@‚É‚æ‚Á‚āCTOPPERSƒvƒƒWƒFƒNƒg‚É
26 * •ñ‚·‚邱‚ƁD
27 * (4) –{ƒ\ƒtƒgƒEƒFƒA‚Ì—˜—p‚É‚æ‚è’¼Ú“I‚Ü‚½‚͊ԐړI‚ɐ¶‚¶‚é‚¢‚©‚Ȃ鑹
28 * ŠQ‚©‚ç‚àCã‹L’˜ìŒ ŽÒ‚¨‚æ‚ÑTOPPERSƒvƒƒWƒFƒNƒg‚ð–Ɛӂ·‚邱‚ƁD
29 * ‚Ü‚½C–{ƒ\ƒtƒgƒEƒFƒA‚̃†[ƒU‚Ü‚½‚̓Gƒ“ƒhƒ†[ƒU‚©‚ç‚Ì‚¢‚©‚Ȃ闝
30 * —R‚ÉŠî‚­¿‹‚©‚ç‚àCã‹L’˜ìŒ ŽÒ‚¨‚æ‚ÑTOPPERSƒvƒƒWƒFƒNƒg‚ð
31 * –Ɛӂ·‚邱‚ƁD
32 *
33 * –{ƒ\ƒtƒgƒEƒFƒA‚́C–³•ÛØ‚Å’ñ‹Ÿ‚³‚ê‚Ä‚¢‚é‚à‚Ì‚Å‚ ‚éDã‹L’˜ìŒ ŽÒ‚¨
34 * ‚æ‚ÑTOPPERSƒvƒƒWƒFƒNƒg‚́C–{ƒ\ƒtƒgƒEƒFƒA‚ÉŠÖ‚µ‚āC“Á’è‚ÌŽg—p–Ú“I
35 * ‚ɑ΂·‚é“K‡«‚àŠÜ‚߂āC‚¢‚©‚È‚é•ÛØ‚às‚í‚È‚¢D‚Ü‚½C–{ƒ\ƒtƒgƒEƒF
36 * ƒA‚Ì—˜—p‚É‚æ‚è’¼Ú“I‚Ü‚½‚͊ԐړI‚ɐ¶‚¶‚½‚¢‚©‚Ȃ鑹ŠQ‚ÉŠÖ‚µ‚Ä‚àC‚»
37 * ‚̐ӔC‚𕉂í‚È‚¢D
38 *
39 * @(#) $Id: echonet_udp_task.c 164 2016-03-07 11:33:50Z coas-nagasima $
40 */
41
42/*
43 * ECHONET Lite UDP’ʐMˆ—ƒ^ƒXƒN
44 */
45#ifdef SUPPORT_INET4
46
47#include <kernel.h>
48#include <string.h>
49#include <stdio.h>
50#include <stdlib.h>
51#include <t_syslog.h>
52#include <t_stdlib.h>
53#include <sil.h>
54
55#include "syssvc/serial.h"
56#include "syssvc/syslog.h"
57#include "echonet.h"
58
59#ifdef _MSC_VER
60#pragma warning(disable : 4005)
61#endif
62#include <lwip/udp.h>
63#include <lwip/igmp.h>
64#ifdef _MSC_VER
65#pragma warning(default : 4005)
66#endif
67
68#include "echonet_task.h"
69#include "echonet_lcl_task.h"
70#include "echonet_dbg.h"
71
72#ifndef ECHONET_UDP_TASK_GET_TIMER
73#define ECHONET_UDP_TASK_GET_TIMER TMO_FEVR
74#endif /* ECHONET_UDP_TASK_GET_TIMER */
75
76#ifndef ECHONET_UDP_TASK_PROGRESS
77#define ECHONET_UDP_TASK_PROGRESS(timer)
78#endif /* ECHONET_UDP_TASK_PROGRESS */
79
80#ifndef ECHONET_UDP_TASK_TIMEOUT
81#define ECHONET_UDP_TASK_TIMEOUT
82#endif /* ECHONET_UDP_TASK_TIMEOUT */
83
84#ifndef ECHONET_UDP_SEND_TO_MBX
85#define ECHONET_UDP_SEND_TO_MBX
86#endif /* ECHONET_UDP_SEND_TO_MBX */
87
88#ifndef ECHONET_NODE_MATCH
89#define ECHONET_NODE_MATCH(enodcb, edata, ipaddr, portno) is_match(enodcb, edata, ipaddr, portno)
90#endif /* ECHONET_NODE_MATCH */
91
92static ip_addr_t localhost;
93static ip_addr_t multicast;
94static ip_addr_t zeroaddr;
95struct udp_pcb *UDP_CEPID;
96
97typedef struct ipv4ep_t {
98 ip_addr_t ipaddr;
99 uint16_t portno;
100} T_IPV4EP;
101
102static ECN_ENOD_ID udp_get_id(T_EDATA *edata, const ip_addr_t *ipaddr, uint16_t portno);
103static int udp_get_ip(T_IPV4EP *fp_ipep, ECN_ENOD_ID fa_enodid);
104void _ecn_int_msg(ECN_FBS_ID fbs_id, ECN_FBS_SSIZE_T a_snd_len);
105void _ecn_esv_msg(ECN_FBS_ID fbs_id);
106static void callback_nblk_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port);
107
108/*
109 * ŽóM‚µ‚½UDPƒf[ƒ^‚ðMAILBOX‚É‘—‚é
110 */
111ER _ecn_udp2mbx(ECN_FBS_ID fbs_id, const T_IPV4EP *dst);
112ER _ecn_udp2mbx(ECN_FBS_ID fbs_id, const T_IPV4EP *dst)
113{
114 ER a_ret = E_OK;
115 ECN_ENOD_ID a_enod_id;
116 const T_ECN_EDT_HDR *t_esv;
117
118 t_esv = (const T_ECN_EDT_HDR *)fbs_id.ptr->payload;
119 if (t_esv->ecn_hdr.ehd1 != ECN_EDH1_ECHONET_LITE /* ECHONET Lite‹KŠi */
120 || t_esv->ecn_hdr.ehd2 != ECN_EDH2_FORMAT_1 /* “d•¶Œ`Ž®1 */) {
121 ECN_DBG_PUT("[UDP ECHO SRV] illegal type (0x%02X,0x%02X)", t_esv->ecn_hdr.ehd1, t_esv->ecn_hdr.ehd2);
122 return E_PAR;
123 }
124
125#ifdef ECN_DBG_PUT_ENA
126 _ecn_dbg_bindmp(fbs_id.ptr, fbs_id.ptr->hdr.length);
127#endif
128
129 fbs_id.ptr->hdr.type = ECN_MSG_ECHONET;
130 fbs_id.ptr->hdr.target.id = ENOD_LOCAL_ID;
131 fbs_id.ptr->hdr.sender.id = ENOD_NOT_MATCH_ID;
132
133 /* IPƒAƒhƒŒƒX‚©‚烊ƒ‚[ƒgECHONETƒm[ƒh‚Ö•ÏŠ· */
134 a_enod_id = udp_get_id((T_EDATA *)fbs_id.ptr, &dst->ipaddr, dst->portno);
135 if (a_enod_id < 0 || tnum_enodadr <= a_enod_id) {
136 ECN_DBG_PUT("[UDP ECHO SRV] udp src(%s) echonet-node not found.",
137 ipaddr_ntoa(&dst->ipaddr));
138 }
139 else {
140 /* ‘—MŒ³ECHONETƒm[ƒh‚ð‹L˜^ */
141 fbs_id.ptr->hdr.sender.id = a_enod_id;
142 }
143 fbs_id.ptr->hdr.reply.id = fbs_id.ptr->hdr.sender.id;
144
145 /* echonet_task‚É‘—‚é */
146 a_ret = snd_mbx(ecn_svc_mailboxid, (T_MSG *)fbs_id.ptr);
147 if (a_ret != E_OK) {
148 ECN_DBG_PUT("[UDP ECHO SRV] snd_mbx(ecn_svc_mailboxid) result = %d:%s", a_ret, itron_strerror(a_ret));
149 goto lb_except;
150 }
151 return a_ret;
152lb_except:
153 _ecn_fbs_del(fbs_id);
154 return a_ret;
155}
156
157/*
158 * ECHONET UDP’ʐMˆ—ƒ^ƒXƒN
159 */
160void echonet_udp_task(intptr_t exinf)
161{
162 ip_addr_t a_src;
163 ER a_ret, a_ret2;
164 ID tskid;
165 ECN_FBS_SSIZE_T a_snd_len;
166 union {
167 T_MSG *p_msg;
168 ECN_FBS_ID fbs_id;
169 } a_mdt;
170 SYSTIM a_prev, a_now;
171 TMO a_timer;
172 err_t err;
173
174 IP4_ADDR(&localhost, 127, 0, 0, 1);
175 IP4_ADDR(&multicast, 224, 0, 23, 0);
176 IP4_ADDR(&zeroaddr, 0, 0, 0, 0);
177
178 get_tid(&tskid);
179 memcpy(&a_src, &netif_default->ip_addr, sizeof(ip_addr_t));
180 ECN_DBG_PUT("[UDP TSK:%d,%d] started, IP Address: %s",
181 tskid, exinf,
182 ipaddr_ntoa(&a_src));
183 memcpy(enodadrb_table[ENOD_LOCAL_ID].ipaddr, &a_src, sizeof(ip_addr_t));
184
185 UDP_CEPID = udp_new();
186 if (UDP_CEPID == NULL) {
187 ECN_DBG_PUT("udp_new()");
188 return;
189 }
190
191 err = udp_bind(UDP_CEPID, &a_src, 3610);
192 if (err != ERR_OK) {
193 ECN_DBG_PUT("udp_bind()");
194 return;
195 }
196
197 udp_recv(UDP_CEPID, callback_nblk_udp, NULL);
198
199 err = igmp_joingroup(&a_src, &multicast);
200 if (err != ERR_OK) {
201 ECN_DBG_PUT("igmp_joingroup()");
202 return;
203 }
204
205 a_ret = act_tsk(ecn_svc_taskid);
206 if (a_ret != E_OK) {
207 ECN_DBG_PUT("act_tsk(%d) result = %d:%s", ecn_svc_taskid, a_ret, itron_strerror(a_ret));
208 return;
209 }
210
211 a_ret = get_tim(&a_now);
212 if (a_ret != E_OK) {
213 ECN_DBG_PUT("get_tim() result = %d:%s", a_ret, itron_strerror(a_ret));
214 return;
215 }
216
217 /* ƒƒbƒZ[ƒWƒ‹[ƒv */
218 for (;;) {
219 a_prev = a_now;
220
221 a_timer = ECHONET_UDP_TASK_GET_TIMER;
222
223 a_ret = trcv_mbx(ecn_udp_mailboxid, &a_mdt.p_msg, a_timer);
224 if ((a_ret != E_OK) && (a_ret != E_TMOUT)) {
225 ECN_DBG_PUT("trcv_mbx() result = %d:%s", a_ret, itron_strerror(a_ret));
226 break;
227 }
228
229 a_ret2 = get_tim(&a_now);
230 if (a_ret2 != E_OK) {
231 ECN_DBG_PUT("get_tim() result = %d:%s", a_ret2, itron_strerror(a_ret2));
232 break;
233 }
234
235 a_timer = a_now - a_prev;
236 ECHONET_UDP_TASK_PROGRESS(a_timer);
237
238 if (a_ret == E_OK) {
239 /* ‘—Mƒf[ƒ^’·‚ðŽæ“¾ */
240 a_snd_len = _ecn_fbs_get_datalen(a_mdt.fbs_id);
241
242 ECN_DBG_PUT("[UDP TSK] trcv_mbx() mbx recv (%d byte)", _ecn_fbs_get_datalen(a_mdt.fbs_id));
243
244 if (0 < a_snd_len) {
245 switch (a_mdt.fbs_id.ptr->hdr.type) {
246 case ECN_MSG_INTERNAL:
247 _ecn_int_msg(a_mdt.fbs_id, a_snd_len);
248 break;
249 case ECN_MSG_ECHONET:
250 _ecn_esv_msg(a_mdt.fbs_id);
251 break;
252 }
253 }
254
255 _ecn_fbs_del(a_mdt.fbs_id);
256 }
257
258 ECHONET_UDP_TASK_TIMEOUT;
259 }
260}
261
262/* ‰ž“š“d•¶—pfbsÝ’è(sender/target‚̐ݒè) */
263static ER _ecn_udp_cre_req_fbs(ID sender, uint8_t cmd, ECN_FBS_ID *pk_req)
264{
265 ER ret;
266 ECN_FBS_ID req;
267
268 ret = _ecn_fbs_cre(1, &req);
269 if (ret != E_OK) {
270 ECN_DBG_PUT("_ecn_udp_cre_req_fbs() : _ecn_fbs_cre() result = %d:%s", ret, itron_strerror(ret));
271 return ret;
272 }
273
274 ret = _ecn_fbs_add_data(req, &cmd, sizeof(cmd));
275 if (ret != E_OK) {
276 _ecn_fbs_del(req);
277 ECN_DBG_PUT("_ecn_udp_cre_req_fbs() : _ecn_fbs_add_data() result = %d:%s", ret, itron_strerror(ret));
278 return ret;
279 }
280
281 req.ptr->hdr.type = ECN_MSG_INTERNAL;
282 req.ptr->hdr.sender.mbxid = sender;
283 req.ptr->hdr.target.mbxid = ecn_udp_mailboxid;
284 req.ptr->hdr.reply.mbxid = sender;
285
286 *pk_req = req;
287
288 return E_OK;
289}
290
291/* ‰ž“š“d•¶—pfbsÝ’è(sender/target‚̐ݒè) */
292static ER _ecn_udp_cre_res_fbs(ECN_FBS_ID req, uint8_t cmd, ECN_FBS_ID *pk_res)
293{
294 ER ret;
295 ECN_FBS_ID res;
296
297 ret = _ecn_fbs_cre(1, &res);
298 if (ret != E_OK) {
299 ECN_DBG_PUT("_ecn_udp_cre_res_fbs() : _ecn_fbs_cre() result = %d:%s", ret, itron_strerror(ret));
300 return ret;
301 }
302
303 ret = _ecn_fbs_add_data(res, &cmd, sizeof(cmd));
304 if (ret != E_OK) {
305 _ecn_fbs_del(res);
306 ECN_DBG_PUT("_ecn_udp_cre_res_fbs() : _ecn_fbs_add_data() result = %d:%s", ret, itron_strerror(ret));
307 return ret;
308 }
309
310 res.ptr->hdr.type = ECN_MSG_INTERNAL;
311 res.ptr->hdr.sender.mbxid = ecn_udp_mailboxid;
312 res.ptr->hdr.target.mbxid = req.ptr->hdr.reply.mbxid;
313 res.ptr->hdr.reply.mbxid = ecn_udp_mailboxid;
314
315 *pk_res = res;
316
317 return E_OK;
318}
319
320/*
321 * “à•”ƒƒbƒZ[ƒWŽóMˆ—
322 */
323void _ecn_int_msg(ECN_FBS_ID fbs_id, ECN_FBS_SSIZE_T a_snd_len)
324{
325 ER result = E_OK, a_ret;
326 ecn_udp_msg_get_ipaddr_req_t msg;
327 ecn_udp_msg_get_ipaddr_error_t err;
328 ECN_FBS_SSIZE_T len;
329 ECN_FBS_ID buf;
330 uint8_t cmd;
331 unsigned int requestid = 0;
332
333 a_ret = _ecn_fbs_get_data(fbs_id, &cmd, 1, &len);
334 if (a_ret != E_OK) {
335 ECN_DBG_PUT("[UDP TSK] _ecn_fbs_get_data() result = %d:%s", a_ret, itron_strerror(a_ret));
336 return;
337 }
338
339 switch (cmd) {
340 // IPƒAƒhƒŒƒX‚ð•ÔM
341 case ECN_UDP_MSG_GET_IPADDR_REQ:
342 if (a_snd_len < sizeof(msg)) {
343 result = E_PAR;
344 break;
345 }
346
347 a_snd_len = 0;
348 a_ret = _ecn_fbs_get_data(fbs_id, &msg, sizeof(msg), &a_snd_len);
349 if (a_ret != E_OK) {
350 ECN_DBG_PUT("[UDP TSK] _ecn_fbs_get_data() result = %d:%s", a_ret, itron_strerror(a_ret));
351 }
352 requestid = msg.requestid;
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("_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("_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.mbxid, (intptr_t)buf.ptr);
379 if (a_ret != E_OK) {
380 _ecn_fbs_del(buf);
381 ECN_DBG_PUT("_ecn_int_msg() : psnd_dtq() result = %d:%s", a_ret, itron_strerror(a_ret));
382 return;
383 }
384 return;
385 default:
386 a_ret = _ecn_fbs_get_data(fbs_id, &requestid, sizeof(requestid), &len);
387 if (a_ret != E_OK) {
388 ECN_DBG_PUT("[UDP TSK] _ecn_fbs_get_data() result = %d:%s", a_ret, itron_strerror(a_ret));
389 return;
390 }
391 break;
392 }
393
394 if (requestid == 0)
395 return;
396
397 a_ret = _ecn_udp_cre_res_fbs(fbs_id, ECN_UDP_MSG_GET_IPADDR_ERROR, &buf);
398 if (a_ret != E_OK) {
399 return;
400 }
401
402 err.requestid = requestid;
403 err.error = result;
404 a_ret = _ecn_fbs_add_data_ex(buf, &err, sizeof(err));
405 if (a_ret != E_OK) {
406 _ecn_fbs_del(buf);
407 ECN_DBG_PUT("_ecn_int_msg() : _ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
408 return;
409 }
410
411 a_ret = psnd_dtq(buf.ptr->hdr.target.mbxid, (intptr_t)buf.ptr);
412 if (a_ret != E_OK) {
413 _ecn_fbs_del(buf);
414 ECN_DBG_PUT("_ecn_int_msg() : psnd_dtq() result = %d:%s", a_ret, itron_strerror(a_ret));
415 return;
416 }
417}
418
419/*
420 * ECHONET “d•¶ŽóMˆ—
421 */
422void _ecn_esv_msg(ECN_FBS_ID fbs_id)
423{
424 struct pbuf *p, *q;
425 T_IPV4EP a_dst;
426 ER a_ret;
427 ECN_FBS_SSIZE_T a_snd_len = fbs_id.ptr->hdr.length;
428
429 IP4_ADDR(&a_dst.ipaddr, 0, 0, 0, 0);
430 a_dst.portno = 0;
431 /* ‘—MæIPƒAƒhƒŒƒX */
432 a_ret = udp_get_ip(&a_dst, fbs_id.ptr->hdr.target.id);
433 if (!a_ret) {
434 ECN_DBG_PUT("[UDP TSK] echonet-node 0x%02X-0x%02X-0x%02X ¨ udp dest(%s)",
435 ((T_EDATA *)fbs_id.ptr)->hdr.edata.deoj.eojx1,
436 ((T_EDATA *)fbs_id.ptr)->hdr.edata.deoj.eojx2,
437 ((T_EDATA *)fbs_id.ptr)->hdr.edata.deoj.eojx3,
438 ipaddr_ntoa(&a_dst.ipaddr));
439
440 if (ip_addr_cmp(&a_dst.ipaddr, &localhost)) {
441 /* ‘—Mæ‚ª127.0.0.1 ¨ mbx‚É“]‘— */
442 ECN_DBG_PUT("redirect ecn_udp_mailboxid ¨ ecn_svc_mailboxid (esv:0x%02X)",
443 ((T_EDATA *)fbs_id.ptr)->hdr.edata.esv);
444
445 a_ret = _ecn_udp2mbx(fbs_id, &a_dst);
446 if (a_ret != E_OK) {
447 syslog(LOG_WARNING, "_ecn_esv_msg() : _ecn_udp2mbx() result = %d:%s", a_ret, itron_strerror(a_ret));
448 }
449 }
450 else {
451 ECN_DBG_PUT("[UDP TSK] udp_snd_dat() to:%s %ubyte(s)",
452 ipaddr_ntoa(&a_dst.ipaddr), a_snd_len);
453#ifdef ECN_DBG_PUT_ENA
454 _ecn_dbg_bindmp(fbs_id.ptr, a_snd_len);
455#endif
456 p = pbuf_alloc(PBUF_TRANSPORT, _ecn_fbs_get_datalen(fbs_id), PBUF_POOL);
457 if (p == NULL) {
458 ECN_DBG_PUT("[UDP TSK] pbuf_alloc()");
459 return;
460 }
461
462 /* fbs‚©‚ço—͗̈æ‚Ƀf[ƒ^‚𒊏o */
463 a_snd_len = 0;
464 for (q = p; q != NULL; q = q->next) {
465 ECN_FBS_SSIZE_T a_len;
466 a_ret = _ecn_fbs_get_data(fbs_id, q->payload, q->len, &a_len);
467 if (a_ret != E_OK) {
468 ECN_DBG_PUT("[UDP TSK] _ecn_fbs_get_data() result = %d:%s", a_ret, itron_strerror(a_ret));
469 pbuf_free(p);
470 return;
471 }
472 a_snd_len += a_len;
473 }
474
475 /* UDP‘—M */
476 a_ret = udp_sendto(UDP_CEPID, p, &a_dst.ipaddr, 3610);
477 if (a_ret < 0) {
478 ECN_DBG_PUT("[UDP TSK] send, error: %s", itron_strerror(a_ret));
479 }
480 pbuf_free(p);
481 }
482
483 /* ƒf[ƒ^‚ª’·‚·‚¬‚Ä1ƒpƒPƒbƒg‚ÉŽû‚Ü‚ç‚È‚©‚Á‚½ê‡ */
484 if (_ecn_fbs_exist_data(fbs_id)) {
485 ECN_DBG_PUT("[UDP TSK] send, data so long: %dbyte(s)", _ecn_fbs_get_datalen(fbs_id));
486 }
487 }
488 else {
489 ECN_DBG_PUT("[UDP TSK] echonet-node 0x%02X-0x%02X-0x%02X not found.",
490 ((T_EDATA *)fbs_id.ptr)->hdr.edata.deoj.eojx1,
491 ((T_EDATA *)fbs_id.ptr)->hdr.edata.deoj.eojx2,
492 ((T_EDATA *)fbs_id.ptr)->hdr.edata.deoj.eojx3);
493 }
494}
495
496/*
497 * ƒmƒ“ƒuƒƒbƒLƒ“ƒOƒR[ƒ‹‚̃R[ƒ‹ƒoƒbƒNŠÖ”
498 */
499static void
500callback_nblk_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
501{
502 ECN_FBS_ID a_fbs_id = {0};
503 ER a_ret = E_OK;
504 ECN_ENOD_ID a_enod_id;
505 const T_ECN_EDT_HDR *t_esv;
506 struct pbuf *q;
507
508 a_ret = _ecn_fbs_cre(p->tot_len, &a_fbs_id);
509 if (a_ret != E_OK) {
510 ECN_DBG_PUT("[UDP ECHO SRV] _ecn_fbs_cre() result = %d:%s", a_ret, itron_strerror(a_ret));
511 pbuf_free(p);
512 return;
513 }
514
515 for (q = p; q != NULL; q = q->next) {
516 a_ret = _ecn_fbs_add_data_ex(a_fbs_id, q->payload, q->len);
517 if (a_ret) {
518 ECN_DBG_PUT("[UDP ECHO SRV] _ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
519 pbuf_free(p);
520 goto lb_except;
521 }
522 }
523
524 pbuf_free(p);
525
526 t_esv = (const T_ECN_EDT_HDR *)a_fbs_id.ptr->payload;
527 if (t_esv->ecn_hdr.ehd1 != ECN_EDH1_ECHONET_LITE /* ECHONET Lite‹KŠi */
528 || t_esv->ecn_hdr.ehd2 != ECN_EDH2_FORMAT_1 /* “d•¶Œ`Ž®1 */) {
529 ECN_DBG_PUT("[UDP ECHO SRV] illegal type (0x%02X,0x%02X)", t_esv->ecn_hdr.ehd1, t_esv->ecn_hdr.ehd2);
530 goto lb_except;
531 }
532
533#ifdef ECN_DBG_PUT_ENA
534 _ecn_dbg_bindmp(a_fbs_id.ptr, a_fbs_id.ptr->hdr.length);
535#endif
536
537 a_fbs_id.ptr->hdr.type = ECN_MSG_ECHONET;
538 a_fbs_id.ptr->hdr.target.id = ENOD_LOCAL_ID;
539 a_fbs_id.ptr->hdr.sender.id = ENOD_NOT_MATCH_ID;
540
541 /* IPƒAƒhƒŒƒX‚©‚烊ƒ‚[ƒgECHONETƒm[ƒh‚Ö•ÏŠ· */
542 a_enod_id = udp_get_id((T_EDATA *)a_fbs_id.ptr, addr, port);
543 if (a_enod_id < 0 || tnum_enodadr <= a_enod_id) {
544 ECN_DBG_PUT("[UDP ECHO SRV] udp src(%s) echonet-node not found.",
545 ipaddr_ntoa(addr));
546 }
547 else {
548 /* ‘—MŒ³ECHONETƒm[ƒh‚ð‹L˜^ */
549 a_fbs_id.ptr->hdr.sender.id = a_enod_id;
550 }
551 a_fbs_id.ptr->hdr.reply.id = a_fbs_id.ptr->hdr.sender.id;
552
553 /* echonet_task‚É‘—‚é */
554 a_ret = snd_mbx(ecn_svc_mailboxid, (T_MSG *)a_fbs_id.ptr);
555 if (a_ret != E_OK) {
556 ECN_DBG_PUT("[UDP ECHO SRV] snd_mbx(ecn_svc_mailboxid) result = %d:%s", a_ret, itron_strerror(a_ret));
557 goto lb_except;
558 }
559 return;
560lb_except:
561 _ecn_fbs_del(a_fbs_id);
562 return;
563}
564
565/*
566 * ƒŠƒ‚[ƒgECHONETƒm[ƒh‚Ì“K‡Šm”F
567 */
568bool_t is_match(const EOBJCB *enodcb, T_EDATA *edata, const void *_ipaddr, uint16_t portno)
569{
570 /*ip_addr_t *ipaddr = (ip_addr_t *)_ipaddr;*/
571 ER ret;
572 T_ENUM_EPC enm;
573 uint8_t epc;
574 uint8_t pdc;
575 uint8_t p_edt[256];
576 int i, j, k;
577 int count;
578 const EOBJINIB *p_eobj;
579 bool_t match;
580
581 if (!edata)
582 return false;
583
584 /* ƒm[ƒhƒXƒ^[ƒgŽžƒCƒ“ƒXƒ^ƒ“ƒXƒŠƒXƒg’Ê’mˆÈŠO‚͏œŠO */
585 if (edata->hdr.edata.esv != ESV_INF
586 || edata->hdr.edata.deoj.eojx1 != EOJ_X1_PROFILE
587 || edata->hdr.edata.deoj.eojx2 != EOJ_X2_NODE_PROFILE
588 || edata->hdr.edata.deoj.eojx3 != 0x01
589 || edata->hdr.edata.seoj.eojx1 != EOJ_X1_PROFILE
590 || edata->hdr.edata.seoj.eojx2 != EOJ_X2_NODE_PROFILE
591 || (edata->hdr.edata.seoj.eojx3 != 0x01
592 && edata->hdr.edata.seoj.eojx3 != 0x02)) {
593 return false;
594 }
595
596 ret = ecn_itr_ini(&enm, edata);
597 if (ret) {
598 syslog(LOG_WARNING, "is_match(): ecn_itr_ini() result = %d:%s", ret, itron_strerror(ret));
599 return false;
600 }
601 while ((ret = ecn_itr_nxt(&enm, &epc, &pdc, p_edt)) == E_OK) {
602 if (enm.is_eof) {
603 break;
604 }
605 ECN_DBG_PUT("is_match(): ecn_itr_nxt() result: epc=0x%02X, pdc=%d", epc, pdc);
606 /* ƒCƒ“ƒXƒ^ƒ“ƒXƒŠƒXƒg’Ê’m‚Ü‚½‚ÍŽ©ƒm[ƒhƒCƒ“ƒXƒ^ƒ“ƒXƒŠƒXƒg‚rˆÈŠO‚͏œŠO */
607 if ((epc != 0xD5) && (epc != 0xD6)) {
608 continue;
609 }
610
611 /* ‚QƒoƒCƒg–ڈȍ~‚Éeoj‚ª—ñ‹“‚³‚ê‚Ä‚¢‚é */
612 count = (pdc - 1) / sizeof(T_ECN_EOJ);
613
614 /* ƒm[ƒh“à‚Ì‹@ŠíƒIƒuƒWƒFƒNƒg‚ðŒŸõ */
615 for (k = 0; k < enodcb->eobjcnt; k++) {
616 p_eobj = enodcb->eobjs[k];
617
618 /* ƒCƒ“ƒXƒ^ƒ“ƒXƒŠƒXƒg‚ðŠm”F */
619 match = false;
620 for (i = 0, j = 1; i < count; i++, j += sizeof(T_ECN_EOJ)) {
621 if (p_eobj->eojx1 != p_edt[j])
622 continue;
623 if (p_eobj->eojx2 != p_edt[j + 1])
624 continue;
625 if (p_eobj->eojx3 != p_edt[j + 2])
626 continue;
627
628 match = true;
629 break;
630 }
631
632 if (!match)
633 return false;
634 }
635
636 /* ‚·‚ׂđµ‚Á‚Ä‚¢‚½‚ç“K‡iƒCƒ“ƒXƒ^ƒ“ƒXƒŠƒXƒg‚Ì•û‚ª‘½‚­‚Ä‚à‚¢‚¢‚±‚Æ‚Æ‚·‚éj */
637 return true;
638 }
639
640 return false;
641}
642
643/*
644 * IPƒAƒhƒŒƒX‚©‚烊ƒ‚[ƒgECHONETƒm[ƒh‚Ö•ÏŠ·
645 */
646ECN_ENOD_ID udp_get_id(T_EDATA *edata, const ip_addr_t *ipaddr, uint16_t portno)
647{
648 T_ENOD_ADDR *ea;
649 int i;
650
651 if (ip_addr_cmp(ipaddr, &localhost))
652 return ENOD_LOCAL_ID;
653 if (ip_addr_cmp(ipaddr, &multicast))
654 return ENOD_MULTICAST_ID;
655
656 /* IPƒAƒhƒŒƒX‚Ì“¯‚¶‚à‚Ì‚ðŒŸõ */
657 for (i = 0, ea = enodadrb_table; i < tnum_enodadr; i++, ea++) {
658 if (!ea->inuse)
659 continue;
660 if (!ip_addr_cmp((ip_addr_t *)ea->ipaddr, ipaddr))
661 continue;
662
663 ECN_CAP_PUT("udp_get_id(): ip-found remote(%d) = %s",
664 i - ENOD_REMOTE_ID, ipaddr_ntoa(ipaddr));
665 return (ECN_ENOD_ID)i;
666 }
667
668 /* ‘Ήž‚·‚郊ƒ‚[ƒgƒm[ƒh‚ðŒŸõ */
669 for (i = ENOD_REMOTE_ID, ea = &enodadrb_table[ENOD_REMOTE_ID]; i < tnum_enodadr; i++, ea++) {
670 if (!ea->inuse)
671 continue;
672 if ((i - ENOD_REMOTE_ID + 1) >= tnum_enodid)
673 break;
674 if (ip_addr_cmp((ip_addr_t *)&ea->ipaddr, &zeroaddr))
675 continue;
676 if (!ECHONET_NODE_MATCH(&eobjcb_table[i - ENOD_REMOTE_ID + 1], edata, ipaddr, portno))
677 continue;
678
679 /* ‘Ήž‚·‚郊ƒ‚[ƒgƒm[ƒh‚ª‚ ‚ê‚ÎIPƒAƒhƒŒƒX‚ðÝ’è */
680 *((ip_addr_t *)ea->ipaddr) = *ipaddr;
681
682 ECN_CAP_PUT("udp_get_id(): enod-found remote(%d) = %s",
683 i - ENOD_REMOTE_ID, ipaddr_ntoa(ipaddr));
684 return (ECN_ENOD_ID)i;
685 }
686
687 /* ‹ó‚«—̈æ‚ð’T‚µ‚ÄŽ©“®“o˜^ */
688 for (i = ENOD_REMOTE_ID, ea = &enodadrb_table[ENOD_REMOTE_ID]; i < tnum_enodadr; i++, ea++) {
689 if (ea->inuse)
690 continue;
691
692 ea->inuse = true;
693 *((ip_addr_t *)ea->ipaddr) = *ipaddr;
694
695 ECN_CAP_PUT("udp_get_id(): empty-found remote(%d) = %s",
696 i - ENOD_REMOTE_ID, ipaddr_ntoa(ipaddr));
697 return (ECN_ENOD_ID)i;
698 }
699
700 return ENOD_NOT_MATCH_ID;
701}
702
703/*
704 * ƒŠƒ‚[ƒgECHONETƒm[ƒh‚©‚çIPƒAƒhƒŒƒX‚Ö•ÏŠ·
705 */
706int udp_get_ip(T_IPV4EP *fp_ipep, ECN_ENOD_ID fa_enodid)
707{
708 T_ENOD_ADDR *ea;
709
710 if (!fp_ipep)
711 return -1; /* NG */
712
713 fp_ipep->portno = 3610;
714
715 if (fa_enodid == ENOD_MULTICAST_ID) {
716 /* target‚ªENOD_MULTICAST_ID‚̏ꍇAƒ}ƒ‹ƒ`ƒLƒƒƒXƒg‚ðs‚¤ */
717 ip_addr_copy(fp_ipep->ipaddr, multicast);
718 return 0; /* ok */
719 }
720
721 if (fa_enodid < ENOD_REMOTE_ID) {
722 /* target‚ª–¢’è‹`ELOCALEAPI‚̏ꍇAƒ[ƒJƒ‹”z‘—‚ðs‚¤ */
723 ip_addr_copy(fp_ipep->ipaddr, localhost);
724 return 0; /* ok */
725 }
726
727 if (fa_enodid >= tnum_enodadr)
728 return -1; /* NG */
729
730 ea = &enodadrb_table[fa_enodid];
731 if (!ea->inuse)
732 return -1; /* NG */
733
734 if (ip_addr_cmp((ip_addr_t *)&ea->ipaddr, &zeroaddr))
735 return -1; /* NG */
736
737 fp_ipep->ipaddr = *((ip_addr_t *)ea->ipaddr);
738 return 0; /* ok */
739}
740
741ER ecn_udp_get_ipaddr(ID sender, int requestid, ECN_ENOD_ID enodid, ECN_FBS_ID *pk_req)
742{
743 ER a_ret;
744 ECN_FBS_ID req;
745
746 a_ret = _ecn_udp_cre_req_fbs(sender, ECN_UDP_MSG_GET_IPADDR_REQ, &req);
747 if (a_ret != E_OK) {
748 return a_ret;
749 }
750
751 a_ret = _ecn_fbs_add_data_ex(req, &requestid, sizeof(((ecn_udp_msg_get_ipaddr_res_t *)0)->requestid));
752 if (a_ret != E_OK) {
753 _ecn_fbs_del(req);
754 ECN_DBG_PUT("ecn_udp_get_ipaddr() : _ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
755 return a_ret;
756 }
757
758 a_ret = _ecn_fbs_add_data_ex(req, &enodid, sizeof(((ecn_udp_msg_get_ipaddr_res_t *)0)->enodid));
759 if (a_ret != E_OK) {
760 _ecn_fbs_del(req);
761 ECN_DBG_PUT("ecn_udp_get_ipaddr() : _ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
762 return a_ret;
763 }
764
765 a_ret = _ecn_fbs_add_data_ex(req, &enodadrb_table[enodid], sizeof(((ecn_udp_msg_get_ipaddr_res_t *)0)->enodadrb));
766 if (a_ret != E_OK) {
767 _ecn_fbs_del(req);
768 ECN_DBG_PUT("ecn_udp_get_ipaddr() : _ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
769 return a_ret;
770 }
771
772 *pk_req = req;
773
774 return E_OK;
775}
776
777char *ipaddr2str(char *buf, int bubsz, uint8_t *ipaddr)
778{
779 return ipaddr_ntoa_r((ip_addr_t *)ipaddr, buf, bubsz);
780}
781
782#endif
Note: See TracBrowser for help on using the repository browser.