static AJ_Status AuthAdvance(AJ_SASL_Context* context, AJ_IOBuffer* rxBuf, AJ_IOBuffer* txBuf) { AJ_Status status = AJ_OK; AJ_InfoPrintf(("AuthAdvance(context=0x%p, rxBuf=0x%p, txBuf=0x%p)\n", context, rxBuf, txBuf)); if (context->state != AJ_SASL_SEND_AUTH_REQ) { /* * All the authentication messages end in a CR/LF so read until we get a newline */ while ((AJ_IO_BUF_AVAIL(rxBuf) == 0) || (*(rxBuf->writePtr - 1) != '\n')) { status = rxBuf->recv(rxBuf, AJ_IO_BUF_SPACE(rxBuf), 3500); if (status != AJ_OK) { break; } } } if (status == AJ_OK) { uint32_t inLen = AJ_IO_BUF_AVAIL(rxBuf); *rxBuf->writePtr = '\0'; status = AJ_SASL_Advance(context, (char*)rxBuf->readPtr, (char*)txBuf->writePtr, AJ_IO_BUF_SPACE(txBuf)); if (status == AJ_OK) { rxBuf->readPtr += inLen; txBuf->writePtr += strlen((char*)txBuf->writePtr); status = txBuf->send(txBuf); } } return status; }
AJ_Status AJ_Net_RecvFrom(AJ_IOBuffer* buf, uint32_t len, uint32_t timeout) { AJ_InfoPrintf(("AJ_Net_RecvFrom(buf=0x%p, len=%d., timeout=%d.)\n", buf, len, timeout)); AJ_Status status = AJ_OK; int ret; uint32_t rx = AJ_IO_BUF_SPACE(buf); unsigned long Recv_lastCall = millis(); AJ_InfoPrintf(("AJ_Net_RecvFrom(): len %d, rx %d, timeout %d\n", len, rx, timeout)); rx = min(rx, len); while ((g_clientUDP.parsePacket() == 0) && (millis() - Recv_lastCall < timeout)) { delay(10); // wait for data or timeout } AJ_InfoPrintf(("AJ_Net_RecvFrom(): millis %d, Last_call %d, timeout %d, Avail %d\n", millis(), Recv_lastCall, timeout, g_clientUDP.available())); ret = g_clientUDP.read(buf->writePtr, rx); AJ_InfoPrintf(("AJ_Net_RecvFrom(): read() returns %d, rx %d\n", ret, rx)); if (ret == -1) { AJ_InfoPrintf(("AJ_Net_RecvFrom(): read() fails. status=AJ_ERR_READ\n")); status = AJ_ERR_READ; } else { if (ret != -1) { AJ_DumpBytes("AJ_Net_RecvFrom", buf->writePtr, ret); } buf->writePtr += ret; AJ_InfoPrintf(("AJ_Net_RecvFrom(): status=AJ_OK\n")); status = AJ_OK; } AJ_InfoPrintf(("AJ_Net_RecvFrom(): status=%s\n", AJ_StatusText(status))); return status; }
static AJ_Status ComposeWhoHas(AJ_IOBuffer* txBuf, const char* prefix) { size_t preLen = strlen(prefix); NSHeader* hdr = (NSHeader*)txBuf->writePtr; uint8_t* p = txBuf->writePtr + 6; size_t outLen = (6 + preLen + 2); AJ_InfoPrintf(("ComposeWhoHas(txbuf=0x%p, prefix=\"%s\")\n", txBuf, prefix)); if (outLen > AJ_IO_BUF_SPACE(txBuf)) { AJ_ErrPrintf(("ComposeWhoHas(): AJ_ERR_RESOURCES\n")); return AJ_ERR_RESOURCES; } hdr->version = MSG_V1 | NSV_V1; hdr->qCount = 1; hdr->aCount = 0; hdr->ttl = 0; hdr->flags = WHO_HAS_MSG; hdr->nameCount = 1; *p++ = (uint8_t)(preLen + 1); memcpy(p, prefix, preLen); /* * Tack wild-card onto the end of the name to indicate it's prefix */ p[preLen] = '*'; txBuf->writePtr += outLen; return AJ_OK; }
static AJ_Status EncryptMessage(AJ_Message* msg) { AJ_IOBuffer* ioBuf = &msg->bus->sock.tx; AJ_Status status; uint8_t key[16]; uint8_t nonce[5]; uint8_t role = AJ_ROLE_KEY_UNDEFINED; uint32_t mlen = MessageLen(msg); uint32_t hlen = mlen - msg->hdr->bodyLen; /* * Check there is room to append the MAC */ if (AJ_IO_BUF_SPACE(ioBuf) < MAC_LENGTH) { return AJ_ERR_RESOURCES; } msg->hdr->bodyLen += MAC_LENGTH; ioBuf->writePtr += MAC_LENGTH; /* * Use the group key for multicast and broadcast signals the session key otherwise. */ if ((msg->hdr->msgType == AJ_MSG_SIGNAL) && !msg->destination) { status = AJ_GetGroupKey(NULL, key); } else { status = AJ_GetSessionKey(msg->destination, key, &role); } if (status != AJ_OK) { AJ_ErrPrintf(("Encryption required but peer %s is not authenticated", msg->destination)); status = AJ_ERR_SECURITY; } else { InitNonce(msg, role, nonce); status = AJ_Encrypt_CCM(key, ioBuf->bufStart, mlen, hlen, MAC_LENGTH, nonce, sizeof(nonce)); } return status; }
/* * Write bytes to an I/O buffer */ static AJ_Status WriteBytes(AJ_Message* msg, const void* data, size_t numBytes, size_t pad) { AJ_Status status = AJ_OK; AJ_IOBuffer* ioBuf = &msg->bus->sock.tx; if (numBytes && !data) { return AJ_ERR_NULL; } while (numBytes + pad) { size_t canWrite = AJ_IO_BUF_SPACE(ioBuf); if ((numBytes + pad) > canWrite) { /* * If we have already marshaled the header we can write what we have in the buffer */ if (msg->hdr) { status = AJ_ERR_RESOURCES; } else { //#pragma calls = AJ_Net_Send status = ioBuf->send(ioBuf); } if (status != AJ_OK) { break; } canWrite = AJ_IO_BUF_SPACE(ioBuf); } /* * Write pad bytes */ while (pad) { *ioBuf->writePtr++ = 0; --canWrite; --pad; } if (numBytes < canWrite) { canWrite = numBytes; } memcpy(ioBuf->writePtr, data, canWrite); ioBuf->writePtr += canWrite; numBytes -= canWrite; } return status; }
static AJ_Status ReadLine(AJ_IOBuffer* rxBuf) { /* * All the authentication messages end in a CR/LF so read until we get a newline */ AJ_Status status = AJ_OK; while ((AJ_IO_BUF_AVAIL(rxBuf) == 0) || (*(rxBuf->writePtr - 1) != '\n')) { status = rxBuf->recv(rxBuf, AJ_IO_BUF_SPACE(rxBuf), 3500); if (status != AJ_OK) { break; } } return status; }
AJ_Status AJ_Net_RecvFrom(AJ_IOBuffer* buf, uint32_t len, uint32_t timeout) { //AJ_InfoPrintf(("AJ_Net_RecvFrom(buf=0x%p, len=%d., timeout=%d.)\n", buf, len, timeout)); AJ_Status status = AJ_OK; int ret; uint32_t rx = AJ_IO_BUF_SPACE(buf); unsigned long Recv_lastCall = millis(); // printf("AJ_Net_RecvFrom(): len %d, rx %d, timeout %d\n", len, rx, timeout); // rx = min(rx, len); while ((sock_rx_state==0) && (millis() - Recv_lastCall < timeout)) { //printf("millis() - Recv_lastCall = %d \n", (millis() - Recv_lastCall)); recv(rx_socket, udp_data_rx, MAIN_WIFI_M2M_BUFFER_SIZE, 0); m2m_wifi_handle_events(NULL); } ret=sock_rx_state; // printf("AJ_Net_RecvFrom(): millis %d, Last_call %d, timeout %d, Avail %d\n", millis(), Recv_lastCall, timeout, g_clientUDP.available()); //ret = g_clientUDP.read(buf->writePtr, rx); //AJ_InfoPrintf(("AJ_Net_RecvFrom(): read() returns %d, rx %d\n", ret, rx)); if (ret == -1) { printf("AJ_Net_RecvFrom(): read() fails. status=AJ_ERR_READ\n"); status = AJ_ERR_READ; } else { if (ret != -1) { AJ_DumpBytes("AJ_Net_RecvFrom", buf->writePtr, ret); } buf->writePtr += ret; // printf("AJ_Net_RecvFrom(): status=AJ_OK\n"); status = AJ_OK; } printf("AJ_Net_RecvFrom(): status=%s\n", AJ_StatusText(status)); return /*sock_rx_state;*/status; }
AJ_Status RxFunc(AJ_IOBuffer* buf, uint32_t len, uint32_t timeout) { size_t rx = AJ_IO_BUF_SPACE(buf); rx = min(len, rx); rx = min(wireBytes, rx); if (!rx) { return AJ_ERR_READ; } else { memcpy(buf->writePtr, wireBuffer, rx); /* * Shuffle the remaining data to the front of the buffer */ memmove(wireBuffer, wireBuffer + rx, wireBytes - rx); wireBytes -= rx; buf->writePtr += rx; return AJ_OK; } }
AJ_Status AJ_Net_Recv(AJ_IOBuffer* buf, uint32_t len, uint32_t timeout) { AJ_Status status = AJ_ERR_READ; uint32_t ret; uint32_t rx = AJ_IO_BUF_SPACE(buf); uint32_t recvd = 0; unsigned long Recv_lastCall = millis(); // first we need to clear out our buffer uint32_t M = 0; //printf("AJ_Net_Recv(buf=0x%p, len=%d., timeout=%d.)\n", buf, len, timeout); if (rxLeftover != 0) { // there was something leftover from before, // printf("AJ_NetRecv(): leftover was: %d\n", rxLeftover); M = min(rx, rxLeftover); memcpy(buf->writePtr, rxDataStash, M); // copy leftover into buffer. buf->writePtr += M; // move the data pointer over memmove(rxDataStash, rxDataStash + M, rxLeftover - M); // shift left-overs toward the start. rxLeftover -= M; recvd += M; // we have read as many bytes as we can // higher level isn't requesting any more if (recvd == rx) { // printf("AJ_Net_Recv(): status=AJ_OK\n"); return AJ_OK; } } if ((M != 0) && (rxLeftover != 0)) { printf("AJ_Net_REcv(): M was: %d, rxLeftover was: %d\n", M, rxLeftover); } //printf("NetRecv before while: tcp_data_rx[0]= %d\n", tcp_data_rx[0]); while ((tcp_rx_ready==0) && (millis() - Recv_lastCall < timeout)) { // recv(tcp_client_socket, gau8SocketTestBuffer, sizeof(gau8SocketTestBuffer), 0); recv(tcp_client_socket, tcp_data_rx, sizeof(tcp_data_rx), 0); // recv(tcp_client_socket, buf->writePtr, sizeof(tcp_data_rx), 0); m2m_wifi_handle_events(NULL); } // printf("NetRecv: tcp_data_rx[0]= %d\n", tcp_data_rx[0]); if (tcp_rx_ready==0) { printf("AJ_Net_Recv(): timeout. status=AJ_ERR_TIMEOUT\n"); status = AJ_ERR_TIMEOUT; } else { memcpy(AJ_in_data_tcp, tcp_data_rx,tcp_rx_ready); uint32_t askFor = rx; askFor -= M; ret=tcp_rx_ready; // printf("AJ_Net_Recv(): ask for: %d\n", askFor); if (askFor < ret) { printf("AJ_Net_Recv(): BUFFER OVERRUN: askFor=%u, ret=%u\n", askFor, ret); } if (ret == -1) { printf("AJ_Net_Recv(): read() failed. status=AJ_ERR_READ\n"); status = AJ_ERR_READ; } else { // printf("AJ_Net_Recv(): ret now %d\n", ret); AJ_DumpBytes("Recv", buf->writePtr, ret); if (ret > askFor) { printf("AJ_Net_Recv(): new leftover %d\n", ret - askFor); // now shove the extra into the stash memcpy(rxDataStash + rxLeftover, buf->writePtr + askFor, ret - askFor); rxLeftover += (ret - askFor); buf->writePtr += rx; } else { buf->writePtr += ret; } status = AJ_OK; } } // printf("!!!!!!!!!!!!!!!buf->writePtr=%x\n",buf->writePtr); tcp_rx_ready=0; return status; }
AJ_Status AJ_Net_Recv(AJ_IOBuffer* buf, uint32_t len, uint32_t timeout) { AJ_Status status = AJ_ERR_READ; uint32_t ret; uint32_t rx = AJ_IO_BUF_SPACE(buf); uint32_t recvd = 0; unsigned long Recv_lastCall = millis(); // first we need to clear out our buffer uint32_t M = 0; AJ_InfoPrintf(("AJ_Net_Recv(buf=0x%p, len=%d., timeout=%d.)\n", buf, len, timeout)); if (rxLeftover != 0) { // there was something leftover from before, AJ_InfoPrintf(("AJ_NetRecv(): leftover was: %d\n", rxLeftover)); M = min(rx, rxLeftover); memcpy(buf->writePtr, rxDataStash, M); // copy leftover into buffer. buf->writePtr += M; // move the data pointer over memmove(rxDataStash, rxDataStash + M, rxLeftover - M); // shift left-overs toward the start. rxLeftover -= M; recvd += M; // we have read as many bytes as we can // higher level isn't requesting any more if (recvd == rx) { AJ_InfoPrintf(("AJ_Net_Recv(): status=AJ_OK\n")); return AJ_OK; } } if ((M != 0) && (rxLeftover != 0)) { AJ_InfoPrintf(("AJ_Net_REcv(): M was: %d, rxLeftover was: %d\n", M, rxLeftover)); } // wait for data to become available // time out if nothing arrives while (g_client.connected() && g_client.available() == 0 && (millis() - Recv_lastCall < timeout)) { delay(50); // wait for data or timeout } // return timeout if nothing is available AJ_InfoPrintf(("AJ_Net_Recv(): millis %d, Last_call %d timeout %d Avail: %d\n", millis(), Recv_lastCall, timeout, g_client.available())); if (g_client.connected() && (millis() - Recv_lastCall >= timeout) && (g_client.available() == 0)) { AJ_InfoPrintf(("AJ_Net_Recv(): timeout. status=AJ_ERR_TIMEOUT\n")); return AJ_ERR_TIMEOUT; } if (g_client.connected()) { uint32_t askFor = rx; askFor -= M; AJ_InfoPrintf(("AJ_Net_Recv(): ask for: %d\n", askFor)); ret = g_client.read(buf->writePtr, askFor); AJ_InfoPrintf(("AJ_Net_Recv(): read(): ret %d askfor %d\n", ret, askFor)); if (askFor < ret) { AJ_InfoPrintf(("AJ_Net_Recv(): BUFFER OVERRUN: askFor=%u, ret=%u\n", askFor, ret)); } if (ret == -1) { AJ_ErrPrintf(("AJ_Net_Recv(): read() failed. status=AJ_ERR_READ\n")); status = AJ_ERR_READ; } else { AJ_InfoPrintf(("AJ_Net_Recv(): ret now %d\n", ret)); AJ_DumpBytes("Recv", buf->writePtr, ret); if (ret > askFor) { AJ_InfoPrintf(("AJ_Net_Recv(): new leftover %d\n", ret - askFor)); // now shove the extra into the stash memcpy(rxDataStash + rxLeftover, buf->writePtr + askFor, ret - askFor); rxLeftover += (ret - askFor); buf->writePtr += rx; } else { buf->writePtr += ret; } status = AJ_OK; } } return status; }
static AJ_Status AJ_Net_RecvFrom(AJ_IOBuffer* buf, uint32_t len, uint32_t timeout) { AJ_Status status; DWORD ret; DWORD rx = AJ_IO_BUF_SPACE(buf); fd_set fds; size_t rc = 0; size_t i; const struct timeval tv = { timeout / 1000, 1000 * (timeout % 1000) }; SOCKET sock; int numSocks = 0; AJ_InfoPrintf(("AJ_Net_RecvFrom(buf=0x%p, len=%d., timeout=%d.)\n", buf, len, timeout)); assert(buf->direction == AJ_IO_BUF_RX); assert(NumMcastSocks > 0); // we sent the discovery requests out on ALL broadcast and multicast interfaces // now we need to listen on the NS version 1 sockets and the mDNS recv sockets FD_ZERO(&fds); for (i = 0; i < NumMcastSocks; ++i) { if (!McastSocks[i].is_mdns || McastSocks[i].is_mdnsrecv) { SOCKET sock = McastSocks[i].sock; FD_SET(sock, &fds); numSocks++; } } // wait for discovery response rc = select(numSocks, &fds, NULL, NULL, &tv); if (rc == 0) { AJ_InfoPrintf(("AJ_Net_RecvFrom(): select() timed out. status=AJ_ERR_TIMEOUT\n")); return AJ_ERR_TIMEOUT; } else if (rc < 0) { AJ_ErrPrintf(("AJ_Net_RecvFrom(): select() failed. WSAGetLastError()=0x%x, status=AJ_ERR_READ\n", WSAGetLastError())); return AJ_ERR_READ; } // ignore multiple replies; only consider the first one to arrive rx = min(rx, len); for (i = 0; i < NumMcastSocks; ++i) { if (!McastSocks[i].is_mdns || McastSocks[i].is_mdnsrecv) { if (FD_ISSET(McastSocks[i].sock, &fds)) { sock = McastSocks[i].sock; if (McastSocks[i].is_mdnsrecv) { buf->flags |= AJ_IO_BUF_MDNS; } else { buf->flags |= AJ_IO_BUF_AJ; } break; } } } if (sock != INVALID_SOCKET) { ret = recvfrom(sock, buf->writePtr, rx, 0, NULL, 0); if (ret == SOCKET_ERROR) { AJ_ErrPrintf(("AJ_Net_RecvFrom(): recvfrom() failed. WSAGetLastError()=0x%x, status=AJ_ERR_READ\n", WSAGetLastError())); status = AJ_ERR_READ; } else { buf->writePtr += ret; status = AJ_OK; } } else { AJ_ErrPrintf(("AJ_Net_RecvFrom(): invalid socket. status=AJ_ERR_READ\n")); status = AJ_ERR_READ; } AJ_InfoPrintf(("AJ_Net_RecvFrom(): status=%s\n", AJ_StatusText(status))); return status; }
static AJ_Status AJ_Net_Recv(AJ_IOBuffer* buf, uint32_t len, uint32_t timeout) { AJ_Status status = AJ_ERR_READ; WSAEVENT events[2]; DWORD rx = AJ_IO_BUF_SPACE(buf); DWORD flags = 0; DWORD ret = SOCKET_ERROR; NetContext* ctx = (NetContext*) buf->context; AJ_InfoPrintf(("AJ_Net_Recv(buf=0x%p, len=%d, timeout=%d)\n", buf, len, timeout)); assert(buf->direction == AJ_IO_BUF_RX); rx = min(rx, len); if (!rx) { return AJ_OK; } /* * Overlapped receives cannot be cancelled. We are relying the fact that a timedout or * interrupted receive will be eventually reposted with the same buffer. */ if (wsaOverlapped.hEvent == INVALID_HANDLE_VALUE) { wsbuf.len = rx; wsbuf.buf = buf->writePtr; memset(&wsaOverlapped, 0, sizeof(WSAOVERLAPPED)); wsaOverlapped.hEvent = recvEvent; ret = WSARecv(ctx->tcpSock, &wsbuf, 1, NULL, &flags, &wsaOverlapped, NULL); if ((ret == SOCKET_ERROR) && (WSAGetLastError() != WSA_IO_PENDING)) { AJ_ErrPrintf(("WSARecv(): failed WSAGetLastError()=%d\n", WSAGetLastError())); return AJ_ERR_READ; } } /* * Assert that the buffer and length are the same in the case where this is a reposting of the * receive after an timeout or interrupt. */ AJ_ASSERT(wsbuf.buf == buf->writePtr); AJ_ASSERT(wsbuf.len == rx); events[0] = wsaOverlapped.hEvent; events[1] = interruptEvent; ret = WSAWaitForMultipleEvents(2, events, FALSE, timeout, TRUE); if (ret == WSA_WAIT_EVENT_0) { if (WSAGetOverlappedResult(ctx->tcpSock, &wsaOverlapped, &rx, TRUE, &flags)) { status = AJ_OK; } } else if (ret == WSA_WAIT_TIMEOUT) { status = AJ_ERR_TIMEOUT; } else if (ret == (WSA_WAIT_EVENT_0 + 1)) { WSAResetEvent(interruptEvent); status = AJ_ERR_INTERRUPTED; } else { AJ_ErrPrintf(("AJ_Net_Recv(): WSAGetLastError()=%d\n", WSAGetLastError())); } if (status == AJ_OK) { /* * Reset recv event and clear overlapped struct for the next call */ WSAResetEvent(wsaOverlapped.hEvent); wsaOverlapped.hEvent = INVALID_HANDLE_VALUE; buf->writePtr += rx; AJ_InfoPrintf(("AJ_Net_Recv(): read %d bytes\n", rx)); } return status; }