samples/net: Add network-related functions to MQTT Publisher

Add TCP/IPv4 routines to this sample.

This MQTT sample code demonstrates how to implement an MQTT publisher
application.

For network application development, see:

* samples/net/echo_server
* samples/net/echo_client

Change-Id: I13ac5ca1da2cd4d984fb595b599c3eab4edc5bf0
Signed-off-by: Flavio Santes <flavio.santes@intel.com>
This commit is contained in:
Flavio Santes 2016-07-29 15:49:51 -05:00 committed by Andrew Boie
commit 8ba4f26e5f
7 changed files with 417 additions and 5 deletions

View file

@ -12,8 +12,6 @@ CONFIG_NETWORKING_IPV6_NO_ND=y
CONFIG_IP_BUF_RX_SIZE=4
CONFIG_IP_BUF_TX_SIZE=4
CONFIG_NETZ=y
# Uncomment the following variables for debugging
#CONFIG_NETWORKING_WITH_LOGGING=y

View file

@ -14,6 +14,12 @@
# limitations under the License.
#
obj-y += mqtt.o
ccflags-y +=-I${ZEPHYR_BASE}/net/ip/contiki
ccflags-y +=-I${ZEPHYR_BASE}/net/ip/contiki/os/lib
ccflags-y +=-I${ZEPHYR_BASE}/net/ip/contiki/os
ccflags-y +=-I${ZEPHYR_BASE}/net/ip
obj-y += mqtt_pack.o
obj-y += netz.o
obj-y += mqtt.o
obj-y += main.o

View file

@ -0,0 +1,19 @@
#ifndef _APP_BUF_H_
#define _APP_BUF_H_
#include <zephyr.h> /* for __deprecated */
#include <stdint.h>
#include <stddef.h>
struct __deprecated app_buf_t;
struct app_buf_t {
uint8_t *buf;
size_t size;
size_t length;
};
#define APP_BUF_INIT(_buf, _size, _length) {.buf = _buf, .size = _size,\
.length = _length}
#endif

View file

@ -17,7 +17,7 @@
#ifndef _MQTT_H_
#define _MQTT_H_
#include <netz.h>
#include "netz.h"
#include "mqtt_pack.h"
/**

View file

@ -17,7 +17,10 @@
#ifndef _MQTT_PKT_H_
#define _MQTT_PKT_H_
#include <app_buf.h>
#include <stdint.h>
#include <stddef.h>
#include "app_buf.h"
/**
* @brief MQTT Packet Type

View file

@ -0,0 +1,223 @@
/*
* Copyright (c) 2016 Intel Corporation
*
* Licensed 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 <netz.h>
#include <net/net_core.h>
#include <net/net_socket.h>
#include <string.h>
#include <errno.h>
void netz_host(struct netz_ctx_t *ctx, struct net_addr *host)
{
return netz_host_ipv4(ctx, host->in_addr.in4_u.u4_addr8[0],
host->in_addr.in4_u.u4_addr8[1],
host->in_addr.in4_u.u4_addr8[2],
host->in_addr.in4_u.u4_addr8[3]);
}
void netz_host_ipv4(struct netz_ctx_t *ctx, uint8_t a1, uint8_t a2,
uint8_t a3, uint8_t a4)
{
uip_ipaddr_t host_addr;
uip_ipaddr(&host_addr, a1, a2, a3, a4);
uip_sethostaddr(&host_addr);
ctx->host.in_addr.in4_u.u4_addr8[0] = a1;
ctx->host.in_addr.in4_u.u4_addr8[1] = a2;
ctx->host.in_addr.in4_u.u4_addr8[2] = a3;
ctx->host.in_addr.in4_u.u4_addr8[3] = a4;
ctx->host.family = AF_INET;
}
void netz_netmask(struct netz_ctx_t *ctx, struct net_addr *netmask)
{
return netz_netmask_ipv4(ctx, netmask->in_addr.in4_u.u4_addr8[0],
netmask->in_addr.in4_u.u4_addr8[1],
netmask->in_addr.in4_u.u4_addr8[2],
netmask->in_addr.in4_u.u4_addr8[3]);
}
void netz_netmask_ipv4(struct netz_ctx_t *ctx, uint8_t n1, uint8_t n2,
uint8_t n3, uint8_t n4)
{
ARG_UNUSED(ctx);
uip_ipaddr_t netmask;
uip_ipaddr(&netmask, n1, n2, n3, n4);
uip_setnetmask(&netmask);
}
void netz_remote(struct netz_ctx_t *ctx, struct net_addr *remote, int port)
{
return netz_remote_ipv4(ctx, remote->in_addr.in4_u.u4_addr8[0],
remote->in_addr.in4_u.u4_addr8[1],
remote->in_addr.in4_u.u4_addr8[2],
remote->in_addr.in4_u.u4_addr8[3], port);
}
void netz_remote_ipv4(struct netz_ctx_t *ctx, uint8_t a1, uint8_t a2,
uint8_t a3, uint8_t a4, int port)
{
ctx->remote.in_addr.in4_u.u4_addr8[0] = a1;
ctx->remote.in_addr.in4_u.u4_addr8[1] = a2;
ctx->remote.in_addr.in4_u.u4_addr8[2] = a3;
ctx->remote.in_addr.in4_u.u4_addr8[3] = a4;
ctx->remote.family = AF_INET;
ctx->remote_port = port;
}
static int netz_prepare(struct netz_ctx_t *ctx, enum ip_protocol proto)
{
#ifdef CONFIG_NETWORKING_WITH_TCP
struct app_buf_t buf = APP_BUF_INIT(NULL, 0, 0);
int rc;
#endif
ctx->connected = 0;
ctx->proto = proto;
ctx->net_ctx = net_context_get(ctx->proto,
&ctx->remote, ctx->remote_port,
&ctx->host, 0);
if (ctx->net_ctx == NULL) {
return -EINVAL;
}
#ifdef CONFIG_NETWORKING_WITH_TCP
/* workaround to activate the IP stack */
rc = netz_tx(ctx, &buf);
if (rc != 0) {
return rc;
}
#endif
ctx->connected = 1;
return 0;
}
int netz_tcp(struct netz_ctx_t *ctx)
{
return netz_prepare(ctx, IPPROTO_TCP);
}
int netz_udp(struct netz_ctx_t *ctx)
{
return netz_prepare(ctx, IPPROTO_UDP);
}
static void netz_sleep(int sleep_ticks)
{
struct nano_timer timer;
nano_timer_init(&timer, NULL);
nano_fiber_timer_start(&timer, sleep_ticks);
nano_fiber_timer_test(&timer, TICKS_UNLIMITED);
}
static int tcp_tx(struct net_context *ctx, uint8_t *buf, size_t size,
int tx_retry_timeout)
{
struct net_buf *nbuf;
uint8_t *ptr;
int rc;
nbuf = ip_buf_get_tx(ctx);
if (nbuf == NULL) {
return -EINVAL;
}
ptr = net_buf_add(nbuf, size);
memcpy(ptr, buf, size);
ip_buf_appdatalen(nbuf) = size;
do {
rc = net_send(nbuf);
if (rc >= 0) {
ip_buf_unref(nbuf);
return 0;
}
switch (rc) {
case -EINPROGRESS:
netz_sleep(tx_retry_timeout);
break;
case -EAGAIN:
case -ECONNRESET:
netz_sleep(tx_retry_timeout);
break;
default:
ip_buf_unref(nbuf);
return -EIO;
}
} while (1);
return 0;
}
static int tcp_rx(struct net_context *ctx, uint8_t *buf, size_t *read_bytes,
size_t size, int rx_timeout)
{
struct net_buf *nbuf;
int rc;
nbuf = net_receive(ctx, rx_timeout);
if (nbuf == NULL) {
return -EIO;
}
*read_bytes = ip_buf_appdatalen(nbuf);
if (*read_bytes > size) {
*read_bytes = size;
rc = -ENOMEM;
} else {
rc = 0;
}
memcpy(buf, ip_buf_appdata(nbuf), *read_bytes);
ip_buf_unref(nbuf);
return rc;
}
int netz_tx(struct netz_ctx_t *ctx, struct app_buf_t *buf)
{
int rc;
/* We don't evaluate if we are connected. */
rc = tcp_tx(ctx->net_ctx, buf->buf, buf->length,
ctx->tx_retry_timeout);
return rc;
}
int netz_rx(struct netz_ctx_t *ctx, struct app_buf_t *buf)
{
int rc;
if (ctx->connected != 1) {
return -ENOTCONN;
}
rc = tcp_rx(ctx->net_ctx, buf->buf, &buf->length, buf->size,
ctx->rx_timeout);
return rc;
}

View file

@ -0,0 +1,163 @@
/*
* Copyright (c) 2016 Intel Corporation
*
* Licensed 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 _NETZ_H_
#define _NETZ_H_
#include <net/ip_buf.h>
#include <net/net_core.h>
#include "app_buf.h"
struct __deprecated netz_ctx_t;
struct netz_ctx_t {
struct net_context *net_ctx;
int connected;
int rx_timeout;
int tx_retry_timeout;
struct net_addr host;
int host_port;
struct net_addr remote;
int remote_port;
enum ip_protocol proto;
};
#define TCP_COMMON_TIMEOUT 20
/**
* @brief NETZ_CTX_INIT Initializes a netz context with default values
*/
#define NETZ_CTX_INIT { .rx_timeout = TCP_COMMON_TIMEOUT, \
.tx_retry_timeout = TCP_COMMON_TIMEOUT, \
.net_ctx = NULL, \
.connected = 0, \
.proto = IPPROTO_UDP, \
.host_port = 0, \
.remote_port = 0}
/**
* @brief NET_ADDR_IPV4_INIT Initializes a net_addr structure with
* an IPv4 address specified by a1, a2, a3 and a4
*/
#define NET_ADDR_IPV4_INIT(a1, a2, a3, a4) {.in_addr.in4_u.u4_addr8[0] = (a1),\
.in_addr.in4_u.u4_addr8[1] = (a2),\
.in_addr.in4_u.u4_addr8[2] = (a3),\
.in_addr.in4_u.u4_addr8[3] = (a4),\
.family = AF_INET}
/**
* @brief netz_host Sets the host IPv4 address (no IPv6 support)
* @param ctx netz context structure
* @param host Network address
*/
void __deprecated netz_host(struct netz_ctx_t *ctx, struct net_addr *host);
/**
* @brief netz_host_ipv4 Sets the host IPv4 address (no IPv6 support)
* @param ctx netz context structure
* @param a1 Byte 0 of the IPv4 address
* @param a2 Byte 1 of the IPv4 address
* @param a3 Byte 2 of the IPv4 address
* @param a4 Byte 3 of the IPv4 address
*/
void __deprecated netz_host_ipv4(struct netz_ctx_t *ctx, uint8_t a1,
uint8_t a2, uint8_t a3, uint8_t a4);
/**
* @brief netz_netmask Sets the host's netmask address
* @param ctx netz context structure
* @param netmask Network address to be used as netmask
*/
void __deprecated netz_netmask(struct netz_ctx_t *ctx,
struct net_addr *netmask);
/**
* @brief netz_netmask_ipv4 Sets the host's netmask IPv4 address
* @param ctx netz context structure
* @param n1 Byte 0 of the IPv4 address
* @param n2 Byte 1 of the IPv4 address
* @param n3 Byte 2 of the IPv4 address
* @param n4 Byte 3 of the IPv4 address
*/
void __deprecated netz_netmask_ipv4(struct netz_ctx_t *ctx, uint8_t n1,
uint8_t n2, uint8_t n3, uint8_t n4);
/**
* @brief netz_remote Sets the address of the remote peer
* @param ctx netz context structure
* @param remote Network address of the remote peer
* @param port Port number of the remote peer
*/
void __deprecated netz_remote(struct netz_ctx_t *ctx, struct net_addr *remote,
int port);
/**
* @brief netz_remote_ipv4 Sets the IPv4 address of the remote peer
* @param ctx netz context structure
* @param a1 Byte 0 of the IPv4 address
* @param a2 Byte 1 of the IPv4 address
* @param a3 Byte 2 of the IPv4 address
* @param a4 Byte 3 of the IPv4 address
*/
void __deprecated netz_remote_ipv4(struct netz_ctx_t *ctx, uint8_t a1,
uint8_t a2, uint8_t a3, uint8_t a4,
int port);
/**
* @brief netz_tcp Initializes the netz context & connects
* to the remote peer
* @param ctx netz context structure
* @return 0 on success
* @return -EINVAL if a null context was obtained
* @return Read netz_tx return codes
*/
int __deprecated netz_tcp(struct netz_ctx_t *ctx);
/**
* @brief netz_udp Initializes the context for UDP transfers
* @param ctx netz context structure
* @return 0 on success
* @return -EINVAL if a null context was obtained
*/
int __deprecated netz_udp(struct netz_ctx_t *ctx);
/**
* @brief netz_tx TCP/UDP data transmission
* @param ctx netz context structure
* @param buf Buffer that contains the data to be sent
* @return 0 on success
* @return -EINVAL if no network buffer is available
* @return -EIO if a TCP error was detected
*/
int __deprecated netz_tx(struct netz_ctx_t *ctx, struct app_buf_t *buf);
/**
* @brief netz_rx TCP/UDP data reception
* @param ctx netz context structure
* @param buf Buffer that contains the received data
* @return 0 on success
* @return -EIO on TCP or network buffer error
* @return -ENOMEM if the space in buf is not enough
* to store the received data
*/
int __deprecated netz_rx(struct netz_ctx_t *ctx, struct app_buf_t *buf);
#endif