You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ma...@apache.org on 2016/07/14 21:15:03 UTC
incubator-mynewt-core git commit: inet default services;
echo, discard and chargen. These can be used when testing data
transfer with IP.
Repository: incubator-mynewt-core
Updated Branches:
refs/heads/develop 78d4bed28 -> c487de2da
inet default services; echo, discard and chargen.
These can be used when testing data transfer with IP.
Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/c487de2d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/c487de2d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/c487de2d
Branch: refs/heads/develop
Commit: c487de2da6cc42fa01ee0290d57aaec690fba3ad
Parents: 78d4bed
Author: Marko Kiiskila <ma...@runtime.io>
Authored: Thu Jul 14 14:13:07 2016 -0700
Committer: Marko Kiiskila <ma...@runtime.io>
Committed: Thu Jul 14 14:13:07 2016 -0700
----------------------------------------------------------------------
.../include/inet_def_service/inet_def_service.h | 25 ++
libs/inet_def_service/pkg.yml | 38 +++
libs/inet_def_service/src/inet_def_service.c | 333 +++++++++++++++++++
3 files changed, 396 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c487de2d/libs/inet_def_service/include/inet_def_service/inet_def_service.h
----------------------------------------------------------------------
diff --git a/libs/inet_def_service/include/inet_def_service/inet_def_service.h b/libs/inet_def_service/include/inet_def_service/inet_def_service.h
new file mode 100644
index 0000000..6b219fe
--- /dev/null
+++ b/libs/inet_def_service/include/inet_def_service/inet_def_service.h
@@ -0,0 +1,25 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef __INET_DEF_SERVICE_H__
+#define __INET_DEF_SERVICE_H__
+
+int inet_def_service_init(uint8_t prio, os_stack_t *stack, uint16_t stack_sz);
+
+#endif /* __INET_DEF_SERVICE_H__ */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c487de2d/libs/inet_def_service/pkg.yml
----------------------------------------------------------------------
diff --git a/libs/inet_def_service/pkg.yml b/libs/inet_def_service/pkg.yml
new file mode 100644
index 0000000..103b0d5
--- /dev/null
+++ b/libs/inet_def_service/pkg.yml
@@ -0,0 +1,38 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+pkg.name: libs/inet_def_service
+pkg.description: INET services chargen, discard and echo
+pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+ - socket
+ - inet
+ - test
+
+pkg.deps:
+ - sys/mn_socket
+ - libs/os
+ - libs/util
+ - libs/testutil
+
+pkg.reqs:
+ - console
+
+pkg.features:
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c487de2d/libs/inet_def_service/src/inet_def_service.c
----------------------------------------------------------------------
diff --git a/libs/inet_def_service/src/inet_def_service.c b/libs/inet_def_service/src/inet_def_service.c
new file mode 100644
index 0000000..fd756bf
--- /dev/null
+++ b/libs/inet_def_service/src/inet_def_service.c
@@ -0,0 +1,333 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <assert.h>
+#include <string.h>
+
+#include <os/os.h>
+#include <os/endian.h>
+#include <mn_socket/mn_socket.h>
+#include <console/console.h>
+
+#include "inet_def_service/inet_def_service.h"
+
+#define ECHO_PORT 7
+#define DISCARD_PORT 9
+#define CHARGEN_PORT 19
+
+enum inet_def_type {
+ INET_DEF_ECHO = 0,
+ INET_DEF_DISCARD,
+ INET_DEF_CHARGEN,
+ INET_DEF_MAXTYPE
+};
+
+#define INET_DEF_FROM_EVENT_TYPE(a) ((a) - OS_EVENT_T_PERUSER)
+#define INET_EVENT_TYPE_FROM_DEF(a) ((a) + OS_EVENT_T_PERUSER)
+
+#define CHARGEN_WRITE_SZ 512
+static const char chargen_pattern[] = "1234567890";
+#define CHARGEN_PATTERN_SZ (sizeof(chargen_pattern) - 1)
+
+static struct os_task inet_def_task;
+static struct os_eventq inet_def_evq;
+
+/*
+ * UDP service.
+ */
+struct inet_def_udp {
+ struct os_event ev; /* Datagram RX reported via event */
+ struct mn_socket *socket;
+ uint32_t pkt_cnt;
+};
+
+/*
+ * Connected TCP socket.
+ */
+struct inet_def_tcp {
+ struct os_event ev; /* Data RX reported with this event */
+ SLIST_ENTRY(inet_def_tcp) list;
+ struct mn_socket *socket;
+ int closed;
+};
+
+/*
+ * TCP service.
+ */
+struct inet_def_listen {
+ struct mn_socket *socket;
+ uint32_t conn_cnt;
+};
+
+static struct inet_def {
+ struct inet_def_listen tcp_service[INET_DEF_MAXTYPE];
+ struct inet_def_udp udp_service[INET_DEF_MAXTYPE];
+ SLIST_HEAD(, inet_def_tcp) tcp_conns; /* List of connected TCP sockets */
+} inet_def;
+
+/*
+ * UDP socket callbacks. Called in context of IP stack task.
+ */
+static void
+inet_def_udp_readable(void *arg, int err)
+{
+ struct inet_def_udp *idu = (struct inet_def_udp *)arg;
+
+ os_eventq_put(&inet_def_evq, &idu->ev);
+}
+
+static const union mn_socket_cb inet_udp_cbs = {
+ .socket.readable = inet_def_udp_readable,
+};
+
+/*
+ * TCP socket callbacks. Called in context of IP stack task.
+ */
+static void
+inet_def_tcp_readable(void *arg, int err)
+{
+ struct inet_def_tcp *idt = (struct inet_def_tcp *)arg;
+
+ if (err) {
+ idt->closed = 1;
+ /*
+ * No locking here. Assuming new connection notifications, as well as
+ * close notifications arrive in context of a single task.
+ */
+ SLIST_REMOVE(&inet_def.tcp_conns, idt, inet_def_tcp, list);
+ }
+ os_eventq_put(&inet_def_evq, &idt->ev);
+}
+
+static const union mn_socket_cb inet_tcp_cbs = {
+ .socket.readable = inet_def_tcp_readable,
+ .socket.writable = inet_def_tcp_readable /* we want the same behavior */
+};
+
+/*
+ * Callback for new connection for TCP listen socket.
+ */
+static int inet_def_newconn(void *arg, struct mn_socket *new)
+{
+ struct inet_def_listen *idl = (struct inet_def_listen *)arg;
+ struct inet_def_tcp *idt;
+ enum inet_def_type type;
+
+ idt = (struct inet_def_tcp *)os_malloc(sizeof(*idt));
+ if (!idt) {
+ return -1;
+ }
+
+ memset(idt, 0, sizeof(*idt));
+ idt->socket = new;
+
+ /*
+ * Event type tells what type of service this connection belongs to.
+ * Ev_arg says whether it's TCP or UDP.
+ */
+ type = idl - &inet_def.tcp_service[0];
+ idt->ev.ev_type = INET_EVENT_TYPE_FROM_DEF(type);
+ idt->ev.ev_arg = (void *)MN_SOCK_STREAM;
+ mn_socket_set_cbs(new, idt, &inet_tcp_cbs);
+ SLIST_INSERT_HEAD(&inet_def.tcp_conns, idt, list);
+
+ if (type == INET_DEF_CHARGEN) {
+ /*
+ * Start transmitting right away.
+ */
+ os_eventq_put(&inet_def_evq, &idt->ev);
+ }
+ return 0;
+}
+
+static const union mn_socket_cb inet_listen_cbs = {
+ .listen.newconn = inet_def_newconn,
+};
+
+static int
+inet_def_create_srv(enum inet_def_type idx, uint16_t port)
+{
+ struct mn_socket *ms;
+ struct mn_sockaddr_in msin;
+
+ memset(&msin, 0, sizeof(msin));
+ msin.msin_len = sizeof(msin);
+ msin.msin_family = MN_AF_INET;
+ msin.msin_port = htons(port);
+
+ /*
+ * Create TCP listen socket for service.
+ */
+ if (mn_socket(&ms, MN_PF_INET, MN_SOCK_STREAM, 0)) {
+ goto err;
+ }
+ inet_def.tcp_service[idx].socket = ms;
+ mn_socket_set_cbs(ms, &inet_def.tcp_service[idx], &inet_listen_cbs);
+
+ if (mn_bind(ms, (struct mn_sockaddr *)&msin)) {
+ goto err;
+ }
+ if (mn_listen(ms, 1)) {
+ goto err;
+ }
+
+ /*
+ * Create UDP socket for service.
+ */
+ if (mn_socket(&ms, MN_PF_INET, MN_SOCK_DGRAM, 0)) {
+ goto err;
+ }
+ inet_def.udp_service[idx].socket = ms;
+ mn_socket_set_cbs(ms, &inet_def.udp_service[idx], &inet_udp_cbs);
+
+ if (mn_bind(ms, (struct mn_sockaddr *)&msin)) {
+ goto err;
+ }
+
+ return 0;
+err:
+ if (inet_def.tcp_service[idx].socket) {
+ mn_close(inet_def.tcp_service[idx].socket);
+ inet_def.tcp_service[idx].socket = NULL;
+ }
+ if (inet_def.udp_service[idx].socket) {
+ mn_close(inet_def.udp_service[idx].socket);
+ inet_def.udp_service[idx].socket = NULL;
+ }
+ return -1;
+}
+
+static void
+inet_def_srv(void *arg)
+{
+ struct inet_def_udp *idu;
+ struct inet_def_tcp *idt;
+ struct mn_socket *sock;
+ struct os_event *ev;
+ struct mn_sockaddr_in msin;
+ struct os_mbuf *m;
+ enum inet_def_type type;
+ int rc;
+ int off;
+ int loop_cnt;
+
+ inet_def_create_srv(INET_DEF_ECHO, ECHO_PORT);
+ inet_def_create_srv(INET_DEF_DISCARD, DISCARD_PORT);
+ inet_def_create_srv(INET_DEF_CHARGEN, CHARGEN_PORT);
+
+ while (1) {
+ /*
+ * Wait here. When event comes, check what type of socket got it,
+ * and then act on it.
+ */
+ ev = os_eventq_get(&inet_def_evq);
+ type = INET_DEF_FROM_EVENT_TYPE(ev->ev_type);
+ idt = (struct inet_def_tcp *)ev;
+ idu = (struct inet_def_udp *)ev;
+ if ((int)ev->ev_arg == MN_SOCK_DGRAM) {
+ sock = idu->socket;
+ } else {
+ sock = idt->socket;
+ }
+ switch (type) {
+ case INET_DEF_ECHO:
+ while (mn_recvfrom(sock, &m, (struct mn_sockaddr *)&msin) == 0) {
+ console_printf("echo %d bytes\n", OS_MBUF_PKTLEN(m));
+ rc = mn_sendto(sock, m, (struct mn_sockaddr *)&msin);
+ if (rc) {
+ console_printf(" failed: %d!!!!\n", rc);
+ os_mbuf_free_chain(m);
+ }
+ }
+ break;
+ case INET_DEF_DISCARD:
+ while (mn_recvfrom(sock, &m, NULL) == 0) {
+ console_printf("discard %d bytes\n", OS_MBUF_PKTLEN(m));
+ os_mbuf_free_chain(m);
+ }
+ break;
+ case INET_DEF_CHARGEN:
+ while (mn_recvfrom(sock, &m, NULL) == 0) {
+ os_mbuf_free_chain(m);
+ }
+ if ((int)ev->ev_arg == MN_SOCK_STREAM && idt->closed) {
+ /*
+ * Don't try to send tons of data to a closed socket.
+ */
+ break;
+ }
+ loop_cnt = 0;
+ do {
+ m = os_msys_get(CHARGEN_WRITE_SZ, 0);
+ if (m) {
+ for (off = 0;
+ OS_MBUF_TRAILINGSPACE(m) >= CHARGEN_PATTERN_SZ;
+ off += CHARGEN_PATTERN_SZ) {
+ os_mbuf_copyinto(m, off, chargen_pattern,
+ CHARGEN_PATTERN_SZ);
+ }
+ console_printf("chargen %d bytes\n", m->om_len);
+ rc = mn_sendto(sock, m, NULL); /* assumes TCP for now */
+ if (rc) {
+ os_mbuf_free_chain(m);
+ if (rc != MN_ENOBUFS && rc != MN_EAGAIN) {
+ console_write(" sendto fail!!! %d\n", rc);
+ }
+ break;
+ }
+ } else {
+ /*
+ * Mbuf shortage. Wait for them to appear.
+ */
+ os_time_delay(1);
+ }
+ loop_cnt++;
+ } while (loop_cnt < 32);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ if ((int)ev->ev_arg == MN_SOCK_STREAM && idt->closed) {
+ /*
+ * Remote end has closed the connection, as indicated in the
+ * callback. Close the socket and free the memory.
+ */
+ mn_socket_set_cbs(idt->socket, NULL, NULL);
+ os_eventq_remove(&inet_def_evq, &idt->ev);
+ mn_close(idt->socket);
+ os_free(idt);
+ }
+ }
+}
+
+int
+inet_def_service_init(uint8_t prio, os_stack_t *stack, uint16_t stack_sz)
+{
+ int i;
+
+ os_eventq_init(&inet_def_evq);
+ SLIST_INIT(&inet_def.tcp_conns);
+ for (i = 0; i < 3; i++) {
+ inet_def.udp_service[i].ev.ev_type = INET_EVENT_TYPE_FROM_DEF(i);
+ inet_def.udp_service[i].ev.ev_arg = (void *)MN_SOCK_DGRAM;
+ }
+ return os_task_init(&inet_def_task, "inet_def_task",
+ inet_def_srv, NULL, prio, OS_WAIT_FOREVER, stack, stack_sz);
+}
+