summaryrefslogtreecommitdiffstats
path: root/runtime/nsd_ptcp.c
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2008-04-23 09:59:01 +0200
committerRainer Gerhards <rgerhards@adiscon.com>2008-04-23 09:59:01 +0200
commit2be459c4d7645ad12f83723be7bb26199fe98b82 (patch)
tree749db3a20481dea667b5405961c173c4317d9e0d /runtime/nsd_ptcp.c
parent22ad77a627fe813acd286b48aaf44945c0480f49 (diff)
downloadrsyslog-2be459c4d7645ad12f83723be7bb26199fe98b82.tar.gz
rsyslog-2be459c4d7645ad12f83723be7bb26199fe98b82.tar.xz
rsyslog-2be459c4d7645ad12f83723be7bb26199fe98b82.zip
objects for receive-side socket abstraction specified
The objects for receiver-side socket abstraction have now be specified. The project as whole does not yet compile and definitely not run, but I'd like to commit some milestones along this way.
Diffstat (limited to 'runtime/nsd_ptcp.c')
-rw-r--r--runtime/nsd_ptcp.c187
1 files changed, 94 insertions, 93 deletions
diff --git a/runtime/nsd_ptcp.c b/runtime/nsd_ptcp.c
index 6f7dd04d..c737c168 100644
--- a/runtime/nsd_ptcp.c
+++ b/runtime/nsd_ptcp.c
@@ -56,30 +56,29 @@ DEFobjCurrIf(glbl)
DEFobjCurrIf(net)
+/* a few deinit helpers */
+
+/* close socket if open (may always be called) */
+static void
+sockClose(int *pSock)
+{
+ if(*pSock >= 0) {
+ close(*pSock);
+ *pSock = -1;
+ }
+}
+
/* Standard-Constructor
*/
BEGINobjConstruct(nsd_ptcp) /* be sure to specify the object type also in END macro! */
pThis->sock = -1;
- pThis->iSessMax = 500; /* default max nbr of sessions -TODO:make configurable--rgerhards, 2008-04-17*/
ENDobjConstruct(nsd_ptcp)
/* destructor for the nsd_ptcp object */
BEGINobjDestruct(nsd_ptcp) /* be sure to specify the object type also in END and CODESTART macros! */
- int i;
CODESTARTobjDestruct(nsd_ptcp)
- if(pThis->sock != -1) {
- close(pThis->sock);
- pThis->sock = -1;
- }
-
- if(pThis->socks != NULL) {
- /* if we have some sockets at this stage, we need to close them */
- for(i = 1 ; i <= pThis->socks[0] ; ++i)
- close(pThis->socks[i]);
- free(pThis->socks);
- }
-
+ sockClose(&pThis->sock);
if(pThis->pRemHostIP != NULL)
free(pThis->pRemHostIP);
if(pThis->pRemHostName != NULL)
@@ -189,33 +188,34 @@ finalize_it:
-/* accept an incoming connection request, sock provides the socket on which we can
- * accept the new session.
- * rgerhards, 2008-03-17
+/* accept an incoming connection request
+ * rgerhards, 2008-04-22
*/
static rsRetVal
-AcceptConnReq(nsd_t **ppThis, int sock)
+AcceptConnReq(nsd_t *pNsd, nsd_t **ppNew)
{
int sockflags;
+ nsd_ptcp_t *pThis = (nsd_ptcp_t*) pNsd;
struct sockaddr_storage addr;
socklen_t addrlen = sizeof(addr);
- nsd_ptcp_t *pThis = NULL;
+ nsd_ptcp_t *pNew = NULL;
int iNewSock = -1;
DEFiRet;
- assert(ppThis != NULL);
+ assert(ppNew != NULL);
+ ISOBJ_TYPE_assert(pThis, nsd_ptcp_t);
- iNewSock = accept(sock, (struct sockaddr*) &addr, &addrlen);
+ iNewSock = accept(pThis->sock, (struct sockaddr*) &addr, &addrlen);
if(iNewSock < 0) {
ABORT_FINALIZE(RS_RET_ACCEPT_ERR);
}
/* construct our object so that we can use it... */
- CHKiRet(nsd_ptcpConstruct(&pThis));
+ CHKiRet(nsd_ptcpConstruct(&pNew));
- CHKiRet(FillRemHost(pThis, (struct sockaddr*) &addr));
+ CHKiRet(FillRemHost(pNew, (struct sockaddr*) &addr));
- /* set the new socket to non-blocking IO */
+ /* set the new socket to non-blocking IO -TODO:do we really need to do this here? Do we always want it? */
if((sockflags = fcntl(iNewSock, F_GETFL)) != -1) {
sockflags |= O_NONBLOCK;
/* SETFL could fail too, so get it caught by the subsequent
@@ -228,41 +228,41 @@ AcceptConnReq(nsd_t **ppThis, int sock)
ABORT_FINALIZE(RS_RET_IO_ERROR);
}
- pThis->sock = iNewSock;
-
- *ppThis = (nsd_t*) pThis;
+ pNew->sock = iNewSock;
+ *ppNew = (nsd_t*) pNew;
finalize_it:
if(iRet != RS_RET_OK) {
- if(pThis != NULL)
- nsd_ptcpDestruct(&pThis);
+ if(pNew != NULL)
+ nsd_ptcpDestruct(&pNew);
/* the close may be redundant, but that doesn't hurt... */
- if(iNewSock >= 0)
- close(iNewSock);
+ sockClose(&iNewSock);
}
RETiRet;
}
-/* initialize the tcp socket for a listner
- * pLstnPort must point to a port name or number. NULL is NOT permitted
- * (hint: we need to be careful when we use this module together with librelp,
- * there NULL indicates the default port
- * default is used.
- * gerhards, 2008-03-17
+/* initialize tcp sockets for a listner. This function returns an array of nds_t
+ * objects. The size of this array is returend in pLstnArrSize.
+ * pLstnPort must point to a port name or number. NULL is NOT permitted. pLstnIP
+ * points to the port to listen to (NULL means "all"), iMaxSess has the maximum
+ * number of sessions permitted.
+ * rgerhards, 2008-04-22
*/
static rsRetVal
-LstnInit(nsd_t *pNsd, uchar *pLstnPort)
+LstnInit(nsd_t ***parrLstnNsd, int *pLstnArrSize, uchar *pLstnPort, uchar *pLstnIP, int iSessMax)
{
- nsd_ptcp_t *pThis = (nsd_ptcp_t*) pNsd;
- struct addrinfo hints, *res, *r;
- int error, maxs, *s, on = 1;
+ DEFiRet;
+ struct addrinfo hints, *res = NULL, *r;
+ nsd_ptcp_t **arrLstn = NULL;
+ int error, maxs, on = 1;
+ int sock;
int sockflags;
- DEFiRet;
- ISOBJ_TYPE_assert(pThis, nsd_ptcp);
+ assert(parrLstnNsd != NULL);
assert(pLstnPort != NULL);
+ assert(iSessMax >= 0);
dbgprintf("creating tcp listen socket on port %s\n", pLstnPort);
@@ -271,7 +271,7 @@ LstnInit(nsd_t *pNsd, uchar *pLstnPort)
hints.ai_family = glbl.GetDefPFFamily();
hints.ai_socktype = SOCK_STREAM;
- error = getaddrinfo(NULL, (char*) pLstnPort, &hints, &res);
+ error = getaddrinfo((char*)pLstnIP, (char*) pLstnPort, &hints, &res);
if(error) {
dbgprintf("error %d querying port '%s'\n", error, pLstnPort);
ABORT_FINALIZE(RS_RET_INVALID_PORT);
@@ -280,20 +280,14 @@ LstnInit(nsd_t *pNsd, uchar *pLstnPort)
/* Count max number of sockets we may open */
for(maxs = 0, r = res; r != NULL ; r = r->ai_next, maxs++)
/* EMPTY */;
- pThis->socks = malloc((maxs+1) * sizeof(int));
- if (pThis->socks == NULL) {
- dbgprintf("couldn't allocate memory for TCP listen sockets, suspending RELP message reception.");
- freeaddrinfo(res);
- ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
- }
+ CHKmalloc(arrLstn = (nsd_ptcp_t**) malloc((maxs+1) * sizeof(nsd_ptcp_t*)));
- *pThis->socks = 0; /* num of sockets counter at start of array */
- s = pThis->socks + 1;
+ *pLstnArrSize = 0; /* num of sockets counter at start of array */
for(r = res; r != NULL ; r = r->ai_next) {
- *s = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
- if (*s < 0) {
+ sock = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
+ if(sock < 0) {
if(!(r->ai_family == PF_INET6 && errno == EAFNOSUPPORT))
- dbgprintf("creating tcp listen socket");
+ dbgprintf("error %d creating tcp listen socket", errno);
/* it is debatable if PF_INET with EAFNOSUPPORT should
* also be ignored...
*/
@@ -301,35 +295,32 @@ LstnInit(nsd_t *pNsd, uchar *pLstnPort)
}
#ifdef IPV6_V6ONLY
- if (r->ai_family == AF_INET6) {
+ if(r->ai_family == AF_INET6) {
int iOn = 1;
- if (setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY,
+ if(setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
(char *)&iOn, sizeof (iOn)) < 0) {
- close(*s);
- *s = -1;
- continue;
+ close(sock);
+ continue;
}
}
#endif
- if(setsockopt(*s, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)) < 0 ) {
+ if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)) < 0 ) {
dbgprintf("error %d setting tcp socket option\n", errno);
- close(*s);
- *s = -1;
+ close(sock);
continue;
}
/* We use non-blocking IO! */
- if((sockflags = fcntl(*s, F_GETFL)) != -1) {
+ if((sockflags = fcntl(sock, F_GETFL)) != -1) {
sockflags |= O_NONBLOCK;
/* SETFL could fail too, so get it caught by the subsequent
* error check.
*/
- sockflags = fcntl(*s, F_SETFL, sockflags);
+ sockflags = fcntl(sock, F_SETFL, sockflags);
}
if(sockflags == -1) {
dbgprintf("error %d setting fcntl(O_NONBLOCK) on tcp socket", errno);
- close(*s);
- *s = -1;
+ close(sock);
continue;
}
@@ -340,62 +331,75 @@ LstnInit(nsd_t *pNsd, uchar *pLstnPort)
*/
#ifndef BSD
if(net.should_use_so_bsdcompat()) {
- if (setsockopt(*s, SOL_SOCKET, SO_BSDCOMPAT,
+ if (setsockopt(sock, SOL_SOCKET, SO_BSDCOMPAT,
(char *) &on, sizeof(on)) < 0) {
errmsg.LogError(NO_ERRCODE, "TCP setsockopt(BSDCOMPAT)");
- close(*s);
- *s = -1;
+ close(sock);
continue;
}
}
#endif
- if( (bind(*s, r->ai_addr, r->ai_addrlen) < 0)
+ if( (bind(sock, r->ai_addr, r->ai_addrlen) < 0)
#ifndef IPV6_V6ONLY
&& (errno != EADDRINUSE)
#endif
) {
+ /* TODO: check if *we* bound the socket - else we *have* an error! */
dbgprintf("error %d while binding tcp socket", errno);
- close(*s);
- *s = -1;
+ close(sock);
continue;
}
- if(listen(*s,pThis->iSessMax / 10 + 5) < 0) {
+ if(listen(sock, iSessMax / 10 + 5) < 0) {
/* If the listen fails, it most probably fails because we ask
* for a too-large backlog. So in this case we first set back
* to a fixed, reasonable, limit that should work. Only if
* that fails, too, we give up.
*/
dbgprintf("listen with a backlog of %d failed - retrying with default of 32.",
- pThis->iSessMax / 10 + 5);
- if(listen(*s, 32) < 0) {
+ iSessMax / 10 + 5);
+ if(listen(sock, 32) < 0) {
dbgprintf("tcp listen error %d, suspending\n", errno);
- close(*s);
- *s = -1;
+ close(sock);
continue;
}
}
- (*pThis->socks)++;
- s++;
+ /* if we reach this point, we were able to obtain a valid socket, which we
+ * now can save to the array of listen sockets. -- rgerhards, 2008-04-22
+ */
+ CHKiRet(nsd_ptcpConstruct(arrLstn+*pLstnArrSize));
+ arrLstn[*pLstnArrSize]->sock = sock;
+ ++(*pLstnArrSize);
}
if(res != NULL)
freeaddrinfo(res);
- if(*pThis->socks != maxs)
- dbgprintf("We could initialize %d RELP TCP listen sockets out of %d we received "
- "- this may or may not be an error indication.\n", *pThis->socks, maxs);
+ if(*pLstnArrSize != maxs)
+ dbgprintf("We could initialize %d TCP listen sockets out of %d we received "
+ "- this may or may not be an error indication.\n", *pLstnArrSize, maxs);
- if(*pThis->socks == 0) {
- dbgprintf("No RELP TCP listen socket could successfully be initialized, "
- "message reception via RELP disabled.\n");
- free(pThis->socks);
+ if(*pLstnArrSize == 0) {
+ dbgprintf("No TCP listen sockets could successfully be initialized, "
+ "message reception disabled.\n");
ABORT_FINALIZE(RS_RET_COULD_NOT_BIND);
}
+ *parrLstnNsd = (nsd_t**) arrLstn;
+ arrLstn = NULL; /* prevent from being freed in error handler */
+
finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(res != NULL)
+ freeaddrinfo(res);
+ if(arrLstn != NULL) {
+ for(maxs = 0 ; maxs < *pLstnArrSize ; ++maxs)
+ nsd_ptcpDestruct(arrLstn+*pLstnArrSize);
+ }
+ }
+
RETiRet;
}
@@ -494,10 +498,7 @@ finalize_it:
freeaddrinfo(res);
if(iRet != RS_RET_OK) {
- if(pThis->sock != -1) {
- close(pThis->sock);
- pThis->sock = -1;
- }
+ sockClose(&pThis->sock);
}
RETiRet;
@@ -519,10 +520,10 @@ CODESTARTobjQueryInterface(nsd_ptcp)
pIf->Construct = (rsRetVal(*)(nsd_t**)) nsd_ptcpConstruct;
pIf->Destruct = (rsRetVal(*)(nsd_t**)) nsd_ptcpDestruct;
pIf->Abort = Abort;
- pIf->LstnInit = LstnInit;
- pIf->AcceptConnReq = AcceptConnReq;
pIf->Rcv = Rcv;
pIf->Send = Send;
+ pIf->LstnInit = LstnInit;
+ pIf->AcceptConnReq = AcceptConnReq;
pIf->Connect = Connect;
finalize_it:
ENDobjQueryInterface(nsd_ptcp)