MODIFIED from mbed official WiflyInterface (interface for Roving Networks Wifly modules). Numerous performance and reliability improvements (see the detailed documentation). Also, tracking changes in mbed official version to retain functional parity.

Dependents:   Smart-WiFly-WebServer PUB_WiflyInterface_Demo

Fork of WiflyInterface by mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers UDPSocket.cpp Source File

UDPSocket.cpp

00001 /* Copyright (C) 2012 mbed.org, MIT License
00002  *
00003  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
00004  * and associated documentation files (the "Software"), to deal in the Software without restriction,
00005  * including without limitation the rights to use, copy, modify, merge, publish, distribute,
00006  * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
00007  * furnished to do so, subject to the following conditions:
00008  *
00009  * The above copyright notice and this permission notice shall be included in all copies or
00010  * substantial portions of the Software.
00011  *
00012  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
00013  * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00014  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00015  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00016  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00017  */
00018 
00019 #include "UDPSocket.h"
00020 
00021 #include <string>
00022 #include <algorithm>
00023 
00024 //#define DEBUG "UDPs"      //Debug is disabled by default
00025 
00026 // How to use this debug macro
00027 //
00028 // ...
00029 // INFO("Stuff to show %d", var); // new-line is automatically appended
00030 // [I myfile  23] Stuff to show 23\r\n
00031 //
00032 #if (defined(DEBUG) && !defined(TARGET_LPC11U24))
00033 #define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
00034 #define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
00035 #define ERR(x, ...)  std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
00036 #else
00037 #define INFO(x, ...)
00038 #define WARN(x, ...)
00039 #define ERR(x, ...)
00040 #endif
00041 
00042 UDPSocket::UDPSocket()
00043 {
00044     endpoint_configured = false;
00045     endpoint_read = false;
00046 }
00047 
00048 int UDPSocket::init(void)
00049 {
00050     wifi->setProtocol(UDP);
00051     wifi->exit();
00052     return 0;
00053 }
00054 
00055 // Server initialization
00056 int UDPSocket::bind(int port)
00057 {
00058     char cmd[17];
00059     
00060     // set local port
00061     sprintf(cmd, "set i l %d\r", port);
00062     if (!wifi->sendCommand(cmd, "AOK"))
00063         return -1;
00064         
00065     // save
00066     if (!wifi->sendCommand("save\r", "Stor", NULL, 5000))
00067         return -1;
00068     
00069     // reboot
00070     wifi->reboot();
00071     
00072     // set udp protocol
00073     wifi->setProtocol(UDP);
00074     
00075     // connect the network
00076     if (wifi->isDHCP()) {
00077         if (!wifi->sendCommand("join\r", "DHCP=ON", NULL, 10000))
00078             return -1;
00079     } else {
00080         if (!wifi->sendCommand("join\r", "Associated", NULL, 10000))
00081             return -1;
00082     }
00083         
00084     // exit
00085     wifi->exit();
00086     wifi->flush();
00087     return 0;
00088 }
00089 
00090 int UDPSocket::join_multicast_group(const char* address) {
00091     return -1;  // unsupported function
00092 }
00093 
00094 int UDPSocket::set_broadcasting(bool broadcast) {
00095     return -1;  // unsupported function
00096 }
00097 
00098 // -1 if unsuccessful, else number of bytes written
00099 int UDPSocket::sendTo(Endpoint &remote, char *packet, int length)
00100 {
00101     Timer tmr;
00102     int idx = 0;
00103     INFO("sendTo(..,..,%d)", length);
00104     confEndpoint(remote);
00105 
00106     tmr.start();
00107     INFO("sendTo %d", tmr.read_ms());
00108     
00109     while ((tmr.read_ms() < _timeout) || _blocking) {
00110 
00111         idx += wifi->send(packet, length);
00112         INFO("  idx: %d", idx);
00113         if (idx == length)
00114             return idx;
00115     }
00116     INFO("  idx; %d @ %d", idx, tmr.read_ms());
00117     return (idx == 0) ? -1 : idx;
00118 }
00119 
00120 // -1 if unsuccessful, else number of bytes received
00121 int UDPSocket::receiveFrom(Endpoint &remote, char *buffer, int length)
00122 {
00123     Timer tmr;
00124     int idx = 0;
00125     int nb_available = 0;
00126     int time = -1;
00127 
00128     if (_blocking) {
00129         while (1) {
00130             nb_available = wifi->readable();
00131             if (nb_available != 0) {
00132                 break;
00133             }
00134         }
00135     }
00136 
00137     tmr.start();
00138 
00139     while (time < _timeout) {
00140 
00141         nb_available = wifi->readable();
00142         for (int i = 0; i < min(nb_available, length); i++) {
00143             buffer[idx] = wifi->getc();
00144             idx++;
00145         }
00146 
00147         if (idx == length) {
00148             break;
00149         }
00150         
00151         time = tmr.read_ms();
00152     }
00153 
00154     readEndpoint(remote);
00155     return (idx == 0) ? -1 : idx;
00156 }
00157 
00158 bool UDPSocket::confEndpoint(Endpoint & ep)
00159 {
00160     char * host;
00161     char cmd[30];
00162     
00163     WARN("Force endpoint not configured");
00164     endpoint_configured = false;
00165     INFO("confEndpoint config'd: %d", endpoint_configured);
00166     if (!endpoint_configured) {
00167         host = ep.get_address();
00168         if (host[0] != '\0') {
00169             // set host
00170             sprintf(cmd, "set i h %s\r", host);
00171             if (!wifi->sendCommand(cmd, "AOK")) {
00172                 INFO("  confEndPoint false.");
00173                 return false;
00174             }
00175             // set remote port
00176             sprintf(cmd, "set i r %d\r", ep.get_port());
00177             if (!wifi->sendCommand(cmd, "AOK")) {
00178                 INFO("  confEndPoint false.");
00179                 return false;
00180             }
00181             wifi->exit();
00182             endpoint_configured = true;
00183             INFO("  confEndPoint.");
00184             return true;
00185         }
00186     }
00187     INFO("  confEndPoint.");
00188     return true;
00189 }
00190 
00191 bool UDPSocket::readEndpoint(Endpoint & ep)
00192 {
00193     char recv[256];
00194     int begin = 0;
00195     int end = 0;
00196     string str;
00197     string addr;
00198     int port;
00199     if (!endpoint_read) {
00200         if (!wifi->sendCommand("get ip\r", NULL, recv))
00201             return false;
00202         wifi->exit();
00203         str = recv;
00204         begin = str.find("HOST=");
00205         end = str.find("PROTO=");
00206         if (begin != string::npos && end != string::npos) {
00207             str = str.substr(begin + 5, end - begin - 5);
00208             int pos = str.find(":");
00209             if (pos != string::npos) {
00210                 addr = str.substr(0, pos);
00211                 port = atoi(str.substr(pos + 1).c_str());
00212                 ep.set_address(addr.c_str(), port);
00213                 endpoint_read = true;
00214                 wifi->flush();
00215                 return true;
00216             }
00217         }
00218         wifi->flush();
00219     }
00220     return false;
00221 }