Handle events from TSHttpTxnServerIntercept. The intercept starts with TS_EVENT_NET_ACCEPT, and then continues with TSVConn events.
| 274 | // starts with TS_EVENT_NET_ACCEPT, and then continues with |
| 275 | // TSVConn events. |
| 276 | static int |
| 277 | InterceptInterceptHook(TSCont contp, TSEvent event, void *edata) |
| 278 | { |
| 279 | argument_type arg(edata); |
| 280 | |
| 281 | VDEBUG("contp=%p, event=%s (%d), edata=%p", contp, TSHttpEventNameLookup(event), event, arg.ptr); |
| 282 | |
| 283 | switch (event) { |
| 284 | case TS_EVENT_NET_ACCEPT: { |
| 285 | // Set up the server intercept. We have the original |
| 286 | // TSHttpTxn from the continuation. We need to connect to the |
| 287 | // real origin and get ready to shuffle data around. |
| 288 | char buf[INET_ADDRSTRLEN]; |
| 289 | socket_type addr; |
| 290 | argument_type cdata(TSContDataGet(contp)); |
| 291 | InterceptState *istate = new InterceptState(); |
| 292 | int fd = -1; |
| 293 | |
| 294 | // This event is delivered by the continuation that we |
| 295 | // attached in InterceptTxnHook, so the continuation data is |
| 296 | // the TSHttpTxn pointer. |
| 297 | VDEBUG("allocated server intercept state istate=%p for txn=%p", istate, cdata.txn); |
| 298 | |
| 299 | // Set up a connection to our real origin, which will be |
| 300 | // 127.0.0.1:$PORT. |
| 301 | memset(&addr, 0, sizeof(addr)); |
| 302 | addr.sin.sin_family = AF_INET; |
| 303 | addr.sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); // XXX config option |
| 304 | addr.sin.sin_port = htons(PORT); // XXX config option |
| 305 | |
| 306 | // Normally, we would use TSNetConnect to connect to a secondary service, but to demonstrate |
| 307 | // the use of TSVConnFdCreate, we do a blocking connect inline. This it not recommended for |
| 308 | // production plugins, since it might block an event thread for an arbitrary time. |
| 309 | fd = ::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); |
| 310 | TSReleaseAssert(fd != -1); |
| 311 | |
| 312 | if (::connect(fd, &addr.sa, sizeof(addr.sin)) == -1) { |
| 313 | // We failed to connect to the intercepted origin. Abort the |
| 314 | // server intercept since we cannot handle it. |
| 315 | VDEBUG("connect failed with %s (%d)", strerror(errno), errno); |
| 316 | TSVConnAbort(arg.vc, TS_VC_CLOSE_ABORT); |
| 317 | |
| 318 | delete istate; |
| 319 | TSContDestroy(contp); |
| 320 | |
| 321 | ::close(fd); |
| 322 | return TS_EVENT_NONE; |
| 323 | } |
| 324 | |
| 325 | if ((istate->server.vc = TSVConnFdCreate(fd)) == nullptr) { |
| 326 | VDEBUG("TSVconnFdCreate() failed"); |
| 327 | TSVConnAbort(arg.vc, TS_VC_CLOSE_ABORT); |
| 328 | |
| 329 | delete istate; |
| 330 | TSContDestroy(contp); |
| 331 | |
| 332 | ::close(fd); |
| 333 | return TS_EVENT_NONE; |
nothing calls this directly
no test coverage detected