/* * This function just returns the work item. If there is data inside that you want * you have to unmarshal it after you receive the work item. */ AJ_Status AJ_WSL_WMI_WaitForWorkItem(uint32_t socket, uint8_t command, wsl_work_item** item, uint32_t timeout) { AJ_Status status; AJ_Time timer; AJ_InitTimer(&timer); // AJ_AlwaysPrintf(("WaitForWorkItem: %x\n", command)); //wsl_work_item* item; status = AJ_QueuePull(AJ_WSL_SOCKET_CONTEXT[socket].workRxQueue, item, timeout); timeout -= AJ_GetElapsedTime(&timer, TRUE); if ((status == AJ_OK) && item && *item) { if ((status == AJ_OK) && ((*item)->itemType == WSL_NET_INTERUPT)) { // We don't care about the interrupted signal for any calls using this function AJ_WSL_WMI_FreeWorkItem((*item)); status = AJ_QueuePull(AJ_WSL_SOCKET_CONTEXT[socket].workRxQueue, item, timeout); } if ((status == AJ_OK) && ((*item)->itemType == command)) { AJ_InfoPrintf(("AJ_WSL_WMI_WaitForWorkItem(): Received work item %s\n", WSL_WorkItemText(command))); return AJ_OK; } else if ((status == AJ_OK) && ((*item)->itemType == WSL_NET_DISCONNECT)) { AJ_InfoPrintf(("Got disconnect while waiting for %s\n", WSL_WorkItemText(command))); // Clean up the network queues int i; for (i = 0; i < AJ_WSL_SOCKET_MAX; i++) { wsl_work_item* clear; AJ_WSL_SOCKET_CONTEXT[i].valid = FALSE; // Removed any stashed data AJ_BufListFree(AJ_WSL_SOCKET_CONTEXT[i].stashedRxList, 1); // Reallocate a new stash AJ_WSL_SOCKET_CONTEXT[i].stashedRxList = AJ_BufListCreate(); // Reset the queue, any work items are now invalid since the socket was closed while (AJ_QueuePull(AJ_WSL_SOCKET_CONTEXT[i].workRxQueue, &clear, 0) == AJ_OK) { AJ_WSL_WMI_FreeWorkItem(clear); } while (AJ_QueuePull(AJ_WSL_SOCKET_CONTEXT[i].workTxQueue, &clear, 0) == AJ_OK) { AJ_WSL_WMI_FreeWorkItem(clear); } AJ_QueueReset(AJ_WSL_SOCKET_CONTEXT[i].workRxQueue); AJ_QueueReset(AJ_WSL_SOCKET_CONTEXT[i].workTxQueue); } AJ_WSL_WMI_FreeWorkItem((*item)); return AJ_ERR_LINK_DEAD; } else if ((status == AJ_OK) && ((*item)->itemType == WSL_NET_DATA_RX)) { // If we got data we want to save it and not throw it away, its still not what we // wanted so we can free the work item as it wont be needed at a higher level AJ_InfoPrintf(("Got data while waiting for %s\n", WSL_WorkItemText(command))); if ((*item)->node->length) { AJ_BufNode* new_node = AJ_BufNodeCreateAndTakeOwnership((*item)->node); AJ_BufListPushTail(AJ_WSL_SOCKET_CONTEXT[socket].stashedRxList, new_node); AJ_WSL_WMI_FreeWorkItem((*item)); return AJ_ERR_NULL; } } else { AJ_WarnPrintf(("AJ_WSL_WMI_WaitForWorkItem(): Received incorrect work item %s, wanted %s\n", WSL_WorkItemText((*item)->itemType), WSL_WorkItemText(command))); // Wrong work item, but return NULL because we can free the item internally AJ_WSL_WMI_FreeWorkItem((*item)); return AJ_ERR_NULL; } } return AJ_ERR_NULL; }
/* * create the WMI request to bind a socket on the target device to an address and port */ int16_t AJ_WSL_NET_socket_recv(AJ_WSL_SOCKNUM sock, uint8_t* buffer, uint32_t sizeBuffer, uint32_t timeout) { // AJ_InfoPrintf(("AJ_WSL_NET_socket_recv()\n")); int16_t ret = -1; uint32_t rx = sizeBuffer; uint32_t stash = 0; // read from stash first. uint16_t stashLength; if (sock >= AJ_WSL_SOCKET_MAX) { // tried to get data from an invalid socket, return an error return ret; } if (AJ_WSL_SOCKET_CONTEXT[sock].valid == FALSE) { // tried to get data from an invalid socket, return the data read from the stash AJ_BufListFree(AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList, 1); AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList = AJ_BufListCreate(); //flush the queue AJ_QueueReset(AJ_WSL_SOCKET_CONTEXT[sock].workRxQueue); return ret; } if (AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList) { stashLength = AJ_BufListLengthOnWire(AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList); if (stashLength != 0) { stash = min(rx, stashLength); AJ_BufListCopyBytes(AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList, stash, buffer); AJ_BufListPullBytes(AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList, stash); // shift left-overs toward the start. ret = stash; sizeBuffer -= stash; } } // wait until there is data if (sizeBuffer) { wsl_work_item* item = NULL; AJ_Status status; // the stash was depleted and you want more data if (AJ_WSL_SOCKET_CONTEXT[sock].valid == FALSE) { // tried to get data from an invalid socket, return the data read from the stash return ret; } status = AJ_QueuePull(AJ_WSL_SOCKET_CONTEXT[sock].workRxQueue, &item, timeout); if (item) { if (item->itemType == WSL_NET_INTERUPT) { // At this point we dont care about the interrupted signal but we are expecting a RX packet // so we need to pull the next item off the queue AJ_WSL_WMI_FreeWorkItem(item); status = AJ_QueuePull(AJ_WSL_SOCKET_CONTEXT[sock].workRxQueue, &item, timeout); } if ((status == AJ_OK) && (item->itemType == WSL_NET_DISCONNECT)) { AJ_InfoPrintf(("Disconnect received\n")); // Clean up the network queues int i; for (i = 0; i < AJ_WSL_SOCKET_MAX; i++) { AJ_WSL_SOCKET_CONTEXT[i].valid = FALSE; // Removed any stashed data AJ_BufListFree(AJ_WSL_SOCKET_CONTEXT[i].stashedRxList, 1); // Reallocate a new stash AJ_WSL_SOCKET_CONTEXT[i].stashedRxList = AJ_BufListCreate(); // Reset the queue, any work items are now invalid since the socket was closed AJ_QueueReset(AJ_WSL_SOCKET_CONTEXT[i].workRxQueue); AJ_QueueReset(AJ_WSL_SOCKET_CONTEXT[i].workTxQueue); } ret = -1; } else if ((status == AJ_OK) && (item->itemType == WSL_NET_CLOSE || item->itemType == AJ_WSL_WORKITEM(AJ_WSL_WORKITEM_SOCKET, WSL_SOCK_CLOSE))) { // Pull the close work item off the queue AJ_QueuePull(AJ_WSL_SOCKET_CONTEXT[sock].workRxQueue, &item, 0); // Socket was closed so tear down the connections AJ_WSL_SOCKET_CONTEXT[sock].valid = FALSE; // Removed any stashed data AJ_BufListFree(AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList, 1); // Reallocate a new stash AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList = AJ_BufListCreate(); // Reset the queue, any work items are now invalid since the socket was closed AJ_QueueReset(AJ_WSL_SOCKET_CONTEXT[sock].workRxQueue); AJ_QueueReset(AJ_WSL_SOCKET_CONTEXT[sock].workTxQueue); ret = -1; } else if ((status == AJ_OK) && (item->itemType == WSL_NET_DATA_RX)) { //AJ_InfoPrintf(("=====DATA RX ITEM RECEIVED=====\n")); //AJ_DumpBytes("DATA RX ITEM", item->node->buffer, item->size); rx = min(sizeBuffer, item->size); memcpy(buffer + stash, item->node->buffer, rx); AJ_BufNodePullBytes(item->node, rx); // check node: if not empty assign to stash. if (item->node->length) { AJ_BufListPushTail(AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList, item->node); item->node = NULL; } ret = rx + stash; } else { AJ_InfoPrintf(("AJ_WSL_NET_socket_recv(): BAD WORK ITEM RECEIVED\n")); } AJ_WSL_WMI_FreeWorkItem(item); } else { ret = 0; AJ_InfoPrintf(("socket_recv timed out\n")); } } return ret; }
/* * Poll over a socket until there is data ready or till a timeout * * Returns -2 on timeout * -1 on interrupted * 1 on success * 0 on close * */ int16_t AJ_WSL_NET_socket_select(AJ_WSL_SOCKNUM sock, uint32_t timeout) { AJ_Time timer; wsl_work_item* peek; AJ_Status status; int16_t ret = 0; // Check if the socket is valid if (sock >= AJ_WSL_SOCKET_MAX) { // tried to get data from an invalid socket, return an error return ret; } if (AJ_WSL_SOCKET_CONTEXT[sock].valid == FALSE) { // tried to get data from an invalid socket, return the data read from the stash AJ_BufListFree(AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList, 1); AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList = AJ_BufListCreate(); //flush the queue return ret; } AJ_InitTimer(&timer); // There are 5 conditions that we need to check for // 1. If we got an interrupted work item // 2. If there is data in the RX stash // 3. If there is a RX work item in the queue // 4. If there is a socket close work item in the queue // 5. If the timeout has expired while (1) { status = AJ_QueuePeek(AJ_WSL_SOCKET_CONTEXT[sock].workRxQueue, &peek); //AJ_AlwaysPrintf(("Item type = %u\n", peek->itemType)); if ((status == AJ_OK) && (peek->itemType == WSL_NET_INTERUPT)) { // Pull the interrupted item off because we dont need it anymore AJ_QueuePull(AJ_WSL_SOCKET_CONTEXT[sock].workRxQueue, &peek, 0); AJ_WSL_WMI_FreeWorkItem(peek); ret = -1; break; } else if (AJ_BufListLengthOnWire(AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList) > 0) { ret = 1; break; } else if ((status == AJ_OK) && (peek->itemType == WSL_NET_DATA_RX)) { ret = 1; break; } else if ((status == AJ_OK) && (peek->itemType == WSL_NET_CLOSE || peek->itemType == WSL_NET_DISCONNECT || peek->itemType == AJ_WSL_WORKITEM(AJ_WSL_WORKITEM_SOCKET, WSL_SOCK_CLOSE))) { // Pull the close work item off the queue AJ_QueuePull(AJ_WSL_SOCKET_CONTEXT[sock].workRxQueue, &peek, 0); // Socket was closed so tear down the connections AJ_WSL_SOCKET_CONTEXT[sock].valid = FALSE; // Removed any stashed data AJ_BufListFree(AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList, 1); // Reallocate a new stash AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList = AJ_BufListCreate(); // Reset the queue, any work items are now invalid since the socket was closed AJ_QueueReset(AJ_WSL_SOCKET_CONTEXT[sock].workRxQueue); AJ_QueueReset(AJ_WSL_SOCKET_CONTEXT[sock].workTxQueue); AJ_WSL_WMI_FreeWorkItem(peek); ret = 0; break; } else if (AJ_GetElapsedTime(&timer, TRUE) >= timeout) { ret = -2; break; } } return ret; }