Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: NetServices MSCUsbHost mbed TMP102 SDFileSystem
Diff: nfuncs.cpp
- Revision:
- 0:67a55a82ce06
diff -r 000000000000 -r 67a55a82ce06 nfuncs.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nfuncs.cpp Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,382 @@
+/* MMEx for MBED - Network Command processing
+ * Copyright (c) 2011 MK
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/**
+ \file nfuncs.cpp
+ \brief Commands starting with N for Networking commands
+*/
+
+#include "nfuncs.h"
+
+EthernetNetIf *eth;
+HTTPClient http;
+HTTPResult result;
+HTTPServer *server;
+bool completed = false;
+
+/**
+ * Global variable to indicate if network is running
+ */
+bool network_enabled = false;
+
+/**
+ * Global variable to indicate if HTTP Server is running
+ */
+bool httpserver_enabled = false;
+
+/**
+ * Poll the network (must be called periodically while server is active)
+ */
+void netpoll()
+{
+ if (network_enabled) {
+ _led3 = 1;
+ Net::poll();
+ _led3 = 0;
+ }
+}
+
+/** main entry for parsing C-commands
+ *
+ */
+void parse_N() {
+ // process parameters
+ DBG_msg("parse_N", inbuf);
+ err_num = noerror;
+
+ wipesp(inbuf); // remove all spaces from string
+
+ if (inbuf[1] != NULL) {
+ switch (inbuf[1]) {
+ case ninit : do_ninit();
+ break;
+ case nstop : do_nstop();
+ break;
+ case ntime : do_ntime();
+ break;
+ case nget : do_nget();
+ break;
+ case nhttp : do_nhttp();
+ break;
+ default : do_ndefault(); // command not recognized
+ break;
+ }
+ } else { do_ndefault(); }
+}
+
+/** initialize the network interface
+ *
+ * syntax: NI
+ */
+void do_ninit() {
+ char * hostname;
+ char * ipnums;
+ char s[50];
+ char ips[4][25];
+
+ DBG_msg("do_ninit", "Network initialisation\n");
+
+ EthernetErr ethErr;
+
+ // check for alternate hostname in parameters
+ hostname = new char [param[par_H_].size() + 1]; // Host parameter
+ strcpy (hostname, param[par_H_].c_str());
+ if (hostname == NULL) hostname = MMEx_Hostname;
+
+ // check for DCHP or not
+ // Parameter J is the fixed IP address in the following format:
+ // ip netmask gateway dns
+ // each ip address is in the format x.y.z.t, separated by spaces
+ // When Param J is empty, DHCP will be used
+ ipnums = new char [param[par_J_].size() + 1]; // Host parameter
+ strcpy (ipnums, param[par_J_].c_str());
+
+
+ if (param[par_J_].size()< 10) {
+ DBG_msg("do_ninit", "DHCP config");
+ // DHCP chosen, initialize network
+ eth = new EthernetNetIf(hostname);
+
+ // eth->setup();
+ } else {
+ // process fixed IP adresses
+ DBG_msg("do_ninit", "fixed IP");
+ DBG_msg("IP adresses", ipnums);
+
+ IpAddr *ipparam[4];
+ sscanf(ipnums, "%s %s %s %s", ips[0], ips[1], ips[2], ips[3]);
+ DBG_msg("IP number", ips[0]);
+ DBG_msg("netmask ", ips[1]);
+ DBG_msg("gateway ", ips[2]);
+ DBG_msg("dns ", ips[3]);
+
+ for ( int i = 0; i < 4; ++i ) {
+ int ip1, ip2, ip3, ip4;
+ sscanf(ips[i], "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4);
+ ipparam[i] = new IpAddr(ip1, ip2, ip3, ip4);
+ }
+ // Setup IP with given adresses
+ eth = new EthernetNetIf(*ipparam[0],*ipparam[1],*ipparam[2],*ipparam[3]);
+ // eth->setup();
+ }
+
+ int count = 0;
+ do {
+ DBG_int("do_ninit setup", ++count);
+ ethErr = eth->setup();
+ if (ethErr) DBG_int("do_ninit timeout", ethErr);
+ } while ((ethErr != ETH_OK) && (count < 5));
+
+ if (ethErr == ETH_OK) {
+ // connection worked
+ network_enabled = true;
+ mldl.attach(&netpoll);
+ DBG_msg("do_ninit", "Connected OK\n");
+ const char* hwAddr = eth->getHwAddr();
+ sprintf(s, "%02x:%02x:%02x:%02x:%02x:%02x",
+ hwAddr[0], hwAddr[1], hwAddr[2], hwAddr[3], hwAddr[4], hwAddr[5]);
+ DBG_msg("ninit MAC addr", s);
+ param[par_M_].assign(s); // set MAC address
+
+ IpAddr ethIp = eth->getIp();
+ sprintf(s, "%d.%d.%d.%d", ethIp[0], ethIp[1], ethIp[2], ethIp[3]);
+ upstring(s);
+ DBG_msg("ninit MAC addr", s);
+ param[par_I_].assign(s); // set MAC address
+
+ sprintf(s, "%s", eth->getHostname());
+ DBG_msg("ninit Hostname", s);
+ param[par_H_].assign(s); // set Hostname
+ } else {
+ // in case initialization did not work
+ network_enabled = false;
+ DBG_msg("ninit", "network timout");
+ send_error(err_net_timeout);
+ }
+}
+
+/** stop the network interface
+ *
+ * syntax: NS
+ */
+void do_nstop() {
+ DBG_msg("do_nstop", inbuf);
+ mldl.attach(NULL);
+ delete eth;
+ network_enabled = false;
+}
+
+/** get network time
+ *
+ * syntax: NT
+ * URL of NTP server must be in parameter U
+ */
+void do_ntime() {
+ char s[255]; // for intermediate results
+ char s1[255]; // for intermediate results
+ time_t ctTime;
+ NTPClient ntp;
+ DBG_msg("do_ntime", inbuf);
+
+ ctTime = time(NULL); // current system time
+ sprintf(s, "%d %s", ctTime, ctime(&ctTime));
+ DBG_msg("MMEx time", s);
+ strcpy(s, param[par_U_].c_str()); // URL from parameter U
+
+ Host server(IpAddr(), 123, s);
+ NTPResult r = ntp.setTime(server);
+ if (r == NTP_OK) {
+ // time set
+ ctTime = time(NULL);
+ sprintf(s1, "%d %s", ctTime, ctime(&ctTime));
+ DBG_msg("MMEx time", s1);
+ } else {
+ // error in setting the time
+ send_error(err_net_NTP);
+ }
+}
+
+
+void request_callback(HTTPResult r) {
+ result = r;
+ completed = true;
+}
+
+/** get file through HTTP Stream
+ *
+ * syntax: NG
+ * URL of must be in parameter U, %n may be used for filename
+ */
+void do_nget() {
+
+ HTTPStream stream;
+ char Buf[512 + 1] = {0};
+ char s[255]; // for temp storage
+ int pnum, pos, count;
+ char * cstr;
+ int rdata, i;
+ bool go = true;
+ bool stopread = false;
+ int numbytes = 0;
+
+ DBG_msg("do_nget", inbuf);
+
+ completed = false;
+
+ count = 0;
+ // next chars on the commandline is the number of bytes to read
+ if (inbuf[2] == NULL) {
+ // no value on the command line
+ numbytes = 0;
+ } else {
+ // now process line
+ for (i = 2; ((inbuf[i] >='0') && (inbuf[i] <= '9')); i++ ) {
+ numbytes = 10 * numbytes + (inbuf[i] - '0');
+ }
+ }
+ DBG_int("do_nget bytes:", numbytes);
+
+ stream.readNext((byte*)Buf, 512); //Point to buffer for the first read
+ strcpy(s, param[par_U_].c_str()); // URL from parameter U
+
+ // check for a % sign in s
+ pos = 0;
+ while ((s[pos] != NULL) && (s[pos] != c_percent)) pos++;
+ if ((s[pos] != NULL) && ((pnum = getpnum(s[pos + 1])) >= 0)) {
+ // found and valid parameter, now insert
+ cstr = new char [param[pnum].size() + 1];
+ strcpy (cstr, param[pnum].c_str());
+ DBG_msg("param", cstr);
+ DBG_int("pos", pos);
+ remchar(s, pos, 2); // remove %n, works better for insert
+ DBG_msg("do_nget", s);
+ insertstr(s, cstr, pos); // insert
+ DBG_msg("do_nget", s);
+ delete[] cstr;
+ }
+
+ HTTPResult r = http.get(s, &stream, request_callback); // try to get the data
+
+ // this is the main loop for reading the file
+ while((!completed)) {
+ Net::poll(); // polls the Networking stack
+ if(stream.readable()) {
+ rdata = stream.readLen(); // number of bytes read
+ DBG_int("rdata", rdata);
+ Buf[stream.readLen()] = 0; //Transform this buffer in zero-terminated char* string
+
+ // now send data to our transmit buffer
+ i = 0;
+ while (go && (i < rdata)) {
+ DBG_chr("rd", Buf[i]);
+ mldl.tx_addp(Buf[i]);
+ i++;
+ count++;
+ // now check if we have to stop?
+ if (!mldl.rx_empty()) {
+ stopread = (mldl.rxx_read(data_mode) < 0); // intentional stop of read
+ DBG_msg("do_nget", "forced stop");
+ }
+ go = !((count == numbytes) || stopread);
+ }
+
+ //Buffer has been read, now we can put more data in it
+ stream.readNext((byte*)Buf, 512);
+ }
+ }
+
+ // we are done with the required number of bytes or found EOF
+ if (!stopread && (count != numbytes)) {
+ // real EOF found, so terminate by sending EOF
+ mldl.tx_add(c_escape);
+ mldl.tx_add(c_eof);
+ DBG_int("do_nget: EOF at byte ", count);
+ }
+
+ if (stopread) {
+ DBG_msg("do_nget", "forced stop read received");
+ mldl.flush_tx(); // empty transmit buffer
+ }
+
+ DBG_int("do_nget: end read at byte ", count);
+}
+
+/** HTTP Server commands
+ *
+ * syntax: NHI[medium]: initialise and start HTTP Server
+ * [medium] = S, U or L for the filesystem to be used
+ * default filesystem is "/local"
+ * \n NHS: stop HTTP Server
+ *
+ */
+void do_nhttp() {
+ char c;
+ char medium[10];
+
+ DBG_msg("do_nhttp", inbuf);
+
+ c = inbuf[3]; // [medium]
+ switch (c) {
+ case f_sdcard : strcpy(medium, rt_sd); // "/sd"
+ break;
+ case f_local : strcpy(medium, rt_local); // "/local"
+ break;
+ case f_usb : strcpy(medium, rt_usb); // "/usb"
+ break;
+ default : strcpy(medium, "/local"); // default
+ break;
+ }
+
+ if (inbuf[2] == ninit) {
+ // HTTP server initialize
+ DBG_msg("HTTP Init", medium);
+ if (!network_enabled) do_ninit();
+ server = new HTTPServer;
+ FSHandler::mount(medium, "/" );
+ server->addHandler<FSHandler>("/");
+ server->addHandler<RPCHandler>("/rpc");
+ server->addHandler<SimpleHandler>("/simple");
+ server->bind(80);
+ httpserver_enabled = true;
+ DBG_msg( "HTTP server", "started" );
+ return;
+ }
+
+ if (inbuf[2] == nstop) {
+ // HTTP Server stop
+ delete server;
+ httpserver_enabled = false;
+ DBG_msg( "HTTP server", "stopped" );
+ return;
+ }
+
+ do_ndefault();
+}
+
+/** send error message, command not recognized
+ *
+ */
+void do_ndefault() {
+ // command not recognized
+ DBG_msg("do_ndefault", inbuf);
+ send_error(err_notrecognized);
+}
\ No newline at end of file