Host library for controlling a WiConnect enabled Wi-Fi module.
Dependents: wiconnect-ota_example wiconnect-web_setup_example wiconnect-test-console wiconnect-tcp_server_example ... more
TcpServer.cpp
00001 /** 00002 * ACKme WiConnect Host Library is licensed under the BSD licence: 00003 * 00004 * Copyright (c)2014 ACKme Networks. 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without modification, 00008 * are permitted provided that the following conditions are met: 00009 * 00010 * 1. Redistributions of source code must retain the above copyright notice, 00011 * this list of conditions and the following disclaimer. 00012 * 2. Redistributions in binary form must reproduce the above copyright notice, 00013 * this list of conditions and the following disclaimer in the documentation 00014 * and/or other materials provided with the distribution. 00015 * 3. The name of the author may not be used to endorse or promote products 00016 * derived from this software without specific prior written permission. 00017 * 00018 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS AND ANY EXPRESS OR IMPLIED 00019 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00020 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00021 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00022 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00023 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00024 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00025 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00026 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00027 * OF SUCH DAMAGE. 00028 */ 00029 00030 #include "Wiconnect.h" 00031 #include "internal/common.h" 00032 #include "api/StringUtil.h" 00033 00034 #ifdef WICONNECT_GPIO_IRQ_ENABLED 00035 #include "api/types/SocketIrqHandlerMap.h" 00036 #endif 00037 00038 #define TCP_SERVER_MONITOR_PERIOD 250 //ms 00039 00040 00041 00042 static WiconnectResult parseIpPortStr(char *str, uint32_t *ipAddress, uint16_t *port); 00043 00044 00045 00046 00047 /*************************************************************************************************/ 00048 WiconnectResult SocketInterface::tcpListen(uint16_t listeningPort, int maxClients GPIO_IRQ_ARG) 00049 { 00050 WiconnectResult result = WICONNECT_ERROR; 00051 00052 enum 00053 { 00054 FS_SET_MAX_CLIENTS, 00055 FS_SET_DATA_GPIO, 00056 FS_START_SERVER, 00057 }; 00058 00059 CHECK_OTHER_COMMAND_EXECUTING(); 00060 00061 if(wiconnect->internalProcessingState == FS_SET_MAX_CLIENTS) 00062 { 00063 if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("set tcp.server.max_clients", maxClients))) 00064 { 00065 wiconnect->internalProcessingState = FS_SET_DATA_GPIO; 00066 } 00067 else if(result == WICONNECT_CMD_RESPONSE_ERROR) 00068 { 00069 // if there was a module error, then the wiconnect version probably doesn't support this option 00070 // just continue to the next state 00071 wiconnect->internalProcessingState = FS_SET_DATA_GPIO; 00072 } 00073 } 00074 00075 if(wiconnect->internalProcessingState == FS_SET_DATA_GPIO) 00076 { 00077 #ifdef WICONNECT_GPIO_IRQ_ENABLED 00078 if(irqPin == PIN_NC) 00079 { 00080 wiconnect->internalProcessingState = FS_START_SERVER; 00081 } 00082 else 00083 { 00084 PinToGpioMapper mapper = wiconnect->pinToGpioMapper; 00085 if(mapper == NULL) 00086 { 00087 return WICONNECT_PINNAME_TO_GPIO_MAPPER_NULL; 00088 } 00089 int8_t gpio = mapper(irqPin); 00090 if(gpio == -1) 00091 { 00092 return WICONNECT_PINNAME_TO_GPIO_NO_MAPPING; 00093 } 00094 else if(!irqHandlers.pinIsRegistered(irqPin)) 00095 { 00096 return WICONNECT_NOT_FOUND; 00097 } 00098 else if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("set tcp.server.data_gpio %d", gpio))) 00099 { 00100 wiconnect->internalProcessingState = FS_START_SERVER; 00101 } 00102 } 00103 #else 00104 wiconnect->internalProcessingState = FS_START_SERVER; 00105 #endif 00106 } 00107 00108 if(wiconnect->internalProcessingState == FS_START_SERVER) 00109 { 00110 if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("tcps start %d", listeningPort))) 00111 { 00112 //#ifdef WICONNECT_ASYNC_TIMER_ENABLED 00113 // if(clientConnectedCallback.isValid() && !wiconnect->nonBlocking) 00114 // { 00115 // serverClientConnectedCallback = clientConnectedCallback; 00116 // serverMonitorTimer.start(this, &SocketInterface::serverClientMonitor, TCP_SERVER_MONITOR_PERIOD); 00117 // } 00118 //#endif 00119 } 00120 } 00121 00122 CHECK_CLEANUP_COMMAND(); 00123 00124 return result; 00125 } 00126 00127 /*************************************************************************************************/ 00128 WiconnectResult SocketInterface::tcpAccept(WiconnectSocket &socket, uint32_t timeoutMs) 00129 { 00130 TimeoutTimer timer; 00131 00132 do 00133 { 00134 uint8_t handle; 00135 uint16_t local, remote; 00136 uint32_t ipAddress; 00137 WiconnectResult result; 00138 00139 if(WICONNECT_SUCCEEDED(result, pollForServerClient(&handle, &local, &remote, &ipAddress))) 00140 { 00141 char ipBuffer[17]; 00142 if(WICONNECT_FAILED(result, socket.init(handle, SOCKET_TYPE_TCP, Wiconnect::ipToStr(ipAddress, ipBuffer), remote, local))) 00143 { 00144 return result; 00145 } 00146 serverConnectedClientList |= (1 << handle); 00147 return WICONNECT_SUCCESS; 00148 } 00149 else if(!(result == WICONNECT_PROCESSING || result == WICONNECT_NOT_FOUND)) 00150 { 00151 return result; 00152 } 00153 00154 } while(timeoutMs == WICONNECT_WAIT_FOREVER || !timer.timedOut(timeoutMs)); 00155 00156 return WICONNECT_TIMEOUT; 00157 } 00158 00159 /*************************************************************************************************/ 00160 WiconnectResult SocketInterface::tcpServerStop(void) 00161 { 00162 WiconnectResult result = WICONNECT_ERROR; 00163 00164 CHECK_OTHER_COMMAND_EXECUTING(); 00165 00166 result = wiconnect->sendCommand("tcps stop"); 00167 00168 CHECK_CLEANUP_COMMAND(); 00169 00170 return result; 00171 } 00172 00173 /*************************************************************************************************/ 00174 WiconnectResult SocketInterface::pollForServerClient(uint8_t *handlePtr, uint16_t *localPort, uint16_t *remotePort, uint32_t *ipAddress) 00175 { 00176 WiconnectResult result; 00177 00178 CHECK_OTHER_COMMAND_EXECUTING(); 00179 00180 if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("list"))) 00181 { 00182 uint32_t connectedClients = 0; 00183 char *line, *savedLine; 00184 result = WICONNECT_NOT_FOUND; 00185 00186 for(savedLine = wiconnect->internalBuffer; (line = StringUtil::strtok_r(savedLine, "\r\n", &savedLine)) != NULL;) 00187 { 00188 char *toks[4], *savedTok; 00189 00190 if(*line != '#') 00191 { 00192 continue; 00193 } 00194 savedTok = line + 2; 00195 00196 for(int i = 0; i < 4 && (toks[i] = StringUtil::strtok_r(savedTok, " ", &savedTok)) != NULL; ++i) 00197 { 00198 if(toks[i] == NULL) 00199 { 00200 result = WICONNECT_RESPONSE_PARSE_ERROR; 00201 goto exit; 00202 } 00203 } 00204 00205 if(strcmp(toks[1], "TCPS") != 0) 00206 { 00207 continue; 00208 } 00209 00210 uint8_t handle = (uint8_t)(*toks[0] - '0'); 00211 if(handle >= WICONNECT_MAX_SOCKETS) 00212 { 00213 result = WICONNECT_RESPONSE_PARSE_ERROR; 00214 goto exit; 00215 } 00216 const uint32_t handleMask = (1 << handle); 00217 connectedClients |= handleMask; 00218 00219 if(result == WICONNECT_SUCCESS) 00220 { 00221 continue; 00222 } 00223 else if(serverConnectedClientList & handleMask) 00224 { 00225 continue; 00226 } 00227 00228 result = WICONNECT_SUCCESS; 00229 00230 if(handlePtr != NULL) 00231 { 00232 *handlePtr = handle; 00233 parseIpPortStr(toks[2], NULL, localPort); 00234 parseIpPortStr(toks[3], ipAddress, remotePort); 00235 } 00236 } 00237 00238 uint32_t mask = 1; 00239 for(int i = 0; i < WICONNECT_MAX_SOCKETS; ++i, mask <<= 1) 00240 { 00241 if(!(connectedClients & mask)) 00242 { 00243 serverConnectedClientList &= ~mask; 00244 } 00245 } 00246 } 00247 00248 00249 exit: 00250 CHECK_CLEANUP_COMMAND(); 00251 00252 return result; 00253 } 00254 00255 /*************************************************************************************************/ 00256 static WiconnectResult parseIpPortStr(char *str, uint32_t *ipAddress, uint16_t *port) 00257 { 00258 char *colon = strchr(str, ':'); 00259 if(colon == NULL) 00260 { 00261 return WICONNECT_RESPONSE_PARSE_ERROR; 00262 } 00263 *colon++ = 0; 00264 00265 if(ipAddress != NULL && !Wiconnect::strToIp(str, ipAddress)) 00266 { 00267 return WICONNECT_RESPONSE_PARSE_ERROR; 00268 } 00269 else if(!StringUtil::strToUint16(colon, port)) 00270 { 00271 return WICONNECT_RESPONSE_PARSE_ERROR; 00272 } 00273 00274 return WICONNECT_SUCCESS; 00275 }
Generated on Tue Jul 12 2022 17:35:58 by 1.7.2