source: EcnlProtoTool/trunk/ntshell/src/fdtable.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: 12.0 KB
RevLine 
[286]1/*
2 * TOPPERS ECHONET Lite Communication Middleware
3 *
4 * Copyright (C) 2017 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$
36 */
[279]37#include <stdint.h>
38#include <stdio.h>
39#include <sys/unistd.h>
40#include <limits.h>
41#include <kernel.h>
42#include <t_syslog.h>
43#include <t_stdlib.h>
44#include <sil.h>
45#include <stdlib.h>
46#include <string.h>
47#include <stdio.h>
48#include <setjmp.h>
49#include "../../../musl-1.1.12/include/poll.h"
50#include "syssvc/serial.h"
51#include "syssvc/syslog.h"
52#include <tinet_config.h>
53#include <netinet/in.h>
54#include <netinet/in_itron.h>
55#include <tinet_nic_defs.h>
56#include <tinet_cfg.h>
57#include <netinet/in_var.h>
58#include <net/ethernet.h>
59#include <net/if6_var.h>
60#include <net/net.h>
61#include <net/if_var.h>
62#include <netinet/udp_var.h>
63#include <ethernet_api.h>
64#include "ff.h"
65#include "socket_stub.h"
66#include "kernel_cfg.h"
67
68#define SIO_PORTID 1
69
70#define IO_TYPE_FREE 0
71#define IO_TYPE_SIO 1
72#define IO_TYPE_FILE 2
73#define IO_TYPE_TCP 3
74#define IO_TYPE_UDP 4
75
76static struct _IO_FILE fd_table[8 * sizeof(FLGPTN)] = {
77 { 0, IO_TYPE_SIO, 0, stdio_close, stdin_read, stdio_write },
78 { 1, IO_TYPE_SIO, 0, stdio_close, stdio_read, stdout_write },
79 { 2, IO_TYPE_SIO, 0, stdio_close, stdio_read, stderr_write },
80};
81#define fd_table_count (sizeof(fd_table) / sizeof(fd_table[0]))
82
83static int new_fd(int type, int id)
84{
85 for (int fd = 3; fd < fd_table_count; fd++) {
86 struct _IO_FILE *fp = &fd_table[fd];
87 if (fp->type != IO_TYPE_FREE)
88 continue;
89
90 fp->fd = fd;
91 fp->type = type;
92 fp->handle = id;
93 return fd;
94 }
95
96 return -1;
97}
98
99static struct _IO_FILE *id_to_fd(int type, int id)
100{
101 for (int fd = 3; fd < fd_table_count; fd++) {
102 struct _IO_FILE *fp = &fd_table[fd];
103 if ((fp->type == type) && (fp->handle == id))
104 return fp;
105 }
106
107 return NULL;
108}
109
110static int delete_fd(int type, int id)
111{
112 struct _IO_FILE *fp = id_to_fd(type, id);
113 if (fp == NULL)
114 return -1;
115
116 memset(fp, 0, sizeof(struct _IO_FILE));
117
118 return 0;
119}
120
121struct _IO_FILE *fd_to_fp(int fd)
122{
123 if ((fd < 0) || (fd >= fd_table_count))
124 return NULL;
125 return &fd_table[fd];
126}
127
128struct _IO_FILE *new_sio_fd(int sioid)
129{
130 int fd = new_fd(IO_TYPE_SIO, sioid);
131 if ((fd < 0) || (fd >= fd_table_count))
132 return NULL;
133
134 struct _IO_FILE *fp = &fd_table[fd];
135 fp->close = sio_close;
136 fp->read = sio_read;
137 fp->write = sio_write;
138
139 return fp;
140}
141
142int delete_sio_fd(int sioid)
143{
144 return delete_fd(IO_TYPE_SIO, sioid);
145}
146
147struct _IO_FILE *sioid_to_fd(int sioid)
148{
149 return id_to_fd(IO_TYPE_SIO, sioid);
150}
151
152struct _IO_FILE *new_file_fd(int fileid)
153{
154 int fd = new_fd(IO_TYPE_FILE, fileid);
155 if ((fd < 0) || (fd >= fd_table_count))
156 return NULL;
157
158 struct _IO_FILE *fp = &fd_table[fd];
159 fp->close = file_close;
160 fp->read = file_read;
161 fp->write = file_write;
162
163 return fp;
164}
165
166int delete_file_fd(int fileid)
167{
168 return delete_fd(IO_TYPE_FILE, fileid);
169}
170
171struct _IO_FILE *fileid_to_fd(int fileid)
172{
173 return id_to_fd(IO_TYPE_FILE, fileid);
174}
175
176struct _IO_FILE *new_tcp_fd(int tcpid)
177{
178 int fd = new_fd(IO_TYPE_TCP, tcpid);
179 if ((fd < 0) || (fd >= fd_table_count))
180 return NULL;
181
182 struct _IO_FILE *fp = &fd_table[fd];
183 fp->close = tcp_fd_close;
184 fp->read = tcp_fd_read;
185 fp->write = tcp_fd_write;
186
187 return fp;
188}
189
190int delete_tcp_fd(int tcpid)
191{
192 return delete_fd(IO_TYPE_TCP, tcpid);
193}
194
195struct _IO_FILE *tcpid_to_fd(int tcpid)
196{
197 return id_to_fd(IO_TYPE_TCP, tcpid);
198}
199
200struct _IO_FILE *new_udp_fd(int udpid)
201{
202 int fd = new_fd(IO_TYPE_UDP, udpid);
203 if ((fd < 0) || (fd >= fd_table_count))
204 return NULL;
205
206 struct _IO_FILE *fp = &fd_table[fd];
207 fp->close = udp_fd_close;
208 fp->read = udp_fd_read;
209 fp->write = udp_fd_write;
210
211 return fp;
212}
213
214int delete_udp_fd(int udpid)
215{
216 return delete_fd(IO_TYPE_UDP, udpid);
217}
218
219struct _IO_FILE *udpid_to_fd(int udpid)
220{
221 return id_to_fd(IO_TYPE_UDP, udpid);
222}
223
224int shell_isatty(int fd)
225{
226 if ((fd < 0) || (fd >= fd_table_count))
227 return 0;
228
229 struct _IO_FILE *fp = &fd_table[fd];
230 if (fp->type == IO_TYPE_SIO)
231 return 1;
232
233 return 0;
234}
235
236struct fd_events {
237 int count;
238 fd_set readfds;
239 fd_set writefds;
240 fd_set errorfds;
241};
242
243ER shell_get_evts(struct fd_events *evts, TMO tmout);
244
245#define TMO_MAX INT_MAX
246
247int select(int n, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tv)
248{
249 ER ret;
250 TMO tmout = TMO_FEVR;
251 struct fd_events evts;
252
253 if (tv != NULL) {
254 if (tv->tv_sec < (TMO_MAX / 1000000))
255 tmout = tv->tv_sec * 1000000 + tv->tv_usec;
256 else
257 tmout = TMO_MAX;
258 }
259
260 memcpy(&evts.readfds, rfds, sizeof(fd_set));
261 memcpy(&evts.writefds, wfds, sizeof(fd_set));
262 memcpy(&evts.errorfds, efds, sizeof(fd_set));
263 evts.count = 0;
264
265 ret = shell_get_evts(&evts, tmout);
266 if (ret == E_OK) {
267 memcpy(rfds, &evts.readfds, sizeof(fd_set));
268 memcpy(wfds, &evts.writefds, sizeof(fd_set));
269 memcpy(efds, &evts.errorfds, sizeof(fd_set));
270 return evts.count;
271 }
272 if (ret == E_TMOUT) {
273 memset(rfds, 0, sizeof(fd_set));
274 memset(wfds, 0, sizeof(fd_set));
275 memset(efds, 0, sizeof(fd_set));
276 return 0;
277 }
278
279 return -1;
280}
281
282int poll(struct pollfd *fds, nfds_t nfds, int timeout)
283{
284 ER ret;
285 TMO tmout;
286 struct fd_events evts;
287
288 if(timeout < 0)
289 tmout = TMO_FEVR;
290 else if (timeout < (TMO_MAX / 1000))
291 tmout = timeout * 1000;
292 else
293 tmout = TMO_MAX;
294
295 memset(&evts, 0, sizeof(evts));
296
297 for (int i = 0; i < nfds; i++) {
298 struct pollfd *pfd = &fds[i];
299 int fd = pfd->fd;
300 if ((fd < 0) || (fd >= fd_table_count))
301 continue;
302
303 if (pfd->events & POLLIN)
304 FD_SET(fd, &evts.readfds);
305 if (pfd->events & POLLOUT)
306 FD_SET(fd, &evts.writefds);
307 if (pfd->events & POLLERR)
308 FD_SET(fd, &evts.errorfds);
309 pfd->revents = 0;
310 }
311
312 ret = shell_get_evts(&evts, tmout);
313 if (ret == E_OK) {
314 int result = 0;
315 for (int i = 0; i < nfds; i++) {
316 struct pollfd *pfd = &fds[i];
317 int fd = pfd->fd;
318 if ((fd < 0) || (fd >= fd_table_count))
319 continue;
320
321 if (FD_ISSET(fd, &evts.readfds))
322 pfd->revents |= POLLIN;
323 if (FD_ISSET(fd, &evts.writefds))
324 pfd->revents |= POLLOUT;
325 if (FD_ISSET(fd, &evts.errorfds))
326 pfd->revents |= POLLERR;
327 if (pfd->revents != 0)
328 result++;
329 }
330 return result;
331 }
332 if (ret == E_TMOUT) {
333 return 0;
334 }
335
336 return -1;
337}
338
339void stdio_update_evts()
340{
341 int fd = STDIN_FILENO;
342 struct _IO_FILE *fp = &fd_table[fd];
343 T_SERIAL_RPOR rpor;
344 FLGPTN flgptn = 0;
345
346 ER ret = serial_ref_por(SIO_PORTID, &rpor);
347 if (ret != E_OK)
348 return;
349
350 if (rpor.reacnt != 0) {
351 if (fp->readevt_w == fp->readevt_r) fp->readevt_w++;
352
353 FD_SET(fd, (fd_set *)&flgptn);
354 }
355 if (rpor.wricnt != 0) {
356 if (fp->writeevt_w == fp->writeevt_r) fp->writeevt_w++;
357
358 FD_SET(fd, (fd_set *)&flgptn);
359 }
360
361 if (flgptn != 0) {
362 set_flg(FLG_SELECT_WAIT, flgptn);
363 }
364}
365
366void stdio_flgptn(FLGPTN *flgptn)
367{
368 int fd = STDIN_FILENO;
369 struct _IO_FILE *fp = &fd_table[fd];
370 T_SERIAL_RPOR rpor;
371 *flgptn = 0;
372
373 ER ret = serial_ref_por(SIO_PORTID, &rpor);
374 if (ret != E_OK)
375 return;
376
377 if (rpor.reacnt != 0) {
378 if (fp->readevt_w == fp->readevt_r) fp->readevt_w++;
379
380 FD_SET(fd, (fd_set *)flgptn);
381 }
382 if (rpor.wricnt != 0) {
383 if (fp->writeevt_w == fp->writeevt_r) fp->writeevt_w++;
384
385 FD_SET(fd, (fd_set *)flgptn);
386 }
387}
388
389ER socket_tcp_callback(ID cepid, FN fncd, void *p_parblk)
390{
391 struct _IO_FILE *fp = tcpid_to_fd(cepid);
392 FLGPTN flgptn = 0;
393
394 if (fp == NULL)
395 return E_PAR;
396
397 int fd = fp->fd;
398 FD_SET(fd, (fd_set *)&flgptn);
399
400 switch (fncd) {
401 case TFN_TCP_RCV_DAT:
402 if (fp->readevt_w == fp->readevt_r) fp->readevt_w++;
403
404 set_flg(FLG_SELECT_WAIT, flgptn);
405 return E_OK;
406
407 case TFN_TCP_SND_DAT:
408 if (fp->writeevt_w == fp->writeevt_r) fp->writeevt_w++;
409
410 set_flg(FLG_SELECT_WAIT, flgptn);
411 return E_OK;
412
413 case TFN_TCP_CAN_CEP:
414 if (fp->errorevt_w == fp->errorevt_r) fp->errorevt_w++;
415
416 set_flg(FLG_SELECT_WAIT, flgptn);
417 return E_OK;
418
419 case TFN_TCP_DEL_REP:
420 delete_tcp_rep(cepid);
421 return E_OK;
422
423 case TFN_TCP_DEL_CEP:
424 delete_tcp_fd(cepid);
425 return E_OK;
426
427 default:
428 return E_OK;
429 }
430}
431
432ER socket_udp_callback(ID cepid, FN fncd, void *p_parblk)
433{
434 struct _IO_FILE *fp = udpid_to_fd(cepid);
435 FLGPTN flgptn = 0;
436
437 if (fp == NULL)
438 return E_PAR;
439
440 int fd = fp->fd;
441 FD_SET(fd, (fd_set *)&flgptn);
442
443 switch (fncd) {
444 case TFN_UDP_CRE_CEP:
445 case TFN_UDP_RCV_DAT:
446 if (fp->readevt_w == fp->readevt_r) fp->readevt_w++;
447
448 set_flg(FLG_SELECT_WAIT, flgptn);
449 return E_OK;
450
451 case TFN_UDP_SND_DAT:
452 if (fp->writeevt_w == fp->writeevt_r) fp->writeevt_w++;
453
454 set_flg(FLG_SELECT_WAIT, flgptn);
455 return E_OK;
456
457 case TFN_UDP_CAN_CEP:
458 if (fp->errorevt_w == fp->errorevt_r) fp->errorevt_w++;
459
460 set_flg(FLG_SELECT_WAIT, flgptn);
461 return E_OK;
462
463 case TFN_UDP_DEL_CEP:
464 delete_udp_fd(cepid);
465 return E_OK;
466
467 default:
468 return E_OK;
469 }
470}
471
472ER shell_get_evts(struct fd_events *evts, TMO tmout)
473{
474 ER ret;
475 FLGPTN waitptn, flgptn = 0;
476
477 stdio_update_evts();
478
479 waitptn = *((FLGPTN *)&evts->readfds) | *((FLGPTN *)&evts->writefds) | *((FLGPTN *)&evts->errorfds);
480 memset(evts, 0, sizeof(*evts));
481
482 /* イベント待ち */
483 ret = twai_flg(FLG_SELECT_WAIT, waitptn, TWF_ORW, &flgptn, tmout);
484 if (ret != E_OK) {
485 if (ret != E_TMOUT) {
486 syslog(LOG_ERROR, "twai_flg => %d", ret);
487 return ret;
488 }
489
490 stdio_flgptn(&flgptn);
491
492 if (flgptn == 0)
493 return E_TMOUT;
494 }
495 flgptn &= waitptn;
496
497 /* 受け取ったフラグのみクリア */
498 ret = clr_flg(FLG_SELECT_WAIT, ~flgptn);
499 if (ret != E_OK) {
500 syslog(LOG_ERROR, "clr_flg => %d", ret);
501 }
502
503 struct _IO_FILE *fp = NULL;
504 for (int fd = 0; fd < fd_table_count; fd++) {
505 if (!FD_ISSET(fd, (fd_set *)&flgptn))
506 continue;
507
508 fp = &fd_table[fd];
509
510 if (fp->readevt_w != fp->readevt_r) {
511 fp->readevt_r++;
512 FD_SET(fd, &evts->readfds);
513 evts->count++;
514 }
515 if (fp->writeevt_w != fp->writeevt_r) {
516 fp->writeevt_r++;
517 FD_SET(fd, &evts->writefds);
518 evts->count++;
519 }
520 if (fp->errorevt_w != fp->errorevt_r) {
521 fp->errorevt_r++;
522 FD_SET(fd, &evts->errorfds);
523 evts->count++;
524 }
525 }
526
527 return E_OK;
528}
529
530void clean_fd()
531{
532 struct _IO_FILE *fp = NULL;
533 for (int fd = 3; fd < fd_table_count; fd++) {
534 fp = &fd_table[fd];
535 if ((fp->type == 0) || (fp->fd == 0))
536 continue;
537
538 fp->close(fp);
539
540 memset(fp, 0, sizeof(*fp));
541 }
542}
Note: See TracBrowser for help on using the repository browser.