static void AJ_WSL_HTCProcessControlMessageResponse_Fake(AJ_BufNode* pNodeHTCBody) { wsl_wmi_cmd_hdr* wmiCmdHdr2; wmiCmdHdr2 = (wsl_wmi_cmd_hdr*)pNodeHTCBody->buffer; AJ_WSL_WMI_CMD_HDR_FROM_WIRE(wmiCmdHdr2); AJ_WSL_WMI_CMD_HDR_Print(wmiCmdHdr2); AJ_BufNodePullBytes(pNodeHTCBody, sizeof(wsl_wmi_cmd_hdr)); if (wmiCmdHdr2->commandID == WMI_SOCKET_CMDID) { wsl_wmi_socket_response_event* pSocketResp = (wsl_wmi_socket_response_event*)pNodeHTCBody->buffer; AJ_WSL_WMI_SOCK_RESPONSE_FROM_WIRE(pSocketResp); switch (pSocketResp->responseType) { case WSL_SOCK_OPEN: { //AJ_AlwaysPrintf(("PING response was received over the wire: addr 0x%x, size 0x%x\n\n", ping->ip_addr, ping->size)); AJ_AlwaysPrintf(("OPEN response was received over the wire, Handle is %x\n\n", pSocketResp->socketHandle)); break; } case WSL_SOCK_PING: { //wsl_wmi_sock_ping* ping = (wsl_wmi_sock_ping*)pNodeHTCBody->buffer; //AJ_WSL_WMI_SOCK_PING_FROM_WIRE(ping); //AJ_AlwaysPrintf(("PING response was received over the wire: addr 0x%x, size 0x%x\n\n", ping->ip_addr, ping->size)); AJ_AlwaysPrintf(("PING response was received over the wire, Handle is %x\n\n", pSocketResp->socketHandle)); break; } default: AJ_ASSERT("unknown socket command\n\n"); } } }
void AJ_WSL_WMI_ProcessSocketDataResponse(AJ_BufNode* pNodeHTCBody) { int8_t socketIndex; uint32_t u32; uint16_t lead, payloadSize, _port; uint32_t _handle, srcAddr; uint16_t ipv6addr[8]; uint16_t bufferOffset = 0; wsl_work_item** ppWork; wsl_work_item* sockResp; // AJ_DumpBytes("WMI_SOCKET_RESPONSE B", pNodeHTCBody->buffer, pNodeHTCBody->length); // Get the initial bytes of data in the packet WMI_Unmarshal(pNodeHTCBody->buffer, "quuq", &lead, &u32, &_handle, &_port); //AJ_BufNodePullBytes(pNodeHTCBody, 12); bufferOffset += 12; // look for the matching handle in the global context then mark it invalid socketIndex = AJ_WSL_FindSocketContext(_handle); if (socketIndex == INVALID_SOCKET) { AJ_WarnPrintf(("data returned for invalid socket. Handle = %lu\n", _handle)); return; } if (AJ_WSL_SOCKET_CONTEXT[socketIndex].domain == WSL_AF_INET6) { bufferOffset += 6; // Get the IPv6 address and payload size WMI_Unmarshal(pNodeHTCBody->buffer + bufferOffset, "6uq", &ipv6addr, &u32, &payloadSize); // Advance the buffer to the start of the payload bufferOffset += 28; } else { bufferOffset += 2; // Get the IPv4 address WMI_Unmarshal(pNodeHTCBody->buffer + bufferOffset, "4q", &srcAddr, &payloadSize); // Advance the buffer to the start of the payload bufferOffset += 12; } sockResp = (wsl_work_item*)AJ_WSL_Malloc(sizeof(wsl_work_item)); memset(sockResp, 0, sizeof(wsl_work_item)); sockResp->itemType = WSL_NET_DATA_RX; sockResp->size = payloadSize; sockResp->node = AJ_BufNodeCreateAndTakeOwnership(pNodeHTCBody); AJ_BufNodePullBytes(sockResp->node, bufferOffset); /// the length of the socket header info header sockResp->node->length = payloadSize; ppWork = &sockResp; AJ_QueuePush(AJ_WSL_SOCKET_CONTEXT[socketIndex].workRxQueue, ppWork, AJ_TIMER_FOREVER); }
static void AJ_WSL_HTCProcessControlMessage_Fake(AJ_BufNode* pNodeHTCBody) { wsl_wmi_cmd_hdr* wmiCmdHdr2; wmiCmdHdr2 = (wsl_wmi_cmd_hdr*)pNodeHTCBody->buffer; AJ_WSL_WMI_CMD_HDR_FROM_WIRE(wmiCmdHdr2); AJ_WSL_WMI_CMD_HDR_Print(wmiCmdHdr2); AJ_BufNodePullBytes(pNodeHTCBody, sizeof(wsl_wmi_cmd_hdr)); if (wmiCmdHdr2->commandID == WMI_SOCKET_CMDID) { wsl_wmi_socket_cmd* pSocketCmd = (wsl_wmi_socket_cmd*)pNodeHTCBody->buffer; AJ_WSL_WMI_SOCKET_CMD_FROM_WIRE(pSocketCmd); AJ_WSL_WMI_SOCKET_CMD_HDR_Print(pSocketCmd); if (pSocketCmd->cmd_type == WSL_SOCK_PING) { switch (pSocketCmd->cmd_type) { case WSL_SOCK_OPEN: { wsl_wmi_sock_open* open = (wsl_wmi_sock_open*)pNodeHTCBody->buffer; AJ_WSL_WMI_SOCK_OPEN_FROM_WIRE(open); AJ_AlwaysPrintf(("OPEN call was received over the wire: domain 0x%x, type 0x%x protocol 0x%x\n\n", open->domain, open->protocol, open->type)); break; } case WSL_SOCK_PING: { wsl_wmi_sock_ping* ping = (wsl_wmi_sock_ping*)pNodeHTCBody->buffer; AJ_WSL_WMI_SOCK_PING_FROM_WIRE(ping); AJ_AlwaysPrintf(("PING call was received over the wire: addr 0x%x, size 0x%x\n\n", ping->ip_addr, ping->size)); break; } default: AJ_ASSERT("unknown socket command\n\n"); } } } }
/* * 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; }
/* * read from the mailbox and do something useful with the HTC message. */ void AJ_WSL_HTC_ProcessIncoming(void) { uint16_t lenRead; uint8_t* bufRead; AJ_BufNode* pNodeHTCBody; uint8_t endpointID; uint8_t flags; uint16_t payloadLength; uint8_t controlBytes[2]; AJ_Status status; status = AJ_WSL_ReadFromMBox(AJ_WSL_SPI_MBOX_0, &lenRead, &bufRead); AJ_ASSERT(status == AJ_OK); // now create a AJ_BufList from the data we read pNodeHTCBody = AJ_BufListCreateNodeExternalZero(bufRead, lenRead, FALSE); pNodeHTCBody->flags = 0; // reset the AJ_BUFNODE_EXTERNAL_BUFFER flag, because I own this now. WMI_Unmarshal(pNodeHTCBody->buffer, "yyqyy", &endpointID, &flags, &payloadLength, &controlBytes[0], &controlBytes[1]); AJ_BufNodePullBytes(pNodeHTCBody, 6); //AJ_WSL_WMI_PrintMessage(pNodeHTCBody); AJ_DumpBytes("HTC_CONTROL", pNodeHTCBody->buffer, pNodeHTCBody->length); /* examine the endpoint of the HTC message*/ if ((flags & AJ_WSL_HTC_RECV_TRAILER_PRESENT) && ((payloadLength - controlBytes[0]) > 0)) { switch (endpointID) { case AJ_WSL_HTC_CONTROL_ENDPOINT: { uint16_t* messageID = (uint16_t*)pNodeHTCBody->buffer; AJ_InfoPrintf(("Read HTC control endpoint, messageID %x\n", *messageID)); switch (*messageID) { case AJ_WSL_HTC_MSG_READY_ID: { /* process the message and change state */ uint16_t readyMessageID; WMI_Unmarshal(pNodeHTCBody->buffer, "qqqyyy", &readyMessageID, &AJ_WSL_HTC_Global.creditCount, &AJ_WSL_HTC_Global.creditSize, &AJ_WSL_HTC_Global.maxEndpoints, &AJ_WSL_HTC_Global.HTCVersion, &AJ_WSL_HTC_Global.maxMessagesPerBundle); /* SIDE EFFECT */ AJ_WarnPrintf(("MSG_READY, credit count %x, credit size:%d\n", AJ_WSL_HTC_Global.creditCount, AJ_WSL_HTC_Global.creditSize)); AJ_WSL_HTC_Global.endpoints[AJ_WSL_HTC_CONTROL_ENDPOINT].state = AJ_WSL_HTC_UNINITIALIZED_RECV_READY; break; } case AJ_WSL_HTC_SERVICE_CONNECT_RESPONSE_ID: { AJ_WarnPrintf(("HTC MSG AJ_WSL_HTC_SERVICE_CONNECT_RESPONSE_ID\n")); break; } default: AJ_WarnPrintf(("HTC MSG ID unknown\n")); AJ_DumpBytes("WMI_SOCKET_RESPONSE", pNodeHTCBody->buffer, pNodeHTCBody->length); break; } break; } case AJ_WSL_HTC_DATA_ENDPOINT1: { // AJ_DumpBytes("DATA ENDPOINT WMI ", pNodeHTCBody->buffer, pNodeHTCBody->length); AJ_WSL_WMI_ProcessWMIEvent(pNodeHTCBody); break; } case AJ_WSL_HTC_DATA_ENDPOINT2: case AJ_WSL_HTC_DATA_ENDPOINT3: case AJ_WSL_HTC_DATA_ENDPOINT4: { AJ_DumpBytes("DATA ENDPOINT WMI_SOCKET_RESPONSE", pNodeHTCBody->bufferStart, pNodeHTCBody->length); AJ_WSL_WMI_ProcessSocketDataResponse(pNodeHTCBody); //AJ_InfoPrintf(("Read HTC data endpoint %d\n", htcHdr.endpointID)); // TODO send the data up to the next API level //AJ_WSL_WMI_PrintMessage(pNodeHTCBody); break; } default: AJ_ErrPrintf(("UNKNOWN Endpoint %d", endpointID)); AJ_ASSERT(FALSE); break; } } /* * Trailers can come on any packet */ if (flags & AJ_WSL_HTC_RECV_TRAILER_PRESENT) { uint16_t packetLength; uint8_t trailerLength = controlBytes[0]; packetLength = payloadLength - trailerLength; //AJ_InfoPrintf(("Read HTC RX trailer, length %d\n", htcHdr.controlBytes[0])); AJ_BufNodePullBytes(pNodeHTCBody, packetLength); // consume the packet, leave the trailer /* * handle multiple trailers per HTC message */ while (trailerLength) { uint8_t trailerType; uint8_t length; //AJ_BufListNodePrintDump(pNodeHTCBody, NULL); WMI_Unmarshal(pNodeHTCBody->buffer, "yy", &trailerType, &length); AJ_BufNodePullBytes(pNodeHTCBody, 2); // consume the trailer trailerLength -= 2; switch (trailerType) { case AJ_WSL_HTC_RXTRAILER_CREDIT_REPORT: { uint8_t credits; uint8_t endpoint; WMI_Unmarshal(pNodeHTCBody->buffer, "yy", &endpoint, &credits); AJ_InfoPrintf(("Add %d credits to endpoint %d\n", credits, endpoint)); AJ_WSL_HTC_Global.endpoints[endpoint].txCredits += credits; break; } default: { AJ_InfoPrintf(("HTC trailer: type not handled %d\n", trailerType)); } } trailerLength -= length; AJ_BufNodePullBytes(pNodeHTCBody, length); // consume the trailer } } //intentionally freeing the buffer here AJ_BufListFreeNodeAndBuffer(pNodeHTCBody, NULL); }