minissdpd/minissdpd.c: write on non blocking unix socket
This commit is contained in:
parent
a4d3546635
commit
af3c6392e5
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: minissdpd.c,v 1.43 2014/12/05 13:43:00 nanard Exp $ */
|
/* $Id: minissdpd.c,v 1.44 2014/12/05 17:31:46 nanard Exp $ */
|
||||||
/* MiniUPnP project
|
/* MiniUPnP project
|
||||||
* (c) 2007-2014 Thomas Bernard
|
* (c) 2007-2014 Thomas Bernard
|
||||||
* website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
* website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||||
|
@ -45,6 +45,9 @@
|
||||||
struct reqelem {
|
struct reqelem {
|
||||||
int socket;
|
int socket;
|
||||||
LIST_ENTRY(reqelem) entries;
|
LIST_ENTRY(reqelem) entries;
|
||||||
|
unsigned char * output_buffer;
|
||||||
|
int output_buffer_offset;
|
||||||
|
int output_buffer_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* device data structures */
|
/* device data structures */
|
||||||
|
@ -164,6 +167,70 @@ parselan_error:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
write_buffer(struct reqelem * req)
|
||||||
|
{
|
||||||
|
if(req->output_buffer && req->output_buffer_len > 0) {
|
||||||
|
int n = write(req->socket,
|
||||||
|
req->output_buffer + req->output_buffer_offset,
|
||||||
|
req->output_buffer_len);
|
||||||
|
if(n >= 0) {
|
||||||
|
req->output_buffer_offset += n;
|
||||||
|
req->output_buffer_len -= n;
|
||||||
|
} else if(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
add_to_buffer(struct reqelem * req, const unsigned char * data, int len)
|
||||||
|
{
|
||||||
|
unsigned char * tmp;
|
||||||
|
if(req->output_buffer_offset > 0) {
|
||||||
|
memmove(req->output_buffer, req->output_buffer + req->output_buffer_offset, req->output_buffer_len);
|
||||||
|
req->output_buffer_offset = 0;
|
||||||
|
}
|
||||||
|
tmp = realloc(req->output_buffer, req->output_buffer_len + len);
|
||||||
|
if(tmp == NULL) {
|
||||||
|
syslog(LOG_ERR, "%s: failed to allocate %d bytes", __func__, req->output_buffer_len + len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
req->output_buffer = tmp;
|
||||||
|
memcpy(req->output_buffer + req->output_buffer_len, data, len);
|
||||||
|
req->output_buffer_len += len;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
write_or_buffer(struct reqelem * req, const unsigned char * data, int len)
|
||||||
|
{
|
||||||
|
if(write_buffer(req) < 0)
|
||||||
|
return -1;
|
||||||
|
if(req->output_buffer && req->output_buffer_len > 0) {
|
||||||
|
return add_to_buffer(req, data, len);
|
||||||
|
} else {
|
||||||
|
int n = write(req->socket, data, len);
|
||||||
|
if(n == len)
|
||||||
|
return len;
|
||||||
|
if(n < 0) {
|
||||||
|
if(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) {
|
||||||
|
n = add_to_buffer(req, data, len);
|
||||||
|
if(n < 0) return n;
|
||||||
|
} else {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
n = add_to_buffer(req, data + n, len - n);
|
||||||
|
if(n < 0) return n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
nts_to_str(int nts)
|
nts_to_str(int nts)
|
||||||
{
|
{
|
||||||
|
@ -757,7 +824,7 @@ void processRequest(struct reqelem * req)
|
||||||
rbuf[0] = nrep;
|
rbuf[0] = nrep;
|
||||||
syslog(LOG_DEBUG, "(s=%d) response : %d device%s",
|
syslog(LOG_DEBUG, "(s=%d) response : %d device%s",
|
||||||
req->socket, nrep, (nrep > 1) ? "s" : "");
|
req->socket, nrep, (nrep > 1) ? "s" : "");
|
||||||
if(write(req->socket, rbuf, rp - rbuf) < 0) {
|
if(write_or_buffer(req, rbuf, rp - rbuf) < 0) {
|
||||||
syslog(LOG_ERR, "(s=%d) write: %m", req->socket);
|
syslog(LOG_ERR, "(s=%d) write: %m", req->socket);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -859,15 +926,11 @@ void processRequest(struct reqelem * req)
|
||||||
/* Inserting new service */
|
/* Inserting new service */
|
||||||
LIST_INSERT_HEAD(&servicelisthead, newserv, entries);
|
LIST_INSERT_HEAD(&servicelisthead, newserv, entries);
|
||||||
newserv = NULL;
|
newserv = NULL;
|
||||||
/*rbuf[0] = '\0';
|
|
||||||
if(write(req->socket, rbuf, 1) < 0)
|
|
||||||
syslog(LOG_ERR, "(s=%d) write: %m", req->socket);
|
|
||||||
*/
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
syslog(LOG_WARNING, "Unknown request type %d", type);
|
syslog(LOG_WARNING, "Unknown request type %d", type);
|
||||||
rbuf[0] = '\0';
|
rbuf[0] = '\0';
|
||||||
if(write(req->socket, rbuf, 1) < 0) {
|
if(write_or_buffer(req, rbuf, 1) < 0) {
|
||||||
syslog(LOG_ERR, "(s=%d) write: %m", req->socket);
|
syslog(LOG_ERR, "(s=%d) write: %m", req->socket);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -1183,6 +1246,10 @@ int main(int argc, char * * argv)
|
||||||
FD_SET(req->socket, &readfds);
|
FD_SET(req->socket, &readfds);
|
||||||
SET_MAX(max_fd, req->socket);
|
SET_MAX(max_fd, req->socket);
|
||||||
}
|
}
|
||||||
|
if(req->output_buffer_len > 0) {
|
||||||
|
FD_SET(req->socket, &writefds);
|
||||||
|
SET_MAX(max_fd, req->socket);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
gettimeofday(&now, NULL);
|
gettimeofday(&now, NULL);
|
||||||
i = get_sendto_fds(&writefds, &max_fd, &now);
|
i = get_sendto_fds(&writefds, &max_fd, &now);
|
||||||
|
@ -1267,16 +1334,17 @@ int main(int argc, char * * argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* processing unix socket requests */
|
/* processing unix socket requests */
|
||||||
for(req = reqlisthead.lh_first; req;)
|
for(req = reqlisthead.lh_first; req;) {
|
||||||
{
|
|
||||||
reqnext = req->entries.le_next;
|
reqnext = req->entries.le_next;
|
||||||
if((req->socket >= 0) && FD_ISSET(req->socket, &readfds))
|
if((req->socket >= 0) && FD_ISSET(req->socket, &readfds)) {
|
||||||
{
|
|
||||||
processRequest(req);
|
processRequest(req);
|
||||||
}
|
}
|
||||||
if(req->socket < 0)
|
if((req->socket >= 0) && FD_ISSET(req->socket, &writefds)) {
|
||||||
{
|
write_buffer(req);
|
||||||
|
}
|
||||||
|
if(req->socket < 0) {
|
||||||
LIST_REMOVE(req, entries);
|
LIST_REMOVE(req, entries);
|
||||||
|
free(req->output_buffer);
|
||||||
free(req);
|
free(req);
|
||||||
}
|
}
|
||||||
req = reqnext;
|
req = reqnext;
|
||||||
|
@ -1286,23 +1354,18 @@ int main(int argc, char * * argv)
|
||||||
{
|
{
|
||||||
struct reqelem * tmp;
|
struct reqelem * tmp;
|
||||||
int s = accept(s_unix, NULL, NULL);
|
int s = accept(s_unix, NULL, NULL);
|
||||||
if(s<0)
|
if(s < 0) {
|
||||||
{
|
|
||||||
syslog(LOG_ERR, "accept(s_unix): %m");
|
syslog(LOG_ERR, "accept(s_unix): %m");
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
syslog(LOG_INFO, "(s=%d) new request connection", s);
|
syslog(LOG_INFO, "(s=%d) new request connection", s);
|
||||||
if(!set_non_blocking(s))
|
if(!set_non_blocking(s))
|
||||||
syslog(LOG_WARNING, "Failed to set new socket non blocking : %m");
|
syslog(LOG_WARNING, "Failed to set new socket non blocking : %m");
|
||||||
tmp = malloc(sizeof(struct reqelem));
|
tmp = malloc(sizeof(struct reqelem));
|
||||||
if(!tmp)
|
if(!tmp) {
|
||||||
{
|
|
||||||
syslog(LOG_ERR, "cannot allocate memory for request");
|
syslog(LOG_ERR, "cannot allocate memory for request");
|
||||||
close(s);
|
close(s);
|
||||||
}
|
} else {
|
||||||
else
|
memset(tmp, 0, sizeof(struct reqelem));
|
||||||
{
|
|
||||||
tmp->socket = s;
|
tmp->socket = s;
|
||||||
LIST_INSERT_HEAD(&reqlisthead, tmp, entries);
|
LIST_INSERT_HEAD(&reqlisthead, tmp, entries);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue