| 57 | } |
| 58 | |
| 59 | void DatagramDestination::SendDatagram (std::shared_ptr<DatagramSession> session, const uint8_t * payload, size_t len, |
| 60 | uint16_t fromPort, uint16_t toPort, const i2p::util::Mapping * options) |
| 61 | { |
| 62 | if (session) |
| 63 | { |
| 64 | std::shared_ptr<I2NPMessage> msg; |
| 65 | switch (session->GetVersion ()) |
| 66 | { |
| 67 | case eDatagramV3: |
| 68 | { |
| 69 | uint8_t flags[] = { 0x00, 0x03 }; // datagram3, no options |
| 70 | if (options) |
| 71 | { |
| 72 | uint8_t optionsBuf[256]; // TODO: evaluate actual size |
| 73 | size_t optionsLen = options->ToBuffer (optionsBuf, 256); |
| 74 | if (optionsLen) flags[1] |= DATAGRAM3_FLAG_OPTIONS; |
| 75 | msg = CreateDataMessage ({{m_Owner->GetIdentity ()->GetIdentHash (), 32}, {flags, 2}, |
| 76 | {optionsBuf, optionsLen}, {payload, len}}, fromPort, toPort, i2p::client::PROTOCOL_TYPE_DATAGRAM3, false); // datagram3 |
| 77 | } |
| 78 | else |
| 79 | msg = CreateDataMessage ({{m_Owner->GetIdentity ()->GetIdentHash (), 32}, |
| 80 | {flags, 2}, {payload, len}}, fromPort, toPort, i2p::client::PROTOCOL_TYPE_DATAGRAM3, false); // datagram3 |
| 81 | break; |
| 82 | } |
| 83 | case eDatagramV1: |
| 84 | { |
| 85 | if (m_Owner->GetIdentity ()->GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1) |
| 86 | { |
| 87 | uint8_t hash[32]; |
| 88 | SHA256(payload, len, hash); |
| 89 | m_Owner->Sign (hash, 32, m_Signature.data ()); |
| 90 | } |
| 91 | else |
| 92 | m_Owner->Sign (payload, len, m_Signature.data ()); |
| 93 | msg = CreateDataMessage ({{m_From.data (), m_From.size ()}, {m_Signature.data (), m_Signature.size ()}, {payload, len}}, |
| 94 | fromPort, toPort, i2p::client::PROTOCOL_TYPE_DATAGRAM, !session->IsRatchets ()); // datagram1 |
| 95 | break; |
| 96 | } |
| 97 | case eDatagramV2: |
| 98 | { |
| 99 | constexpr uint8_t flags[] = { 0x00, 0x02 }; // datagram2, no options |
| 100 | // signature |
| 101 | std::vector<uint8_t> signedData (len + 32 + 2); |
| 102 | memcpy (signedData.data (), m_Owner->GetIdentity ()->GetIdentHash (), 32); |
| 103 | memcpy (signedData.data () + 32, flags, 2); |
| 104 | memcpy (signedData.data () + 34, payload, len); |
| 105 | m_Owner->Sign (signedData.data (), signedData.size (), m_Signature.data ()); |
| 106 | // TODO: offline signatures and options |
| 107 | msg = CreateDataMessage ({{m_From.data (), m_From.size ()}, {flags, 2}, {payload, len}, |
| 108 | {m_Signature.data (), m_Signature.size ()}}, fromPort, toPort, i2p::client::PROTOCOL_TYPE_DATAGRAM2, false); // datagram2 |
| 109 | |
| 110 | break; |
| 111 | } |
| 112 | default: |
| 113 | LogPrint (eLogError, "Datagram: datagram type ", (int)session->GetVersion (), " is not supported"); |
| 114 | } |
| 115 | if (msg) session->SendMsg(msg); |
| 116 | } |
no test coverage detected