source: asp3_tinet_ecnl_arm/trunk/ntshell/src/fdtable.c@ 352

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

arm向けASP3版ECNLを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 16.0 KB
Line 
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 */
37#include "shellif.h"
38#include <stdint.h>
39#include <kernel.h>
40#include <t_syslog.h>
41#include <t_stdlib.h>
42#include <sil.h>
43#include "syssvc/serial.h"
44#include "syssvc/syslog.h"
45#include "target_syssvc.h"
46#ifndef NTSHELL_NO_SOCKET
47#include <tinet_config.h>
48#include <netinet/in.h>
49#include <netinet/in_itron.h>
50#include <tinet_nic_defs.h>
51#include <tinet_cfg.h>
52#include <netinet/in_var.h>
53#include <net/ethernet.h>
54#include <net/if6_var.h>
55#include <net/net.h>
56#include <net/if_var.h>
57#include <netinet/udp_var.h>
58#include <netinet/tcp.h>
59#include <netinet/tcp_var.h>
60#endif
61#include "ff.h"
62#include "socket_stub.h"
63#include "kernel_cfg.h"
64#include <string.h>
65
66#define IO_TYPE_FREE 0
67#define IO_TYPE_SIO 1
68#define IO_TYPE_FILE 2
69#define IO_TYPE_DIR 3
70#define IO_TYPE_TCP 4
71#define IO_TYPE_UDP 5
72
73static struct _IO_FILE fd_table[8 * sizeof(FLGPTN)] = {
74 { 0, IO_TYPE_SIO, 0, stdio_close, stdin_read, stdio_write, sio_seek, sio_ioctl },
75 { 1, IO_TYPE_SIO, 0, stdio_close, stdio_read, stdout_write, sio_seek, sio_ioctl },
76 { 2, IO_TYPE_SIO, 0, stdio_close, stdio_read, stderr_write, sio_seek, sio_ioctl },
77};
78#define fd_table_count (sizeof(fd_table) / sizeof(fd_table[0]))
79
80static int new_fd(int type, int id)
81{
82 for (int fd = 3; fd < fd_table_count; fd++) {
83 struct _IO_FILE *fp = &fd_table[fd];
84 if (fp->type != IO_TYPE_FREE)
85 continue;
86
87 fp->fd = fd;
88 fp->type = type;
89 fp->handle = id;
90 return fd;
91 }
92
93 return -ENOMEM;
94}
95
96static struct _IO_FILE *id_to_fd(int type, int id)
97{
98 for (int fd = 3; fd < fd_table_count; fd++) {
99 struct _IO_FILE *fp = &fd_table[fd];
100 if ((fp->type == type) && (fp->handle == id))
101 return fp;
102 }
103
104 return NULL;
105}
106
107static int delete_fd(int type, int id)
108{
109 struct _IO_FILE *fp = id_to_fd(type, id);
110 if (fp == NULL)
111 return -EBADF;
112
113 return delete_fp(fp);
114}
115
116int delete_fp(struct _IO_FILE *fp)
117{
118 free(fp->pfile);
119 fp->pfile = NULL;
120 free(fp->pdir);
121 fp->pdir = NULL;
122 free(fp->psock);
123 fp->psock = NULL;
124 memset(fp, 0, sizeof(struct _IO_FILE));
125
126 return 0;
127}
128
129struct _IO_FILE *fd_to_fp(int fd)
130{
131 if ((fd < 0) || (fd >= fd_table_count))
132 return NULL;
133 return &fd_table[fd];
134}
135
136struct _IO_FILE *new_sio_fd(int sioid)
137{
138 int fd = new_fd(IO_TYPE_SIO, sioid);
139 if ((fd < 0) || (fd >= fd_table_count))
140 return NULL;
141
142 struct _IO_FILE *fp = &fd_table[fd];
143 fp->close = sio_close;
144 fp->read = sio_read;
145 fp->write = sio_write;
146 fp->seek = sio_seek;
147 fp->ioctl = sio_ioctl;
148 fp->writable = 1;
149
150 return fp;
151}
152
153int delete_sio_fd(int sioid)
154{
155 return delete_fd(IO_TYPE_SIO, sioid);
156}
157
158struct _IO_FILE *sioid_to_fd(int sioid)
159{
160 return id_to_fd(IO_TYPE_SIO, sioid);
161}
162
163struct _IO_FILE *new_file_fd(int fileid)
164{
165 int fd = new_fd(IO_TYPE_FILE, fileid);
166 if ((fd < 0) || (fd >= fd_table_count))
167 return NULL;
168
169 struct _IO_FILE *fp = &fd_table[fd];
170 fp->close = file_close;
171 fp->read = file_read;
172 fp->write = file_write;
173 fp->seek = file_seek;
174 fp->ioctl = file_ioctl;
175 fp->writable = 1;
176 fp->pfile = malloc(sizeof(FIL));
177 memset(fp->pfile, 0, sizeof(FIL));
178
179 return fp;
180}
181
182int delete_file_fd(int fileid)
183{
184 return delete_fd(IO_TYPE_FILE, fileid);
185}
186
187struct _IO_FILE *fileid_to_fd(int fileid)
188{
189 return id_to_fd(IO_TYPE_FILE, fileid);
190}
191
192struct _IO_FILE *new_dir_fd(int fileid)
193{
194 int fd = new_fd(IO_TYPE_DIR, fileid);
195 if ((fd < 0) || (fd >= fd_table_count))
196 return NULL;
197
198 struct _IO_FILE *fp = &fd_table[fd];
199 fp->close = dir_close;
200 fp->read = dir_read;
201 fp->write = dir_write;
202 fp->seek = dir_seek;
203 fp->ioctl = dir_ioctl;
204 fp->writable = 0;
205 fp->pdir = malloc(sizeof(struct _IO_DIR));
206 memset(fp->pdir, 0, sizeof(struct _IO_DIR));
207
208 return fp;
209}
210
211int delete_dir_fd(int dirid)
212{
213 return delete_fd(IO_TYPE_DIR, dirid);
214}
215
216struct _IO_FILE *dirid_to_fd(int dirid)
217{
218 return id_to_fd(IO_TYPE_DIR, dirid);
219}
220
221#ifndef NTSHELL_NO_SOCKET
222struct _IO_FILE *new_tcp_fd(int tcpid)
223{
224 int fd = new_fd(IO_TYPE_TCP, tcpid);
225 if ((fd < 0) || (fd >= fd_table_count))
226 return NULL;
227
228 struct _IO_FILE *fp = &fd_table[fd];
229 fp->close = tcp_fd_close;
230 fp->read = tcp_fd_read;
231 fp->write = tcp_fd_write;
232 fp->seek = tcp_fd_seek;
233 fp->ioctl = tcp_fd_ioctl;
234 fp->writable = 0;
235 fp->psock = malloc(sizeof(socket_t));
236 memset(fp->psock, 0, sizeof(socket_t));
237
238 return fp;
239}
240
241int delete_tcp_fd(int tcpid)
242{
243 return delete_fd(IO_TYPE_TCP, tcpid);
244}
245
246struct _IO_FILE *tcpid_to_fd(int tcpid)
247{
248 return id_to_fd(IO_TYPE_TCP, tcpid);
249}
250
251struct _IO_FILE *new_udp_fd(int udpid)
252{
253 int fd = new_fd(IO_TYPE_UDP, udpid);
254 if ((fd < 0) || (fd >= fd_table_count))
255 return NULL;
256
257 struct _IO_FILE *fp = &fd_table[fd];
258 fp->close = udp_fd_close;
259 fp->read = udp_fd_read;
260 fp->write = udp_fd_write;
261 fp->seek = udp_fd_seek;
262 fp->ioctl = udp_fd_ioctl;
263 fp->writable = 1;
264 fp->psock = malloc(sizeof(socket_t));
265 memset(fp->psock, 0, sizeof(socket_t));
266
267 return fp;
268}
269
270int delete_udp_fd(int udpid)
271{
272 return delete_fd(IO_TYPE_UDP, udpid);
273}
274
275struct _IO_FILE *udpid_to_fd(int udpid)
276{
277 return id_to_fd(IO_TYPE_UDP, udpid);
278}
279
280#endif
281
282struct fd_events {
283 int count;
284 fd_set readfds;
285 fd_set writefds;
286 fd_set errorfds;
287};
288
289ER shell_get_evts(struct fd_events *evts, TMO tmout);
290
291#define TMO_MAX INT_MAX
292
293int shell_select(int n, fd_set *__restrict rfds, fd_set *__restrict wfds, fd_set *__restrict efds, struct timeval *__restrict tv)
294{
295 ER ret;
296 TMO tmout = TMO_FEVR;
297 struct fd_events evts;
298
299 if (tv != NULL) {
300 if (tv->tv_sec < (TMO_MAX / 1000000))
301 tmout = tv->tv_sec * 1000000 + tv->tv_usec;
302 else
303 tmout = TMO_MAX;
304 }
305
306 memcpy(&evts.readfds, rfds, sizeof(fd_set));
307 memcpy(&evts.writefds, wfds, sizeof(fd_set));
308 memcpy(&evts.errorfds, efds, sizeof(fd_set));
309 evts.count = 0;
310
311 ret = shell_get_evts(&evts, tmout);
312 if (ret == E_OK) {
313 memcpy(rfds, &evts.readfds, sizeof(fd_set));
314 memcpy(wfds, &evts.writefds, sizeof(fd_set));
315 memcpy(efds, &evts.errorfds, sizeof(fd_set));
316 return evts.count;
317 }
318 if (ret == E_TMOUT) {
319 memset(rfds, 0, sizeof(fd_set));
320 memset(wfds, 0, sizeof(fd_set));
321 memset(efds, 0, sizeof(fd_set));
322 return 0;
323 }
324
325 return -EBADF;
326}
327
328int shell_poll(struct pollfd *fds, nfds_t nfds, int timeout)
329{
330 ER ret;
331 TMO tmout;
332 struct fd_events evts;
333
334 if(timeout < 0)
335 tmout = TMO_FEVR;
336 else if (timeout < (TMO_MAX / 1000))
337 tmout = timeout * 1000;
338 else
339 tmout = TMO_MAX;
340
341 memset(&evts, 0, sizeof(evts));
342
343 for (int i = 0; i < nfds; i++) {
344 struct pollfd *pfd = &fds[i];
345 int fd = pfd->fd;
346 if ((fd < 0) || (fd >= fd_table_count))
347 continue;
348
349 if (pfd->events & POLLIN)
350 FD_SET(fd, &evts.readfds);
351 if (pfd->events & POLLOUT)
352 FD_SET(fd, &evts.writefds);
353 if (pfd->events & POLLERR)
354 FD_SET(fd, &evts.errorfds);
355 pfd->revents = 0;
356 }
357
358 ret = shell_get_evts(&evts, tmout);
359 if (ret == E_OK) {
360 int result = 0;
361 for (int i = 0; i < nfds; i++) {
362 struct pollfd *pfd = &fds[i];
363 int fd = pfd->fd;
364 if ((fd < 0) || (fd >= fd_table_count))
365 continue;
366
367 if (FD_ISSET(fd, &evts.readfds))
368 pfd->revents |= POLLIN;
369 if (FD_ISSET(fd, &evts.writefds))
370 pfd->revents |= POLLOUT;
371 if (FD_ISSET(fd, &evts.errorfds))
372 pfd->revents |= POLLERR;
373 if (pfd->revents != 0)
374 result++;
375 }
376 return result;
377 }
378 if (ret == E_TMOUT) {
379 return 0;
380 }
381
382 return -EBADF;
383}
384
385/* TODO:コールバック化したい */
386void stdio_update_evts()
387{
388 int fd = STDIN_FILENO;
389 struct _IO_FILE *fp = &fd_table[fd];
390 T_SERIAL_RPOR rpor;
391 FLGPTN flgptn = 0;
392
393 ER ret = serial_ref_por(SIO_PORTID, &rpor);
394 if (ret != E_OK)
395 return;
396
397 if (rpor.reacnt != 0) {
398 if (fp->readevt_w == fp->readevt_r) fp->readevt_w++;
399
400 FD_SET(fd, (fd_set *)&flgptn);
401 }
402 if (rpor.wricnt < rpor.wbufsz) {
403 if (fp->writeevt_w == fp->writeevt_r) fp->writeevt_w++;
404
405 FD_SET(fd, (fd_set *)&flgptn);
406 }
407
408 if (flgptn != 0) {
409 set_flg(FLG_SELECT_WAIT, flgptn);
410 }
411}
412
413/* TODO:コールバック化したい */
414void stdio_flgptn(FLGPTN *flgptn)
415{
416 int fd = STDIN_FILENO;
417 struct _IO_FILE *fp = &fd_table[fd];
418 T_SERIAL_RPOR rpor;
419 *flgptn = 0;
420
421 ER ret = serial_ref_por(SIO_PORTID, &rpor);
422 if (ret != E_OK)
423 return;
424
425 if (rpor.reacnt != 0) {
426 if (fp->readevt_w == fp->readevt_r) fp->readevt_w++;
427
428 FD_SET(fd, (fd_set *)flgptn);
429 }
430 if (rpor.wricnt < rpor.wbufsz) {
431 if (fp->writeevt_w == fp->writeevt_r) fp->writeevt_w++;
432
433 FD_SET(fd, (fd_set *)flgptn);
434 }
435}
436
437#ifndef NTSHELL_NO_SOCKET
438
439ER socket_tcp_callback(ID cepid, FN fncd, void *p_parblk)
440{
441 struct _IO_FILE *fp = tcpid_to_fd(cepid);
442 FLGPTN flgptn = 0;
443
444 if (fp == NULL)
445 return E_PAR;
446
447 int fd = fp->fd;
448 FD_SET(fd, (fd_set *)&flgptn);
449
450 switch (fncd) {
451 case TFN_TCP_RCV_DAT:
452 if (fp->readevt_w == fp->readevt_r) fp->readevt_w++;
453
454 set_flg(FLG_SELECT_WAIT, flgptn);
455 return E_OK;
456
457 case TFN_TCP_SND_DAT:
458 if (fp->writeevt_w == fp->writeevt_r) fp->writeevt_w++;
459
460 set_flg(FLG_SELECT_WAIT, flgptn);
461 return E_OK;
462
463 case TFN_TCP_CAN_CEP:
464 if (fp->errorevt_w == fp->errorevt_r) fp->errorevt_w++;
465
466 set_flg(FLG_SELECT_WAIT, flgptn);
467 return E_OK;
468
469 case TFN_TCP_DEL_REP:
470 delete_tcp_rep(cepid);
471 return E_OK;
472
473 case TFN_TCP_DEL_CEP:
474 delete_tcp_fd(cepid);
475 return E_OK;
476
477 default:
478 return E_OK;
479 }
480}
481
482ER socket_udp_callback(ID cepid, FN fncd, void *p_parblk)
483{
484 struct _IO_FILE *fp = udpid_to_fd(cepid);
485 FLGPTN flgptn = 0;
486
487 if (fp == NULL)
488 return E_PAR;
489
490 int fd = fp->fd;
491 FD_SET(fd, (fd_set *)&flgptn);
492
493 switch (fncd) {
494 case TFN_UDP_CRE_CEP:
495 case TFN_UDP_RCV_DAT:
496 if (fp->readevt_w == fp->readevt_r) fp->readevt_w++;
497
498 set_flg(FLG_SELECT_WAIT, flgptn);
499 return E_OK;
500
501 case TFN_UDP_SND_DAT:
502 if (fp->writeevt_w == fp->writeevt_r) fp->writeevt_w++;
503
504 set_flg(FLG_SELECT_WAIT, flgptn);
505 return E_OK;
506
507 case TFN_UDP_CAN_CEP:
508 if (fp->errorevt_w == fp->errorevt_r) fp->errorevt_w++;
509
510 set_flg(FLG_SELECT_WAIT, flgptn);
511 return E_OK;
512
513 case TFN_UDP_DEL_CEP:
514 delete_udp_fd(cepid);
515 return E_OK;
516
517 default:
518 return E_OK;
519 }
520}
521
522#endif
523
524ER shell_get_evts(struct fd_events *evts, TMO tmout)
525{
526 ER ret;
527 FLGPTN waitptn, flgptn = 0, readfds = 0, writefds = 0;
528 struct _IO_FILE *fp = NULL;
529 int count = 0;
530
531 stdio_update_evts();
532
533#ifndef NTSHELL_NO_SOCKET
534 waitptn = *((FLGPTN *)&evts->errorfds);
535#else
536 waitptn = *((FLGPTN *)&evts->readfds) | *((FLGPTN *)&evts->errorfds);
537#endif
538 for (int fd = 0; fd < fd_table_count; fd++) {
539 fp = &fd_table[fd];
540
541#ifndef NTSHELL_NO_SOCKET
542 if (FD_ISSET(fd, &evts->readfds)) {
543 if ((fp->type == IO_TYPE_TCP)
544 && (GET_TCP_CEP(fp->psock->cepid)->rwbuf_count > 0)) {
545 FD_SET(fd, (fd_set *)&readfds);
546 count++;
547 if (fp->readevt_w == fp->readevt_r) fp->readevt_r--;
548 }
549 else {
550 FD_SET(fd, (fd_set *)&waitptn);
551 }
552 }
553#endif
554 if (FD_ISSET(fd, &evts->writefds)) {
555 if (fp->writable) {
556 FD_SET(fd, (fd_set *)&writefds);
557 count++;
558 }
559 else {
560 FD_SET(fd, (fd_set *)&waitptn);
561 }
562 }
563 }
564 memset(evts, 0, sizeof(*evts));
565
566 if (waitptn == 0) {
567 memcpy(&evts->readfds, &readfds, sizeof(evts->readfds));
568 memcpy(&evts->writefds, &writefds, sizeof(evts->writefds));
569 evts->count = count;
570 return E_OK;
571 }
572 else if ((readfds | writefds) != 0){
573 set_flg(FLG_SELECT_WAIT, (readfds | writefds));
574 }
575
576 /* イベント待ち */
577 ret = twai_flg(FLG_SELECT_WAIT, waitptn, TWF_ORW, &flgptn, tmout);
578 if (ret != E_OK) {
579 if (ret != E_TMOUT) {
580 syslog(LOG_ERROR, "twai_flg => %d", ret);
581 return ret;
582 }
583
584 stdio_flgptn(&flgptn);
585
586 if (flgptn == 0)
587 return E_TMOUT;
588 }
589 flgptn &= waitptn;
590
591 /* 受け取ったフラグのみクリア */
592 ret = clr_flg(FLG_SELECT_WAIT, ~flgptn);
593 if (ret != E_OK) {
594 syslog(LOG_ERROR, "clr_flg => %d", ret);
595 }
596
597 count = 0;
598 for (int fd = 0; fd < fd_table_count; fd++) {
599 if (!FD_ISSET(fd, (fd_set *)&waitptn))
600 continue;
601
602 fp = &fd_table[fd];
603
604 if (fp->readevt_w != fp->readevt_r) {
605 fp->readevt_r++;
606 FD_SET(fd, &evts->readfds);
607 count++;
608 }
609 if (fp->writeevt_w != fp->writeevt_r) {
610 fp->writeevt_r++;
611 fp->writable = 1;
612 }
613 if (fp->writable) {
614 FD_SET(fd, &evts->writefds);
615 count++;
616 }
617 if (fp->errorevt_w != fp->errorevt_r) {
618 fp->errorevt_r++;
619 FD_SET(fd, &evts->errorfds);
620 count++;
621 }
622 }
623 evts->count = count;
624
625 return E_OK;
626}
627
628void clean_fd()
629{
630 struct _IO_FILE *fp = NULL;
631 for (int fd = 3; fd < fd_table_count; fd++) {
632 fp = &fd_table[fd];
633 if ((fp->type == 0) || (fp->fd == 0))
634 continue;
635
636 fp->close(fp);
637
638 delete_fp(fp);
639 }
640}
641
642int shell_ioctl(int fd, int request, void *arg)
643{
644 struct _IO_FILE *fp = fd_to_fp(fd);
645 if (fp == NULL)
646 return -EBADF;
647
648 return fp->ioctl(fp, request, arg);
649}
650
651#ifdef NTSHELL_NO_SOCKET
652
653int shell_socket(int family, int type, int protocol)
654{
655 return -ENOMEM;
656}
657
658int shell_bind(int fd, const struct sockaddr *addr, socklen_t len)
659{
660 return -ENOMEM;
661}
662
663int shell_listen(int fd, int backlog)
664{
665 return -ENOMEM;
666}
667
668int shell_connect(int fd, const struct sockaddr *addr, socklen_t len)
669{
670 return -ENOMEM;
671}
672
673int shell_accept(int fd, struct sockaddr *__restrict addr, socklen_t *__restrict len)
674{
675 return -ENOMEM;
676}
677
678ssize_t shell_send(int fd, const void *buf, size_t len, int flags)
679{
680 return -ENOMEM;
681}
682
683ssize_t shell_sendto(int fd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t alen)
684{
685 return -ENOMEM;
686}
687
688ssize_t shell_sendmsg(int fd, const struct msghdr *msg, int flags)
689{
690 return -ENOMEM;
691}
692
693ssize_t shell_recv(int fd, void *buf, size_t len, int flags)
694{
695 return -ENOMEM;
696}
697
698ssize_t shell_recvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr *__restrict addr, socklen_t *__restrict alen)
699{
700 return -ENOMEM;
701}
702
703ssize_t shell_recvmsg(int fd, struct msghdr *msg, int flags)
704{
705 return -ENOMEM;
706}
707
708int shell_shutdown(int fd, int how)
709{
710 return -ENOMEM;
711}
712
713int shell_getsockopt(int fd, int level, int optname, void *optval, socklen_t *__restrict optlen)
714{
715 return -ENOMEM;
716}
717
718int shell_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen)
719{
720 return -ENOMEM;
721}
722
723int shell_getpeername(int fd, struct sockaddr *restrict addr, socklen_t *restrict len)
724{
725 return -ENOMEM;
726}
727
728int shell_getsockname(int fd, struct sockaddr *restrict addr, socklen_t *restrict len)
729{
730 return -ENOMEM;
731}
732#endif
Note: See TracBrowser for help on using the repository browser.