// attached in InterceptTxnHook, so the continuation data is
// the TSHttpTxn pointer.
VDEBUG("allocated server intercept state istate=%p for txn=%p", istate, cdata.txn);
// Set up a connection to our real origin, which will be
// 127.0.0.1:$PORT.
memset(&addr, 0, sizeof(addr));
addr.sin.sin_family = AF_INET;
addr.sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); // XXX config option
addr.sin.sin_port = htons(PORT); // XXX config option
// Normally, we would use TSNetConnect to connect to a secondary service, but to demonstrate
// the use of TSVConnFdCreate, we do a blocking connect inline. This it not recommended for
// production plugins, since it might block an event thread for an arbitrary time.
fd = ::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
TSReleaseAssert(fd != -1);
if (::connect(fd, &addr.sa, sizeof(addr.sin)) == -1) {
// We failed to connect to the intercepted origin. Abort the
// server intercept since we cannot handle it.
VDEBUG("connect failed with %s (%d)", strerror(errno), errno);
TSVConnAbort(arg.vc, TS_VC_CLOSE_ABORT);
delete istate;
TSContDestroy(contp);
::close(fd);
return TS_EVENT_NONE;
}
if ((istate->server.vc = TSVConnFdCreate(fd)) == nullptr) {
VDEBUG("TSVconnFdCreate() failed");
TSVConnAbort(arg.vc, TS_VC_CLOSE_ABORT);
delete istate;
TSContDestroy(contp);
::close(fd);
return TS_EVENT_NONE;
}
VDEBUG("binding client vc=%p to %s:%u", istate->client.vc, inet_ntop(AF_INET, &addr.sin.sin_addr, buf, sizeof(buf)),
(unsigned)ntohs(addr.sin.sin_port));
istate->txn = cdata.txn;
istate->client.vc = arg.vc;
// Reset the continuation data to be our intercept state
// block. We will need this so that we can access both of the