Skip to content

Commit

Permalink
Backport async accept patch to prevent DNS resolution from blocking a…
Browse files Browse the repository at this point in the history
…ccepts.
  • Loading branch information
abh3 committed Sep 24, 2013
1 parent 1f1441e commit 780852f
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 24 deletions.
60 changes: 55 additions & 5 deletions src/Xrd/XrdInet.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <sys/types.h>
#include <sys/socket.h>

#include "XrdSys/XrdSysDNS.hh"
#include "XrdSys/XrdSysError.hh"

#include "Xrd/XrdInet.hh"
Expand All @@ -45,6 +46,7 @@

#include "XrdNet/XrdNetOpts.hh"
#include "XrdNet/XrdNetPeer.hh"
#include "XrdNet/XrdNetSecurity.hh"

/******************************************************************************/
/* G l o b a l s */
Expand All @@ -56,18 +58,52 @@
/* A c c e p t */
/******************************************************************************/

XrdLink *XrdInet::Accept(int opts, int timeout)
XrdLink *XrdInet::Accept(int opts, int timeout, XrdSysSemaphore *theSem)
{
XrdNetPeer myPeer;
XrdLink *lp;
int ismyfd, lnkopts = (opts & XRDNET_MULTREAD ? XRDLINK_RDLOCK : 0);
char *hname = 0;
int ismyfd, anum=0, lnkopts = (opts & XRDNET_MULTREAD ? XRDLINK_RDLOCK : 0);

// Perform regular accept
// Perform regular accept. This will be a unique TCP socket. We loop here
// until the accept succeeds as it should never fail at this stage.
//
opts |= XRDNET_NORLKUP;
while(!XrdNet::Accept(myPeer, opts, timeout))
{if (timeout >= 0)
{if (theSem) theSem->Post();
return (XrdLink *)0;
}
sleep(1); anum++;
if (!(anum%60)) eDest->Emsg("Accept", "Unable to accept connections!");
}

// If authorization was defered, tell call we accepted the connection but
// will be doing a background check on this connection.
//
if (!XrdNet::Accept(myPeer, opts | (netOpts & XRDNET_NORLKUP), timeout))
return (XrdLink *)0;
if (theSem) theSem->Post();
if ((ismyfd = (myPeer.fd == iofd))) lnkopts |= XRDLINK_NOCLOSE;

// Authorize by ip address or full (slow) hostname format. We defer the check
// so that the next accept can occur before we do any DNS resolution.
//
if (Patrol)
{if (!(hname = Patrol->Authorize(&myPeer.InetAddr)))
{eDest->Emsg("Accept",EACCES,"accept TCP connection from",
myPeer.InetName);
if (!ismyfd) close(myPeer.fd);
return (XrdLink *)0;
}
} else if (!(netOpts & XRDNET_NORLKUP))
hname = XrdSysDNS::getHostName(myPeer.InetAddr);

// Undo the nodnr option if we actually forced it here
//
if (hname)
{if (myPeer.InetName) free(myPeer.InetName);
myPeer.InetName = hname;
}

// Allocate a new network object
//
if (!(lp = XrdLink::Alloc(myPeer, lnkopts)))
Expand Down Expand Up @@ -112,3 +148,17 @@ XrdLink *XrdInet::Connect(const char *host, int port, int opts, int tmo)
//
return lp;
}

/******************************************************************************/
/* S e c u r e */
/******************************************************************************/

void XrdInet::Secure(XrdNetSecurity *secp)
{

// If we don't have a Patrol object then use the one supplied. Otherwise
// merge the supplied object into the existing object.
//
if (Patrol) Patrol->Merge(secp);
else Patrol = secp;
}
8 changes: 6 additions & 2 deletions src/Xrd/XrdInet.hh
Original file line number Diff line number Diff line change
Expand Up @@ -40,22 +40,26 @@
//
class XrdOucTrace;
class XrdSysError;
class XrdSysSemaphore;
class XrdNetSecurity;
class XrdLink;

class XrdInet : public XrdNet
{
public:

XrdLink *Accept(int opts=0, int timeout=-1);
XrdLink *Accept(int opts=0, int timeout=-1, XrdSysSemaphore *theSem=0);

XrdLink *Connect(const char *host, int port, int opts=0, int timeout=-1);

void Secure(XrdNetSecurity *secp);

XrdInet(XrdSysError *erp, XrdOucTrace *tP, XrdNetSecurity *secp=0)
: XrdNet(erp, secp), XrdTrace(tP) {}
: XrdNet(erp,0), Patrol(secp), XrdTrace(tP) {}
~XrdInet() {}
private:

XrdNetSecurity *Patrol;
XrdOucTrace *XrdTrace;
static const char *TraceID;
};
Expand Down
48 changes: 32 additions & 16 deletions src/Xrd/XrdMain.cc
Original file line number Diff line number Diff line change
Expand Up @@ -82,16 +82,27 @@
/* L o c a l C l a s s e s */
/******************************************************************************/

class XrdMain
class XrdMain : XrdJob
{
public:

XrdInet *theNet;
int thePort;
static XrdConfig Config;

XrdMain() : theNet(0), thePort(0) {}
XrdMain(XrdInet *nP) : theNet(nP), thePort(nP->Port()) {}
XrdSysSemaphore *theSem;
XrdProtocol *theProt;
XrdInet *theNet;
int thePort;
static XrdConfig Config;

void DoIt() {XrdLink *newlink;
if ((newlink = theNet->Accept(0, -1, theSem)))
{newlink->setProtocol(theProt);
newlink->DoIt();
}
}

XrdMain() : XrdJob("main accept"), theSem(0), theProt(0),
theNet(0), thePort(0) {}
XrdMain(XrdInet *nP) : XrdJob("main accept"), theSem(0),
theProt(0), theNet(nP), thePort(nP->Port()) {}
~XrdMain() {}
};

Expand All @@ -102,16 +113,21 @@ XrdConfig XrdMain::Config;
/******************************************************************************/

void *mainAccept(void *parg)
{ XrdMain *Parms = (XrdMain *)parg;
XrdInet *myNet = Parms->theNet;
XrdScheduler *mySched = Parms->Config.ProtInfo.Sched;
XrdProtLoad ProtSelect(Parms->thePort);
XrdLink *newlink;
{ XrdMain *Parms = (XrdMain *)parg;
XrdScheduler *mySched = Parms->Config.ProtInfo.Sched;
XrdProtLoad ProtSelect(Parms->thePort);
XrdSysSemaphore accepted(0);

while(1) if ((newlink = myNet->Accept(XRDNET_NODNTRIM)))
{newlink->setProtocol((XrdProtocol *)&ProtSelect);
mySched->Schedule((XrdJob *)newlink);
}
// Complete the parms
//
Parms->theSem = &accepted;
Parms->theProt = (XrdProtocol *)&ProtSelect;

// Simply schedule new accepts
//
while(1) {mySched->Schedule((XrdJob *)Parms);
accepted.Wait();
}

return (void *)0;
}
Expand Down
2 changes: 1 addition & 1 deletion src/XrdNet/XrdNet.hh
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ int Port() {return Portnum;}
// constraints. The supplied object is ultimately deleted in the
// process and cannot be referenced.
//
void Secure(XrdNetSecurity *secp);
virtual void Secure(XrdNetSecurity *secp);

// setDefaults() sets the default socket options, and buffer size for UDP
// sockets (default is 32k) or window size for TCP sockets
Expand Down

0 comments on commit 780852f

Please sign in to comment.