void *ad_open(const char *fn, struct adinfo *nfo) { adecoder *d = (adecoder*) calloc(1, sizeof(adecoder)); ad_clear_nfo(nfo); d->b = choose_backend(fn); if (!d->b) { dbg(0, "fatal: no decoder backend available"); free(d); return NULL; } d->d = d->b->open(fn, nfo); if (!d->d) { free(d); return NULL; } return (void*)d; }
/* * choose_backend parses incoming HTTP request and routes it to the appropriate * backend. It assumes that clients don't do HTTP pipelining, handling only * one request request for each connection. To give a hint to backend about * this it inserts "Connection: close" header into each forwarded request. */ static int connect_backend(struct conn_data *conn, struct http_message *hm) { struct mg_connection *nc = conn->client.nc; struct http_backend *be = choose_backend(hm); write_log("%ld %.*s %.*s backend=%s\n", (long) time(NULL), (int) hm->method.len, hm->method.p, (int) hm->uri.len, hm->uri.p, be ? be->host_port : "not defined"); if (be == NULL) return 0; if (be->redirect != 0) { mg_printf(nc, "HTTP/1.1 302 Found\r\nLocation: %s\r\n\r\n", be->host_port); return 1; } struct be_conn *bec = get_conn(be); if (bec != NULL) { bec->nc->handler = ev_handler; #ifdef DEBUG write_log("conn=%p to %p (%s) reusing bec=%p\n", conn, be, be->host_port, bec); #endif } else { bec = malloc(sizeof(*conn->be_conn)); memset(bec, 0, sizeof(*bec)); bec->nc = mg_connect(nc->mgr, be->host_port, ev_handler); #ifdef DEBUG write_log("conn=%p new conn to %p (%s) bec=%p\n", conn, be, be->host_port, bec); #endif if (bec->nc == NULL) { free(bec); write_log("Connection to [%s] failed\n", be->host_port); return 0; } } bec->be = be; conn->be_conn = bec; conn->backend.nc = bec->nc; conn->backend.nc->user_data = conn; mg_set_protocol_http_websocket(conn->backend.nc); return 1; }
static void ev_handler(struct ns_connection *nc, int ev, void *ev_data) { struct iobuf *io = &nc->recv_iobuf; struct ns_connection *peer = (struct ns_connection *) nc->proto_data; switch (ev) { case NS_CONNECT: if (* (int *) ev_data != 0) { /* TODO(lsm): mark backend as defunct, try it later on */ fprintf(stderr, "connect(%s) failed\n", s_http_backends[(int) nc->user_data].host_port); ns_printf(nc->proto_data, "%s%s\r\n", s_error_500, s_content_len_0); } break; case NS_RECV: /* * For incoming client connection, nc->proto_data points to the respective * backend connection. For backend connection, nc->proto_data points * to the respective incoming client connection. */ if (peer == NULL) { choose_backend(nc); } else { /* Forward data to peer */ ns_send(peer, io->buf, io->len); iobuf_remove(io, io->len); } break; case NS_CLOSE: /* We're closing, detach our peer */ if (peer != NULL) { peer->proto_data = NULL; peer->flags |= NSF_SEND_AND_CLOSE; } break; } }