This repository has been archived by the owner on Sep 20, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #44 from smlng/coap-chat
coap-chat: a simple chat application using gCoAP
- Loading branch information
Showing
4 changed files
with
263 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# name of your application | ||
APPLICATION = coap_chat | ||
|
||
# If no BOARD is found in the environment, use this default: | ||
BOARD ?= native | ||
|
||
# This has to be the absolute path to the RIOT base directory: | ||
RIOTBASE ?= $(CURDIR)/../../RIOT | ||
|
||
USEMODULE += gnrc_netdev_default | ||
USEMODULE += auto_init_gnrc_netif | ||
# Specify the mandatory networking modules | ||
USEMODULE += gnrc_ipv6_default | ||
USEMODULE += gcoap | ||
# Additional networking modules that can be dropped if not needed | ||
USEMODULE += gnrc_icmpv6_echo | ||
# Add also the shell, some shell commands | ||
USEMODULE += shell | ||
USEMODULE += shell_commands | ||
|
||
# Comment this out to disable code in RIOT that does safety checking | ||
# which is not needed in a production environment but helps in the | ||
# development process: | ||
DEVELHELP ?= 0 | ||
|
||
# Change this to 0 show compiler invocation lines by default: | ||
QUIET ?= 1 | ||
|
||
include $(RIOTBASE)/Makefile.include |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
## About | ||
|
||
This application provides a simple command line chat using (g)CoAP as transport. | ||
It allows to send (short) messages to any (IPv6) address reachable by the node. | ||
All messages are sent to and received for a CoAP resource with path `/chat`. | ||
|
||
## Usage | ||
|
||
To send messages use the `chat` shell command, it can be invoked as follows: | ||
|
||
``` | ||
chat <destination> <nickname> <message> | ||
``` | ||
|
||
- **destination:** a reachable IPv6 address, may even be multicast `ff02::1` | ||
- **nickname:** your chat nickname, anything is allowed, but keep it short | ||
- **message:** what ever text you want to share, be brief, size is limited | ||
|
||
The message format is plain text and will be send as *nickname: message*, the | ||
maximum message size is 63 chars - so keep *nickname* and *message* short :) | ||
Please be aware that all CoAP messages are sent as non-confirmable, hence there | ||
is no retransmission in case of packet loss. | ||
|
||
## Notes | ||
|
||
The code base of this application aims for simplicity, thus it only provides | ||
a minimalistic set of functions. An advanced CoAP application can be found in | ||
the [RIOT examples](https://github.com/RIOT-OS/RIOT/tree/master/examples/gcoap). | ||
|
||
The application also ships with a number of standard shell commands, such as | ||
`ifconfig` to allow for network interface configuration. Just type `help` in | ||
the shell to see a full list and description of all available commands. | ||
|
||
By default this application is configured to run as an IPv6 node, i.e. it does | ||
not include any routing or relaying functionality - such needs to be handled | ||
by other nodes. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
/* | ||
* Copyright (c) 2018 HAW Hamburg | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser | ||
* General Public License v2.1. See the file LICENSE in the top level | ||
* directory for more details. | ||
*/ | ||
|
||
/** | ||
* @ingroup applications | ||
* @{ | ||
* | ||
* @file | ||
* @brief coap-chat - CoAP helper functions | ||
* | ||
* @author Sebastian Meiling <s@mlng.net> | ||
* | ||
* @} | ||
*/ | ||
|
||
#include <stdint.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
|
||
#include "net/gcoap.h" | ||
|
||
#define ENABLE_DEBUG (0) | ||
#include "debug.h" | ||
|
||
#define COAP_CHAT_PATH "/chat" | ||
|
||
static ssize_t _chat_handler(coap_pkt_t *pdu, uint8_t *buf, size_t len, void *ctx); | ||
|
||
/* CoAP resources */ | ||
static const coap_resource_t _resources[] = { | ||
{ COAP_CHAT_PATH, COAP_POST, _chat_handler, NULL }, | ||
}; | ||
|
||
static gcoap_listener_t _listener = { | ||
&_resources[0], | ||
sizeof(_resources) / sizeof(_resources[0]), | ||
NULL | ||
}; | ||
|
||
static ssize_t _chat_handler(coap_pkt_t *pdu, uint8_t *buf, size_t len, void *ctx) | ||
{ | ||
(void)ctx; | ||
|
||
if (pdu->payload_len > 0) { | ||
printf("\n[ CHAT ] %.*s\n\n", pdu->payload_len, (char *)pdu->payload); | ||
return gcoap_response(pdu, buf, len, COAP_CODE_CHANGED); | ||
} | ||
return gcoap_response(pdu, buf, len, COAP_CODE_BAD_REQUEST); | ||
} | ||
|
||
static size_t _send(uint8_t *buf, size_t len, char *addr_str) | ||
{ | ||
ipv6_addr_t addr; | ||
sock_udp_ep_t remote; | ||
|
||
remote.family = AF_INET6; | ||
|
||
/* parse for interface */ | ||
int iface = ipv6_addr_split_iface(addr_str); | ||
if (iface == -1) { | ||
if (gnrc_netif_numof() == 1) { | ||
/* assign the single interface found in gnrc_netif_numof() */ | ||
remote.netif = (uint16_t)gnrc_netif_iter(NULL)->pid; | ||
} | ||
else { | ||
remote.netif = SOCK_ADDR_ANY_NETIF; | ||
} | ||
} | ||
else { | ||
if (gnrc_netif_get_by_pid(iface) == NULL) { | ||
DEBUG("[CoAP] interface not valid"); | ||
return 0; | ||
} | ||
remote.netif = iface; | ||
} | ||
|
||
/* parse destination address */ | ||
if (ipv6_addr_from_str(&addr, addr_str) == NULL) { | ||
DEBUG("[CoAP] unable to parse destination address"); | ||
return 0; | ||
} | ||
if ((remote.netif == SOCK_ADDR_ANY_NETIF) && ipv6_addr_is_link_local(&addr)) { | ||
DEBUG("[CoAP] must specify interface for link local target"); | ||
return 0; | ||
} | ||
memcpy(&remote.addr.ipv6[0], &addr.u8[0], sizeof(addr.u8)); | ||
|
||
/* parse port */ | ||
remote.port = GCOAP_PORT; | ||
|
||
return gcoap_req_send2(buf, len, &remote, NULL); | ||
} | ||
|
||
int coap_post(char *addr, char *msgbuf, size_t msglen) | ||
{ | ||
assert(msglen < GCOAP_PDU_BUF_SIZE); | ||
|
||
coap_pkt_t pdu; | ||
uint8_t buf[GCOAP_PDU_BUF_SIZE]; | ||
size_t len = 0; | ||
|
||
gcoap_req_init(&pdu, buf, GCOAP_PDU_BUF_SIZE, COAP_POST, COAP_CHAT_PATH); | ||
|
||
memcpy(pdu.payload, msgbuf, msglen); | ||
|
||
len = gcoap_finish(&pdu, msglen, COAP_FORMAT_TEXT); | ||
|
||
DEBUG("[CoAP] coap_post: sending msg ID %u, %u bytes\n", | ||
coap_get_id(&pdu), (unsigned) len); | ||
|
||
if (!_send(buf, len, addr)) { | ||
puts("[CoAP] coap_post: msg send failed"); | ||
return -1; | ||
} | ||
return len; | ||
} | ||
|
||
void coap_init(void) | ||
{ | ||
gcoap_register_listener(&_listener); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
/* | ||
* Copyright (c) 2018 HAW Hamburg | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser | ||
* General Public License v2.1. See the file LICENSE in the top level | ||
* directory for more details. | ||
*/ | ||
|
||
/** | ||
* @ingroup applications | ||
* @{ | ||
* | ||
* @file | ||
* @brief coap-chat - Main loop and shell handlers | ||
* | ||
* @author Sebastian Meiling <s@mlng.net> | ||
* | ||
* @} | ||
*/ | ||
|
||
#include <stdio.h> | ||
#include "msg.h" | ||
|
||
#include "net/gcoap.h" | ||
#include "kernel_types.h" | ||
#include "shell.h" | ||
|
||
#define BUFLEN (64U) | ||
#define MAIN_QUEUE_SIZE (4) | ||
|
||
static msg_t _main_msg_queue[MAIN_QUEUE_SIZE]; | ||
|
||
extern int coap_post(const char *addr, const char *buf, size_t buflen); | ||
extern void coap_init(void); | ||
|
||
int chat(int argc, char **argv) | ||
{ | ||
if (argc < 4) { | ||
puts("usage: chat <addr> <nick> <msg>"); | ||
return 1; | ||
} | ||
|
||
char buf[BUFLEN] = { 0 }; | ||
size_t len = snprintf(buf, BUFLEN, "%s: %s", argv[2], argv[3]); | ||
for (int i = 4; i < argc; ++i) { | ||
len += snprintf(buf + len, BUFLEN - len, " %s", argv[i]); | ||
} | ||
coap_post(argv[1], buf, len); | ||
|
||
return 0; | ||
} | ||
|
||
static const shell_command_t shell_commands[] = { | ||
{ "chat", "CoAP chat", chat }, | ||
{ NULL, NULL, NULL } | ||
}; | ||
|
||
int main(void) | ||
{ | ||
/* for the thread running the shell */ | ||
msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE); | ||
/* init coap listener */ | ||
coap_init(); | ||
/* start shell */ | ||
puts("All up, running the shell now"); | ||
char line_buf[SHELL_DEFAULT_BUFSIZE]; | ||
shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); | ||
|
||
/* should never be reached */ | ||
return 0; | ||
} |