Пример #1
0
int socket_api_test_create_destroy(socket_stack_t stack, socket_address_family_t disable_family)
{
    struct socket s;
    int afi, pfi;
    socket_error_t err;
    const struct socket_api * api = socket_get_api(stack);
    TEST_CLEAR();
    if (!TEST_NEQ(api, NULL)) {
        // Test cannot continue without API.
        return 0;
    }
    err = api->init();
    if (!TEST_EQ(err, SOCKET_ERROR_NONE)) {
        return 0;
    }

    // Create a socket for each address family
    for (afi = SOCKET_AF_UNINIT; afi <= SOCKET_AF_MAX; afi++) {
        socket_address_family_t af = static_cast<socket_address_family_t>(afi);
        // Create a socket for each protocol family
        for (pfi = SOCKET_PROTO_UNINIT; pfi <= SOCKET_PROTO_MAX; pfi++) {
            socket_proto_family_t pf = static_cast<socket_proto_family_t>(pfi);
            // Zero the implementation
            s.impl = NULL;
            err = api->create(&s, af, pf, &create_test_handler);
            // catch expected failing cases
            if (af == SOCKET_AF_UNINIT || af == SOCKET_AF_MAX ||
                    pf == SOCKET_PROTO_UNINIT || pf == SOCKET_PROTO_MAX ||
                    af == disable_family) {
                TEST_NEQ(err, SOCKET_ERROR_NONE);
                continue;
            }
            TEST_EQ(err, SOCKET_ERROR_NONE);
            if (!TEST_NEQ(s.impl, NULL)) {
                continue;
            }
            // Destroy the socket;
            err = api->destroy(&s);
            TEST_EQ(err, SOCKET_ERROR_NONE);
            // Zero the implementation
            s.impl = NULL;
            // Create a socket with a NULL handler
            err = api->create(&s, af, pf, NULL);
            TEST_NEQ(err, SOCKET_ERROR_NONE);
            TEST_EQ(s.impl, NULL);
            // A NULL impl is not explicitly an exception since it can be zeroed during disconnect
            // Destroy the socket
            err = api->destroy(&s);
            TEST_EQ(err, SOCKET_ERROR_NONE);
            // Try destroying a socket that hasn't been created
            s.impl = NULL;
            err = api->destroy(&s);
            TEST_EQ(err, SOCKET_ERROR_NONE);

            /*
             * Because the allocator is stack-dependent, there is no way to test for a
             * memory leak in a portable way
             */
        }
    }
    TEST_RETURN();
}
Пример #2
0
int socket_api_test_echo_server_stream(socket_stack_t stack, socket_address_family_t af, const char* local_addr, uint16_t port)
{
    struct socket s;
    struct socket cs;
    struct socket_addr addr;
    socket_error_t err;
    const struct socket_api *api = socket_get_api(stack);
    server_socket = &s;
    client_socket = &cs;
    mbed::Timeout to;
    mbed::Ticker ticker;
    // Create the socket
    TEST_CLEAR();

    if (!TEST_NEQ(api, NULL)) {
        // Test cannot continue without API.
        TEST_RETURN();
    }
    err = api->init();
    if (!TEST_EQ(err, SOCKET_ERROR_NONE)) {
        TEST_RETURN();
    }

    // Zero the socket implementation
    s.impl = NULL;
    // Create a socket
    err = api->create(&s, af, SOCKET_STREAM, &server_cb);
    if (!TEST_EQ(err, SOCKET_ERROR_NONE)) {
        TEST_RETURN();
    }

    err = api->str2addr(&s, &addr, local_addr);
    if (!TEST_EQ(err, SOCKET_ERROR_NONE)) {
        TEST_RETURN();
    }

    // start the TCP timer
    uint32_t interval_ms = api->periodic_interval(&s);
    TEST_NEQ(interval_ms, 0);
    uint32_t interval_us = interval_ms * 1000;
    socket_api_handler_t periodic_task = api->periodic_task(&s);
    if (TEST_NEQ(periodic_task, NULL)) {
        ticker.attach_us(periodic_task, interval_us);
    }

    err = api->bind(&s, &addr, port);
    if (!TEST_EQ(err, SOCKET_ERROR_NONE)) {
        TEST_RETURN();
    }
    void *data = malloc(SOCKET_SENDBUF_MAXSIZE);
    if(!TEST_NEQ(data, NULL)) {
        TEST_RETURN();
    }
    // Tell the host test to try and connect
    TEST_PRINT(">>> EC,%s,%d\r\n", local_addr, port);

    bool quit = false;
    // For several iterations
    while (!quit) {
        timedout = false;
        server_event_done = false;
        incoming = false;
        to.attach(onTimeout, SOCKET_TEST_SERVER_TIMEOUT);
        // Listen for incoming connections
        err = api->start_listen(&s, 0);
        if (!TEST_EQ(err, SOCKET_ERROR_NONE)) {
            TEST_EXIT();
        }
        // Reset the state of client_rx_done
        client_rx_done = false;
        // Wait for a connect event
        while (!timedout && !incoming) {
            __WFI();
        }
        if (TEST_EQ(timedout,0)) {
            to.detach();
        } else {
            TEST_EXIT();
        }
        if(!TEST_EQ(server_event.event, SOCKET_EVENT_ACCEPT)) {
            TEST_PRINT("Event: %d\r\n",(int)client_event.event);
            continue;
        }
        // Stop listening
        server_event_done = false;
        // err = api->stop_listen(&s);
        // TEST_EQ(err, SOCKET_ERROR_NONE);
        // Accept an incoming connection
        cs.impl = server_event.i.a.newimpl;
        cs.family = s.family;
        cs.stack  = s.stack;
        err = api->accept(&cs, client_cb);
        if(!TEST_EQ(err, SOCKET_ERROR_NONE)) {
            continue;
        }
        to.attach(onTimeout, SOCKET_TEST_SERVER_TIMEOUT);

                    // Client should test for successive connections being rejected
        // Until Client disconnects
        while (client_event.event != SOCKET_EVENT_ERROR && client_event.event != SOCKET_EVENT_DISCONNECT) {
            // Wait for a read event
            while (!client_event_done && !client_rx_done && !timedout) {
                __WFI();
            }
            if (!TEST_EQ(client_event_done, false)) {
                client_event_done = false;
                continue;
            }
            // Reset the state of client_rx_done
            client_rx_done = false;

            // Receive some data
            size_t len = SOCKET_SENDBUF_MAXSIZE;
            err = api->recv(&cs, data, &len);
            if (!TEST_NEQ(err, SOCKET_ERROR_WOULD_BLOCK)) {
            	TEST_PRINT("Rx Would Block\r\n");
            	continue;
            }
            if (!TEST_EQ(err, SOCKET_ERROR_NONE)) {
            	TEST_PRINT("err: (%d) %s\r\n", err, socket_strerror(err));
                break;
            }

            // Check if the server should halt
            if (strncmp((const char *)data, "quit", 4) == 0) {
                quit = true;
                break;
            }
            // Send some data
            err = api->send(&cs, data, len);
            if (!TEST_EQ(err, SOCKET_ERROR_NONE)) {
                break;
            }
        }
        to.detach();
        TEST_NEQ(timedout, true);

        // Close client socket
        err = api->close(&cs);
        TEST_EQ(err, SOCKET_ERROR_NONE);
    }
    err = api->stop_listen(&s);
    TEST_EQ(err, SOCKET_ERROR_NONE);
test_exit:
    ticker.detach();
    TEST_PRINT(">>> KILL,EC\r\n");
    free(data);
    // Destroy server socket
    TEST_RETURN();
}
Пример #3
0
int socket_api_test_connect_close(socket_stack_t stack, socket_address_family_t af, const char* server, uint16_t port)
{
    struct socket s;
    int pfi;
    socket_error_t err;
    const struct socket_api * api = socket_get_api(stack);
    struct socket_addr addr;

    ConnectCloseSock = &s;
    TEST_CLEAR();
    if (!TEST_NEQ(api, NULL)) {
        // Test cannot continue without API.
        TEST_RETURN();
    }
    err = api->init();
    if (!TEST_EQ(err, SOCKET_ERROR_NONE)) {
        TEST_RETURN();
    }

	// Create a socket for each protocol family
	for (pfi = SOCKET_PROTO_UNINIT+1; pfi < SOCKET_PROTO_MAX; pfi++) {
		socket_proto_family_t pf = static_cast<socket_proto_family_t>(pfi);
		// Zero the implementation
		s.impl = NULL;
		err = api->create(&s, af, pf, &connect_close_handler);
		// catch expected failing cases
		TEST_EQ(err, SOCKET_ERROR_NONE);
		if (!TEST_NEQ(s.impl, NULL)) {
			continue;
		}
		// Tell the host launch a server
		TEST_PRINT(">>> ES,%d\r\n", pf);

		// connect to a remote host
		err = api->str2addr(&s, &addr, server);
		TEST_EQ(err, SOCKET_ERROR_NONE);

		timedout = 0;
		connected = 0;
		mbed::Timeout to;
		to.attach(onTimeout, SOCKET_TEST_TIMEOUT);
		err = api->connect(&s, &addr, port);
		TEST_EQ(err, SOCKET_ERROR_NONE);
		if (err!=SOCKET_ERROR_NONE) {
			printf("err = %d\r\n", err);
		}
		switch (pf) {
		case SOCKET_DGRAM:
			while ((!api->is_connected(&s)) && (!timedout)) {
				__WFI();
			}
			break;
		case SOCKET_STREAM:
			while (!connected && !timedout) {
				__WFI();
			}
			break;
		default: break;
		}
		to.detach();
		TEST_EQ(timedout, 0);

		// close the connection
		timedout = 0;
		closed = 0;
		to.attach(onTimeout, SOCKET_TEST_TIMEOUT);
		err = api->close(&s);
		TEST_EQ(err, SOCKET_ERROR_NONE);
		if (err!=SOCKET_ERROR_NONE) {
			printf("err = %d\r\n", err);
		}
		switch (pf) {
			case SOCKET_DGRAM:
				while ((api->is_connected(&s)) && (!timedout)) {
					__WFI();
				}
				break;
			case SOCKET_STREAM:
				while (!closed && !timedout) {
					__WFI();
				}
				break;
			default: break;
		}
		to.detach();
		TEST_EQ(timedout, 0);
		// Tell the host to kill the server
		TEST_PRINT(">>> KILL ES\r\n");

		// Destroy the socket
		err = api->destroy(&s);
		TEST_EQ(err, SOCKET_ERROR_NONE);
	}
    TEST_RETURN();
}
Пример #4
0
int socket_api_test_echo_client_connected(socket_stack_t stack, socket_address_family_t af, socket_proto_family_t pf, bool connect,
        const char* server, uint16_t port)
{
    struct socket s;
    socket_error_t err;
    const struct socket_api *api = socket_get_api(stack);
    client_socket = &s;
    mbed::Timeout to;
    // Create the socket
    TEST_CLEAR();
    TEST_PRINT("\r\n%s af: %d, pf: %d, connect: %d, server: %s:%d\r\n",__func__, (int) af, (int) pf, (int) connect, server, (int) port);

    if (!TEST_NEQ(api, NULL)) {
        // Test cannot continue without API.
        TEST_RETURN();
    }
    err = api->init();
    if (!TEST_EQ(err, SOCKET_ERROR_NONE)) {
        TEST_RETURN();
    }

    struct socket_addr addr;
    // Resolve the host address
    err = blocking_resolve(stack, af, server, &addr);
    if (!TEST_EQ(err, SOCKET_ERROR_NONE)) {
        TEST_RETURN();
    }
    // Tell the host launch a server
    TEST_PRINT(">>> ES,%d\r\n", pf);
    // Allocate a data buffer for tx/rx
    void *data = malloc(SOCKET_SENDBUF_MAXSIZE);

    // Zero the socket implementation
    s.impl = NULL;
    // Create a socket
    err = api->create(&s, af, pf, &client_cb);
    if (!TEST_EQ(err, SOCKET_ERROR_NONE)) {
        TEST_EXIT();
    }
    // Connect to a host
    if (connect) {
        client_event_done = false;
        timedout = 0;
        to.attach(onTimeout, SOCKET_TEST_TIMEOUT);
        err = api->connect(&s, &addr, port);
        if (!TEST_EQ(err, SOCKET_ERROR_NONE)) {
            TEST_EXIT();
        }
        // Override event for dgrams.
        if (pf == SOCKET_DGRAM) {
            client_event.event = SOCKET_EVENT_CONNECT;
            client_event_done = true;
        }
        // Wait for onConnect
        while (!timedout && !client_event_done) {
            __WFI();
        }

        // Make sure that the correct event occurred
        if (!TEST_EQ(client_event.event, SOCKET_EVENT_CONNECT)) {
            TEST_EXIT();
        }
        to.detach();
    }

    // For several iterations
    for (size_t i = 0; i < SOCKET_SENDBUF_ITERATIONS; i++) {
        // Fill some data into a buffer
        const size_t nWords = SOCKET_SENDBUF_BLOCKSIZE * (1 << i) / sizeof(uint16_t);
        for (size_t j = 0; j < nWords; j++) {
            *((uint16_t*) data + j) = j;
        }
        // Send the data
        client_tx_done = false;
        client_rx_done = false;
        timedout = 0;
        to.attach(onTimeout, SOCKET_TEST_TIMEOUT);

        if(connect) {
            err = api->send(&s, data, nWords * sizeof(uint16_t));
        } else {
            err = api->send_to(&s, data, nWords * sizeof(uint16_t), &addr, port);
        }
        if (!TEST_EQ(err, SOCKET_ERROR_NONE)) {
            TEST_PRINT("Failed to send %u bytes\r\n", nWords * sizeof(uint16_t));
        } else {
            size_t tx_bytes = 0;
            do {
                // Wait for the onSent callback
                while (!timedout && !client_tx_done) {
                    __WFI();
                }
                if (!TEST_EQ(timedout,0)) {
                    break;
                }
                if (!TEST_NEQ(client_tx_info.sentbytes, 0)) {
                    break;
                }
                tx_bytes += client_tx_info.sentbytes;
                if (tx_bytes < nWords * sizeof(uint16_t)) {
                    client_tx_done = false;
                    continue;
                }
                to.detach();
                TEST_EQ(tx_bytes, nWords * sizeof(uint16_t));
                break;
            } while (1);
        }
        timedout = 0;
        to.attach(onTimeout, SOCKET_TEST_TIMEOUT);
        memset(data, 0, nWords * sizeof(uint16_t));
        // Wait for the onReadable callback
        size_t rx_bytes = 0;
        do {
            while (!timedout && !client_rx_done) {
                __WFI();
            }
            if (!TEST_EQ(timedout,0)) {
                break;
            }
            size_t len = SOCKET_SENDBUF_MAXSIZE - rx_bytes;
            // Receive data
            if (connect) {
                err = api->recv(&s, (void*) ((uintptr_t) data + rx_bytes), &len);
            } else {
                struct socket_addr rxaddr;
                uint16_t rxport = 0;
                // addr may contain unused data in the storage element.
                memcpy(&rxaddr, &addr, sizeof(rxaddr));
                // Receive from...
                err = api->recv_from(&s, (void*) ((uintptr_t) data + rx_bytes), &len, &rxaddr, &rxport);
                int rc = memcmp(&rxaddr.ipv6be, &addr.ipv6be, sizeof(rxaddr.ipv6be));
                if(!TEST_EQ(rc, 0)) {
                    TEST_PRINT("Spurious receive packet\r\n");
                }
                TEST_EQ(rxport, port);
            }
            if (!TEST_EQ(err, SOCKET_ERROR_NONE)) {
                break;
            }
            rx_bytes += len;
            if (rx_bytes < nWords * sizeof(uint16_t)) {
                client_rx_done = false;
                continue;
            }
            to.detach();
            break;
        } while (1);
        if(!TEST_EQ(rx_bytes, nWords * sizeof(uint16_t))) {
            TEST_PRINT("Expected %u, got %u\r\n", nWords * sizeof(uint16_t), rx_bytes);
        }

        // Validate that the two buffers are the same
        bool match = true;
        size_t j;
        for (j = 0; match && j < nWords; j++) {
            match = (*((uint16_t*) data + j) == j);
        }
        if(!TEST_EQ(match, true)) {
            TEST_PRINT("Mismatch in %u byte packet at offset %u\r\n", nWords * sizeof(uint16_t), j * sizeof(uint16_t));
        }

    }
    if (connect) {
        // close the socket
        client_event_done = false;
        timedout = 0;
        to.attach(onTimeout, SOCKET_TEST_TIMEOUT);
        err = api->close(&s);
        TEST_EQ(err, SOCKET_ERROR_NONE);

        // Override event for dgrams.
        if (pf == SOCKET_DGRAM) {
            client_event.event = SOCKET_EVENT_DISCONNECT;
            client_event_done = true;
        }

        // wait for onClose
        while (!timedout && !client_event_done) {
            __WFI();
        }
        if (TEST_EQ(timedout,0)) {
            to.detach();
        }
        // Make sure that the correct event occurred
        TEST_EQ(client_event.event, SOCKET_EVENT_DISCONNECT);
    }

    // destroy the socket
    err = api->destroy(&s);
    TEST_EQ(err, SOCKET_ERROR_NONE);

test_exit:
    TEST_PRINT(">>> KILL,ES\r\n");
    free(data);
    TEST_RETURN();
}
Пример #5
0
int test_socket_stack_registry() {
    unsigned int i;
    socket_error_t err = SOCKET_ERROR_NONE;
    printf("Testing stack registry...\n");
    TEST_CLEAR();

    // Try to register a stack marked as Uninitialized
    expect_fail_api.stack = SOCKET_STACK_UNINIT;
    expect_fail_api.version = SOCKET_ABSTRACTION_LAYER_VERSION;
    err = socket_register_stack((&expect_fail_api));
    TEST_NEQ(err,SOCKET_ERROR_NONE);

    // Register a NULL socket api
    memset(&expect_fail_api, 0, sizeof(struct socket_api));
    expect_fail_api.version = SOCKET_ABSTRACTION_LAYER_VERSION;
    err = socket_register_stack(&expect_fail_api);
    TEST_NEQ(err,SOCKET_ERROR_NONE);

    // Register a socket api with one zeroed API.
    memset(&expect_fail_api, 1, sizeof(struct socket_api));
    expect_fail_api.version = SOCKET_ABSTRACTION_LAYER_VERSION;
    expect_fail_api.create = NULL;
    expect_fail_api.stack = static_cast<socket_stack_t>(SOCKET_STACK_UNINIT + 1);
    err = socket_register_stack(&expect_fail_api);
    TEST_NEQ(err,SOCKET_ERROR_NONE);

    // Register a socket api with the version set wrong
    memset(&expect_fail_api, 1, sizeof(struct socket_api));
    expect_fail_api.version = 0;
    expect_fail_api.stack = static_cast<socket_stack_t>(SOCKET_STACK_UNINIT + 1);
    err = socket_register_stack(&expect_fail_api);
    TEST_NEQ(err,SOCKET_ERROR_NONE);

    // Register two of the same socket api's
    memset(&test_api[0], 1, sizeof(struct socket_api));
    memset(&expect_fail_api, 1, sizeof(struct socket_api));
    test_api[0].stack = static_cast<socket_stack_t>(SOCKET_STACK_UNINIT + 1);
    test_api[0].version = SOCKET_ABSTRACTION_LAYER_VERSION;
    expect_fail_api.stack = static_cast<socket_stack_t>(SOCKET_STACK_UNINIT + 1);
    expect_fail_api.version = SOCKET_ABSTRACTION_LAYER_VERSION;
    err = socket_register_stack(&test_api[0]);
    TEST_EQ(err,SOCKET_ERROR_NONE);
    err = socket_register_stack(&expect_fail_api);
    TEST_NEQ(err,SOCKET_ERROR_NONE);

    // Register the same stack again, but with the stack ID changed

    test_api[0].stack = static_cast<socket_stack_t>(static_cast<uint32_t>(test_api[0].stack) + 1);
    test_api[0].version = SOCKET_ABSTRACTION_LAYER_VERSION;
    err = socket_register_stack(&test_api[0]);
    TEST_NEQ(err,SOCKET_ERROR_NONE);
    test_api[0].stack = static_cast<socket_stack_t>(static_cast<uint32_t>(test_api[0].stack) - 1);

    // Try to register a stack outside the accepted range
    expect_fail_api.stack = SOCKET_STACK_MAX;
    expect_fail_api.version = SOCKET_ABSTRACTION_LAYER_VERSION;
    err = socket_register_stack(&expect_fail_api);
    TEST_NEQ(err,SOCKET_ERROR_NONE);

    // One stack is already registered
    // Try to register the maximum number of stacks
    for (i = 1; i < SOCKET_MAX_STACKS; i++) {
        socket_stack_t stack = static_cast<socket_stack_t>(SOCKET_STACK_UNINIT + 1 + i);
        memset (&test_api[i],1,sizeof(struct socket_api));
        test_api[i].stack = stack;
        test_api[i].version = SOCKET_ABSTRACTION_LAYER_VERSION;
        err = socket_register_stack(&test_api[i]);
        TEST_EQ(err,SOCKET_ERROR_NONE);
    }
    // Then register one more.
    expect_fail_api.stack = static_cast<socket_stack_t>(SOCKET_MAX_STACKS + 1);
    expect_fail_api.version = SOCKET_ABSTRACTION_LAYER_VERSION;
    err = socket_register_stack(&expect_fail_api);
    TEST_NEQ(err,SOCKET_ERROR_NONE);

    // Extract an uninit socket api
    const struct socket_api *papi;
    papi = socket_get_api(SOCKET_STACK_UNINIT);
    TEST_EQ(papi, NULL);

    if (SOCKET_MAX_STACKS < SOCKET_STACK_MAX - 1) {
        // Get a valid, but unregistered stack
        papi = socket_get_api(static_cast<socket_stack_t>(SOCKET_STACK_MAX - 1));
        TEST_EQ(papi, NULL);
    }
    // Verify all registered stacks
    for (i = 0; i < SOCKET_MAX_STACKS; i++) {
        socket_stack_t stack = static_cast<socket_stack_t>(SOCKET_STACK_UNINIT + 1 + i);
        papi = socket_get_api(stack);
        TEST_EQ(papi, &test_api[i]);
    }

    return test_pass_global;
}