static void client_recv_cb(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) { struct client_context *client = stream->data; struct remote_context *remote = client->remote; int clen; if (nread > 0) { reset_timer(remote); uv_read_stop(&client->handle.stream); switch (client->stage) { case XSTAGE_HANDSHAKE: if (verify_methods(buf->base, nread)) { handshake(client); } else { logger_log(LOG_ERR, "invalid method packet"); close_client(client); close_remote(remote); } break; case XSTAGE_REQUEST: if (verify_request(buf->base, nread)) { request_start(client, buf->base); } else { logger_log(LOG_ERR, "invalid request packet"); close_client(client); close_remote(remote); } break; case XSTAGE_FORWARD: clen = nread + PRIMITIVE_BYTES; uint8_t *c = client->buf + HEADER_BYTES; int rc = crypto_encrypt(c, (uint8_t*)buf->base, nread); if (rc) { logger_log(LOG_ERR, "encrypt failed"); close_client(client); close_remote(remote); } forward_to_remote(remote, c, clen); break; default: break; } } else if (nread < 0) { if (nread != UV_EOF) { char addrbuf[INET6_ADDRSTRLEN + 1] = {0}; uint16_t port = ip_name(&client->addr, addrbuf, sizeof addrbuf); logger_log(LOG_ERR, "receive from %s:%d failed: %s", addrbuf, port, uv_strerror(nread)); } close_client(client); close_remote(remote); } }
/* * When a new query is received over a UDP socket from a client, the * udp_response state machine is started. See also ev_udp_in_read(), * which is the only place from where udp_response_start() is called. * * udp_response_start() starts a new transaction. First creates a new * root context for it, and starts the forwarding of the original query. * * forwarding is performed by starting a new child request, which * if all goes well result in some resource records in our context. * * when the forwarded request finished successfully, udp_response_finish() * is responsible for interpreting it and sending a response back to the client. * */ int udp_response_start (u_char *mesg_buf, int mesg_len, struct sockaddr *sa_p, Nia *inif) { const char *fn = "udp_response_start()"; Context *cont; syslog (LOG_DEBUG, "%s: start", fn); /* create context */ cont = context_create(); if (!cont) return (response_abort (cont, -1)); cont->mesg.p = mesg_buf; cont->mesg_len = mesg_len; cont->wp = mesg_buf + mesg_len; /* just after the answer section */ cont->q_id = cont->mesg.hdr->id; cont->netifaddr = nia_copy (inif); memcpy (cont->peer, sa_p, SOCKADDR_SIZEOF(*sa_p)); if (cont->mesg.hdr->opcode == OP_QUERY) { syslog (LOG_DEBUG, "%s: OPCODE = OP_QUERY", fn); /* query-response specific variables */ cont->process = udp_response_recursive_process; cont->retry = udp_response_recursive_retry; /* do the forwarding, send request to forwarder */ switch (request_start (cont, QUERY_TCP)) { case 0: /* We got a response */ return (0); case 1: /* Something wrong with the query */ cont->mesg.hdr->rcode = RC_FMTERR; return (udp_response_finish (cont)); default: /* We failed ourselves somehow */ cont->mesg.hdr->rcode = RC_SERVERERR; return (udp_response_finish (cont)); } } else { syslog (LOG_NOTICE, "%s: OPCODE unknown(%d)", fn, cont->mesg.hdr->opcode); cont->mesg.hdr->rcode = RC_NIMP; return udp_response_finish (cont); } /* NOTREACHED */ return 0; }
void download_make_request(char *md5sum, struct sockaddr_in *host) { request *req; uint16_t req_no; Packet p; int sockfd; req = (request *) malloc(sizeof(request)); // Call back req->timeout = (OnTimeout) download_request_timeout; req_no = request_start(req); sockfd = get_outgoing_socket(); fillin_packet(&p, REQUEST_WANTFILE, MAX_DIGEST_BIN_BYTES, req_no); send_packet(sockfd, host, &p, md5sum); printf("download request sent\n"); }
void *run_airplane(void *parameters) { thread_args_t *args; int airplane_id; args = (thread_args_t *) parameters; airplane_id = args->airplane_id; while(1) { request_landing(airplane_id); land(airplane_id); stop(airplane_id); request_start(airplane_id); start(airplane_id); fly(airplane_id); } return NULL; }
int tcp_response_reading_process (Context *cont) { const char *fn = "tcp_response_reading_process()"; int len; syslog (LOG_DEBUG, "%s: start", fn); if (cont->tout) cont->tout->handler = NULL; if (context_timeout_register (cont, cont->timeout)) return(response_abort (cont, -1)); len = read (cont->conn_sock, cont->wp, cont->mesg_len - (cont->wp - cont->mesg.p)); if (len <= 0) return(response_abort (cont, -1)); cont->wp += len; if (cont->wp < (cont->mesg.p + cont->mesg_len)) { syslog (LOG_DEBUG, "%s: left %zd bytes -- continue.", fn, (cont->mesg.p + cont->mesg_len) - cont->wp); /* SUCCESS */ return 0; /* the processing continues ... */ } /* all data has been read now */ ev_tcp_conn_in_remove (cont->conn_sock); if (cont->mesg.hdr->opcode == OP_QUERY) { if (cont->tout) cont->tout->handler = NULL; /* * don't register input list, * child context takes input */ switch (request_start (cont, QUERY_TCP)) { case 0: /* * We forwarded the request without problems, * asycnhronously awaiting a response. * goto recursive_processing state * clear events, child will call me then */ if (cont->tout) cont->tout->handler = NULL; cont->process = tcp_response_recursive_process; cont->retry = tcp_response_recursive_retry; /* SUCCESS */ return 0; case 1: /* Something wrong with the query */ syslog (LOG_NOTICE, "%s: Request failed", fn); cont->mesg.hdr->rcode = RC_FMTERR; default: /* totd failed itself somehow */ syslog (LOG_NOTICE, "%s: Totd failed", fn); cont->mesg.hdr->rcode = RC_SERVERERR; } } else cont->mesg.hdr->rcode = RC_NIMP; /* * Not OP_QUERY or Request failed brings us here * * Go to writing state. Timeout already done in this function * Register new output event */ if (!ev_tcp_out_register (cont->conn_sock, cont)) { assemble_response (cont); /* state change */ cont->process = tcp_response_writing_process; cont->retry = tcp_response_writing_retry; cont->wp = NULL; syslog (LOG_DEBUG, "%s: end (writing:)", fn); /* SUCCESS */ return 0; } /* FAILURE */ return (response_abort (cont, -1)); }