/* * TOPPERS ECHONET Lite Communication Middleware * * Copyright (C) 2017 Cores Co., Ltd. Japan * * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する. * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー * スコード中に含まれていること. * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記 * の無保証規定を掲載すること. * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ * と. * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著 * 作権表示,この利用条件および下記の無保証規定を掲載すること. * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに * 報告すること. * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること. * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを * 免責すること. * * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ * の責任を負わない. * * @(#) $Id: socket_stub.c 286 2017-05-02 15:25:33Z coas-nagasima $ */ #include #include #if 0 #include #include #include #include #include #include #endif #include #include "sys/unistd.h" #include #include #include #include #include #include #include #include #include #include #include #include "syssvc/syslog.h" #include #include #include #include #include #include #include #include #include #include #include //#include extern const ID tmax_tcp_cepid; #include "ff.h" #include "socket_stub.h" #define SO_REUSEADDR 2 typedef struct id_table_t { int used; ID id; } id_table_t; id_table_t tcp_repid_table[] = { {0, USR_TCP_REP1}, {0, USR_TCP_REP2}, {0, USR_TCP_REP3}, {0, USR_TCP_REP4} }; #define tcp_repid_table_count (sizeof(tcp_repid_table) / sizeof(tcp_repid_table[0])) id_table_t tcp_cepid_table[] = { {0, USR_TCP_CEP1}, {0, USR_TCP_CEP2}, {0, USR_TCP_CEP3}, {0, USR_TCP_CEP4}, {0, USR_TCP_CEP5}, {0, USR_TCP_CEP6}, {0, USR_TCP_CEP7}, {0, USR_TCP_CEP8} }; #define tcp_cepid_table_count (sizeof(tcp_cepid_table) / sizeof(tcp_cepid_table[0])) id_table_t udp_cepid_table[] = { {0, USR_UDP_CEP1}, {0, USR_UDP_CEP2}, {0, USR_UDP_CEP3}, {0, USR_UDP_CEP4} }; #define udp_cepid_table_count (sizeof(udp_cepid_table) / sizeof(udp_cepid_table[0])) ID new_id(id_table_t *table, int count) { for (int i = 0; i < count; i++) { id_table_t *item = &table[i]; if (item->used != 0) continue; item->used = 1; return item->id; } return -1; } int delete_id(id_table_t *table, int count, ID id) { for (int i = 0; i < count; i++) { id_table_t *item = &table[i]; if ((item->used == 0) || (item->id != id)) continue; item->used = 0; return 0; } return -1; } int delete_tcp_rep(int repid) { delete_tcp_fd(tmax_tcp_cepid + repid); } unsigned char tcp_buf[tcp_cepid_table_count][2 * 512]; unsigned char *id_to_buff(ID id) { for (int i = 0; i < tcp_cepid_table_count; i++) { id_table_t *item = &tcp_cepid_table[i]; if ((item->used == 0) || (item->id != id)) continue; return tcp_buf[i]; } return NULL; } typedef struct _IO_FILE SOCKET; int socket(int family, int type, int protocol) { SOCKET *fp; switch (family) { case AF_INET: case AF_INET6: break; default: return -1; } switch (type) { case SOCK_STREAM: fp = new_tcp_fd(0); break; case SOCK_DGRAM: fp = new_udp_fd(0); break; default: return -1; } if (fp == NULL) { return -1; } fp->socket.family = family; fp->socket.type = type; fp->socket.protocol = protocol; return fp->fd; } int bind(int fd, const struct sockaddr *addr, socklen_t len) { SOCKET *fp = fd_to_fp(fd); if (fp == NULL) { return -1; } if (fp->socket.family != addr->sa_family) { return -1; } ER ret; switch (addr->sa_family) { case AF_INET: { if (len < 8) { return -1; } struct sockaddr_in *addr_in = (struct sockaddr_in *)addr; memcpy(&fp->socket.laddr4, addr, len); switch (fp->socket.type) { case SOCK_STREAM: { ID cepid = new_id(tcp_cepid_table, tcp_cepid_table_count); if (cepid < 0) return -1; fp->socket.buf_size = 512 + 512; fp->socket.buf = id_to_buff(cepid); T_TCP_CCEP ccep = { 0, fp->socket.buf, 512, &fp->socket.buf[512], 512, socket_tcp_callback }; ret = tcp_cre_cep(cepid, &ccep); if (ret != E_OK) { delete_id(tcp_cepid_table, tcp_cepid_table_count, cepid); return -1; } fp->handle = cepid; fp->socket.cepid = cepid; break; } case SOCK_DGRAM: { ID cepid = new_id(udp_cepid_table, udp_cepid_table_count); if (cepid < 0) return -1; T_UDP_CCEP ccep = { 0, {ntohl(addr_in->sin_addr.s_addr), ntohs(addr_in->sin_port)}, socket_udp_callback }; ret = udp_cre_cep(cepid, &ccep); if (ret != E_OK) { delete_id(udp_cepid_table, udp_cepid_table_count, cepid); return -1; } fp->handle = cepid; fp->socket.cepid = cepid; break; } default: return -1; } break; } case AF_INET6: { if (len < 20) { return -1; } memcpy(&fp->socket.laddr4, addr, len); break; } } return 0; } int listen(int fd, int backlog) { SOCKET *fp = fd_to_fp(fd); if ((fp == NULL) || (fp->socket.type != SOCK_STREAM)) { return -1; } fp->socket.backlog = backlog; ER ret; switch (fp->socket.family) { case AF_INET: { ID repid = new_id(tcp_repid_table, tcp_repid_table_count); if (repid < 0) return -1; struct sockaddr_in *laddr = &fp->socket.laddr4; T_TCP_CREP crep = { 0, {ntohl(laddr->sin_addr.s_addr), ntohs(laddr->sin_port)} }; ret = tcp_cre_rep(repid, &crep); if (ret != E_OK) { delete_id(tcp_repid_table, tcp_repid_table_count, repid); return -1; } fp->socket.repid = repid; break; } case AF_INET6: { break; } } return 0; } int connect(int fd, const struct sockaddr *addr, socklen_t len) { SOCKET *fp = fd_to_fp(fd); if ((fp == NULL) || (fp->socket.type != SOCK_STREAM)) { return -1; } ER ret; switch (fp->socket.family) { case AF_INET: { if (len < 8) { return -1; } if (fp->socket.cepid == 0) { ID cepid = new_id(tcp_cepid_table, tcp_cepid_table_count); if (cepid < 0) return -1; fp->socket.buf_size = 512 + 512; fp->socket.buf = id_to_buff(cepid); T_TCP_CCEP ccep = { 0, fp->socket.buf, 512, &fp->socket.buf[512], 512, socket_tcp_callback }; ret = tcp_cre_cep(cepid, &ccep); if (ret != E_OK) { delete_id(tcp_cepid_table, tcp_cepid_table_count, cepid); return -1; } fp->handle = cepid; fp->socket.cepid = cepid; } struct sockaddr_in *laddr = &fp->socket.laddr4; struct sockaddr_in *raddr = &fp->socket.raddr4; memset(raddr, 0, sizeof(*raddr)); memcpy(raddr, addr, len); T_IPV4EP lep = { ntohl(laddr->sin_addr.s_addr), ntohs(laddr->sin_port) }; T_IPV4EP rep = { ntohl(raddr->sin_addr.s_addr), ntohs(raddr->sin_port) }; ret = tcp_con_cep(fp->socket.cepid, &lep, &rep, TMO_FEVR); if (ret < 0) { return -1; } break; } case AF_INET6: { break; } } return 0; } int accept(int fd, struct sockaddr *addr, socklen_t *len) { SOCKET *lfp = fd_to_fp(fd); if ((lfp == NULL) || (lfp->socket.type != SOCK_STREAM)) { return -1; } SOCKET *fp = new_tcp_fd(0); if (fp == NULL) { return -1; } memcpy(&fp->socket, &lfp->socket, sizeof(fp->socket)); ER ret; switch (fp->socket.family) { case AF_INET: { ID cepid; if (fp->socket.cepid == 0) { cepid = new_id(tcp_cepid_table, tcp_cepid_table_count); if (cepid < 0) return -1; fp->socket.buf_size = 512 + 512; fp->socket.buf = id_to_buff(cepid); T_TCP_CCEP ccep = { 0, fp->socket.buf, 512, &fp->socket.buf[512], 512, socket_tcp_callback }; ret = tcp_cre_cep(cepid, &ccep); if (ret != E_OK) { delete_id(tcp_cepid_table, tcp_cepid_table_count, cepid); return -1; } fp->handle = cepid; fp->socket.cepid = cepid; } else { cepid = lfp->socket.cepid; lfp->handle = tmax_tcp_cepid + lfp->socket.repid; lfp->socket.cepid = 0; lfp->socket.buf_size = 0; lfp->socket.buf = 0; } T_IPV4EP rep = { 0, 0 }; ret = tcp_acp_cep(fp->socket.cepid, fp->socket.repid, &rep, TMO_FEVR); if (ret < 0) { return -1; } struct sockaddr_in *raddr = &fp->socket.raddr4; memset(raddr, 0, sizeof(*raddr)); raddr->sin_family = AF_INET; raddr->sin_port = htons(rep.portno); raddr->sin_addr.s_addr = htonl(rep.ipaddr); break; } case AF_INET6: { break; } } if (addr != NULL && len != NULL) { int sz = *len; if (sz < 8) { return -1; } struct sockaddr_in *raddr = &fp->socket.raddr4; if (sz > sizeof(*raddr)) sz = sizeof(*raddr); memcpy(addr, raddr, sz); *len = sizeof(*raddr); } return fp->fd; } ssize_t send(int fd, const void *buf, size_t len, int flags) { SOCKET *fp = fd_to_fp(fd); if (fp == NULL) { return -1; } int ret = 0; switch (fp->socket.family) { case AF_INET: { switch (fp->socket.type) { case SOCK_STREAM: { if (flags & MSG_OOB) { ret = tcp_snd_oob(fp->socket.cepid, (void *)buf, len, TMO_FEVR); if (ret < 0) { return -1; } } else { ret = tcp_snd_dat(fp->socket.cepid, (void *)buf, len, TMO_FEVR); if (ret < 0) { return -1; } } break; } case SOCK_DGRAM: { return -1; } } break; } case AF_INET6: { break; } } return ret; } ssize_t sendto(int fd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t alen) { SOCKET *fp = fd_to_fp(fd); if (fp == NULL) { return -1; } int ret = 0; switch (fp->socket.family) { case AF_INET: { switch (fp->socket.type) { case SOCK_STREAM: { if ((addr != NULL) && (alen != 0)) { return -1; } if (flags & MSG_OOB) { ret = tcp_snd_oob(fp->socket.cepid, (void *)buf, len, TMO_FEVR); if (ret < 0) { return -1; } } else { ret = tcp_snd_dat(fp->socket.cepid, (void *)buf, len, TMO_FEVR); if (ret < 0) { return -1; } } break; } case SOCK_DGRAM: { int sz = alen; if (sz < 8) { return -1; } struct sockaddr_in *raddr = &fp->socket.raddr4; memset(raddr, 0, sizeof(*raddr)); memcpy(raddr, addr, sz); T_IPV4EP rep = { ntohl(raddr->sin_addr.s_addr), ntohs(raddr->sin_port) }; ret = udp_snd_dat(fp->socket.cepid, &rep, (void *)buf, len, TMO_FEVR); if (ret < 0) { return -1; } break; } } break; } case AF_INET6: { break; } } return ret; } ssize_t recv(int fd, void *buf, size_t len, int flags) { SOCKET *fp = fd_to_fp(fd); if (fp == NULL) { return -1; } int ret = 0; switch (fp->socket.family) { case AF_INET: { switch (fp->socket.type) { case SOCK_STREAM: { if (flags & MSG_OOB) { ret = tcp_rcv_oob(fp->socket.cepid, buf, len); if (ret < 0) { return -1; } } else { ret = tcp_rcv_dat(fp->socket.cepid, buf, len, TMO_FEVR); if (ret < 0) { return -1; } } break; } case SOCK_DGRAM: { T_IPV4EP rep = { 0, 0 }; ret = udp_rcv_dat(fp->socket.cepid, &rep, buf, len, TMO_FEVR); if (ret < 0) { return -1; } } } break; } case AF_INET6: { break; } } return ret; } ssize_t recvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr *addr, socklen_t *alen) { SOCKET *fp = fd_to_fp(fd); if (fp == NULL) { return -1; } int ret = 0; switch (fp->socket.family) { case AF_INET: { switch (fp->socket.type) { case SOCK_STREAM: { if (flags & MSG_OOB) { ret = tcp_rcv_oob(fp->socket.cepid, buf, len); if (ret < 0) { return -1; } } else { ret = tcp_rcv_dat(fp->socket.cepid, buf, len, TMO_FEVR); if (ret < 0) { return -1; } } break; } case SOCK_DGRAM: { T_IPV4EP rep = { 0, 0 }; ret = udp_rcv_dat(fp->socket.cepid, &rep, buf, len, TMO_FEVR); if (ret < 0) { return -1; } int sz = *alen; struct sockaddr_in raddr; memset(&raddr, 0, sizeof(raddr)); raddr.sin_family = AF_INET; raddr.sin_port = htons(rep.portno); raddr.sin_addr.s_addr = htonl(rep.ipaddr); if (sz > sizeof(raddr)) sz = sizeof(raddr); memcpy(addr, &raddr, sz); } } break; } case AF_INET6: { break; } } return ret; } int shutdown(int fd, int how) { SOCKET *fp = fd_to_fp(fd); if (fp == NULL) { return -1; } ER ret; switch (fp->socket.family) { case AF_INET: { switch (fp->socket.type) { case SOCK_STREAM: { ret = tcp_sht_cep(fp->socket.cepid); if (ret < 0) { return -1; } break; } } break; } case AF_INET6: { break; } } return 0; } int getsockopt(int fd, int level, int optname, void *optval, socklen_t *optlen) { SOCKET *fp = fd_to_fp(fd); if (fp == NULL) { return -1; } ER ret; switch (fp->socket.family) { case AF_INET: { switch (fp->socket.type) { case SOCK_STREAM: { switch (optname) { case SO_REUSEADDR: if (fp->socket.flags & SO_REUSEADDR) { *(bool *)optval = true; } else { *(bool *)optval = false; } break; default: ret = tcp_get_opt(fp->socket.cepid, optname, (void *)optval, *optlen); if (ret < 0) { return -1; } *optlen = ret; break; } break; } case SOCK_DGRAM: { ret = udp_get_opt(fp->socket.cepid, optname, (void *)optval, *optlen); if (ret < 0) { return -1; } *optlen = ret; break; } } break; } case AF_INET6: { break; } } return 0; } int setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen) { SOCKET *fp = fd_to_fp(fd); if (fp == NULL) { return -1; } ER ret; switch (fp->socket.family) { case AF_INET: { switch (fp->socket.type) { case SOCK_STREAM: { switch (optname) { case SO_REUSEADDR: if (*(bool *)optval) { fp->socket.flags |= SO_REUSEADDR; } else { fp->socket.flags &= ~SO_REUSEADDR; } break; default: ret = tcp_set_opt(fp->socket.cepid, optname, (void *)optval, optlen); if (ret < 0) { return -1; } break; } break; } case SOCK_DGRAM: { ret = udp_set_opt(fp->socket.cepid, optname, (void *)optval, optlen); if (ret < 0) { return -1; } break; } } break; } case AF_INET6: { break; } } return 0; } int tcp_fd_close(struct _IO_FILE *fp) { ER ret; switch (fp->socket.family) { case AF_INET: { if (fp->socket.cepid != 0) { ID cepid = fp->socket.cepid; ret = tcp_sht_cep(cepid); if (ret < 0) { //return -1; } ret = tcp_cls_cep(cepid, TMO_FEVR); if (ret < 0) { //return -1; } ret = tcp_del_cep(cepid); delete_tcp_fd(cepid); delete_id(tcp_cepid_table, tcp_cepid_table_count, cepid); if (ret < 0) { return -1; } } else if (fp->socket.repid != 0) { ID repid = fp->socket.repid; ret = tcp_del_rep(repid); delete_tcp_fd(tmax_tcp_cepid + repid); delete_id(tcp_repid_table, tcp_repid_table_count, repid); if (ret < 0) { return -1; } } else { return -1; } break; } case AF_INET6: { break; } } return 0; } size_t tcp_fd_read(struct _IO_FILE *fp, unsigned char *dst, size_t dstsz) { return recv(fp->fd, dst, dstsz, 0); } size_t tcp_fd_write(struct _IO_FILE *fp, const unsigned char *src, size_t srcsz) { return send(fp->fd, src, srcsz, 0); } off_t tcp_fd_seek(struct _IO_FILE *fp, off_t ofs, int org) { return -1; } int udp_fd_close(struct _IO_FILE *fp) { ER ret; ID cepid; switch (fp->socket.family) { case AF_INET: { cepid = fp->socket.cepid; ret = udp_del_cep(cepid); delete_udp_fd(cepid); delete_id(udp_cepid_table, udp_cepid_table_count, cepid); if (ret < 0) { return -1; } break; } case AF_INET6: { break; } } return 0; } size_t udp_fd_read(struct _IO_FILE *fp, unsigned char *dst, size_t dstsz) { return recv(fp->fd, dst, dstsz, 0); } size_t udp_fd_write(struct _IO_FILE *fp, const unsigned char *src, size_t srcsz) { return send(fp->fd, src, srcsz, 0); } off_t udp_fd_seek(struct _IO_FILE *fp, off_t ofs, int org) { return -1; } #ifndef TCP_CFG_EXTENTIONS ER tcp_cre_rep(ID repid, T_TCP_CREP *pk_crep) { syslog(LOG_ERROR, "tcp_cre_rep not implement"); shell_abort(); return E_SYS; } ER tcp_cre_cep(ID cepid, T_TCP_CCEP *pk_ccep) { syslog(LOG_ERROR, "tcp_cre_cep not implement"); shell_abort(); return E_SYS; } #endif #ifndef UDP_CFG_EXTENTIONS ER udp_cre_cep(ID cepid, T_UDP_CCEP *pk_ccep) { syslog(LOG_ERROR, "udp_cre_cep not implement"); shell_abort(); return E_SYS; } #endif #ifndef TCP_CFG_EXTENTIONS ER_UINT tcp_snd_oob(ID cepid, void *data, int_t len, TMO tmout) { syslog(LOG_ERROR, "tcp_snd_oob not implement"); shell_abort(); return E_SYS; } ER_UINT tcp_rcv_oob(ID cepid, void *data, int_t len) { syslog(LOG_ERROR, "tcp_rcv_oob not implement"); shell_abort(); return E_SYS; } ER tcp_set_opt(ID cepid, int_t optname, void *optval, int_t optlen) { syslog(LOG_ERROR, "tcp_set_opt not implement"); shell_abort(); return E_SYS; } ER tcp_get_opt(ID cepid, int_t optname, void *optval, int_t optlen) { syslog(LOG_ERROR, "tcp_get_opt not implement"); shell_abort(); return E_SYS; } #endif #ifndef UDP_CFG_EXTENTIONS ER udp_get_opt(ID cepid, int_t optname, void *optval, int_t optlen) { syslog(LOG_ERROR, "udp_get_opt not implement"); shell_abort(); return E_SYS; } ER udp_set_opt(ID cepid, int_t optname, void *optval, int_t optlen) { syslog(LOG_ERROR, "udp_set_opt not implement"); shell_abort(); return E_SYS; } #endif