bool build_and_send_packet(struct nabto_stream_s* stream, uint8_t type, uint32_t seq, const uint8_t* winInfoData, size_t winInfoSize, uint8_t* data, uint16_t size, struct nabto_stream_sack_data* sackData) { enum { l_win = NP_PAYLOAD_WINDOW_SYN_BYTELENGTH - NP_PAYLOAD_WINDOW_BYTELENGTH }; uint8_t* ptr; nabto_connect* con = stream->connection; uint8_t* buf = nabtoCommunicationBuffer; struct nabto_stream_tcb* tcb = &stream->u.tcb; uint32_t ackToSend = unabto_stream_ack_number_to_send(tcb); uint16_t recvWinSize = unabto_stream_advertised_window_size(tcb); if (con == NULL) { return false; } nabtoSetFutureStamp(&tcb->ackStamp, 2*tcb->cfg.timeoutMsec); ptr = insert_data_header(buf, con->spnsi, con->nsico, stream->streamTag); ptr = insert_payload(ptr, NP_PAYLOAD_TYPE_WINDOW, 0, l_win + winInfoSize + (type == NP_PAYLOAD_WINDOW_FLAG_ACK ? 2 : 0)); WRITE_FORWARD_U8 (ptr, type); WRITE_FORWARD_U8 (ptr, NP_STREAM_VERSION); WRITE_FORWARD_U16(ptr, stream->idCP); WRITE_FORWARD_U16(ptr, stream->idSP); WRITE_FORWARD_U32(ptr, seq); WRITE_FORWARD_U32(ptr, ackToSend); if (type == NP_PAYLOAD_WINDOW_FLAG_ACK) { WRITE_FORWARD_U16(ptr, recvWinSize); } if (winInfoSize) { memcpy(ptr, (const void*) winInfoData, winInfoSize); ptr += winInfoSize; } if (sackData && sackData->nPairs > 0) { uint8_t i; ptr = insert_payload(ptr, NP_PAYLOAD_TYPE_SACK, 0, 8 * sackData->nPairs); for (i = 0; i < sackData->nPairs; i++) { WRITE_FORWARD_U32(ptr, sackData->pairs[i].start); WRITE_FORWARD_U32(ptr, sackData->pairs[i].end); } } ptr = insert_payload(ptr, NP_PAYLOAD_TYPE_CRYPTO, 0, 0); if (send_and_encrypt_packet_con(con, data, size, ptr)) { tcb->ackSent = ackToSend; tcb->lastSentAdvertisedWindow = recvWinSize; stream->stats.sentPackets++; return true; } else { return false; } }
uint8_t* insert_rendezvous_stats_payload(uint8_t* ptr, uint8_t* end, nabto_connect* con) { UNABTO_ASSERT(ptr <= end); if (end-ptr < NP_PAYLOAD_RENDEZVOUS_STATS_BYTELENGTH) { return NULL; } ptr = insert_payload(ptr, NP_PAYLOAD_TYPE_RENDEZVOUS_STATS, 0, 7); WRITE_FORWARD_U8(ptr, NP_PAYLOAD_RENDEZVOUS_STATS_VERSION); WRITE_FORWARD_U8(ptr, con->clientNatType); WRITE_FORWARD_U8(ptr, nmc.context.natType); WRITE_FORWARD_U16(ptr, con->rendezvousConnectState.portsOpened); WRITE_FORWARD_U16(ptr, con->rendezvousConnectState.socketsOpened); return ptr; }
uint8_t* insert_connection_stats_payload(uint8_t* ptr, uint8_t* end, nabto_connect* con) { nabto_stamp_t now; uint32_t connectionAge; UNABTO_ASSERT(ptr <= end); if (end-ptr < NP_PAYLOAD_CONNECTION_STATS_BYTELENGTH) { return NULL; } ptr = insert_payload(ptr, NP_PAYLOAD_TYPE_CONNECTION_STATS, 0, 21); WRITE_FORWARD_U8(ptr, NP_PAYLOAD_CONNECTION_STATS_VERSION); now = nabtoGetStamp(); connectionAge = nabtoStampDiff2ms(nabtoStampDiff(&now, &con->stats.connectionStart)); WRITE_FORWARD_U32(ptr, connectionAge); WRITE_FORWARD_U32(ptr, con->stats.packetsReceived); WRITE_FORWARD_U32(ptr, con->stats.packetsSent); WRITE_FORWARD_U32(ptr, con->stats.bytesReceived); WRITE_FORWARD_U32(ptr, con->stats.bytesSent); return ptr; }
bool unabto_dns_fallback_data_send_packet_start_request(unabto_dns_fallback_session* session, uint16_t chunks, nabto_endpoint* ep, uint16_t totalLength) { uint8_t requestBuffer[19]; uint8_t* ptr = requestBuffer; uint8_t* buffer; uint8_t* end; uint16_t id; size_t length; WRITE_FORWARD_U8(ptr, UDF_TYPE_SEND_START); WRITE_FORWARD_U16(ptr, 19); WRITE_FORWARD_U16(ptr, session->sessionId); WRITE_FORWARD_U16(ptr, session->random++); WRITE_FORWARD_U16(ptr, session->packetId); WRITE_FORWARD_U16(ptr, chunks); WRITE_FORWARD_U32(ptr, ep->addr); WRITE_FORWARD_U16(ptr, ep->port); WRITE_FORWARD_U16(ptr, totalLength); buffer = requestEncoded; end = buffer + ENCODED_BUFFER_SIZE; buffer = unabto_dns_fallback_encode_request_as_question(buffer, end, requestBuffer, 19, session->domain, &id); if (buffer == NULL) { return false; } length = buffer - requestEncoded; NABTO_LOG_INFO(("Sending DNS start request id: %" PRIu16, id)); nabto_write(session->dnsClient.sockets[(session->dnsClient.lastUsedSocket++) % DNS_CLIENT_SOCKETS], requestEncoded, length, session->dnsClient.dnsServer.addr, session->dnsClient.dnsServer.port); return true; }
bool unabto_dns_fallback_data_send_packet_chunk_request(unabto_dns_fallback_session* session, uint8_t* start, uint16_t dataStart, uint16_t length, uint16_t chunkId) { uint8_t* ptr = requestBuffer; size_t requestLength; uint8_t* buffer; uint8_t* end; uint16_t id; size_t packetLength; WRITE_FORWARD_U8(ptr, UDF_TYPE_SEND_CHUNK); WRITE_FORWARD_U16(ptr, length+13); WRITE_FORWARD_U16(ptr, session->sessionId); WRITE_FORWARD_U16(ptr, session->random++); WRITE_FORWARD_U16(ptr, session->packetId); WRITE_FORWARD_U16(ptr, chunkId); WRITE_FORWARD_U16(ptr, dataStart); memcpy(ptr, start, length); ptr += length; requestLength = ptr - requestBuffer; buffer = requestEncoded; end = buffer + ENCODED_BUFFER_SIZE; buffer = unabto_dns_fallback_encode_request_as_question(buffer, end, requestBuffer, requestLength, session->domain, &id); if (buffer == NULL) { return false; } packetLength = buffer - requestEncoded; NABTO_LOG_INFO(("Sending DNS chunk request id: %" PRIu16, id)); nabto_write(session->dnsClient.sockets[(session->dnsClient.lastUsedSocket++) % DNS_CLIENT_SOCKETS], requestEncoded, packetLength, session->dnsClient.dnsServer.addr, session->dnsClient.dnsServer.port); return true; }
uint8_t* insert_connect_stats_payload(uint8_t* ptr, uint8_t* end, nabto_connect* con) { uint8_t connectionType; UNABTO_ASSERT(ptr <= end); if (end-ptr < NP_PAYLOAD_CONNECT_STATS_BYTELENGTH) { return NULL; } ptr = insert_payload(ptr, NP_PAYLOAD_TYPE_CONNECT_STATS, 0, 2); switch (get_connection_type(con)) { case NCT_LOCAL: connectionType = NP_PAYLOAD_CONNECT_STATS_CONNECTION_TYPE_LOCAL; break; case NCT_CONNECTING: connectionType = NP_PAYLOAD_CONNECT_STATS_CONNECTION_TYPE_CONNECTING; break; case NCT_REMOTE_RELAY: connectionType = NP_PAYLOAD_CONNECT_STATS_CONNECTION_TYPE_UDP_RELAY; break; case NCT_REMOTE_RELAY_MICRO: connectionType = NP_PAYLOAD_CONNECT_STATS_CONNECTION_TYPE_TCP_RELAY; break; case NCT_REMOTE_P2P: connectionType = NP_PAYLOAD_CONNECT_STATS_CONNECTION_TYPE_P2P; break; } WRITE_FORWARD_U8(ptr, NP_PAYLOAD_CONNECT_STATS_VERSION); WRITE_FORWARD_U8(ptr, connectionType); return ptr; }
uint8_t* insert_cp_id_payload(uint8_t* ptr, uint8_t* end, nabto_connect* con) { size_t cpIdLength = strlen(con->clientId); UNABTO_ASSERT(ptr <= end); if ((size_t)(end - ptr) < NP_PAYLOAD_CP_ID_BYTELENGTH + cpIdLength) { return NULL; } ptr = insert_payload(ptr, NP_PAYLOAD_TYPE_CP_ID, 0, 1+cpIdLength); WRITE_FORWARD_U8(ptr, NP_PAYLOAD_CP_ID_TYPE_MAIL); memcpy(ptr, (const void*) con->clientId, cpIdLength); ptr += cpIdLength; return ptr; }
bool unabto_dns_fallback_data_send_get_request(unabto_dns_fallback_session* session) { uint8_t* ptr = requestBuffer; size_t requestLength; uint8_t* buffer = nabtoCommunicationBuffer; uint8_t* end = buffer + nabtoCommunicationBufferSize; size_t packetLength; WRITE_FORWARD_U8(ptr, UDF_TYPE_GET); WRITE_FORWARD_U16(ptr, 9); WRITE_FORWARD_U16(ptr, session->sessionId); WRITE_FORWARD_U16(ptr, session->random++); WRITE_FORWARD_U16(ptr, session->recvFrequency); requestLength = ptr - requestBuffer; buffer = unabto_dns_fallback_encode_request_as_question(buffer, end, requestBuffer, requestLength, session->domain, &session->current_get_identification); if (buffer == NULL) { return false; } packetLength = buffer - nabtoCommunicationBuffer; NABTO_LOG_INFO(("Sending DNS get request id: %" PRIu16 " timeout: %" PRIu16, session->current_get_identification, session->recvFrequency)); nabto_write(session->dnsClient.sockets[(session->dnsClient.lastUsedSocket++) % DNS_CLIENT_SOCKETS], nabtoCommunicationBuffer, packetLength, session->dnsClient.dnsServer.addr, session->dnsClient.dnsServer.port); return true; }