You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2016/07/13 18:07:48 UTC
[2/4] incubator-mynewt-core git commit: MYNEWT-314;
First take on the socket interface.
MYNEWT-314; First take on the socket interface.
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/2fbc2b69
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/2fbc2b69
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/2fbc2b69
Branch: refs/heads/ble_hs_api
Commit: 2fbc2b699b92d2143cb6b152c57a93bb5bb26983
Parents: 8da07ef
Author: Marko Kiiskila <ma...@runtime.io>
Authored: Mon Jul 11 16:59:46 2016 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Tue Jul 12 16:48:06 2016 -0700
----------------------------------------------------------------------
sys/mn_socket/include/mn_socket/mn_socket.h | 141 +++++++++++++++++++
sys/mn_socket/include/mn_socket/mn_socket_ops.h | 82 +++++++++++
sys/mn_socket/pkg.yml | 31 ++++
sys/mn_socket/src/mn_socket.c | 123 ++++++++++++++++
sys/mn_socket/src/mn_socket_aconv.c | 57 ++++++++
sys/mn_socket/src/test/mn_sock_test.c | 82 +++++++++++
6 files changed, 516 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/2fbc2b69/sys/mn_socket/include/mn_socket/mn_socket.h
----------------------------------------------------------------------
diff --git a/sys/mn_socket/include/mn_socket/mn_socket.h b/sys/mn_socket/include/mn_socket/mn_socket.h
new file mode 100644
index 0000000..75ebc8c
--- /dev/null
+++ b/sys/mn_socket/include/mn_socket/mn_socket.h
@@ -0,0 +1,141 @@
+/**
+ * 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 __SYS_MN_SOCKET_H_
+#define __SYS_MN_SOCKET_H_
+
+#include <inttypes.h>
+
+/*
+ * Address/protocol family.
+ */
+#define MN_AF_INET 4
+#define MN_PF_INET MN_AF_INET
+#define MN_AF_INET6 6
+#define MN_PF_INET6 MN_AF_INET6
+
+/*
+ * Socket types
+ */
+#define MN_SOCK_STREAM 1
+#define MN_SOCK_DGRAM 2
+
+/*
+ * Error codes from mn_socket interface.
+ */
+#define MN_EAFNOSUPPORT 1
+#define MN_EPROTONOSUPPORT 2
+#define MN_ENOBUFS 3
+#define MN_EINVAL 4
+#define MN_ENOTCONN 5
+#define MN_ECONNABORTED 6
+#define MN_EDESTADDRREQ 7
+#define MN_EADDRINUSE 8
+#define MN_ETIMEDOUT 9
+#define MN_EAGAIN 10
+#define MN_EUNKNOWN 11
+
+struct mn_socket;
+struct mn_socket_ops;
+struct mn_sock_cb;
+struct os_mbuf;
+
+struct mn_socket {
+ const union mn_socket_cb *ms_cbs; /* filled in by user */
+ const struct mn_socket_ops *ms_ops; /* filled in by mn_socket */
+};
+
+/*
+ * Callbacks. Socket callbacks are for sockets which exchange
+ * data. Listen callback is for TCP listen sockets.
+ */
+union mn_socket_cb {
+ struct {
+ void (*readable)(struct mn_socket *, int err);
+ void (*writable)(struct mn_socket *, int err);
+ } socket;
+ struct {
+ int (*newconn)(struct mn_socket *listen, struct mn_socket *new);
+ } listen;
+};
+
+struct mn_sockaddr {
+ uint8_t msa_len;
+ uint8_t msa_family;
+ char msa_data[2];
+};
+
+struct mn_sockaddr_in {
+ uint8_t msin_len;
+ uint8_t msin_family;
+ uint16_t msin_port;
+ uint32_t msin_addr;
+};
+
+struct mn_sockaddr_in6 {
+ uint8_t msin6_len;
+ uint8_t msin6_family;
+ uint16_t msin6_port;
+ uint32_t msin6_flowinfo;
+ uint32_t msin6_addr[4];
+};
+
+/*
+ * Socket calls.
+ *
+ * mn_connect() for TCP is asynchronous. Once connection has been established,
+ * socket callback (*writable) will be called.
+ *
+ * mn_sendto() is asynchronous as well. If it fails due to buffer shortage,
+ * socket provider should call (*writable) when more data can be sent.
+ *
+ * mn_recvfrom() returns immediatelly if no data is available. If data arrives,
+ * the callback (*readable) will be called. Once that happens, owner of the
+ * socket should keep calling mn_recvfrom() until it has drained all the
+ * data from the socket.
+ *
+ * If remote end closes the socket, socket callback (*readable) will be
+ * called.
+ */
+int mn_socket(struct mn_socket **, uint8_t domain, uint8_t type, uint8_t proto);
+int mn_bind(struct mn_socket *, struct mn_sockaddr *);
+int mn_connect(struct mn_socket *, struct mn_sockaddr *);
+int mn_listen(struct mn_socket *, uint8_t qlen);
+
+int mn_recvfrom(struct mn_socket *, struct os_mbuf **,
+ struct mn_sockaddr *from);
+int mn_sendto(struct mn_socket *, struct os_mbuf *, struct mn_sockaddr *to);
+
+int mn_getsockopt(struct mn_socket *, uint8_t level, uint8_t optname,
+ void *optval);
+int mn_setsockopt(struct mn_socket *, uint8_t level, uint8_t optname,
+ void *optval);
+
+int mn_getsockname(struct mn_socket *, struct mn_sockaddr *);
+int mn_getpeername(struct mn_socket *, struct mn_sockaddr *);
+
+int mn_close(struct mn_socket *);
+
+#define mn_socket_set_cbs(sock, cbs) (sock)->ms_cbs = (cbs)
+
+/*
+ * Address conversion
+ */
+int mn_inet_pton(int af, const char *src, void *dst);
+
+#endif /* __SYS_MN_SOCKET_H_ */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/2fbc2b69/sys/mn_socket/include/mn_socket/mn_socket_ops.h
----------------------------------------------------------------------
diff --git a/sys/mn_socket/include/mn_socket/mn_socket_ops.h b/sys/mn_socket/include/mn_socket/mn_socket_ops.h
new file mode 100644
index 0000000..6e768eb
--- /dev/null
+++ b/sys/mn_socket/include/mn_socket/mn_socket_ops.h
@@ -0,0 +1,82 @@
+/**
+ * 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 __SYS_MN_SOCKET_OPS_H_
+#define __SYS_MN_SOCKET_OPS_H_
+
+#include <inttypes.h>
+
+/*
+ * Interface for socket providers.
+ * - mso_create() creates a socket, memory allocation has to be done by
+ * the socket provider.
+ * - mso_close() closes the socket, memory should be freed. User should not
+ * be using the socket pointer once it has been closed.
+ */
+struct mn_socket_ops {
+ int (*mso_create)(struct mn_socket **, uint8_t domain, uint8_t type,
+ uint8_t protocol);
+ int (*mso_close)(struct mn_socket *);
+
+ int (*mso_bind)(struct mn_socket *, struct mn_sockaddr *);
+ int (*mso_connect)(struct mn_socket *, struct mn_sockaddr *);
+ int (*mso_listen)(struct mn_socket *, uint8_t qlen);
+
+ int (*mso_sendto)(struct mn_socket *, struct os_mbuf *,
+ struct mn_sockaddr *to);
+ int (*mso_recvfrom)(struct mn_socket *, struct os_mbuf **,
+ struct mn_sockaddr *from);
+
+ int (*mso_getsockopt)(struct mn_socket *, uint8_t level, uint8_t name,
+ void *val);
+ int (*mso_setsockopt)(struct mn_socket *, uint8_t level, uint8_t name,
+ void *val);
+
+ int (*mso_getsockname)(struct mn_socket *, struct mn_sockaddr *);
+ int (*mso_getpeername)(struct mn_socket *, struct mn_sockaddr *);
+};
+
+int mn_socket_ops_reg(const struct mn_socket_ops *ops);
+
+static inline void
+mn_socket_writable(struct mn_socket *s, int error)
+{
+ if (s->ms_cbs && s->ms_cbs->socket.writable) {
+ s->ms_cbs->socket.writable(s, error);
+ }
+}
+
+static inline void
+mn_socket_readable(struct mn_socket *s, int error)
+{
+ if (s->ms_cbs && s->ms_cbs->socket.readable) {
+ s->ms_cbs->socket.readable(s, error);
+ }
+}
+
+static inline int
+mn_socket_newconn(struct mn_socket *s, struct mn_socket *new)
+{
+ if (s->ms_cbs && s->ms_cbs->listen.newconn) {
+ return s->ms_cbs->listen.newconn(s, new);
+ } else {
+ return -1;
+ }
+}
+
+#endif /* __SYS_MN_SOCKET_OPS_H_ */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/2fbc2b69/sys/mn_socket/pkg.yml
----------------------------------------------------------------------
diff --git a/sys/mn_socket/pkg.yml b/sys/mn_socket/pkg.yml
new file mode 100644
index 0000000..0c9c064
--- /dev/null
+++ b/sys/mn_socket/pkg.yml
@@ -0,0 +1,31 @@
+#
+# 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: sys/mn_socket
+pkg.description: Socket interface for Mynewt.
+pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+ - socket
+ - IP
+
+pkg.deps:
+ - libs/os
+ - libs/util
+ - libs/testutil
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/2fbc2b69/sys/mn_socket/src/mn_socket.c
----------------------------------------------------------------------
diff --git a/sys/mn_socket/src/mn_socket.c b/sys/mn_socket/src/mn_socket.c
new file mode 100644
index 0000000..2a3602c
--- /dev/null
+++ b/sys/mn_socket/src/mn_socket.c
@@ -0,0 +1,123 @@
+/**
+ * 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 <inttypes.h>
+#include <assert.h>
+
+#include <os/os.h>
+
+#include "mn_socket/mn_socket.h"
+#include "mn_socket/mn_socket_ops.h"
+
+/*
+ * Currently there can be just one provider of sockets.
+ */
+static const struct mn_socket_ops *mn_sock_tgt;
+
+int
+mn_socket_ops_reg(const struct mn_socket_ops *ops)
+{
+ if (mn_sock_tgt) {
+ /*
+ * XXXX for now.
+ */
+ return -1;
+ }
+ mn_sock_tgt = ops;
+ return 0;
+}
+
+int
+mn_socket(struct mn_socket **sp, uint8_t domain, uint8_t type, uint8_t proto)
+{
+ int rc;
+
+ *sp = NULL;
+ /*
+ * XXX Look up where socket should go.
+ */
+ if (!mn_sock_tgt) {
+ return MN_EINVAL;
+ }
+ rc = mn_sock_tgt->mso_create(sp, domain, type, proto);
+ if (*sp) {
+ (*sp)->ms_ops = mn_sock_tgt;
+ }
+ return rc;
+}
+
+int
+mn_bind(struct mn_socket *s, struct mn_sockaddr *addr)
+{
+ return s->ms_ops->mso_bind(s, addr);
+}
+
+int
+mn_connect(struct mn_socket *s, struct mn_sockaddr *addr)
+{
+ return s->ms_ops->mso_connect(s, addr);
+}
+
+int
+mn_listen(struct mn_socket *s, uint8_t qlen)
+{
+ return s->ms_ops->mso_listen(s, qlen);
+}
+
+int
+mn_recvfrom(struct mn_socket *s, struct os_mbuf **mp, struct mn_sockaddr *from)
+{
+ return s->ms_ops->mso_recvfrom(s, mp, from);
+}
+
+int
+mn_sendto(struct mn_socket *s, struct os_mbuf *m, struct mn_sockaddr *to)
+{
+ return s->ms_ops->mso_sendto(s, m, to);
+}
+
+int
+mn_getsockopt(struct mn_socket *s, uint8_t level, uint8_t name, void *val)
+{
+ return s->ms_ops->mso_getsockopt(s, level, name, val);
+}
+
+int
+mn_setsockopt(struct mn_socket *s, uint8_t level, uint8_t name, void *val)
+{
+ return s->ms_ops->mso_setsockopt(s, level, name, val);
+}
+
+int
+mn_getsockname(struct mn_socket *s, struct mn_sockaddr *addr)
+{
+ return s->ms_ops->mso_getsockname(s, addr);
+}
+
+int
+mn_getpeername(struct mn_socket *s, struct mn_sockaddr *addr)
+{
+ return s->ms_ops->mso_getpeername(s, addr);
+}
+
+int
+mn_close(struct mn_socket *s)
+{
+ return s->ms_ops->mso_close(s);
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/2fbc2b69/sys/mn_socket/src/mn_socket_aconv.c
----------------------------------------------------------------------
diff --git a/sys/mn_socket/src/mn_socket_aconv.c b/sys/mn_socket/src/mn_socket_aconv.c
new file mode 100644
index 0000000..5053eac
--- /dev/null
+++ b/sys/mn_socket/src/mn_socket_aconv.c
@@ -0,0 +1,57 @@
+/**
+ * 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 <ctype.h>
+#include <os/queue.h>
+#include "mn_socket/mn_socket.h"
+
+int
+mn_inet_pton(int af, const char *src, void *dst)
+{
+ const char *ch_src;
+ uint8_t *ch_tgt;
+ int val;
+ int cnt;
+
+ if (af == MN_PF_INET) {
+ cnt = 0;
+ ch_tgt = dst;
+ val = 0;
+ for (ch_src = src; *ch_src; ch_src++) {
+ if (cnt > 4) {
+ return 0;
+ }
+ if (isdigit(*ch_src)) {
+ val = val * 10 + *ch_src - '0';
+ if (val > 255) {
+ return 0;
+ }
+ *ch_tgt = val;
+ } else if (*ch_src == '.') {
+ ++cnt;
+ val = 0;
+ ch_tgt++;
+ } else {
+ return 0;
+ }
+ }
+ return 1;
+ } else {
+ return MN_EAFNOSUPPORT;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/2fbc2b69/sys/mn_socket/src/test/mn_sock_test.c
----------------------------------------------------------------------
diff --git a/sys/mn_socket/src/test/mn_sock_test.c b/sys/mn_socket/src/test/mn_sock_test.c
new file mode 100644
index 0000000..a8d9cc2
--- /dev/null
+++ b/sys/mn_socket/src/test/mn_sock_test.c
@@ -0,0 +1,82 @@
+/**
+ * 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 <stdio.h>
+#include <string.h>
+
+#include <os/os.h>
+#include <testutil/testutil.h>
+
+#include "mn_socket/mn_socket.h"
+
+TEST_CASE(inet_pton_test)
+{
+ int rc;
+ uint8_t addr[8];
+ struct test_vec {
+ char *str;
+ uint8_t cmp[4];
+ };
+ struct test_vec ok_vec[] = {
+ { "1.1.1.1", { 1, 1, 1, 1 } },
+ { "1.2.3.4", { 1, 2, 3, 4 } },
+ { "010.001.255.255", { 10, 1, 255, 255 } },
+ { "001.002.005.006", { 1, 2, 5, 6 } }
+ };
+ struct test_vec invalid_vec[] = {
+ { "a.b.c.d" },
+ { "1a.b3.4.2" },
+ { "1.3.4.2a" },
+ { "1111.3.4.2" },
+ { "3.256.1.0" },
+ };
+ int i;
+
+ for (i = 0; i < sizeof(ok_vec) / sizeof(ok_vec[0]); i++) {
+ memset(addr, 0xa5, sizeof(addr));
+ rc = mn_inet_pton(MN_PF_INET, ok_vec[i].str, addr);
+ TEST_ASSERT(rc == 1);
+ TEST_ASSERT(!memcmp(ok_vec[i].cmp, addr, sizeof(uint32_t)));
+ TEST_ASSERT(addr[5] == 0xa5);
+ }
+ for (i = 0; i < sizeof(invalid_vec) / sizeof(invalid_vec[0]); i++) {
+ rc = mn_inet_pton(MN_PF_INET, invalid_vec[i].str, addr);
+ TEST_ASSERT(rc == 0);
+ }
+}
+
+TEST_SUITE(mn_socket_test_all)
+{
+ inet_pton_test();
+}
+
+#ifdef MYNEWT_SELFTEST
+
+int
+main(int argc, char **argv)
+{
+ tu_config.tc_print_results = 1;
+ tu_init();
+
+ mn_socket_test_all();
+
+ return tu_any_failed;
+}
+#endif
+