source: EcnlProtoTool/trunk/ntshell/src/fdtable.c@ 331

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

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

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