Esempio n. 1
0
static int
tcp_client(const char *srcaddr, const char *dstaddr, void **ctxp)
{
	struct tcp_ctx *tctx;
	struct sockaddr_storage sa;
	int ret;

	ret = tcp_setup_new(dstaddr, TCP_SIDE_CLIENT, ctxp);
	if (ret != 0)
		return (ret);
	tctx = *ctxp;
	if (srcaddr == NULL)
		return (0);
	ret = tcp_addr(srcaddr, 0, &sa);
	if (ret != 0) {
		tcp_close(tctx);
		return (ret);
	}
	if (bind(tctx->tc_fd, (struct sockaddr *)&sa, sa.ss_len) == -1) {
		ret = errno;
		tcp_close(tctx);
		return (ret);
	}
	return (0);
}
Esempio n. 2
0
int main() {
    GREENTEA_SETUP(20, "tcp_echo_client");

    EthernetInterface eth;
    eth.connect();

    printf("MBED: TCPClient IP address is '%s'\n", eth.get_ip_address());
    printf("MBED: TCPClient waiting for server IP and port...\n");

    greentea_send_kv("target_ip", eth.get_ip_address());

    bool result = false;

    char recv_key[] = "host_port";
    char ipbuf[60] = {0};
    char portbuf[16] = {0};
    unsigned int port = 0;

    greentea_send_kv("host_ip", " ");
    greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf));

    greentea_send_kv("host_port", " ");
    greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf));
    sscanf(portbuf, "%u", &port);

    printf("MBED: Server IP address received: %s:%d \n", ipbuf, port);

    TCPSocket sock(&eth);
    SocketAddress tcp_addr(ipbuf, port);
    if (sock.connect(tcp_addr) == 0) {
        printf("HTTP: Connected to %s:%d\r\n", ipbuf, port);
        printf("tx_buffer buffer size: %u\r\n", sizeof(tx_buffer));
        printf("rx_buffer buffer size: %u\r\n", sizeof(rx_buffer));

        prep_buffer(tx_buffer, sizeof(tx_buffer));
        sock.send(tx_buffer, sizeof(tx_buffer));

        // Server will respond with HTTP GET's success code
        const int ret = sock.recv(rx_buffer, sizeof(rx_buffer));
        
        result = !memcmp(tx_buffer, rx_buffer, sizeof(tx_buffer));
        
        TEST_ASSERT_EQUAL(ret, sizeof(rx_buffer));
        TEST_ASSERT_EQUAL(true, result);
    }

    sock.close();
    eth.disconnect();
    GREENTEA_TESTSUITE_RESULT(result);
}
Esempio n. 3
0
static bool
tcp_address_match(const void *ctx, const char *addr)
{
	const struct tcp_ctx *tctx = ctx;
	struct sockaddr_storage sa1, sa2;
	socklen_t salen;

	PJDLOG_ASSERT(tctx != NULL);
	PJDLOG_ASSERT(tctx->tc_magic == TCP_CTX_MAGIC);

	if (tcp_addr(addr, PROTO_TCP_DEFAULT_PORT, &sa1) != 0)
		return (false);

	salen = sizeof(sa2);
	if (getpeername(tctx->tc_fd, (struct sockaddr *)&sa2, &salen) == -1)
		return (false);

	if (sa1.ss_family != sa2.ss_family || sa1.ss_len != sa2.ss_len)
		return (false);

	switch (sa1.ss_family) {
	case AF_INET:
	    {
		struct sockaddr_in *sin1, *sin2;

		sin1 = (struct sockaddr_in *)&sa1;
		sin2 = (struct sockaddr_in *)&sa2;

		return (memcmp(&sin1->sin_addr, &sin2->sin_addr,
		    sizeof(sin1->sin_addr)) == 0);
	    }
	case AF_INET6:
	    {
		struct sockaddr_in6 *sin1, *sin2;

		sin1 = (struct sockaddr_in6 *)&sa1;
		sin2 = (struct sockaddr_in6 *)&sa2;

		return (memcmp(&sin1->sin6_addr, &sin2->sin6_addr,
		    sizeof(sin1->sin6_addr)) == 0);
	    }
	default:
		return (false);
	}
}
Esempio n. 4
0
static int
tcp_setup_new(const char *addr, int side, void **ctxp)
{
	struct tcp_ctx *tctx;
	int ret, nodelay;

	PJDLOG_ASSERT(addr != NULL);
	PJDLOG_ASSERT(side == TCP_SIDE_CLIENT ||
	    side == TCP_SIDE_SERVER_LISTEN);
	PJDLOG_ASSERT(ctxp != NULL);

	tctx = malloc(sizeof(*tctx));
	if (tctx == NULL)
		return (errno);

	/* Parse given address. */
	if ((ret = tcp_addr(addr, PROTO_TCP_DEFAULT_PORT, &tctx->tc_sa)) != 0) {
		free(tctx);
		return (ret);
	}

	PJDLOG_ASSERT(tctx->tc_sa.ss_family != AF_UNSPEC);

	tctx->tc_fd = socket(tctx->tc_sa.ss_family, SOCK_STREAM, 0);
	if (tctx->tc_fd == -1) {
		ret = errno;
		free(tctx);
		return (ret);
	}

	PJDLOG_ASSERT(tctx->tc_sa.ss_family != AF_UNSPEC);

	/* Socket settings. */
	nodelay = 1;
	if (setsockopt(tctx->tc_fd, IPPROTO_TCP, TCP_NODELAY, &nodelay,
	    sizeof(nodelay)) == -1) {
		pjdlog_errno(LOG_WARNING, "Unable to set TCP_NOELAY");
	}

	tctx->tc_side = side;
	tctx->tc_magic = TCP_CTX_MAGIC;
	*ctxp = tctx;

	return (0);
}
Esempio n. 5
0
int tcp_setup(enum setup_action action, char * addr, char * port)
{
	struct addrinfo * addrinfo = tcp_addr(addr, port);

	int fd;

	struct addrinfo * item;
	for(item = addrinfo; item != NULL; item = item->ai_next) {

		fd = addr_socket(item);

		if (fd < 0) {
			switch (errno) {
				case EAFNOSUPPORT:
					// Address family not supported.
					// Most likely disabled IPv6.
					// Try next.
					continue;
				case EPROTONOSUPPORT:
					// (address family, protocol) combination not supported.
					// Maybe `getaddrinfo` picked some funky protocol instead
					// of TCP. Maybe we should enforce TCP?
					// Try next.
					continue;
				case EPROTOTYPE:
					// (socket type, protocol) combination not supported.
					// `getaddrinfo` picked a non-stream protocol.
					// Should never happen. I hope.
					// Bail out.
				case EMFILE:
					// Out of FDs for process.
					// Bail out.
				case ENFILE:
					// Out of FDs for system.
					// Bail out.
				case ENOBUF:
					// Out of system resources.
					// Bail out.
				case ENOMEM:
					// Out of memory.
					// Bail out.
					perror("socket");
					exit(1);
				case EACCES:
					// Access denied.
					// This process is not allowed to use create this type of
					// socket.
					// Try next.
					perror("socket");
					continue;
			}
		}

		if (action == CONNECT) {
			int e = addr_connect(fd, item);

			if (e) {
				switch (errno) {
					case ECONNREFUSED:
						// Try next address.
					case EINTR:
						// Interrupted. Async establishment.
						// Must now do async poll.
					case ENETUNREACH:
						// Try next
					case EPROTOTYPE:
						// The socket on the other end is not TCP.
						// Bad namelookup result?
						// Try next
					case ETIMEOUT:
						// Try next
					case EADDRINUSE:
						// Shit, it's i bruk, try next
					case ECONNRESET:
						// How is this different from ECONNREFUSED
						// Try next
					case EHOSTUNREACH:
						// try next
					case EACCES:
						// Try next.
					case ENETDOWN:
						// try next
					case EADDRNOTAVAIL:
						// OS ran out of available tcp ports.
						// Try next. Maybe we'll get a different socket type.
						// Flag error.
					case ENOBUFS:
						// Ran out of buffer space.
						// Abort.
					default:
						// This list of errors in not exaustive. But should be
						// enough for blocking tcp using getaddrinfo with a fresh
						// socket.
						perror("Unexpected error in connect");
				}
				close(fd);
				continue;
			}
		}

		if (action == BIND) {
			setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int));
			{
				int e = addr_bind(fd, item);

				if (e) {
					perror("bind");
					close(fd);
					continue;
				}
			}

			{
				int e = listen(fd, SOMAXCONN);

				if (e) {
					perror("listen");
					close(fd);
					continue;
				}
			}
		}