Пример #1
0
/*JSON{ "type":"method", "class": "String", "name" : "charAt",
         "description" : "Return a single character at the given position in the String.",
         "generate" : "jswrap_string_charAt",
         "params" : [ [ "pos", "int", "The character number in the string. Negative values return characters from end of string (-1 = last char)"] ],
         "return" : ["JsVar", "The character in the string"]
}*/
JsVar *jswrap_string_charAt(JsVar *parent, JsVarInt idx) {
  // We do this so we can handle '/0' in a string
  JsVar *r = jsvNewFromEmptyString();
  if (r) { // out of mem?
    char ch = jsvGetCharInString(parent, (int)idx);
    jsvAppendStringBuf(r, &ch, 1);
  }
  return r;
}
Пример #2
0
/*JSON{ "type":"staticmethod", "class": "String", "name" : "fromCharCode",
         "description" : "Return the character represented by the given character code.",
         "generate" : "jswrap_string_fromCharCode",
         "params" : [ [ "code", "int", "The character code to create a character from (range 0-255)"] ],
         "return" : ["JsVar", "The character"]
}*/
JsVar *jswrap_string_fromCharCode(JsVarInt code) {
  // We do this so we can handle '/0' in a string
  JsVar *r = jsvNewFromEmptyString();
  if (r) { // out of mem?
    char ch = code;
    jsvAppendStringBuf(r, &ch, 1);
  }
  return r;
}
Пример #3
0
/*JSON{
  "type" : "method",
  "class" : "String",
  "name" : "charAt",
  "generate" : "jswrap_string_charAt",
  "params" : [
    ["pos","int","The character number in the string. Negative values return characters from end of string (-1 = last char)"]
  ],
  "return" : ["JsVar","The character in the string"]
}
Return a single character at the given position in the String.
*/
JsVar *jswrap_string_charAt(JsVar *parent, JsVarInt idx) {
  // We do this so we can handle '/0' in a string
  JsVar *r = jsvNewFromEmptyString();
  if (r && jsvIsString(parent) && idx>=0) {
    JsvStringIterator it;
    jsvStringIteratorNew(&it, parent, (size_t)idx);
    if (jsvStringIteratorHasChar(&it)) {
      char ch = jsvStringIteratorGetChar(&it);
      jsvAppendStringBuf(r, &ch, 1);
    }
    jsvStringIteratorFree(&it);
  }
  return r;
}
Пример #4
0
/*JSON{
  "type" : "staticmethod",
  "class" : "String",
  "name" : "fromCharCode",
  "generate" : "jswrap_string_fromCharCode",
  "params" : [
    ["code","JsVarArray","One or more character codes to create a string from (range 0-255)."]
  ],
  "return" : ["JsVar","The character"]
}
Return the character(s) represented by the given character code(s).
*/
JsVar *jswrap_string_fromCharCode(JsVar *arr) {
  assert(jsvIsArray(arr));

  JsVar *r = jsvNewFromEmptyString();
  if (!r) return 0;

  JsvObjectIterator it;
  jsvObjectIteratorNew(&it, arr);
  while (jsvObjectIteratorHasValue(&it)) {
    char ch = (char)jsvGetIntegerAndUnLock(jsvObjectIteratorGetValue(&it));
    jsvAppendStringBuf(r, &ch, 1);
    jsvObjectIteratorNext(&it);
  }
  jsvObjectIteratorFree(&it);

  return r;
}
Пример #5
0
/*JSON{  "type" : "method", "class" : "File", "name" : "read",
         "generate" : "jswrap_file_read",
         "description" : [ "Read data in a file in byte size chunks"],
         "params" : [ ["length", "int32", "is an integer specifying the number of bytes to read."] ],
         "return" : [ "JsVar", "A string containing the characters that were read" ]
}*/
JsVar *jswrap_file_read(JsVar* parent, int length) {
  JsVar *buffer = 0;
  FRESULT res = 0;
  size_t bytesRead = 0;
  if (jsfsInit()) {
    JsFile file;
    if (fileGetFromVar(&file, parent)) {
      if(file.data.mode == FM_READ || file.data.mode == FM_READ_WRITE) {
        char buf[32];
        size_t actual = 0;
        while (bytesRead < (size_t)length) {
          size_t requested = (size_t)length - bytesRead;
          if (requested > sizeof( buf ))
            requested = sizeof( buf );
          actual = 0;
    #ifndef LINUX
          res = f_read(&file.data.handle, buf, requested, &actual);
          if(res) break;
    #else
          actual = fread(buf, 1, requested, file.data.handle);
    #endif
          if (actual>0) {
            if (!buffer) {
              buffer = jsvNewFromEmptyString();
              if (!buffer) return 0; // out of memory
            }
            jsvAppendStringBuf(buffer, buf, actual);
          }
          bytesRead += actual;
          if(actual != requested) break;
        }
        fileSetVar(&file);
      }
    }
  }
  if (res) jsfsReportError("Unable to read file", res);

  // automatically close this file if we're at the end of it
  if (bytesRead!=(size_t)length)
    jswrap_file_close(parent);

  return buffer;
}
Пример #6
0
/*JSON{  "type" : "staticmethod", "class" : "fs", "name" : "readFileSync", "ifndef" : "SAVE_ON_FLASH",
         "generate" : "wrap_fat_readFile",
         "description" : [ "Read all data from a file and return as a string" ],
         "params" : [ [ "path", "JsVar", "The path of the file to read" ] ],
         "return" : [ "JsVar", "A string containing the contents of the file" ]
}*/
JsVar *wrap_fat_readFile(JsVar *path) {
  char pathStr[JS_DIR_BUF_SIZE] = "";
  if (!jsvIsUndefined(path))
    jsvGetString(path, pathStr, JS_DIR_BUF_SIZE);

  JsVar *result = jsvNewFromEmptyString();
  if (!result) return 0; // out of memory

  FRESULT res = 0;
  if (jsfsInit()) {
#ifndef LINUX
    FIL file;
    if ((res=f_open(&file, pathStr, FA_READ)) == FR_OK) {
#else
    FILE *file = fopen(pathStr, "r");
    if (file) {
#endif
      // re-use pathStr buffer
      size_t bytesRead = JS_DIR_BUF_SIZE;
      while (res==FR_OK && bytesRead==JS_DIR_BUF_SIZE) {
#ifndef LINUX
        res = f_read (&file, pathStr, JS_DIR_BUF_SIZE, &bytesRead);
#else
        bytesRead = fread(pathStr,1,JS_DIR_BUF_SIZE,file);
#endif
        jsvAppendStringBuf(result, pathStr, (int)bytesRead);
      }
#ifndef LINUX
      f_close(&file);
#else
      fclose(file);
#endif
    }
  }

  if (res) jsfsReportError("Unable to read file", res);
  return result;
}
Пример #7
0
/*JSON{  "type" : "staticmethod", "class" : "fs", "name" : "readFileSync", "ifndef" : "SAVE_ON_FLASH",
         "generate" : "wrap_fat_readFile",
         "description" : [ "Read all data from a file and return as a string" ],
         "params" : [ [ "path", "JsVar", "The path of the file to read" ] ],
         "return" : [ "JsVar", "A string containing the contents of the file (or undefined if the file doesn't exist)" ]
}*/
JsVar *wrap_fat_readFile(JsVar *path) {
  char pathStr[JS_DIR_BUF_SIZE] = "";
  if (!jsvIsUndefined(path))
    jsvGetString(path, pathStr, JS_DIR_BUF_SIZE);

  JsVar *result = 0; // undefined unless we read the file

  FRESULT res = 0;
  if (jsfsInit()) {
#ifndef LINUX
    FIL file;
    if ((res=f_open(&file, pathStr, FA_READ)) == FR_OK) {
#else
    FILE *file = fopen(pathStr, "r");
    if (file) {
#endif
      result = jsvNewFromEmptyString();
      if (result) { // out of memory?
        // re-use pathStr buffer
        size_t bytesRead = JS_DIR_BUF_SIZE;
        while (res==FR_OK && bytesRead==JS_DIR_BUF_SIZE) {
#ifndef LINUX
          res = f_read (&file, pathStr, JS_DIR_BUF_SIZE, &bytesRead);
#else
          bytesRead = fread(pathStr,1,JS_DIR_BUF_SIZE,file);
#endif
          if (!jsvAppendStringBuf(result, pathStr, (int)bytesRead))
            break; // was out of memory
        }
      }
#ifndef LINUX
      f_close(&file);
#else
      fclose(file);
#endif
    }
  }

  if (res) jsfsReportError("Unable to read file", res);
  return result;
}

  /*JSON{  "type" : "staticmethod", "class" : "fs", "name" : "unlink",
           "generate" : "wrap_fat_unlink",
           "description" : [ "Delete the given file", "NOTE: Espruino does not yet support Async file IO, so this function behaves like the 'Sync' version." ],
           "params" : [ [ "path", "JsVar", "The path of the file to delete" ] ],
           "return" : [ "bool", "True on success, or false on failure" ]
  }*/
  /*JSON{  "type" : "staticmethod", "class" : "fs", "name" : "unlinkSync", "ifndef" : "SAVE_ON_FLASH",
           "generate" : "wrap_fat_unlink",
           "description" : [ "Delete the given file" ],
           "params" : [ [ "path", "JsVar", "The path of the file to delete" ] ],
           "return" : [ "bool", "True on success, or false on failure" ]
  }*/
bool wrap_fat_unlink(JsVar *path) {
    char pathStr[JS_DIR_BUF_SIZE] = "";
    if (!jsvIsUndefined(path))
      jsvGetString(path, pathStr, JS_DIR_BUF_SIZE);

#ifndef LINUX
    FRESULT res = 0;
    if (jsfsInit()) {
      f_unlink(pathStr);
    }
#else
    FRESULT res = remove(pathStr);
#endif

    if (res) {
      jsfsReportError("Unable to delete file", res);
      return false;
    }
    return true;
  }
Пример #8
0
bool socketClientConnectionsIdle(JsNetwork *net) {
    char *buf = alloca(net->chunkSize); // allocate on stack

    JsVar *arr = socketGetArray(HTTP_ARRAY_HTTP_CLIENT_CONNECTIONS,false);
    if (!arr) return false;

    bool hadSockets = false;
    JsvObjectIterator it;
    jsvObjectIteratorNew(&it, arr);
    while (jsvObjectIteratorHasValue(&it)) {
        hadSockets = true;
        // Get connection, socket, and socket type
        // For normal sockets, socket==connection, but for HTTP connection is httpCRq and socket is httpCRs
        JsVar *connection = jsvObjectIteratorGetValue(&it);
        SocketType socketType = socketGetType(connection);
        JsVar *socket = ((socketType&ST_TYPE_MASK)==ST_HTTP) ? jsvObjectGetChild(connection,HTTP_NAME_RESPONSE_VAR,0) : jsvLockAgain(connection);
        bool socketClosed = false;
        JsVar *receiveData = 0;

        bool hadHeaders = false;
        int error = 0; // error code received from netXxxx functions
        bool isHttp = (socketType&ST_TYPE_MASK) == ST_HTTP;
        bool closeConnectionNow = jsvGetBoolAndUnLock(jsvObjectGetChild(connection, HTTP_NAME_CLOSENOW, false));
        bool alreadyConnected = jsvGetBoolAndUnLock(jsvObjectGetChild(connection, HTTP_NAME_CONNECTED, false));
        int sckt = (int)jsvGetIntegerAndUnLock(jsvObjectGetChild(connection,HTTP_NAME_SOCKET,0))-1; // so -1 if undefined
        if (sckt>=0) {
            if (isHttp)
                hadHeaders = jsvGetBoolAndUnLock(jsvObjectGetChild(connection,HTTP_NAME_HAD_HEADERS,0));
            else
                hadHeaders = true;
            receiveData = jsvObjectGetChild(connection,HTTP_NAME_RECEIVE_DATA,0);

            /* We do this up here because we want to wait until we have been once
             * around the idle loop (=callbacks have been executed) before we run this */
            if (hadHeaders)
                socketClientPushReceiveData(connection, socket, &receiveData);

            JsVar *sendData = jsvObjectGetChild(connection,HTTP_NAME_SEND_DATA,0);
            if (!closeConnectionNow) {
                // send data if possible
                if (sendData && !jsvIsEmptyString(sendData)) {
                    // don't try to send if we're already in error state
                    int num = 0;
                    if (error == 0) num = socketSendData(net, connection, sckt, &sendData);
                    if (num > 0 && !alreadyConnected && !isHttp) { // whoa, we sent something, must be connected!
                        jsiQueueObjectCallbacks(connection, HTTP_NAME_ON_CONNECT, &connection, 1);
                        jsvObjectSetChildAndUnLock(connection, HTTP_NAME_CONNECTED, jsvNewFromBool(true));
                        alreadyConnected = true;
                    }
                    if (num < 0) {
                        closeConnectionNow = true;
                        error = num;
                    }
                    jsvObjectSetChild(connection, HTTP_NAME_SEND_DATA, sendData); // _http_send prob updated sendData
                } else {
                    // no data to send, do we want to close? do so.
                    if (jsvGetBoolAndUnLock(jsvObjectGetChild(connection, HTTP_NAME_CLOSE, false)))
                        closeConnectionNow = true;
                }
                // Now read data if possible (and we have space for it)
                if (!receiveData || !hadHeaders) {
                    int num = netRecv(net, sckt, buf, net->chunkSize);
                    //if (num != 0) printf("recv returned %d\r\n", num);
                    if (!alreadyConnected && num == SOCKET_ERR_NO_CONN) {
                        ; // ignore... it's just telling us we're not connected yet
                    } else if (num < 0) {
                        closeConnectionNow = true;
                        error = num;
                        // disconnected without headers? error.
                        if (!hadHeaders && error == SOCKET_ERR_CLOSED) error = SOCKET_ERR_NO_RESP;
                    } else {
                        // did we just get connected?
                        if (!alreadyConnected && !isHttp) {
                            jsiQueueObjectCallbacks(connection, HTTP_NAME_ON_CONNECT, &connection, 1);
                            jsvObjectSetChildAndUnLock(connection, HTTP_NAME_CONNECTED, jsvNewFromBool(true));
                            alreadyConnected = true;
                            // if we do not have any data to send, issue a drain event
                            if (!sendData || (int)jsvGetStringLength(sendData) == 0)
                                jsiQueueObjectCallbacks(connection, HTTP_NAME_ON_DRAIN, &connection, 1);
                        }
                        // got data add it to our receive buffer
                        if (num > 0) {
                            if (!receiveData) {
                                receiveData = jsvNewFromEmptyString();
                                jsvObjectSetChild(connection, HTTP_NAME_RECEIVE_DATA, receiveData);
                            }
                            if (receiveData) { // could be out of memory
                                jsvAppendStringBuf(receiveData, buf, (size_t)num);
                                if ((socketType&ST_TYPE_MASK)==ST_HTTP && !hadHeaders) {
                                    // for HTTP see whether we now have full response headers
                                    JsVar *resVar = jsvObjectGetChild(connection,HTTP_NAME_RESPONSE_VAR,0);
                                    if (httpParseHeaders(&receiveData, resVar, false)) {
                                        hadHeaders = true;
                                        jsvObjectSetChildAndUnLock(connection, HTTP_NAME_HAD_HEADERS, jsvNewFromBool(hadHeaders));
                                        jsiQueueObjectCallbacks(connection, HTTP_NAME_ON_CONNECT, &resVar, 1);
                                    }
                                    jsvUnLock(resVar);
                                    jsvObjectSetChild(connection, HTTP_NAME_RECEIVE_DATA, receiveData);
                                }
                            }
                        }
                    }
                }
                jsvUnLock(sendData);
            }
        }

        if (closeConnectionNow) {
            socketClientPushReceiveData(connection, socket, &receiveData);
            if (!receiveData) {
                if ((socketType&ST_TYPE_MASK) != ST_HTTP)
                    jsiQueueObjectCallbacks(socket, HTTP_NAME_ON_END, &socket, 1);

                // If we had data to send but the socket closed, this is an error
                JsVar *sendData = jsvObjectGetChild(connection,HTTP_NAME_SEND_DATA,0);
                if (sendData && jsvGetStringLength(sendData) > 0 && error == SOCKET_ERR_CLOSED)
                    error = SOCKET_ERR_UNSENT_DATA;
                jsvUnLock(sendData);

                _socketConnectionKill(net, connection);
                JsVar *connectionName = jsvObjectIteratorGetKey(&it);
                jsvObjectIteratorNext(&it);
                jsvRemoveChild(arr, connectionName);
                jsvUnLock(connectionName);
                socketClosed = true;

                // fire error event, if there is an error
                bool hadError = fireErrorEvent(error, connection, NULL);

                // close callback must happen after error callback
                JsVar *params[1] = { jsvNewFromBool(hadError) };
                jsiQueueObjectCallbacks(socket, HTTP_NAME_ON_CLOSE, params, 1);
                jsvUnLock(params[0]);
            }
        }


        if (!socketClosed) {
            jsvObjectIteratorNext(&it);
        }

        jsvUnLock3(receiveData, connection, socket);
    }
    jsvUnLock(arr);

    return hadSockets;
}
Пример #9
0
bool socketServerConnectionsIdle(JsNetwork *net) {
    char *buf = alloca(net->chunkSize); // allocate on stack

    JsVar *arr = socketGetArray(HTTP_ARRAY_HTTP_SERVER_CONNECTIONS,false);
    if (!arr) return false;

    bool hadSockets = false;
    JsvObjectIterator it;
    jsvObjectIteratorNew(&it, arr);
    while (jsvObjectIteratorHasValue(&it)) {
        hadSockets = true;
        // Get connection, socket, and socket type
        // For normal sockets, socket==connection, but for HTTP we split it into a request and a response
        JsVar *connection = jsvObjectIteratorGetValue(&it);
        SocketType socketType = socketGetType(connection);
        JsVar *socket = ((socketType&ST_TYPE_MASK)==ST_HTTP) ? jsvObjectGetChild(connection,HTTP_NAME_RESPONSE_VAR,0) : jsvLockAgain(connection);

        int sckt = (int)jsvGetIntegerAndUnLock(jsvObjectGetChild(connection,HTTP_NAME_SOCKET,0))-1; // so -1 if undefined
        bool closeConnectionNow = jsvGetBoolAndUnLock(jsvObjectGetChild(connection, HTTP_NAME_CLOSENOW, false));
        int error = 0;

        if (!closeConnectionNow) {
            int num = netRecv(net, sckt, buf, net->chunkSize);
            if (num<0) {
                // we probably disconnected so just get rid of this
                closeConnectionNow = true;
                error = num;
            } else {
                // add it to our request string
                if (num>0) {
                    JsVar *receiveData = jsvObjectGetChild(connection,HTTP_NAME_RECEIVE_DATA,0);
                    JsVar *oldReceiveData = receiveData;
                    if (!receiveData) receiveData = jsvNewFromEmptyString();
                    if (receiveData) {
                        jsvAppendStringBuf(receiveData, buf, (size_t)num);
                        bool hadHeaders = jsvGetBoolAndUnLock(jsvObjectGetChild(connection,HTTP_NAME_HAD_HEADERS,0));
                        if (!hadHeaders && httpParseHeaders(&receiveData, connection, true)) {
                            hadHeaders = true;
                            jsvObjectSetChildAndUnLock(connection, HTTP_NAME_HAD_HEADERS, jsvNewFromBool(hadHeaders));
                            JsVar *server = jsvObjectGetChild(connection,HTTP_NAME_SERVER_VAR,0);
                            JsVar *args[2] = { connection, socket };
                            jsiQueueObjectCallbacks(server, HTTP_NAME_ON_CONNECT, args, ((socketType&ST_TYPE_MASK)==ST_HTTP) ? 2 : 1);
                            jsvUnLock(server);
                        }
                        if (hadHeaders && !jsvIsEmptyString(receiveData)) {
                            // Keep track of how much we received (so we can close once we have it)
                            if ((socketType&ST_TYPE_MASK)==ST_HTTP) {
                                jsvObjectSetChildAndUnLock(connection, HTTP_NAME_RECEIVE_COUNT,
                                                           jsvNewFromInteger(
                                                               jsvGetIntegerAndUnLock(jsvObjectGetChild(connection, HTTP_NAME_RECEIVE_COUNT, JSV_INTEGER)) +
                                                               jsvGetStringLength(receiveData)
                                                           ));
                            }
                            // execute 'data' callback or save data
                            if (jswrap_stream_pushData(connection, receiveData, false)) {
                                // clear received data
                                jsvUnLock(receiveData);
                                receiveData = 0;
                            }
                        }
                        // if received data changed, update it
                        if (receiveData != oldReceiveData)
                            jsvObjectSetChild(connection,HTTP_NAME_RECEIVE_DATA,receiveData);
                        jsvUnLock(receiveData);
                    }
                }
            }

            // send data if possible
            JsVar *sendData = jsvObjectGetChild(socket,HTTP_NAME_SEND_DATA,0);
            if (sendData && !jsvIsEmptyString(sendData)) {
                int sent = socketSendData(net, socket, sckt, &sendData);
                // FIXME? checking for errors is a bit iffy. With the esp8266 network that returns
                // varied error codes we'd want to skip SOCKET_ERR_CLOSED and let the recv side deal
                // with normal closing so we don't miss the tail of what's received, but other drivers
                // return -1 (which is the same value) for all errors. So we rely on the check ~12 lines
                // down if(num>0)closeConnectionNow=false instead.
                if (sent < 0) {
                    closeConnectionNow = true;
                    error = sent;
                }
                jsvObjectSetChild(socket, HTTP_NAME_SEND_DATA, sendData); // socketSendData prob updated sendData
            }
            // only close if we want to close, have no data to send, and aren't receiving data
            bool wantClose = jsvGetBoolAndUnLock(jsvObjectGetChild(socket,HTTP_NAME_CLOSE,0));
            if (wantClose && (!sendData || jsvIsEmptyString(sendData)) && num<=0) {
                bool reallyCloseNow = true;
                if ((socketType&ST_TYPE_MASK)==ST_HTTP) {
                    // Check if we had a Content-Length header - if so, we need to wait until we have received that amount
                    JsVar *headers = jsvObjectGetChild(connection,"headers",0);
                    if (headers) {
                        JsVarInt contentLength = jsvGetIntegerAndUnLock(jsvObjectGetChild(headers,"Content-Length",0));
                        JsVarInt contentReceived = jsvGetIntegerAndUnLock(jsvObjectGetChild(connection, HTTP_NAME_RECEIVE_COUNT, 0));
                        if (contentLength > contentReceived) {
                            reallyCloseNow = false;
                        }
                        jsvUnLock(headers);
                    }
                }
                closeConnectionNow = reallyCloseNow;
            } else if (num > 0)
                closeConnectionNow = false; // guarantee that anything received is processed
            jsvUnLock(sendData);
        }
        if (closeConnectionNow) {
            // send out any data that we were POSTed
            JsVar *receiveData = jsvObjectGetChild(connection,HTTP_NAME_RECEIVE_DATA,0);
            bool hadHeaders = jsvGetBoolAndUnLock(jsvObjectGetChild(connection,HTTP_NAME_HAD_HEADERS,0));
            if (hadHeaders && !jsvIsEmptyString(receiveData)) {
                // execute 'data' callback or save data
                jswrap_stream_pushData(connection, receiveData, true);
            }
            jsvUnLock(receiveData);

            // fire error events
            bool hadError = fireErrorEvent(error, connection, socket);

            // fire the close listeners
            JsVar *params[1] = { jsvNewFromBool(hadError) };
            jsiQueueObjectCallbacks(connection, HTTP_NAME_ON_CLOSE, params, 1);
            jsiQueueObjectCallbacks(socket, HTTP_NAME_ON_CLOSE, params, 1);
            jsvUnLock(params[0]);

            _socketConnectionKill(net, connection);
            JsVar *connectionName = jsvObjectIteratorGetKey(&it);
            jsvObjectIteratorNext(&it);
            jsvRemoveChild(arr, connectionName);
            jsvUnLock(connectionName);
        } else
            jsvObjectIteratorNext(&it);
        jsvUnLock2(connection, socket);
    }
    jsvObjectIteratorFree(&it);
    jsvUnLock(arr);

    return hadSockets;
}
Пример #10
0
/**
 * Send data through SPI.
 * The data can be in a variety of formats including:
 * * `numeric` - A single byte is transmitted.
 * * `string` - Each character in the string is transmitted.
 * * `iterable` - An iterable object is transmitted.
 * \return the Received bytes (MISO).  This is byte array.
 */
JsVar *jswrap_spi_send(
    JsVar *parent,  //!< A description of the SPI device to send data through.
    JsVar *srcdata, //!< The data to send through SPI.
    Pin    nss_pin  //!< The pin to toggle low then high (CS)
  ) {
  // Debug
  // jsiConsolePrintf("jswrap_spi_send called: parent=%j, srcdata=%j, nss_pin=%p\n", parent, srcdata, nss_pin);
  NOT_USED(parent);
  IOEventFlags device = jsiGetDeviceFromClass(parent);

  jswrap_spi_send_data data;
  if (!jsspiGetSendFunction(parent, &data.spiSend, &data.spiSendData))
    return 0;

  JsVar *dst = 0;

  // we're sending and receiving
  if (DEVICE_IS_SPI(device)) jshSPISetReceive(device, true);

  // assert NSS
  if (nss_pin!=PIN_UNDEFINED) jshPinOutput(nss_pin, false);

  // Now that we are setup, we can send the data.

  // Handle the data being a single byte value
  if (jsvIsNumeric(srcdata)) {
    int r = data.spiSend((unsigned char)jsvGetInteger(srcdata), &data.spiSendData);
    if (r<0) r = data.spiSend(-1, &data.spiSendData);
    dst = jsvNewFromInteger(r); // retrieve the byte (no send!)
  }
  // Handle the data being a string
  else if (jsvIsString(srcdata)) {
    dst = jsvNewFromEmptyString();
    JsvStringIterator it;
    jsvStringIteratorNew(&it, srcdata, 0);
    int incount = 0, outcount = 0;
    while (jsvStringIteratorHasChar(&it) && !jspIsInterrupted()) {
      unsigned char in = (unsigned char)jsvStringIteratorGetChar(&it);
      incount++;
      int out = data.spiSend(in, &data.spiSendData);
      if (out>=0) {
        outcount++;
        char outc = (char)out;
        jsvAppendStringBuf(dst, (char*)&outc, 1);
      }
      jsvStringIteratorNext(&it);
    }
    jsvStringIteratorFree(&it);
    // finally add the remaining bytes  (no send!)
    while (outcount < incount && !jspIsInterrupted()) {
      outcount++;
      unsigned char out = (unsigned char)data.spiSend(-1, &data.spiSendData);
      jsvAppendStringBuf(dst, (char*)&out, 1);
    }
  }
  // Handle the data being an iterable.
  else {
    int nBytes = jsvIterateCallbackCount(srcdata);
    dst = jsvNewTypedArray(ARRAYBUFFERVIEW_UINT8, nBytes);
    if (dst) {
      data.rxAmt = data.txAmt = 0;
      jsvArrayBufferIteratorNew(&data.it, dst, 0);
      // Write data
      jsvIterateCallback(srcdata, (void (*)(int,  void *))jswrap_spi_send_cb, &data);
      // Wait until SPI send is finished, and flush data
      while (data.rxAmt < data.txAmt && !jspIsInterrupted())
        jswrap_spi_send_cb(-1, &data);
      jsvArrayBufferIteratorFree(&data.it);
    }
  }

  // de-assert NSS
  if (nss_pin!=PIN_UNDEFINED) jshPinOutput(nss_pin, true);
  return dst;
}
Пример #11
0
JsVar *wrap_fat_readdir(JsVar *path) {
  JsVar *arr = 0; // undefined unless we can open card

  char pathStr[JS_DIR_BUF_SIZE] = "";
  if (!jsvIsUndefined(path))
    jsvGetString(path, pathStr, JS_DIR_BUF_SIZE);
#ifdef LINUX
  if (!pathStr[0]) strcpy(pathStr, "."); // deal with empty readdir
#endif

  FRESULT res = 0;
  if (jsfsInit()) {
#ifndef LINUX
    DIR dirs;
    if ((res=f_opendir(&dirs, pathStr)) == FR_OK) {
      char lfnBuf[_MAX_LFN+1];
      FILINFO Finfo;
      Finfo.lfname = lfnBuf;
      Finfo.lfsize = sizeof(lfnBuf);
#else
    DIR *dir = opendir(pathStr);
    if(dir) {
#endif
      arr = jsvNewWithFlags(JSV_ARRAY);
      if (arr) { // could be out of memory
#ifndef LINUX
        while (((res=f_readdir(&dirs, &Finfo)) == FR_OK) && Finfo.fname[0]) {
          char *fn = GET_FILENAME(Finfo);
#else
        struct dirent *pDir=NULL;
        while((pDir = readdir(dir)) != NULL) {
          char *fn = (*pDir).d_name;
#endif
          JsVar *fnVar = jsvNewFromString(fn);
          if (fnVar) {// out of memory?
            jsvArrayPush(arr, fnVar);
            jsvUnLock(fnVar);
          }
        }
      }
#ifdef LINUX
      closedir(dir);
#endif
    }
  }
  if (res) jsfsReportError("Unable to list files", res);
  return arr;
}

/*JSON{  "type" : "staticmethod", "class" : "fs", "name" : "writeFile",
         "generate_full" : " wrap_fat_writeOrAppendFile(path, data, false)",
         "description" : [ "Write the data to the given file", "NOTE: Espruino does not yet support Async file IO, so this function behaves like the 'Sync' version." ],
         "params" : [ [ "path", "JsVar", "The path of the file to write" ],
                      [ "data", "JsVar", "The data to write to the file" ] ],
         "return" : [ "bool", "True on success, false on failure" ]
}*/
/*JSON{  "type" : "staticmethod", "class" : "fs", "name" : "writeFileSync", "ifndef" : "SAVE_ON_FLASH",
         "generate_full" : " wrap_fat_writeOrAppendFile(path, data, false)",
         "description" : [ "Write the data to the given file" ],
         "params" : [ [ "path", "JsVar", "The path of the file to write" ],
                      [ "data", "JsVar", "The data to write to the file" ] ],
         "return" : [ "bool", "True on success, false on failure" ]
}*/
/*JSON{  "type" : "staticmethod", "class" : "fs", "name" : "appendFile",
         "generate_full" : " wrap_fat_writeOrAppendFile(path, data, true)",
         "description" : [ "Append the data to the given file, created a new file if it doesn't exist", "NOTE: Espruino does not yet support Async file IO, so this function behaves like the 'Sync' version." ],
         "params" : [ [ "path", "JsVar", "The path of the file to write" ],
                      [ "data", "JsVar", "The data to write to the file" ] ],
         "return" : [ "bool", "True on success, false on failure" ]
}*/
/*JSON{  "type" : "staticmethod", "class" : "fs", "name" : "appendFileSync", "ifndef" : "SAVE_ON_FLASH",
         "generate_full" : "wrap_fat_writeOrAppendFile(path, data, true)",
         "description" : [ "Append the data to the given file, created a new file if it doesn't exist" ],
         "params" : [ [ "path", "JsVar", "The path of the file to write" ],
                      [ "data", "JsVar", "The data to write to the file" ] ],
         "return" : [ "bool", "True on success, false on failure" ]
}*/
bool wrap_fat_writeOrAppendFile(JsVar *path, JsVar *data, bool append) {
  char pathStr[JS_DIR_BUF_SIZE] = "";
  if (!jsvIsUndefined(path))
    jsvGetString(path, pathStr, JS_DIR_BUF_SIZE);

  FRESULT res = 0;
  if (jsfsInit()) {
#ifndef LINUX
    FIL file;

    if ((res=f_open(&file, pathStr, FA_WRITE|(append ? FA_OPEN_ALWAYS : FA_CREATE_ALWAYS))) == FR_OK) {

      if (append) {
        // move to end of file to append data
        f_lseek(&file, file.fsize);
//        if (res != FR_OK) jsfsReportError("Unable to move to end of file", res);
      }
#else
      FILE *file = fopen(pathStr, append?"a":"w");
      if (file) {
#endif

      JsvStringIterator it;
      JsVar *dataString = jsvAsString(data, false);
      jsvStringIteratorNew(&it, dataString, 0);
      size_t toWrite = 0;
      size_t written = 0;

      while (jsvStringIteratorHasChar(&it) && res==FR_OK && written==toWrite) {

        // re-use pathStr buffer
        toWrite = 0;
        while (jsvStringIteratorHasChar(&it) && toWrite < JS_DIR_BUF_SIZE) {
          pathStr[toWrite++] = jsvStringIteratorGetChar(&it);
          jsvStringIteratorNext(&it);
        }
#ifndef LINUX
        res = f_write(&file, pathStr, toWrite, &written);
#else
        written = fwrite(pathStr, 1, toWrite, file);
#endif
      }
      jsvStringIteratorFree(&it);
      jsvUnLock(dataString);
#ifndef LINUX
      f_close(&file);
#else
      fclose(file);
#endif
    }
  }
  if (res) {
    jsfsReportError("Unable to write file", res);
    return false;
  }
  return true;
}

/*JSON{  "type" : "staticmethod", "class" : "fs", "name" : "readFile",
         "generate" : "wrap_fat_readFile",
         "description" : [ "Read all data from a file and return as a string", "NOTE: Espruino does not yet support Async file IO, so this function behaves like the 'Sync' version." ],
         "params" : [ [ "path", "JsVar", "The path of the file to read" ] ],
         "return" : [ "JsVar", "A string containing the contents of the file (or undefined if the file doesn't exist)" ]
}*/
/*JSON{  "type" : "staticmethod", "class" : "fs", "name" : "readFileSync", "ifndef" : "SAVE_ON_FLASH",
         "generate" : "wrap_fat_readFile",
         "description" : [ "Read all data from a file and return as a string" ],
         "params" : [ [ "path", "JsVar", "The path of the file to read" ] ],
         "return" : [ "JsVar", "A string containing the contents of the file (or undefined if the file doesn't exist)" ]
}*/
JsVar *wrap_fat_readFile(JsVar *path) {
  char pathStr[JS_DIR_BUF_SIZE] = "";
  if (!jsvIsUndefined(path))
    jsvGetString(path, pathStr, JS_DIR_BUF_SIZE);

  JsVar *result = 0; // undefined unless we read the file

  FRESULT res = 0;
  if (jsfsInit()) {
#ifndef LINUX
    FIL file;
    if ((res=f_open(&file, pathStr, FA_READ)) == FR_OK) {
#else
    FILE *file = fopen(pathStr, "r");
    if (file) {
#endif
      result = jsvNewFromEmptyString();
      if (result) { // out of memory?
        // re-use pathStr buffer
        size_t bytesRead = JS_DIR_BUF_SIZE;
        while (res==FR_OK && bytesRead==JS_DIR_BUF_SIZE) {
#ifndef LINUX
          res = f_read (&file, pathStr, JS_DIR_BUF_SIZE, &bytesRead);
#else
          bytesRead = fread(pathStr,1,JS_DIR_BUF_SIZE,file);
#endif
          if (!jsvAppendStringBuf(result, pathStr, (int)bytesRead))
            break; // was out of memory
        }
      }
#ifndef LINUX
      f_close(&file);
#else
      fclose(file);
#endif
    }
  }

  if (res) jsfsReportError("Unable to read file", res);
  return result;
}

  /*JSON{  "type" : "staticmethod", "class" : "fs", "name" : "unlink",
           "generate" : "wrap_fat_unlink",
           "description" : [ "Delete the given file", "NOTE: Espruino does not yet support Async file IO, so this function behaves like the 'Sync' version." ],
           "params" : [ [ "path", "JsVar", "The path of the file to delete" ] ],
           "return" : [ "bool", "True on success, or false on failure" ]
  }*/
  /*JSON{  "type" : "staticmethod", "class" : "fs", "name" : "unlinkSync", "ifndef" : "SAVE_ON_FLASH",
           "generate" : "wrap_fat_unlink",
           "description" : [ "Delete the given file" ],
           "params" : [ [ "path", "JsVar", "The path of the file to delete" ] ],
           "return" : [ "bool", "True on success, or false on failure" ]
  }*/
bool wrap_fat_unlink(JsVar *path) {
    char pathStr[JS_DIR_BUF_SIZE] = "";
    if (!jsvIsUndefined(path))
      jsvGetString(path, pathStr, JS_DIR_BUF_SIZE);

#ifndef LINUX
    FRESULT res = 0;
    if (jsfsInit()) {
      res = f_unlink(pathStr);
    }
#else
    FRESULT res = remove(pathStr);
#endif

    if (res) {
      jsfsReportError("Unable to delete file", res);
      return false;
    }
    return true;
  }
Пример #12
0
bool socketClientConnectionsIdle(JsNetwork *net) {
    char buf[64];

    JsVar *arr = socketGetArray(HTTP_ARRAY_HTTP_CLIENT_CONNECTIONS,false);
    if (!arr) return false;

    bool hadSockets = false;
    JsvObjectIterator it;
    jsvObjectIteratorNew(&it, arr);
    while (jsvObjectIteratorHasValue(&it)) {
        hadSockets = true;
        // Get connection, socket, and socket type
        // For normal sockets, socket==connection, but for HTTP we split it into a request and a response
        JsVar *connection = jsvObjectIteratorGetValue(&it);
        SocketType socketType = socketGetType(connection);
        JsVar *socket = (socketType==ST_HTTP) ? jsvObjectGetChild(connection,HTTP_NAME_RESPONSE_VAR,0) : jsvLockAgain(connection);

        bool closeConnectionNow = jsvGetBoolAndUnLock(jsvObjectGetChild(connection, HTTP_NAME_CLOSENOW, false));
        int sckt = (int)jsvGetIntegerAndUnLock(jsvObjectGetChild(connection,HTTP_NAME_SOCKET,0))-1; // so -1 if undefined
        if (sckt<0) closeConnectionNow = true;
        bool hadHeaders = true;
        if (socketType==ST_HTTP)
            hadHeaders = jsvGetBoolAndUnLock(jsvObjectGetChild(connection,HTTP_NAME_HAD_HEADERS,0));
        JsVar *receiveData = jsvObjectGetChild(connection,HTTP_NAME_RECEIVE_DATA,0);

        /* We do this up here because we want to wait until we have been once
         * around the idle loop (=callbacks have been executed) before we run this */
        if (hadHeaders)
            socketClientPushReceiveData(connection, socket, &receiveData);

        if (!closeConnectionNow) {
            JsVar *sendData = jsvObjectGetChild(connection,HTTP_NAME_SEND_DATA,0);
            // send data if possible
            if (sendData) {
                bool b = socketSendData(net, connection, sckt, &sendData);
                if (!b)
                    closeConnectionNow = true;
                jsvObjectSetChild(connection, HTTP_NAME_SEND_DATA, sendData); // _http_send prob updated sendData
            } else {
                if (jsvGetBoolAndUnLock(jsvObjectGetChild(connection, HTTP_NAME_CLOSE, false)))
                    closeConnectionNow = true;
            }
            // Now read data if possible
            int num = net->recv(net, sckt, buf, sizeof(buf));
            if (num<0) {
                // we probably disconnected so just get rid of this
                closeConnectionNow = true;
            } else {
                // add it to our request string
                if (num>0) {
                    if (!receiveData) {
                        receiveData = jsvNewFromEmptyString();
                        jsvObjectSetChild(connection, HTTP_NAME_RECEIVE_DATA, receiveData);
                    }
                    if (receiveData) { // could be out of memory
                        jsvAppendStringBuf(receiveData, buf, (size_t)num);
                        if (socketType==ST_HTTP && !hadHeaders) {
                            JsVar *resVar = jsvObjectGetChild(connection,HTTP_NAME_RESPONSE_VAR,0);
                            if (httpParseHeaders(&receiveData, resVar, false)) {
                                hadHeaders = true;
                                jsvUnLock(jsvObjectSetChild(connection, HTTP_NAME_HAD_HEADERS, jsvNewFromBool(hadHeaders)));
                                jsiQueueObjectCallbacks(connection, HTTP_NAME_ON_CONNECT, &resVar, 1);
                            }
                            jsvUnLock(resVar);
                            jsvObjectSetChild(connection, HTTP_NAME_RECEIVE_DATA, receiveData);
                        }
                    }
                }
            }
            jsvUnLock(sendData);
        }

        if (closeConnectionNow) {
            socketClientPushReceiveData(connection, socket, &receiveData);
            if (socketType != ST_HTTP)
                jsiQueueObjectCallbacks(socket, HTTP_NAME_ON_END, 0, 0);
            jsiQueueObjectCallbacks(socket, HTTP_NAME_ON_CLOSE, 0, 0);

            _socketConnectionKill(net, connection);
            JsVar *connectionName = jsvObjectIteratorGetKey(&it);
            jsvObjectIteratorNext(&it);
            jsvRemoveChild(arr, connectionName);
            jsvUnLock(connectionName);
        } else {
            jsvObjectIteratorNext(&it);
        }

        jsvUnLock(receiveData);
        jsvUnLock(connection);
        jsvUnLock(socket);
    }
    jsvUnLock(arr);

    return hadSockets;
}
Пример #13
0
bool socketServerConnectionsIdle(JsNetwork *net) {
    char buf[64];

    JsVar *arr = socketGetArray(HTTP_ARRAY_HTTP_SERVER_CONNECTIONS,false);
    if (!arr) return false;

    bool hadSockets = false;
    JsvObjectIterator it;
    jsvObjectIteratorNew(&it, arr);
    while (jsvObjectIteratorHasValue(&it)) {
        hadSockets = true;
        // Get connection, socket, and socket type
        // For normal sockets, socket==connection, but for HTTP we split it into a request and a response
        JsVar *connection = jsvObjectIteratorGetValue(&it);
        SocketType socketType = socketGetType(connection);
        JsVar *socket = (socketType==ST_HTTP) ? jsvObjectGetChild(connection,HTTP_NAME_RESPONSE_VAR,0) : jsvLockAgain(connection);

        int sckt = (int)jsvGetIntegerAndUnLock(jsvObjectGetChild(connection,HTTP_NAME_SOCKET,0))-1; // so -1 if undefined
        bool closeConnectionNow = jsvGetBoolAndUnLock(jsvObjectGetChild(connection, HTTP_NAME_CLOSENOW, false));

        if (!closeConnectionNow) {
            int num = net->recv(net, sckt, buf,sizeof(buf));
            if (num<0) {
                // we probably disconnected so just get rid of this
                closeConnectionNow = true;
            } else {
                // add it to our request string
                if (num>0) {
                    JsVar *receiveData = jsvObjectGetChild(connection,HTTP_NAME_RECEIVE_DATA,0);
                    JsVar *oldReceiveData = receiveData;
                    if (!receiveData) receiveData = jsvNewFromEmptyString();
                    if (receiveData) {
                        jsvAppendStringBuf(receiveData, buf, (size_t)num);
                        bool hadHeaders = jsvGetBoolAndUnLock(jsvObjectGetChild(connection,HTTP_NAME_HAD_HEADERS,0));
                        if (!hadHeaders && httpParseHeaders(&receiveData, connection, true)) {
                            hadHeaders = true;
                            jsvUnLock(jsvObjectSetChild(connection, HTTP_NAME_HAD_HEADERS, jsvNewFromBool(hadHeaders)));
                            JsVar *server = jsvObjectGetChild(connection,HTTP_NAME_SERVER_VAR,0);
                            JsVar *args[2] = { connection, socket };
                            jsiQueueObjectCallbacks(server, HTTP_NAME_ON_CONNECT, args, (socketType==ST_HTTP) ? 2 : 1);
                            jsvUnLock(server);
                        }
                        if (hadHeaders && !jsvIsEmptyString(receiveData)) {
                            // execute 'data' callback or save data
                            jswrap_stream_pushData(connection, receiveData);
                            // clear received data
                            jsvUnLock(receiveData);
                            receiveData = 0;
                        }
                        // if received data changed, update it
                        if (receiveData != oldReceiveData)
                            jsvObjectSetChild(connection,HTTP_NAME_RECEIVE_DATA,receiveData);
                        jsvUnLock(receiveData);
                    }
                }
            }

            // send data if possible
            JsVar *sendData = jsvObjectGetChild(socket,HTTP_NAME_SEND_DATA,0);
            if (sendData) {
                if (!socketSendData(net, socket, sckt, &sendData))
                    closeConnectionNow = true;
                jsvObjectSetChild(socket, HTTP_NAME_SEND_DATA, sendData); // socketSendData prob updated sendData
            }
            // only close if we want to close, have no data to send, and aren't receiving data
            if (jsvGetBoolAndUnLock(jsvObjectGetChild(socket,HTTP_NAME_CLOSE,0)) && !sendData && num<=0)
                closeConnectionNow = true;
            jsvUnLock(sendData);
        }
        if (closeConnectionNow) {
            // send out any data that we were POSTed
            JsVar *receiveData = jsvObjectGetChild(connection,HTTP_NAME_RECEIVE_DATA,0);
            bool hadHeaders = jsvGetBoolAndUnLock(jsvObjectGetChild(connection,HTTP_NAME_HAD_HEADERS,0));
            if (hadHeaders && !jsvIsEmptyString(receiveData)) {
                // execute 'data' callback or save data
                jswrap_stream_pushData(connection, receiveData);
            }
            jsvUnLock(receiveData);
            // fire the close listeners
            jsiQueueObjectCallbacks(connection, HTTP_NAME_ON_CLOSE, 0, 0);
            jsiQueueObjectCallbacks(socket, HTTP_NAME_ON_CLOSE, 0, 0);

            _socketConnectionKill(net, connection);
            JsVar *connectionName = jsvObjectIteratorGetKey(&it);
            jsvObjectIteratorNext(&it);
            jsvRemoveChild(arr, connectionName);
            jsvUnLock(connectionName);
        } else
            jsvObjectIteratorNext(&it);
        jsvUnLock(connection);
        jsvUnLock(socket);
    }
    jsvObjectIteratorFree(&it);
    jsvUnLock(arr);

    return hadSockets;
}
Пример #14
0
void httpClientConnectionsIdle() {
  char buf[64];

  JsVar *arr = httpGetArray(HTTP_ARRAY_HTTP_CLIENT_CONNECTIONS,false);
  if (!arr) return;

  JsArrayIterator it;
  jsvArrayIteratorNew(&it, arr);
  while (jsvArrayIteratorHasElement(&it)) {
    JsVar *connection = jsvArrayIteratorGetElement(&it);
    bool closeConnectionNow = jsvGetBoolAndUnLock(jsvObjectGetChild(connection, HTTP_NAME_CLOSENOW, false));
    SOCKET sckt = (SOCKET)jsvGetIntegerAndUnLock(jsvObjectGetChild(connection,HTTP_NAME_SOCKET,0))-1; // so -1 if undefined
    bool hadHeaders = jsvGetBoolAndUnLock(jsvObjectGetChild(connection,HTTP_NAME_HAD_HEADERS,0));
    JsVar *receiveData = jsvObjectGetChild(connection,HTTP_NAME_RECEIVE_DATA,0);

    /* We do this up here because we want to wait until we have been once
     * around the idle loop (=callbacks have been executed) before we run this */
    if (hadHeaders && receiveData) {
      JsVar *resVar = jsvObjectGetChild(connection,HTTP_NAME_RESPONSE_VAR,0);
      jsiQueueObjectCallbacks(resVar, HTTP_NAME_ON_DATA, receiveData, 0);
      jsvUnLock(resVar);
      // clear - because we have issued a callback
      jsvObjectSetChild(connection,HTTP_NAME_RECEIVE_DATA,0);
    }

    if (sckt!=INVALID_SOCKET) {
      JsVar *sendData = jsvObjectGetChild(connection,HTTP_NAME_SEND_DATA,0);
      // send data if possible
      if (sendData) {
        // this will wait to see if we can write any more, but ALSO
        // will wait for connection
        fd_set writefds;
        FD_ZERO(&writefds);
        FD_SET(sckt, &writefds);
        struct timeval time;
        time.tv_sec = 0;
        time.tv_usec = 0;
        int n = select(sckt+1, 0, &writefds, 0, &time);
        if (n==SOCKET_ERROR ) {
           // we probably disconnected so just get rid of this
          closeConnectionNow = true;
        } else if (FD_ISSET(sckt, &writefds)) {
          if (!_http_send(sckt, &sendData))
            closeConnectionNow = true;
          jsvObjectSetChild(connection, HTTP_NAME_SEND_DATA, sendData); // _http_send prob updated sendData
        }
#ifdef USE_CC3000
      } else { // When in CC3000, write then read (FIXME)
#else
      } // When in Linux, just read and write at the same time
      {
#endif
        // Now receive data
        fd_set s;
        FD_ZERO(&s);
        FD_SET(sckt,&s);
        // check for waiting clients
        struct timeval timeout;
        timeout.tv_sec = 0;
  #ifdef USE_CC3000
        timeout.tv_usec = 5000; // 5 millisec
  #else
        timeout.tv_usec = 0;
  #endif
        int n = select(sckt+1,&s,NULL,NULL,&timeout);
        if (n==SOCKET_ERROR) {
          // we probably disconnected so just get rid of this
          closeConnectionNow = true;
        } else if (n>0) {
          // receive data
          int num = (int)recv(sckt,buf,sizeof(buf),0);
          // add it to our request string
          if (num>0) {
            if (!receiveData) {
              receiveData = jsvNewFromEmptyString();
              jsvObjectSetChild(connection, HTTP_NAME_RECEIVE_DATA, receiveData);
            }
            if (receiveData) { // could be out of memory
              jsvAppendStringBuf(receiveData, buf, num);
              if (!hadHeaders) {
                JsVar *resVar = jsvObjectGetChild(connection,HTTP_NAME_RESPONSE_VAR,0);
                if (httpParseHeaders(&receiveData, resVar, false)) {
                  hadHeaders = true;
                  jsvUnLock(jsvObjectSetChild(connection, HTTP_NAME_HAD_HEADERS, jsvNewFromBool(hadHeaders)));
                  jsiQueueObjectCallbacks(connection, HTTP_NAME_ON_CONNECT, resVar, 0);
                }
                jsvUnLock(resVar);
                jsvObjectSetChild(connection, HTTP_NAME_RECEIVE_DATA, receiveData);
              }
            }
          } else if (num==0) {
            // select says data, but recv says 0 means connection is closed
            closeConnectionNow = true;
          }
        } else {
  #ifdef USE_CC3000
          // Nothing to send or receive, and closed
          if (!sendData && cc3000_socket_has_closed(sckt))
            closeConnectionNow = true;
  #endif
        }
      }
      jsvUnLock(sendData);
    }
    jsvUnLock(receiveData);
    if (closeConnectionNow) {
      JsVar *resVar = jsvObjectGetChild(connection,HTTP_NAME_RESPONSE_VAR,0);
      jsiQueueObjectCallbacks(resVar, HTTP_NAME_ON_CLOSE, 0, 0);
      jsvUnLock(resVar);

      _httpClientConnectionKill(connection);
      JsVar *connectionName = jsvArrayIteratorGetIndex(&it);
      jsvArrayIteratorNext(&it);
      jsvRemoveChild(arr, connectionName);
      jsvUnLock(connectionName);
    } else
      jsvArrayIteratorNext(&it);
    jsvUnLock(connection);
  }
  jsvUnLock(arr);
}
Пример #15
0
void httpServerConnectionsIdle() {
  char buf[64];

  JsVar *arr = httpGetArray(HTTP_ARRAY_HTTP_SERVER_CONNECTIONS,false);
  if (!arr) return;
  JsArrayIterator it;
  jsvArrayIteratorNew(&it, arr);
  while (jsvArrayIteratorHasElement(&it)) {
    JsVar *connection = jsvArrayIteratorGetElement(&it);
    JsVar *connectReponse = jsvObjectGetChild(connection,HTTP_NAME_RESPONSE_VAR,0);
    SOCKET sckt = (SOCKET)jsvGetIntegerAndUnLock(jsvObjectGetChild(connection,HTTP_NAME_SOCKET,0))-1; // so -1 if undefined
    bool closeConnectionNow = jsvGetBoolAndUnLock(jsvObjectGetChild(connection, HTTP_NAME_CLOSENOW, false));
    bool hadData = false;
    // TODO: look for unreffed connections?
    fd_set s;
    FD_ZERO(&s);
    FD_SET(sckt,&s);
    // check for waiting clients
    struct timeval timeout;
    timeout.tv_sec = 0;
    timeout.tv_usec = 0;
    int n = select(sckt+1,&s,NULL,NULL,&timeout);
    if (n==SOCKET_ERROR) {
      // we probably disconnected so just get rid of this
      closeConnectionNow = true;
    } else if (n>0) {
      hadData = true;
      // receive data
      int num = (int)recv(sckt,buf,sizeof(buf),0);
      // add it to our request string
      if (num>0) {
        JsVar *receiveData = jsvObjectGetChild(connection,HTTP_NAME_RECEIVE_DATA,0);
        if (!receiveData) {
          receiveData = jsvNewFromEmptyString();
          jsvObjectSetChild(connection,HTTP_NAME_RECEIVE_DATA,receiveData);
        }
        if (receiveData) {
          jsvAppendStringBuf(receiveData, buf, num);
          bool hadHeaders = jsvGetBoolAndUnLock(jsvObjectGetChild(connection,HTTP_NAME_HAD_HEADERS,0));
          if (!hadHeaders && httpParseHeaders(&receiveData, connection, true)) {
            hadHeaders = true;
            jsvUnLock(jsvObjectSetChild(connection, HTTP_NAME_HAD_HEADERS, jsvNewFromBool(hadHeaders)));
            JsVar *resVar = jsvObjectGetChild(connection,HTTP_NAME_RESPONSE_VAR,0);
            JsVar *server = jsvObjectGetChild(connection,HTTP_NAME_SERVER_VAR,0);
            jsiQueueObjectCallbacks(server, HTTP_NAME_ON_CONNECT, connection, resVar);
            jsvUnLock(server);
            jsvUnLock(resVar);
          }
          jsvUnLock(receiveData);
        }
      }
    }

    // send data if possible
    JsVar *sendData = jsvObjectGetChild(connectReponse,HTTP_NAME_SEND_DATA,0);
    if (sendData) {
      fd_set writefds;
      FD_ZERO(&writefds);
      FD_SET(sckt, &writefds);
      struct timeval time;
      time.tv_sec = 0;
      time.tv_usec = 0;
      int n = select(sckt+1, 0, &writefds, 0, &time);
      if (n==SOCKET_ERROR ) {
         // we probably disconnected so just get rid of this
        closeConnectionNow = true;
      } else if (FD_ISSET(sckt, &writefds)) {
        if (!_http_send(sckt, &sendData))
          closeConnectionNow = true;
      }
      jsvObjectSetChild(connectReponse, HTTP_NAME_SEND_DATA, sendData); // _http_send prob updated sendData
    } else {
#ifdef USE_CC3000
      // nothing to send, nothing to receive, and closed...
      if (!hadData && cc3000_socket_has_closed(sckt))
        closeConnectionNow = true;
#endif
    }
    if (jsvGetBoolAndUnLock(jsvObjectGetChild(connectReponse,HTTP_NAME_CLOSE,0)) && !sendData)
      closeConnectionNow = true;
    jsvUnLock(sendData);
    if (closeConnectionNow) {
      JsVar *resVar = jsvObjectGetChild(connection,HTTP_NAME_RESPONSE_VAR,0);
      jsiQueueObjectCallbacks(resVar, HTTP_NAME_ON_CLOSE, 0, 0);
      jsvUnLock(resVar);

      _httpServerConnectionKill(connection);
      JsVar *connectionName = jsvArrayIteratorGetIndex(&it);
      jsvArrayIteratorNext(&it);
      jsvRemoveChild(arr, connectionName);
      jsvUnLock(connectionName);
    } else
      jsvArrayIteratorNext(&it);
    jsvUnLock(connection);
    jsvUnLock(connectReponse);
  }
  jsvArrayIteratorFree(&it);
  jsvUnLock(arr);
}
Пример #16
0
JsVar *jswrap_spi_send(JsVar *parent, JsVar *srcdata, Pin nss_pin) {
  NOT_USED(parent);
  IOEventFlags device = jsiGetDeviceFromClass(parent);

  jswrap_spi_send_data data;
  if (!jsspiGetSendFunction(parent, &data.spiSend, &data.spiSendData))
    return 0;

  JsVar *dst = 0;

  // we're sending and receiving
  if (DEVICE_IS_SPI(device)) jshSPISetReceive(device, true);

  // assert NSS
  if (nss_pin!=PIN_UNDEFINED) jshPinOutput(nss_pin, false);

  // send data
  if (jsvIsNumeric(srcdata)) {
    int r = data.spiSend((unsigned char)jsvGetInteger(srcdata), &data.spiSendData);
    if (r<0) r = data.spiSend(-1, &data.spiSendData);
    dst = jsvNewFromInteger(r); // retrieve the byte (no send!)
  } else if (jsvIsString(srcdata)) {
    dst = jsvNewFromEmptyString();
    JsvStringIterator it;
    jsvStringIteratorNew(&it, srcdata, 0);
    int incount = 0, outcount = 0;
    while (jsvStringIteratorHasChar(&it) && !jspIsInterrupted()) {
      unsigned char in = (unsigned char)jsvStringIteratorGetChar(&it);
      incount++;
      int out = data.spiSend(in, &data.spiSendData);
      if (out>=0) {
        outcount++;
        char outc = (char)out;
        jsvAppendStringBuf(dst, (char*)&outc, 1);
      }
      jsvStringIteratorNext(&it);
    }
    jsvStringIteratorFree(&it);
    // finally add the remaining bytes  (no send!)
    while (outcount < incount && !jspIsInterrupted()) {
      outcount++;
      unsigned char out = (unsigned char)data.spiSend(-1, &data.spiSendData);
      jsvAppendStringBuf(dst, (char*)&out, 1);
    }
  } else {
    int nBytes = jsvIterateCallbackCount(srcdata);
    dst = jsvNewTypedArray(ARRAYBUFFERVIEW_UINT8, nBytes);
    if (dst) {
      data.rxAmt = data.txAmt = 0;
      jsvArrayBufferIteratorNew(&data.it, dst, 0);
      // Write data
      jsvIterateCallback(srcdata, (void (*)(int,  void *))jswrap_spi_send_cb, &data);
      // Wait until SPI send is finished, and flush data
      while (data.rxAmt < data.txAmt && !jspIsInterrupted())
        jswrap_spi_send_cb(-1, &data);
      jsvArrayBufferIteratorFree(&data.it);
    }
  }

  // de-assert NSS
  if (nss_pin!=PIN_UNDEFINED) jshPinOutput(nss_pin, true);
  return dst;
}