/* * Secure eXtended Message Passing framework * Secure eXtended Transport layer implementation (libsxt). * * socket wrapper * * (c) Alexander Vdolainen 2016 * * libsxmp is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * libsxmp is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see ."; * */ #include #include #include #include #include #include #include #include #include sxtsocket_t *sxtsocket_new(void) { sxtsocket_t *s = malloc(sizeof(sxtsocket_t)); if(!s) return NULL; s->state = SXTSOCKET_NIL; return s; } int sxtsocket_close(sxtsocket_t *s) { if(!s) return SXT_EINVAL; if(s->state == SXTSOCKET_ACTIVE || s->state == SXTSOCKET_DEAD) { close(s->fd); s->state = SXTSOCKET_CLOSED; } /* in other cases ignore, already closed or never opened */ return SXT_SUCCESS; } int sxtsocket_setnb(sxtsocket_t *s) { #ifndef WIN32 int fdmode; #endif if(!s || s->state != SXTSOCKET_ACTIVE) return SXT_EINVAL; #ifndef WIN32 fdmode = fcntl(s->fd, F_GETFL, 0); fdmode |= O_NDELAY; if(fcntl(s->fd, F_SETFL, fdmode)) return SXT_EIO; #endif return SXT_SUCCESS; } ssize_t sxtsocket_read(sxtsocket_t *s, void *buf, size_t bufsize) { ssize_t rcnt = -1; if(!s || s->state != SXTSOCKET_ACTIVE) goto __failed; rcnt = read(s->fd, buf, bufsize); __failed: return rcnt; } ssize_t sxtsocket_write(sxtsocket_t *s, void *buf, size_t bufsize) { ssize_t wcnt = -1; if(!s || s->state != SXTSOCKET_ACTIVE) goto __failed; wcnt = write(s->fd, (const void *)buf, bufsize); __failed: return wcnt; } int sxtsocket_poll(sxtsocket_t **rsck, int rscksz, sxtsocket_t **wsck, int wscksz, int tm_msec, int **ra, int **wa) { int r = 0, i = 0, err = SXTSCT_ERR, c, ii; struct pollfd *fds = NULL; int *rr = NULL, *wr = NULL; if(!rsck || !wsck) return SXTSCT_ERR; if(!rscksz || !wscksz) return SXTSCT_ERR; if(!(fds = malloc(sizeof(struct pollfd)*(rscksz + wscksz)))) return SXTSCT_ERR; else memset(fds, 0, sizeof(struct pollfd)*(rscksz + wscksz)); /* fill and check given values */ for(i = 0; i < rscksz; i++) { if(rsck[i]->state != SXTSOCKET_ACTIVE) goto __failed; fds[i].fd = rsck[i]->fd; fds[i].events = POLLIN | POLLPRI; } for(; i < rscksz + wscksz; i++) { if(wsck[i - rscksz]->state != SXTSOCKET_ACTIVE) goto __failed; fds[i].fd = wsck[i - rscksz]->fd; fds[i].events = POLLOUT; } r = poll(fds, rscksz + wscksz, tm_msec); if(!r) { err = SXTSCT_TMO; goto __failed; } else if(r < 0) goto __failed; for(i = 0, c = 0; i < rscksz; i++) { if(fds[i].revents) { if((fds[i].revents & POLLHUP) || (fds[i].revents & POLLERR)) rsck[i]->state = SXTSOCKET_DEAD; c++; } } if(c) { if(!(rr = malloc(sizeof(int)*(c + 1)))) { err = SXTSCT_ERR; goto __failed; } for(i = 0, ii = 0; i < rscksz; i++) { if(fds[i].revents) { rr[ii] = i; ii++; } } rr[ii] = -1; err = 0; err |= SXTSCK_RDR; } if((r - c) > 0) { r -= c; if(!(wr = malloc(sizeof(int)*(r + 1)))) { err = SXTSCT_ERR; goto __failed; } for(i = rscksz, ii = 0; i < (rscksz + wscksz); i++) { if(fds[i].revents) { if((fds[i].revents & POLLHUP) || (fds[i].revents & POLLERR)) wsck[i - rscksz]->state = SXTSOCKET_DEAD; wr[ii] = i - rscksz; ii++; } } wr[ii] = -1; if(err == SXTSCT_ERR) err = 0; err |= SXTSCK_WRR; } r = 0; __failed: if(fds) free(fds); if(r > 0 && err == SXTSCT_ERR) { if(rr) free(rr); if(wr) free(wr); } return err; } void sxtsocket_free(sxtsocket_t *s) { if(!s) return; else sxtsocket_close(s); free(s); return; }