Roy van Dam / Mbed 2 deprecated NetRelais

Dependencies:   EthernetInterface NetworkAPI mbed-rtos mbed

Fork of NetRelais by Roy van Dam

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers controller.cpp Source File

controller.cpp

00001 /**
00002  * Copyright (c) 2012, Roy van Dam <roy@vandam-innovations.com>
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright notice, this
00009  *    list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright notice,
00011  *    this list of conditions and the following disclaimer in the documentation
00012  *    and/or other materials provided with the distribution.
00013  *
00014  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00015  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00016  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00017  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
00018  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00019  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00020  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00021  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00022  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00023  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00024  */
00025 
00026 #include "controller.hpp"
00027 
00028 Controller::~Controller()
00029 {
00030     this->stop();
00031 }
00032 
00033 int
00034 Controller::start(int port, int max_pending)
00035 {
00036     if (this->_network.server.open() < 0) {
00037         printf("Could not open server socket.\n\r");
00038         return -1;
00039     }
00040     
00041     if (this->_network.server.bind(port) < 0) {
00042         printf("Could not bind server socket to port '%d'.\n\r", port);
00043         return -1;
00044     }
00045     
00046     if (this->_network.server.listen(max_pending) < 0) {
00047         printf("Could not put server socket into listening mode.\n\r");
00048         return -1;
00049     }
00050     
00051     return 0;
00052 }
00053 
00054 int
00055 Controller::stop()
00056 {
00057     this->_network.server.close();
00058     this->_network.client.close();
00059     return 0;
00060 }
00061 
00062 int
00063 Controller::dispatch()
00064 {
00065     int result = 0;
00066     network::Buffer buffer(256);
00067 
00068     while (this->_network.server.getStatus() == network::Socket::Listening) {
00069         if (this->_network.server.accept(this->_network.client) < 0) {
00070             printf("Warning: failed to accept connection.\n\r");
00071             continue;
00072         }
00073                         
00074         printf("Client connected '%s:%d'.\n\r",
00075             this->_network.client.getRemoteEndpoint().getAddress().toString().c_str(),
00076             this->_network.client.getRemoteEndpoint().getPort());
00077         
00078         while (this->_network.client.getStatus() == network::Socket::Connected) {
00079             buffer.flush();
00080             
00081             switch (this->_network.client.read(buffer)) {
00082                 case -1:
00083                     printf("Warning: failed to read data from client.\n\r");
00084                     break;
00085                 
00086                 case 0:
00087                     printf("Connection closed.\n\r");
00088                     break;
00089                 
00090                 default:
00091                     printf("Received %d bytes.\n\r%s\r", buffer.length(), (char *)buffer.data());
00092                     
00093                     // Parse command
00094                     result = this->_parseCommand(buffer);
00095     
00096                     // Format reply code
00097                     buffer.flush();
00098                     buffer.length(std::snprintf(
00099                         (char *)buffer.data(), buffer.size(),
00100                         "e;%i;", result));
00101                    
00102                     if (buffer.length() < 4) {
00103                         printf("Warning: failed to format error reply.\n\r");
00104                         continue;
00105                     }
00106                     
00107                     if (this->_network.client.write(buffer) < 0) {
00108                         printf("Warning: failed to reply.\n\r");
00109                     }
00110                     continue;
00111             }
00112             
00113             this->_network.client.shutdown();
00114             this->_network.client.close();
00115         }
00116     }
00117     
00118     return 0;
00119 }
00120 
00121 int
00122 Controller::_parseCommand(network::Buffer &buffer)
00123 {
00124     int index = 0;
00125     network::Buffer response(32);
00126     char *cursor = (char *)buffer.data();
00127     
00128     enum Controller::ParseState state = Controller::S_Init;
00129     enum Controller::Command command = Controller::C_None;
00130     
00131     while (cursor != NULL) {
00132         switch (state) {
00133             case Controller::S_Init: {
00134                 if (((*cursor) == 'r') && ((*(cursor + 1)) == ':')) {
00135                     command = Controller::C_Read;
00136                     state = Controller::S_Index;
00137                     cursor += 2;
00138                     continue;
00139                 }
00140                 
00141                 if (((*cursor) == 'w') && ((*(cursor + 1)) == ':')) {
00142                     command = Controller::C_Write;
00143                     state = Controller::S_Index;
00144                     cursor += 2;
00145                     continue;
00146                 }
00147                 
00148                 return Controller::E_InvalidCommand;
00149             }
00150             
00151             case Controller::S_Index: {
00152                 if (std::sscanf(cursor, "%d;", &index) != 1) {
00153                     return Controller::E_InvalidFormat;
00154                 }
00155                 
00156                 char *offset;
00157                 switch (command) {
00158                     case Controller::C_Read: {
00159                         offset = std::strchr(cursor, ';');
00160                         break;
00161                     }
00162                     
00163                     case Controller::C_Write: {
00164                         offset = std::strchr(cursor, ':');
00165                         break;
00166                     }
00167                 }
00168                 
00169                 if (offset == NULL) {
00170                     return Controller::E_InvalidFormat;
00171                 }
00172                 
00173                 cursor = offset + 1;
00174                 state = Controller::S_Execute;
00175                 continue;
00176             }
00177             
00178             case Controller::S_Execute: {
00179                 switch (command) {
00180                     case Controller::C_Read: {
00181                         DigitalIn *input = this->getInput(index);
00182                         if (input == NULL) {
00183                             return Controller::E_UnknownIndex;
00184                         }
00185                         
00186                         response.length(std::snprintf(
00187                             (char *)response.data(), response.size(),
00188                             "r:%d:%d;", index, input->read()));
00189                        
00190                         if (response.length() < 6) {
00191                             printf("Warning: failed to format reply.\n\r");
00192                             return Controller::E_Internal;
00193                         }
00194                         
00195                         if (this->_network.client.write(response) < 0) {
00196                             printf("Warning: failed to reply on read request.\n\r");
00197                             return Controller::E_Internal;
00198                         }
00199                         
00200                         if ((*cursor) == 0 || (*(cursor + 1)) == 0) {
00201                             return 0;
00202                         }
00203                         
00204                         command = Controller::C_None;
00205                         state = Controller::S_Init;
00206                         continue;
00207                     }
00208                     
00209                     case Controller::C_Write: {
00210                         DigitalOut *output = this->getOutput(index);
00211                         if (output == NULL) {
00212                             return Controller::E_UnknownIndex;
00213                         }
00214                     
00215                         int value = 0;
00216                         if (std::sscanf(cursor, "%d;", &value) != 1) {
00217                             return Controller::E_InvalidFormat;
00218                         }
00219                         
00220                         char *offset = std::strchr(cursor, ';');
00221                         if (offset == NULL) {
00222                             return Controller::E_InvalidFormat;
00223                         }                         
00224                         cursor = offset + 1;
00225                         
00226                         if (value != 0 && value != 1) {
00227                             return Controller::E_InvalidValue;
00228                         }
00229                         
00230                         output->write(value);
00231                         
00232                         if ((*cursor) == 0 || (*(cursor + 1)) == 0) {
00233                             return 0;
00234                         }
00235                         
00236                         command = Controller::C_None;
00237                         state = Controller::S_Init;
00238                         continue;
00239                     }
00240                 }
00241             }
00242         }
00243     }
00244     
00245     return 0;
00246 }
00247 
00248 
00249 int
00250 Controller::addOutput(DigitalOut *output)
00251 {
00252     if (this->_outputExists(output)) {
00253         return false;
00254     }
00255     
00256     this->_io.output.push_back(output);
00257     return true;
00258 }
00259 
00260 int
00261 Controller::addInput(DigitalIn *input)
00262 {
00263     if (this->_inputExists(input)) {
00264         return false;
00265     }
00266     
00267     this->_io.input.push_back(input);
00268     return true;
00269 }
00270 
00271 DigitalOut *
00272 Controller::getOutput(size_t index)
00273 {
00274     Controller::DigitalOutputList::iterator output;
00275     output = this->_io.output.begin();
00276     output = output + (int)index;
00277     
00278     if (output >= this->_io.output.end()) {
00279         return NULL;
00280     }
00281     
00282     return (*output);
00283 }
00284 
00285 DigitalIn *
00286 Controller::getInput(size_t index)
00287 {
00288     DigitalInputList::iterator input;
00289     input = this->_io.input.begin();
00290     input = input + (int)index;
00291     
00292     if (input >= this->_io.input.end()) {
00293         return NULL;
00294     }
00295     
00296     return (*input);
00297 }
00298 
00299 bool
00300 Controller::_outputExists(DigitalOut *output)
00301 {
00302     DigitalOutputList::iterator entry;
00303     entry = this->_io.output.begin();
00304     for (;entry != this->_io.output.end(); entry++) {
00305         if (output == (*entry)) {
00306             return true;
00307         }
00308     }
00309     
00310     return false;
00311 }
00312 
00313 bool
00314 Controller::_inputExists(DigitalIn *input)
00315 {
00316     Controller::DigitalInputList::iterator entry;
00317     entry = this->_io.input.begin();
00318     for (;entry != this->_io.input.end(); entry++) {
00319         if (input == (*entry)) {
00320             return true;
00321         }
00322     }
00323     
00324     return false;
00325 }