Contiki 3.x
shell-rime-netcmd.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008, Swedish Institute of Computer Science.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  */
32 
33 /**
34  * \file
35  * A brief description of what this file is.
36  * \author
37  * Adam Dunkels <adam@sics.se>
38  */
39 
40 #include "contiki.h"
41 #include "contiki-conf.h"
42 #include "shell-rime.h"
43 
44 #include "dev/leds.h"
45 
46 #include "lib/crc16.h"
47 #include "lib/random.h"
48 
49 #include "net/rime/rime.h"
50 #include "net/rime/route.h"
51 #include "net/rime/trickle.h"
52 
53 #include "net/rime/timesynch.h"
54 
55 #if CONTIKI_TARGET_NETSIM
56 #include "ether.h"
57 #endif /* CONTIKI_TARGET_NETSIM */
58 
59 #include <stdio.h>
60 #ifndef HAVE_SNPRINTF
61 int snprintf(char *str, size_t size, const char *format, ...);
62 #endif /* HAVE_SNPRINTF */
63 #include <string.h>
64 
65 
66 #define COLLECT_REXMITS 4
67 
68 #define TRICKLEMSG_HDR_SIZE 2
69 
70 struct trickle_msg {
71  uint16_t crc;
72  char netcmd[1];
73 };
74 
75 static struct trickle_conn trickle;
76 /*---------------------------------------------------------------------------*/
77 PROCESS(shell_netcmd_process, "netcmd");
78 PROCESS(shell_netcmd_server_process, "netcmd server");
79 SHELL_COMMAND(netcmd_command,
80  "netcmd",
81  "netcmd <command>: run a command on all nodes in the network",
82  &shell_netcmd_process);
83 /*---------------------------------------------------------------------------*/
84 PROCESS_THREAD(shell_netcmd_server_process, ev, data)
85 {
86  static struct process *child_command;
87  int err;
88  PROCESS_BEGIN();
89 
90  /* XXX: direct output to null. */
91  printf("netcmd server got command string '%s'\n", (char *)data);
92  err = shell_start_command(data, strlen((char * )data), NULL, &child_command);
93  if(err == SHELL_FOREGROUND && process_is_running(child_command)) {
94  PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_EXIT ||
95  (ev == PROCESS_EVENT_EXITED &&
96  data == child_command));
97  if(ev == PROCESS_EVENT_EXIT) {
98  process_exit(child_command);
99  }
100  }
101 
102  PROCESS_END();
103 }
104 /*---------------------------------------------------------------------------*/
105 PROCESS_THREAD(shell_netcmd_process, ev, data)
106 {
107  struct trickle_msg *msg;
108  int len;
109 
110  PROCESS_BEGIN();
111 
112  /* Get the length of the command line, excluding a terminating NUL character. */
113  len = strlen((char *)data);
114 
115  /* Check the length of the command line to see that it is small
116  enough to fit in a packet. We count with 32 bytes of header,
117  which may be a little too much, but at least we are on the safe
118  side. */
119  if(len > PACKETBUF_SIZE - 32) {
120  char buf[32];
121  snprintf(buf, sizeof(buf), "%d", len);
122  shell_output_str(&netcmd_command, "command line too large: ", buf);
123  } else {
124 
125  packetbuf_clear();
126  msg = packetbuf_dataptr();
127  packetbuf_set_datalen(len + 1 + TRICKLEMSG_HDR_SIZE);
128  strcpy(msg->netcmd, data);
129 
130  /* Terminate the string with a NUL character. */
131  msg->netcmd[len] = 0;
132  msg->crc = crc16_data(msg->netcmd, len, 0);
133  printf("netcmd sending '%s'\n", msg->netcmd);
134  trickle_send(&trickle);
135  }
136 
137  PROCESS_END();
138 }
139 /*---------------------------------------------------------------------------*/
140 static void
141 recv_trickle(struct trickle_conn *c)
142 {
143  struct trickle_msg *msg;
144  uint16_t crc;
145  int len;
146 
147  msg = packetbuf_dataptr();
148 
149  if(packetbuf_datalen() > 1 + TRICKLEMSG_HDR_SIZE) {
150 
151  /* First ensure that the old process is killed. */
152  process_exit(&shell_netcmd_server_process);
153 
154  len = packetbuf_datalen() - 1 - TRICKLEMSG_HDR_SIZE;
155 
156  /* Make sure that the incoming command is null-terminated. */
157  msg->netcmd[len] = 0;
158  memcpy(&crc, &msg->crc, sizeof(crc));
159 
160  if(crc == crc16_data(msg->netcmd, len, 0)) {
161  /* Start the server process with the incoming command. */
162  process_start(&shell_netcmd_server_process, (void *)msg->netcmd);
163  }
164  }
165 }
166 const static struct trickle_callbacks trickle_callbacks = { recv_trickle };
167 /*---------------------------------------------------------------------------*/
168 void
169 shell_rime_netcmd_init(void)
170 {
171  trickle_open(&trickle, CLOCK_SECOND * 4, SHELL_RIME_CHANNEL_NETCMD,
172  &trickle_callbacks);
173  shell_register_command(&netcmd_command);
174 }
175 /*---------------------------------------------------------------------------*/
int process_is_running(struct process *p)
Check if a process is running.
Definition: process.c:383
void shell_output_str(struct shell_command *c, char *text1, const char *text2)
Output strings from a shell command.
Definition: shell.c:383
int shell_start_command(char *commandline, int commandline_len, struct shell_command *child, struct process **started_process)
Start a shell command from another shell command.
Definition: shell.c:308
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition: process.h:120
#define NULL
The null pointer.
Header file for a simple time synchronization mechanism
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
Definition: packetbuf.c:200
Header file for the Rime stack
uint16_t packetbuf_datalen(void)
Get the length of the data in the packetbuf.
Definition: packetbuf.c:239
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
Definition: process.h:273
#define PROCESS_END()
Define the end of a process.
Definition: process.h:131
void shell_register_command(struct shell_command *c)
Register a command with the shell.
Definition: shell.c:413
#define PROCESS_WAIT_EVENT_UNTIL(c)
Wait for an event to be posted to the process, with an extra condition.
Definition: process.h:157
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
void packetbuf_clear(void)
Clear and reset the packetbuf.
Definition: packetbuf.c:77
void process_start(struct process *p, process_data_t data)
Start a process.
Definition: process.c:99
A brief description of what this file is.
Header file for Trickle (reliable single source flooding) for Rime
#define PACKETBUF_SIZE
The size of the packetbuf, in bytes.
Definition: packetbuf.h:65
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
Definition: packetbuf.c:207
Header file for the CRC16 calculcation
unsigned short crc16_data(const unsigned char *data, int len, unsigned short acc)
Calculate the CRC16 over a data area.
Definition: crc16.c:66
void process_exit(struct process *p)
Cause a process to exit.
Definition: process.c:202
#define SHELL_COMMAND(name, command, description, process)
Define a shell command.
Definition: shell.h:219
Header file for the Rime route table
#define CLOCK_SECOND
A second, measured in system clock time.
Definition: clock.h:82