|
|
|
/*
|
|
|
|
* Secure eXtended Message Passing framework
|
|
|
|
* Secure eXtended Transport layer implementation (libsxt).
|
|
|
|
*
|
|
|
|
* socket wrapper
|
|
|
|
*
|
|
|
|
* (c) Alexander Vdolainen 2016 <avdolainen@zoho.com>
|
|
|
|
*
|
|
|
|
* 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 2.1 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 <http://www.gnu.org/licenses/>.";
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <poll.h>
|
|
|
|
|
|
|
|
#include <sxt/errno.h>
|
|
|
|
#include <sxt/socket.h>
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|