Example #1
0
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;
}
Example #3
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");
}
Example #4
0
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;
}
Example #5
0
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));
}