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
internal/types/Socket.cpp
- Committer:
- dan_ackme
- Date:
- 2014-08-11
- Revision:
- 1:6ec9998427ad
- Parent:
- 0:ea85c4bb5e1f
- Child:
- 6:8a87a59d0d21
File content as of revision 1:6ec9998427ad:
/* * Copyright 2014, ACKme Networks * All Rights Reserved. * * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks; * the contents of this file may not be disclosed to third parties, copied * or duplicated in any form, in whole or in part, without the prior * written permission of ACKme Networks. */ #include <assert.h> #include <stdarg.h> #include "Wiconnect.h" #include "internal/common.h" #include "StringUtil.h" #define CHECK_CONNECTED() if(!isConnected()) return WICONNECT_NOT_CONNECTED /*************************************************************************************************/ Socket::Socket(int rxBufferLen_, void *rxBuffer_, int txBufferLen_, void *txBuffer_) { wiconnect = Wiconnect::getInstance(); memset(&txBuffer, 0, sizeof(Buffer)); memset(&rxBuffer, 0, sizeof(Buffer)); txBuffer.size = !wiconnect->nonBlocking ? txBufferLen_ : 0; txBuffer.buffer = (uint8_t*)txBuffer_; rxBuffer.size = !wiconnect->nonBlocking ? rxBufferLen_ : 0; rxBuffer.buffer = (uint8_t*)rxBuffer_; if(txBuffer.size > 0) { if(txBuffer_ == NULL) { #ifdef WICONNECT_ENABLE_MALLOC assert(wiconnect->_malloc != NULL); txBuffer.buffer = (uint8_t*)wiconnect->_malloc(txBufferLen_); assert(txBuffer.buffer != NULL); txBuffer.allocated = true; #else assert(0); #endif } } if(rxBuffer.size > 0) { if(rxBuffer_ == NULL) { #ifdef WICONNECT_ENABLE_MALLOC assert(wiconnect->_malloc != NULL); rxBuffer.buffer = (uint8_t*)wiconnect->_malloc(rxBufferLen_); assert(rxBuffer.buffer != NULL); rxBuffer.allocated = true; #else assert(0); #endif } } init(SOCKET_INVALID_HANDLE, SOCKET_TYPE_UNKNOWN, NULL, 0, 0); } /*************************************************************************************************/ WiconnectResult Socket::init(uint8_t handle_, SocketType type_, const char *host_, uint16_t remotePort_, uint16_t localPort_) { handle = handle_; type = type_; remotePort = remotePort_; localPort = localPort_; connected = true; txBuffer.ptr = txBuffer.buffer; rxBuffer.ptr = rxBuffer.buffer; strncpy(host, host_, sizeof(host)-1); return WICONNECT_SUCCESS; } /*************************************************************************************************/ Socket::~Socket() { while((handle != SOCKET_INVALID_HANDLE) && (close() == WICONNECT_PROCESSING)) { } #ifdef WICONNECT_ENABLE_MALLOC if(txBuffer.allocated && txBuffer.size > 0) { assert(wiconnect->_free != NULL); wiconnect->_free(txBuffer.buffer); } if(rxBuffer.allocated && rxBuffer.size > 0) { assert(wiconnect->_free != NULL); wiconnect->_free(rxBuffer.buffer); } #endif } /*************************************************************************************************/ bool Socket::isConnected() { return connected; } /*************************************************************************************************/ SocketType Socket::getType() { return type; } /*************************************************************************************************/ const char* Socket::getHost() { return host; } /*************************************************************************************************/ uint16_t Socket::getLocalPort() { return localPort; } /*************************************************************************************************/ uint16_t Socket::getRemotePort() { return remotePort; } /*************************************************************************************************/ uint8_t Socket::getHandle() { return handle; } /*************************************************************************************************/ WiconnectResult Socket::close() { WiconnectResult result; CHECK_CONNECTED(); CHECK_OTHER_COMMAND_EXECUTING(); if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("close %d", handle))) { connected = false; } CHECK_CLEANUP_COMMAND(); return result; } /*************************************************************************************************/ WiconnectResult Socket::poll(bool *rxDataAvailablePtr) { WiconnectResult result; int32_t status; CHECK_CONNECTED(); CHECK_OTHER_COMMAND_EXECUTING(); *rxDataAvailablePtr = false; if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("poll %d", handle))) { if(!WICONNECT_FAILED(result, wiconnect->responseToInt32(&status))) { if(status == 2) { connected = false; } else if(status == 1) { *rxDataAvailablePtr = true; } } } CHECK_CLEANUP_COMMAND(); return result; } /*************************************************************************************************/ WiconnectResult Socket::write(int length, bool flush) { CHECK_CONNECTED(); if( txBuffer.size == 0) { return WICONNECT_UNSUPPORTED; } else if(length > txBuffer.size) { return WICONNECT_OVERFLOW; } txBuffer.bytesPending = length; return flush ? flushTxBuffer() : WICONNECT_SUCCESS; } /*************************************************************************************************/ WiconnectResult Socket::write(const void* buffer, int length, bool flush) { WiconnectResult result = WICONNECT_SUCCESS; CHECK_CONNECTED(); if(txBuffer.size > 0) { // NOTE: txBuffer only available in blocking mode (so no need to check if a cmd is executing) const uint8_t *src = (const uint8_t *)buffer; while(length > 0) { int bytesToWrite = MIN(length, txBuffer.size - txBuffer.bytesPending); uint8_t *dst = (uint8_t*)&txBuffer.buffer[txBuffer.bytesPending]; memcpy(dst, src, bytesToWrite); txBuffer.bytesPending += bytesToWrite; length -= bytesToWrite; src += bytesToWrite; if((txBuffer.bytesPending >= txBuffer.size) && WICONNECT_FAILED(result, flushTxBuffer())) { break; } } if(flush && txBuffer.bytesPending > 0) { result = flushTxBuffer(); } } else { if(WICONNECT_IS_IDLE()) { txBuffer.ptr = (uint8_t*)buffer; txBuffer.bytesPending = length; } result = flushTxBuffer(); } return result; } /*************************************************************************************************/ WiconnectResult Socket::read(void* buffer, uint16_t maxLength, uint16_t *bytesRead) { WiconnectResult result; CHECK_CONNECTED(); CHECK_OTHER_COMMAND_EXECUTING(); if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand((char*)buffer, maxLength, "read %d %d", handle, maxLength-2))) { *bytesRead = wiconnect->getLastCommandResponseLength(); } CHECK_CLEANUP_COMMAND(); return result; } /*************************************************************************************************/ WiconnectResult Socket::read(uint8_t **bufferPtr, uint16_t *bytesReadPtr) { WiconnectResult result = WICONNECT_SUCCESS; CHECK_CONNECTED(); if(rxBuffer.size == 0) { return WICONNECT_UNSUPPORTED; } else if(bufferPtr != NULL && bytesReadPtr == NULL) { return WICONNECT_BAD_ARG; } else if(rxBuffer.bytesPending < rxBuffer.size - 2) { const int bytesToRead = rxBuffer.size - rxBuffer.bytesPending - 2; char* ptr = (char*)&rxBuffer.buffer[rxBuffer.bytesPending]; if(!WICONNECT_FAILED(result, wiconnect->sendCommand(ptr, bytesToRead+2, "read %d %d", handle, bytesToRead))) { rxBuffer.bytesPending += wiconnect->getLastCommandResponseLength(); } } if(bufferPtr != NULL) { *bufferPtr = rxBuffer.buffer; *bytesReadPtr = rxBuffer.bytesPending; clearRxBuffer(); } return result; } /*************************************************************************************************/ WiconnectResult Socket::getc(uint8_t *c) { WiconnectResult result; if(rxBuffer.size == 0) { return WICONNECT_UNSUPPORTED; } read_data: if(rxBuffer.bytesPending == 0 && WICONNECT_FAILED(result, read())) { return result; } else if(rxBuffer.ptr < &rxBuffer.buffer[rxBuffer.bytesPending]) { *c = *rxBuffer.ptr; ++rxBuffer.ptr; return WICONNECT_SUCCESS; } else { clearRxBuffer(); goto read_data; } } /*************************************************************************************************/ WiconnectResult Socket::putc(uint8_t c, bool flush) { WiconnectResult result = WICONNECT_SUCCESS; CHECK_CONNECTED(); if(txBuffer.size == 0) { return WICONNECT_UNSUPPORTED; } else if(txBuffer.bytesPending < txBuffer.size) { uint8_t *ptr = (uint8_t*)&txBuffer.buffer[txBuffer.bytesPending]; *ptr = c; ++txBuffer.bytesPending; if(flush || txBuffer.bytesPending >= txBuffer.size) { result = flushTxBuffer(); } } else { result = WICONNECT_OVERFLOW; } return result; } /*************************************************************************************************/ WiconnectResult Socket::puts(const char *s, bool flush) { const int len = strlen(s); return write(s, len, flush); } /*************************************************************************************************/ WiconnectResult Socket::printf(const char* format, ...) { WiconnectResult result = WICONNECT_SUCCESS; CHECK_CONNECTED(); if(txBuffer.size == 0) { return WICONNECT_UNSUPPORTED; } const int available = txBuffer.size - txBuffer.bytesPending; char *ptr = (char*)&txBuffer.buffer[txBuffer.bytesPending]; va_list args; va_start(args, format); const int len = vsnprintf(ptr, available, format, args); if(len > available) { return WICONNECT_OVERFLOW; } else { txBuffer.bytesPending += len; } if(txBuffer.bytesPending >= txBuffer.size) { result = flushTxBuffer(); } return result; } /*************************************************************************************************/ WiconnectResult Socket::flushTxBuffer() { WiconnectResult result = WICONNECT_SUCCESS; CHECK_CONNECTED(); CHECK_OTHER_COMMAND_EXECUTING(); if(txBuffer.bytesPending > 0) { result = wiconnect->sendCommand(ReaderFunc(this, &Socket::writeDataCallback), NULL, "write %d %d", handle, txBuffer.bytesPending); } CHECK_CLEANUP_COMMAND(); if(result != WICONNECT_PROCESSING) { txBuffer.ptr = txBuffer.buffer; txBuffer.bytesPending = 0; } return result; } /*************************************************************************************************/ void Socket::clearRxBuffer() { rxBuffer.bytesPending = 0; rxBuffer.ptr = rxBuffer.buffer; } /*************************************************************************************************/ uint8_t* Socket::getTxBuffer() { return txBuffer.buffer; } /*************************************************************************************************/ int Socket::getTxBufferSize() { return txBuffer.size; } /*************************************************************************************************/ int Socket::getTxBufferBytesPending() { return txBuffer.bytesPending; } /*************************************************************************************************/ uint8_t* Socket::getRxBuffer() { return rxBuffer.buffer; } /*************************************************************************************************/ int Socket::getRxBufferSize() { return rxBuffer.size; } /*************************************************************************************************/ int Socket::getRxBufferBytesPending() { return rxBuffer.bytesPending; } /*************************************************************************************************/ WiconnectResult Socket::writeDataCallback(void *user, void *data, int maxReadSize, int *bytesRead) { if(txBuffer.bytesPending == 0) { *bytesRead = EOF; } else { int bytesToWrite = MIN(maxReadSize, txBuffer.bytesPending); memcpy(data, txBuffer.ptr, bytesToWrite); txBuffer.ptr += bytesToWrite; txBuffer.bytesPending -= bytesToWrite; *bytesRead = bytesToWrite; } return WICONNECT_SUCCESS; }