// Get next peer manager packet. Also encapsulates packets for relaying if necessary. Returns length if successful. static int peermgtGetNextPacket(struct s_peermgt *mgt, unsigned char *pbuf, const int pbuf_size, struct s_peeraddr *target) { int tnow; int outlen; int relayid; int relayct; int relaypeerid; int depth; struct s_packet_data data; tnow = utilGetTime(); while((outlen = (peermgtGetNextPacketGen(mgt, pbuf, pbuf_size, tnow, target))) > 0) { depth = 0; while(outlen > 0) { if(depth < peermgt_DECODE_RECURSION_MAX_DEPTH) { // limit encapsulation depth if(!peeraddrIsInternal(target)) { // address is external, packet is ready for sending return outlen; } else { if(((packet_PEERID_SIZE + outlen) < peermgt_MSGSIZE_MAX) && (peeraddrGetIndirect(target, &relayid, &relayct, &relaypeerid))) { // address is indirect, encapsulate packet for relaying if(peermgtIsActiveRemoteIDCT(mgt, relayid, relayct)) { // generate relay-in packet utilWriteInt32(&mgt->relaymsgbuf[0], relaypeerid); memcpy(&mgt->relaymsgbuf[packet_PEERID_SIZE], pbuf, outlen); data.pl_buf = mgt->relaymsgbuf; data.pl_buf_size = packet_PEERID_SIZE + outlen; data.peerid = mgt->data[relayid].remoteid; data.seq = ++mgt->data[relayid].remoteseq; data.pl_length = packet_PEERID_SIZE + outlen; data.pl_type = packet_PLTYPE_RELAY_IN; data.pl_options = 0; // encode relay-in packet outlen = packetEncode(pbuf, pbuf_size, &data, &mgt->ctx[relayid]); if(outlen > 0) { mgt->data[relayid].lastsend = tnow; *target = mgt->data[relayid].remoteaddr; } else { outlen = 0; } } else { outlen = 0; } } else { outlen = 0; } } depth++; } else { outlen = 0; } } } return 0; }
/// Main processing method void Dvbt1RSEncoderComponent::process() { // request input DataSet< uint8_t >* in = NULL; getInputDataSet("input1", in); // calculate sizes int insize = in ? (int) in->data.size() : 0; int numpacks = (insize + tsOffset_) / TS_PACKET_SIZE; int outsize = numpacks * RS_PACKET_SIZE; // request output DataSet< uint8_t >* out = NULL; getOutputDataSet("output1", out, outsize); // print debug info if(debug_x) LOG(LINFO) << "in/out: " << insize + tsOffset_ << "(" << insize << "+" << tsOffset_ << ")/" << outsize; // fill the messagewords for(ByteVecIt init = in->data.begin(), outit = out->data.begin(); init < in->data.end(); init++) { // copy in reverse order rsCodeWord_[TS_PACKET_SIZE - 1 - tsOffset_] = *init; // trigger encoding if(++tsOffset_ == TS_PACKET_SIZE) { int status = packetEncode(rsCodeWord_, rsCodeWord_ + T1_KK); if (status) LOG(LERROR) << "Problem encoding a R-S word"; // copy information part for(int b = 0; b < TS_PACKET_SIZE; b++, outit++) *outit = rsCodeWord_[TS_PACKET_SIZE - 1 - b]; // copy parity part for(int b = 0; b < T1_NN_KK; b++, outit++) *outit = rsCodeWord_[T1_NN - 1 - b]; // reset TS pointer tsOffset_ = 0; } } //Copy the timestamp and sample rate for the DataSets out->timeStamp = in->timeStamp; out->sampleRate = in->sampleRate; // release input and output releaseInputDataSet("input1", in); releaseOutputDataSet("output1", out); }
static int packetTestsuiteMsg(const int random_msg) { unsigned char plbuf[packetTestsuite_PLBUF_SIZE]; unsigned char plbufdec[packetTestsuite_PLBUF_SIZE]; struct s_packet_data testdata = { .pl_buf_size = packetTestsuite_PLBUF_SIZE, .pl_buf = plbuf }; struct s_packet_data testdatadec = { .pl_buf_size = packetTestsuite_PLBUF_SIZE, .pl_buf = plbufdec }; unsigned char pkbuf[packetTestsuite_PKBUF_SIZE]; struct s_crypto ctx[2]; unsigned char secret[64]; unsigned char nonce[16]; struct s_seq_state seqstate; char str[4096]; int len; memset(secret, 23, 64); memset(nonce, 5, 16); cryptoCreate(ctx, 2); if(!cryptoSetKeys(&ctx[0], 1, secret, 64, nonce, 16)) return 0; if(!cryptoSetKeys(&ctx[1], 1, secret, 64, nonce, 16)) return 0; seqInit(&seqstate, 0); memset(plbuf, 0, packetTestsuite_PLBUF_SIZE); if(random_msg) RAND_pseudo_bytes(plbuf, packetTestsuite_PLBUF_SIZE); else strcpy((char *)plbuf, "moo"); len = packetTestsuite_PLBUF_SIZE; testdata.pl_length = len; testdata.pl_type = 0; testdata.pl_options = 0; testdata.peerid = plbuf[0]; testdata.seq = 1; utilByteArrayToHexstring(str, 4096, plbuf, len); printf("%s (len=%d, peerid=%d) -> ", str, len, testdata.peerid); len = packetEncode(pkbuf, packetTestsuite_PKBUF_SIZE, &testdata, &ctx[0]); if(!(len > 0)) return 0; utilByteArrayToHexstring(str, 4096, pkbuf, len); printf("%s (%d) -> ", str, len); if(!(packetDecode(&testdatadec, pkbuf, len, &ctx[1], &seqstate))) return 0; if(!(testdatadec.pl_length > 0)) return 0; if(!(testdatadec.peerid == plbuf[0])) return 0; if(!memcmp(testdatadec.pl_buf, testdata.pl_buf, packetTestsuite_PLBUF_SIZE) == 0) return 0; utilByteArrayToHexstring(str, 4096, testdatadec.pl_buf, testdatadec.pl_length); printf("%s (len=%d, peerid=%d)\n", str, testdatadec.pl_length, testdatadec.peerid); cryptoDestroy(ctx, 2); return 1; }
// Generate next peer manager packet. Returns length if successful. static int peermgtGetNextPacketGen(struct s_peermgt *mgt, unsigned char *pbuf, const int pbuf_size, const int tnow, struct s_peeraddr *target) { int used = mapGetKeyCount(&mgt->map); int len; int outlen; int fragoutlen; int peerid; int relayid; int usetargetaddr; int i; int fragcount; int fragpos; const int plbuf_size = peermgt_MSGSIZE_MIN; unsigned char plbuf[plbuf_size]; struct s_msg authmsg; struct s_packet_data data; // send out user data outlen = mgt->outmsg.len; fragoutlen = mgt->fragoutsize; if(outlen > 0 && (!(fragoutlen > 0))) { if(mgt->outmsgbroadcast) { // get PeerID for broadcast message do { peerid = peermgtGetNextID(mgt); mgt->outmsgbroadcastcount++; } while((!(peermgtIsActiveRemoteID(mgt, peerid) && peermgtGetRemoteFlag(mgt, peerid, peermgt_FLAG_USERDATA))) && (mgt->outmsgbroadcastcount < used)); if(mgt->outmsgbroadcastcount >= used) { mgt->outmsgbroadcast = 0; mgt->outmsg.len = 0; } } else { // get PeerID for unicast message peerid = mgt->outmsgpeerid; mgt->outmsg.len = 0; } if(peermgtIsActiveRemoteID(mgt, peerid)) { // check if session is active if(peermgtGetRemoteFlag(mgt, peerid, peermgt_FLAG_USERDATA)) { if((mgt->fragmentation > 0) && (outlen > peermgt_MSGSIZE_MIN)) { // start generating fragmented userdata packets mgt->fragoutpeerid = peerid; mgt->fragoutcount = (((outlen - 1) / peermgt_MSGSIZE_MIN) + 1); // calculate number of fragments mgt->fragoutsize = outlen; fragoutlen = outlen; mgt->fragoutpos = 0; } else { // generate userdata packet data.pl_buf = mgt->outmsg.msg; data.pl_buf_size = outlen; data.peerid = mgt->data[peerid].remoteid; data.seq = ++mgt->data[peerid].remoteseq; data.pl_length = outlen; data.pl_type = packet_PLTYPE_USERDATA; data.pl_options = 0; len = packetEncode(pbuf, pbuf_size, &data, &mgt->ctx[peerid]); if(len > 0) { mgt->data[peerid].lastsend = tnow; *target = mgt->data[peerid].remoteaddr; return len; } } } } } // send out fragments if(fragoutlen > 0) { fragcount = mgt->fragoutcount; fragpos = mgt->fragoutpos; peerid = mgt->fragoutpeerid; if(peermgtIsActiveRemoteID(mgt, peerid)) { // check if session is active // generate fragmented packet data.pl_buf = &mgt->outmsg.msg[(fragpos * peermgt_MSGSIZE_MIN)]; if(fragoutlen > peermgt_MSGSIZE_MIN) { // start or middle fragment data.pl_buf_size = peermgt_MSGSIZE_MIN; data.pl_length = peermgt_MSGSIZE_MIN; mgt->fragoutsize = (fragoutlen - peermgt_MSGSIZE_MIN); } else { // end fragment data.pl_buf_size = fragoutlen; data.pl_length = fragoutlen; mgt->fragoutsize = 0; } data.peerid = mgt->data[peerid].remoteid; data.seq = ++mgt->data[peerid].remoteseq; data.pl_type = packet_PLTYPE_USERDATA_FRAGMENT; data.pl_options = (fragcount << 4) | (fragpos); len = packetEncode(pbuf, pbuf_size, &data, &mgt->ctx[peerid]); mgt->fragoutpos = (fragpos + 1); if(len > 0) { mgt->data[peerid].lastsend = tnow; *target = mgt->data[peerid].remoteaddr; return len; } } else { // session not active anymore, abort sending fragments mgt->fragoutsize = 0; } } // send out request-response packet outlen = mgt->rrmsg.len; if(outlen > 0) { peerid = mgt->rrmsgpeerid; usetargetaddr = mgt->rrmsgusetargetaddr; mgt->rrmsg.len = 0; mgt->rrmsgusetargetaddr = 0; if((outlen < peermgt_MSGSIZE_MAX) && (peermgtIsActiveRemoteID(mgt, peerid))) { // check if session is active data.pl_buf = mgt->rrmsg.msg; data.pl_buf_size = peermgt_MSGSIZE_MAX; data.pl_length = outlen; data.pl_type = mgt->rrmsgtype; data.pl_options = 0; data.peerid = mgt->data[peerid].remoteid; data.seq = ++mgt->data[peerid].remoteseq; len = packetEncode(pbuf, pbuf_size, &data, &mgt->ctx[peerid]); if(len > 0) { if(usetargetaddr > 0) { *target = mgt->rrmsgtargetaddr; } else { mgt->data[peerid].lastsend = tnow; *target = mgt->data[peerid].remoteaddr; } return len; } } } // send peerinfo to peers for(i=0; i<used; i++) { peerid = peermgtGetNextID(mgt); if(peerid > 0) { if((tnow - mgt->data[peerid].lastrecv) < peermgt_RECV_TIMEOUT) { // check if session has expired if(mgt->data[peerid].state == peermgt_STATE_COMPLETE) { // check if session is active if(((tnow - mgt->data[peerid].lastsend) > peermgt_KEEPALIVE_INTERVAL) || ((tnow - mgt->data[peerid].lastpeerinfo) > peermgt_PEERINFO_INTERVAL)) { // check if we should send peerinfo packet data.pl_buf = plbuf; data.pl_buf_size = plbuf_size; data.peerid = mgt->data[peerid].remoteid; data.seq = ++mgt->data[peerid].remoteseq; peermgtGenPacketPeerinfo(&data, mgt); len = packetEncode(pbuf, pbuf_size, &data, &mgt->ctx[peerid]); if(len > 0) { mgt->data[peerid].lastsend = tnow; mgt->data[peerid].lastpeerinfo = tnow; *target = mgt->data[peerid].remoteaddr; return len; } } } } else { peermgtDeleteID(mgt, peerid); } } } // send auth manager message if(authmgtGetNextMsg(&mgt->authmgt, &authmsg, target)) { data.pl_buf = authmsg.msg; data.pl_buf_size = authmsg.len; data.peerid = 0; data.seq = 0; data.pl_length = authmsg.len; if(data.pl_length > 0) { data.pl_type = packet_PLTYPE_AUTH; data.pl_options = 0; len = packetEncode(pbuf, pbuf_size, &data, &mgt->ctx[0]); if(len > 0) { mgt->data[0].lastsend = tnow; return len; } } } // connect new peer if((authmgtUsedSlotCount(&mgt->authmgt) < ((authmgtSlotCount(&mgt->authmgt) / 4) * 3)) && ((tnow - mgt->lastconnect) > peermgt_NEWCONNECT_INTERVAL)) { i = nodedbNextID(&mgt->nodedb, peermgt_NEWCONNECT_MAX_AGE, 0, 1); if(!(i < 0)) { peerid = peermgtGetID(mgt, nodedbGetNodeID(&mgt->nodedb, i)); if(peerid < 0) { // check if node is already connected // node is not connected yet if(peermgtConnect(mgt, nodedbGetNodeAddress(&mgt->nodedb, i))) { // try to connect if(peermgtConnect(mgt, nodedbGetIndirectNodeAddress(&mgt->nodedb, i))) { // try to connect via relay relayid = 0; // on success, dont change indirect entry in NodeDB } else { relayid = -1; // on failure, delete indirect entry in NodeDB } nodedbUpdate(&mgt->nodedb, nodedbGetNodeID(&mgt->nodedb, i), NULL, 0, 0, 1, relayid, 0, 0); mgt->lastconnect = tnow; } } else { // node is already connected if(peeraddrIsInternal(&mgt->data[peerid].remoteaddr)) { peermgtSendPingToAddr(mgt, NULL, peerid, mgt->data[peerid].conntime, nodedbGetNodeAddress(&mgt->nodedb, i)); // try to switch peer to a direct connection nodedbUpdate(&mgt->nodedb, nodedbGetNodeID(&mgt->nodedb, i), NULL, 0, 0, 1, 0, 0, 0); mgt->lastconnect = tnow; } } } } return 0; }