Ejemplo n.º 1
0
static int
do_l2t_write_rpl2(struct sge_iq *iq, const struct rss_header *rss,
    struct mbuf *m)
{
	struct adapter *sc = iq->adapter;
	const struct cpl_l2t_write_rpl *rpl = (const void *)(rss + 1);
	unsigned int tid = GET_TID(rpl);
	unsigned int idx = tid % L2T_SIZE;
	int rc;

	rc = do_l2t_write_rpl(iq, rss, m);
	if (rc != 0)
		return (rc);

	if (tid & F_SYNC_WR) {
		struct l2t_entry *e = &sc->l2t->l2tab[idx - sc->vres.l2t.start];

		mtx_lock(&e->lock);
		if (e->state != L2T_STATE_SWITCHING) {
			send_pending(sc, e);
			e->state = L2T_STATE_VALID;
		}
		mtx_unlock(&e->lock);
	}

	return (0);
}
Ejemplo n.º 2
0
int
do_l2t_write_rpl2(struct sge_iq *iq, const struct rss_header *rss,
    struct mbuf *m)
{
	struct adapter *sc = iq->adapter;
	const struct cpl_l2t_write_rpl *rpl = (const void *)(rss + 1);
	unsigned int tid = GET_TID(rpl);
	unsigned int idx = tid % L2T_SIZE;

	if (__predict_false(rpl->status != CPL_ERR_NONE)) {
		log(LOG_ERR,
		    "Unexpected L2T_WRITE_RPL (%u) for entry at hw_idx %u\n",
		    rpl->status, idx);
		return (EINVAL);
	}

	if (tid & F_SYNC_WR) {
		struct l2t_entry *e = &sc->l2t->l2tab[idx - sc->vres.l2t.start];

		mtx_lock(&e->lock);
		if (e->state != L2T_STATE_SWITCHING) {
			send_pending(sc, e);
			e->state = L2T_STATE_VALID;
		}
		mtx_unlock(&e->lock);
	}

	return (0);
}
Ejemplo n.º 3
0
/**
 * Sends all pending aggregate message for a given group
 */
void send_all_pending(int listidx)
{
    int i;

    for (i = 0; i < MAX_PEND; i++) {
        if (group_list[listidx].pending[i].msg != 0) {
            send_pending(listidx, i);
        }
    }
}
Ejemplo n.º 4
0
/**
 * Sends all pending aggregate message for a given group
 */
void send_all_pending(struct pr_group_list_t *group)
{
    int i;

    for (i = 0; i < MAX_PEND; i++) {
        if (group->pending[i].msg != 0) {
            send_pending(group, i);
        }
    }
}
Ejemplo n.º 5
0
int
t4_l2t_send_slow(struct adapter *sc, struct wrqe *wr, struct l2t_entry *e)
{

again:
	switch (e->state) {
	case L2T_STATE_STALE:     /* entry is stale, kick off revalidation */

		if (resolve_entry(sc, e) != EWOULDBLOCK)
			goto again;	/* entry updated, re-examine state */

		/* Fall through */

	case L2T_STATE_VALID:     /* fast-path, send the packet on */

		t4_wrq_tx(sc, wr);
		return (0);

	case L2T_STATE_RESOLVING:
	case L2T_STATE_SYNC_WRITE:

		mtx_lock(&e->lock);
		if (e->state != L2T_STATE_SYNC_WRITE &&
		    e->state != L2T_STATE_RESOLVING) {
			/* state changed by the time we got here */
			mtx_unlock(&e->lock);
			goto again;
		}
		arpq_enqueue(e, wr);
		mtx_unlock(&e->lock);

		if (resolve_entry(sc, e) == EWOULDBLOCK)
			break;

		mtx_lock(&e->lock);
		if (e->state == L2T_STATE_VALID && !STAILQ_EMPTY(&e->wr_list))
			send_pending(sc, e);
		if (e->state == L2T_STATE_FAILED)
			resolution_failed(e);
		mtx_unlock(&e->lock);
		break;

	case L2T_STATE_FAILED:
		resolution_failed_for_wr(wr);
		return (EHOSTUNREACH);
	}

	return (0);
}
Ejemplo n.º 6
0
/**
 * Puts the given message on the pending message list.  If it doesn't match
 * any pending message and there are no open slots, first send what's pending.
 * If the pending list is full after adding the given message, then send.
 */
void check_pending(int listidx, int hostidx, const unsigned char *message)
{
    struct infoack_h *infoack;
    struct status_h *status;
    struct complete_h *complete;
    const uint8_t *func;
    struct pr_pending_info_t *pending;
    int match, pendidx;

    func = message;
    infoack = (struct infoack_h *)message;
    status = (struct status_h *)message;
    complete = (struct complete_h *)message;

    for (pendidx = 0; pendidx < MAX_PEND; pendidx++) {
        pending = &group_list[listidx].pending[pendidx];
        if (group_list[listidx].pending[pendidx].msg == 0) {
            match = 1;
            break;
        }

        match = (*func == pending->msg);
        switch (*func) {
        case REGISTER:
            // REGISTER always matches itself
            break;
        case INFO_ACK:
            // Only in response to FILEINFO.
            // Responses to KEYINFO are not forwarded.
            match = match && (ntohs(infoack->file_id) == pending->file_id);
            break;
        case STATUS:
            match = match && ((ntohs(status->file_id) == pending->file_id) &&
                              (status->pass == pending->pass) &&
                              (ntohs(status->section) == pending->section));
            break;
        case COMPLETE:
            match = match && ((ntohs(complete->file_id) == pending->file_id) &&
                              (complete->status == pending->comp_status));
            break;
        default:
            log(group_list[listidx].group_id, 0, "Tried to check pending "
                    "on invalid type %s", func_name(*func));
            return;
        }
        if (match) {
            break;
        }
    }

    if (!match) {
        send_all_pending(listidx);
        pendidx = 0;
        pending = &group_list[listidx].pending[pendidx];
    }

    pending->msg = *func;
    if (group_list[listidx].destinfo[hostidx].pending != pendidx) {
        group_list[listidx].destinfo[hostidx].pending = pendidx;
        pending->count++;
    }

    switch (*func) {
    case INFO_ACK:
        if (pending->count == 1) {
            pending->partial = 1;
        }
        pending->file_id = ntohs(infoack->file_id);
        pending->partial = pending->partial &&
                            ((infoack->flags & FLAG_PARTIAL) != 0);
        break;
    case STATUS:
        pending->file_id = ntohs(status->file_id);
        pending->pass = status->pass;
        pending->section = ntohs(status->section);
        pending->seq = group_list[listidx].last_seq;
        if (!pending->naklist) {
            pending->naklist = calloc(group_list[listidx].blocksize, 1);
            if (pending->naklist == NULL) {
                syserror(0, 0, "calloc failed!");
                exit(1);
            }
        }
        if (ntohl(status->nak_count) != 0) {
            add_naks_to_pending(listidx, pendidx, message);
        }
        break;
    case COMPLETE:
        pending->file_id = ntohs(complete->file_id);
        pending->comp_status = complete->status;
        break;
    }

    if (pending->count == max_msg_dest(listidx, *func)) {
        send_pending(listidx, pendidx);
    } else {
        int total_pending, i;

        for (total_pending = 0, i = 0; i < MAX_PEND; i++) {
            total_pending += group_list[listidx].pending[i].count;
        }
        if (total_pending == 1) {
            set_timeout(listidx, 1);
        }
    }
}
Ejemplo n.º 7
0
/**
 * Puts the given message on the pending message list.  If it doesn't match
 * any pending message and there are no open slots, first send what's pending.
 * If the pending list is full after adding the given message, then send.
 */
void check_pending(struct pr_group_list_t *group, int hostidx,
                   const unsigned char *message)
{
    const struct fileinfoack_h *fileinfoack;
    const struct status_h *status;
    const struct complete_h *complete;
    const uint8_t *func;
    struct pr_pending_info_t *pending;
    int match, pendidx, hlen;

    func = message;
    fileinfoack = (const struct fileinfoack_h *)message;
    status = (const struct status_h *)message;
    complete = (const struct complete_h *)message;

    glog3(group, "check_timeout: looking for pending %s", func_name(*func));
    for (pendidx = 0; pendidx < MAX_PEND; pendidx++) {
        pending = &group->pending[pendidx];
        if (group->pending[pendidx].msg == 0) {
            glog3(group, "check_timeout: found empty slot %d", pendidx);
            match = 1;
            break;
        }

        match = (*func == pending->msg);
        switch (*func) {
        case REGISTER:
            // REGISTER always matches itself
            break;
        case FILEINFO_ACK:
            match = match && (ntohs(fileinfoack->file_id) == pending->file_id);
            break;
        case STATUS:
            match = match && ((ntohs(status->file_id) == pending->file_id) &&
                              (ntohs(status->section) == pending->section));
            break;
        case COMPLETE:
            match = match && ((ntohs(complete->file_id) == pending->file_id) &&
                              (complete->status == pending->comp_status));
            break;
        default:
            glog1(group, "Tried to check pending on invalid type %s",
                         func_name(*func));
            return;
        }
        if (match) {
            break;
        }
    }

    if (!match) {
        send_all_pending(group);
        pendidx = 0;
        pending = &group->pending[pendidx];
    }

    glog3(group, "check_timeout: found match at slot %d", pendidx);
    pending->msg = *func;
    if (group->destinfo[hostidx].pending != pendidx) {
        group->destinfo[hostidx].pending = pendidx;
        pending->count++;
    }

    switch (*func) {
    case REGISTER:
        hlen = sizeof(struct register_h);
        if (pending->count == 1) {
            gettimeofday(&pending->rx_tstamp, NULL);
            pending->tstamp = group->destinfo[hostidx].regtime;
            glog3(group, "send time = %d.%06d",
                         pending->tstamp.tv_sec, pending->tstamp.tv_usec);
            glog3(group, "rx time = %d.%06d",
                         pending->rx_tstamp.tv_sec, pending->rx_tstamp.tv_usec);
        }
        break;
    case FILEINFO_ACK:
        hlen = sizeof(struct fileinfoack_h);
        if (pending->count == 1) {
            pending->partial = 1;
            gettimeofday(&pending->rx_tstamp, NULL);
            pending->tstamp.tv_sec = ntohl(fileinfoack->tstamp_sec);
            pending->tstamp.tv_usec = ntohl(fileinfoack->tstamp_usec);
            glog3(group, "send time = %d.%06d",
                         pending->tstamp.tv_sec, pending->tstamp.tv_usec);
            glog3(group, "rx time = %d.%06d",
                         pending->rx_tstamp.tv_sec, pending->rx_tstamp.tv_usec);
        }
        pending->file_id = ntohs(fileinfoack->file_id);
        pending->partial = pending->partial &&
                            ((fileinfoack->flags & FLAG_PARTIAL) != 0);
        break;
    case STATUS:
        hlen = sizeof(struct status_h);
        pending->file_id = ntohs(status->file_id);
        pending->section = ntohs(status->section);
        if (!pending->naklist) {
            pending->naklist = safe_calloc(group->blocksize, 1);
        }
        add_naks_to_pending(group, pendidx, message);
        break;
    case COMPLETE:
        hlen = sizeof(struct complete_h);
        pending->file_id = ntohs(complete->file_id);
        pending->comp_status = complete->status;
        break;
    }

    if ((*func != STATUS) &&
            (pending->count == max_msg_dest(group, *func, hlen))) {
        send_pending(group, pendidx);
    } else {
        int total_pending, i;

        glog3(group, "check_timeout: getting pending count for %s",
                     func_name(*func));
        for (total_pending = 0, i = 0; i < MAX_PEND; i++) {
            glog3(group, "check_timeout: adding %d pending for %d",
                         group->pending[i].count, i);
            total_pending += group->pending[i].count;
        }
        if (total_pending == 1) {
            set_timeout(group, 1, 0);
        }
    }
}
Ejemplo n.º 8
0
int main(int argc , char *argv[]) {
    int socket_desc , client_sock , read_size;
    socklen_t c;
    struct sockaddr_in server , client;
    char client_message[0xFFFF];

#ifdef _WIN32
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);
#else
    signal(SIGPIPE, SIG_IGN);
#endif

    socket_desc = socket(AF_INET , SOCK_STREAM , 0);
    if (socket_desc == -1) {
        printf("Could not create socket");
        return 0;
    }

    int port = 2000;
    if (argc > 1) {
        port = atoi(argv[1]);
        if (port <= 0)
            port = 2000;
    }
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons(port);
     
    if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0) {
        perror("bind failed. Error");
        return 1;
    }
    int enable = 1;
    setsockopt(socket_desc, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
     
    listen(socket_desc , 3);
     
    c = sizeof(struct sockaddr_in);

    unsigned int size;

    struct TLSContext *server_context = tls_create_context(1, TLS_V12);
    // load keys
    load_keys(server_context, "testcert/fullchain.pem", "testcert/privkey.pem");
    
    char source_buf[0xFFFF];
    int source_size = read_from_file("tlshelloworld.c", source_buf, 0xFFFF);
    while (1) {
        identity_str[0] = 0;

        client_sock = accept(socket_desc, (struct sockaddr *)&client, &c);
        if (client_sock < 0) {
            perror("accept failed");
            return 1;
        }
        struct TLSContext *context = tls_accept(server_context);

        // uncomment next line to request client certificate
        tls_request_client_certificate(context);

        // make the TLS context serializable (this must be called before negotiation)
        tls_make_exportable(context, 1);

        fprintf(stderr, "Client connected\n");
        while ((read_size = recv(client_sock, client_message, sizeof(client_message), 0)) > 0) {
            if (tls_consume_stream(context, client_message, read_size, verify_signature) > 0)
                break;
        }

        send_pending(client_sock, context);

        if (read_size > 0) {
            fprintf(stderr, "USED CIPHER: %s\n", tls_cipher_name(context));
            int ref_packet_count = 0;
            int res;
            while ((read_size = recv(client_sock, client_message, sizeof(client_message) , 0)) > 0) {
                if (tls_consume_stream(context, client_message, read_size, verify_signature) < 0) {
                    fprintf(stderr, "Error in stream consume\n");
                    break;
                }
                send_pending(client_sock, context);
                if (tls_established(context) == 1) {
                    unsigned char read_buffer[0xFFFF];
                    int read_size = tls_read(context, read_buffer, sizeof(read_buffer) - 1);
                    if (read_size > 0) {
                        read_buffer[read_size] = 0;
                        unsigned char export_buffer[0xFFF];
                        // simulate serialization / deserialization to another process
                        char sni[0xFF];
                        sni[0] = 0;
                        if (context->sni)
                            snprintf(sni, 0xFF, "%s", context->sni);
    /* COOL STUFF => */ int size = tls_export_context(context, export_buffer, sizeof(export_buffer), 1);
                        if (size > 0) {
    /* COOLER STUFF => */   struct TLSContext *imported_context = tls_import_context(export_buffer, size);
    // This is cool because a context can be sent to an existing process.
    // It will work both with fork and with already existing worker process.
                            fprintf(stderr, "Imported context (size: %i): %x\n", size, imported_context);
                            if (imported_context) {
                                // destroy old context
                                tls_destroy_context(context);
                                // simulate serialization/deserialization of context
                                context = imported_context;
                            }
                        }
                        // ugly inefficient code ... don't write like me
                        char send_buffer[0xF000];
                        char send_buffer_with_header[0xF000];
                        char out_buffer[0xFFF];
                        int tls_version = 2;
                        switch (context->version) {
                            case TLS_V10:
                                tls_version = 0;
                                break;
                            case TLS_V11:
                                tls_version = 1;
                                break;
                        }
                        snprintf(send_buffer, sizeof(send_buffer), "Hello world from TLS 1.%i (used chipher is: %s), SNI: %s\r\nYour identity is: %s\r\n\r\nCertificate: %s\r\n\r\nBelow is the received header:\r\n%s\r\nAnd the source code for this example: \r\n\r\n%s", tls_version, tls_cipher_name(context), sni, identity_str, tls_certificate_to_string(server_context->certificates[0], out_buffer, sizeof(out_buffer)), read_buffer, source_buf);
                        int content_length = strlen(send_buffer);
                        snprintf(send_buffer_with_header, sizeof(send_buffer), "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-type: text/plain\r\nContent-length: %i\r\n\r\n%s", content_length, send_buffer);
                        tls_write(context, send_buffer_with_header, strlen(send_buffer_with_header));
                        tls_close_notify(context);
                        send_pending(client_sock, context);
                        break;
                    }
                }
            }
        }
#ifdef __WIN32
        shutdown(client_sock, SD_BOTH);
        closesocket(client_sock);
#else
        shutdown(client_sock, SHUT_RDWR);
        close(client_sock);
#endif
        tls_destroy_context(context);
    }
    tls_destroy_context(server_context);
    return 0;
}
Ejemplo n.º 9
0
static int run_server(struct sockaddr *sa, socklen_t salen)
{
    static quicly_conn_t **conns;
    size_t num_conns = 0;
    int fd, ret;

    if ((fd = socket(sa->sa_family, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
        perror("socket(2) failed");
        return 1;
    }
    int on = 1;
    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) != 0) {
        perror("setsockopt(SO_REUSEADDR) failed");
        return 1;
    }
    if (bind(fd, sa, salen) != 0) {
        perror("bind(2) failed");
        return 1;
    }

    while (1) {
        fd_set readfds;
        struct timeval *tv, tvbuf;
        do {
            int64_t timeout_at = INT64_MAX;
            size_t i;
            for (i = 0; i != num_conns; ++i) {
                int64_t conn_to = quicly_get_first_timeout(conns[i]);
                if (conn_to < timeout_at)
                    timeout_at = conn_to;
            }
            if (timeout_at != INT64_MAX) {
                int64_t delta = timeout_at - ctx.now(&ctx);
                if (delta > 0) {
                    tvbuf.tv_sec = delta / 1000;
                    tvbuf.tv_usec = (delta % 1000) * 1000;
                } else {
                    tvbuf.tv_sec = 0;
                    tvbuf.tv_usec = 0;
                }
                tv = &tvbuf;
            } else {
                tv = NULL;
            }
            FD_ZERO(&readfds);
            FD_SET(fd, &readfds);
        } while (select(fd + 1, &readfds, NULL, NULL, tv) == -1 && errno == EINTR);
        if (FD_ISSET(fd, &readfds)) {
            uint8_t buf[4096];
            struct msghdr mess;
            struct sockaddr sa;
            struct iovec vec;
            memset(&mess, 0, sizeof(mess));
            mess.msg_name = &sa;
            mess.msg_namelen = sizeof(sa);
            vec.iov_base = buf;
            vec.iov_len = sizeof(buf);
            mess.msg_iov = &vec;
            mess.msg_iovlen = 1;
            ssize_t rret;
            while ((rret = recvmsg(fd, &mess, 0)) <= 0)
                ;
            if (verbosity >= 2)
                hexdump("recvmsg", buf, rret);
            quicly_decoded_packet_t packet;
            if (quicly_decode_packet(&packet, buf, rret) == 0) {
                if (packet.has_connection_id) {
                    quicly_conn_t *conn = NULL;
                    size_t i;
                    for (i = 0; i != num_conns; ++i) {
                        if (quicly_get_connection_id(conns[i]) == packet.connection_id) {
                            conn = conns[i];
                            break;
                        }
                    }
                    if (conn != NULL) {
                        /* existing connection */
                        quicly_receive(conn, &packet);
                        if (quicly_get_state(conn) == QUICLY_STATE_1RTT_ENCRYPTED && quicly_get_next_stream_id(conn) == 1) {
                            quicly_stream_t *stream;
                            ret = quicly_open_stream(conn, &stream);
                            assert(ret == 0);
                            stream->on_update = on_resp_receive;
                            send_data(stream, "GET / HTTP/1.0\r\n\r\n");
                        }
                    } else {
                        /* new connection */
                        if (quicly_accept(&conn, &ctx, &sa, mess.msg_namelen, NULL, &packet) == 0) {
                            assert(conn != NULL);
                            conns = realloc(conns, sizeof(*conns) * (num_conns + 1));
                            assert(conns != NULL);
                            conns[num_conns++] = conn;
                        } else {
                            assert(conn == NULL);
                        }
                    }
                    if (conn != NULL && send_pending(fd, conn) != 0) {
                        for (i = 0; i != num_conns; ++i) {
                            if (conns[i] == conn) {
                                memcpy(conns + i, conns + i + 1, (num_conns - i - 1) * sizeof(*conns));
                                --num_conns;
                                break;
                            }
                        }
                        quicly_free(conn);
                    }
                } else {
                    fprintf(stderr, "ignoring packet without connection-id\n");
                }
            }
        }
    }
}
Ejemplo n.º 10
0
static int run_client(struct sockaddr *sa, socklen_t salen, const char *host)
{
    int fd, ret;
    struct sockaddr_in local;
    quicly_conn_t *conn = NULL;

    if ((fd = socket(sa->sa_family, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
        perror("socket(2) failed");
        return 1;
    }
    memset(&local, 0, sizeof(local));
    local.sin_family = AF_INET;
    if (bind(fd, (void *)&local, sizeof(local)) != 0) {
        perror("bind(2) failed");
        return 1;
    }
    ret = quicly_connect(&conn, &ctx, host, sa, salen, NULL);
    assert(ret == 0);
    send_pending(fd, conn);

    while (1) {
        fd_set readfds;
        struct timeval *tv, tvbuf;
        do {
            int64_t timeout_at = conn != NULL ? quicly_get_first_timeout(conn) : INT64_MAX;
            if (timeout_at != INT64_MAX) {
                int64_t delta = timeout_at - quicly_get_context(conn)->now(quicly_get_context(conn));
                if (delta > 0) {
                    tvbuf.tv_sec = delta / 1000;
                    tvbuf.tv_usec = (delta % 1000) * 1000;
                } else {
                    tvbuf.tv_sec = 0;
                    tvbuf.tv_usec = 0;
                }
                tv = &tvbuf;
            } else {
                tv = NULL;
            }
            FD_ZERO(&readfds);
            FD_SET(fd, &readfds);
        } while (select(fd + 1, &readfds, NULL, NULL, tv) == -1 && errno == EINTR);
        if (FD_ISSET(fd, &readfds)) {
            uint8_t buf[4096];
            struct msghdr mess;
            struct sockaddr sa;
            struct iovec vec;
            memset(&mess, 0, sizeof(mess));
            mess.msg_name = &sa;
            mess.msg_namelen = sizeof(sa);
            vec.iov_base = buf;
            vec.iov_len = sizeof(buf);
            mess.msg_iov = &vec;
            mess.msg_iovlen = 1;
            ssize_t rret;
            while ((rret = recvmsg(fd, &mess, 0)) <= 0)
                ;
            if (verbosity >= 2)
                hexdump("recvmsg", buf, rret);
            quicly_decoded_packet_t packet;
            if (quicly_decode_packet(&packet, buf, rret) == 0) {
                quicly_receive(conn, &packet);
                if (quicly_get_state(conn) == QUICLY_STATE_1RTT_ENCRYPTED && quicly_get_next_stream_id(conn) == 1) {
                    quicly_stream_t *stream;
                    ret = quicly_open_stream(conn, &stream);
                    assert(ret == 0);
                    stream->on_update = on_resp_receive;
                    send_data(stream, "GET /\r\n");
                }
            }
        }
        if (conn != NULL && send_pending(fd, conn) != 0) {
            quicly_free(conn);
            conn = NULL;
        }
    }
}