void Base64encoder::encode(std::istream& istream_in, std::ostream& ostream_in)
{
    base64_init_encodestate(&_state);

    const int N = _buffersize;
    char* plaintext = new char[N];
    char* code = new char[2*N];
    int plainlength;
    int codelength;

    do
    {
        istream_in.read(plaintext, N);
        plainlength = istream_in.gcount();

        codelength = encode(plaintext, plainlength, code);
        ostream_in.write(code, codelength);
    }
    while (istream_in.good() && plainlength > 0);

    codelength = encode_end(code);
    ostream_in.write(code, codelength);

    base64_init_encodestate(&_state);

    delete [] code;
    delete [] plaintext;
}
Beispiel #2
0
bool serialize(const int devfd, struct bitcoin_storage *const st, bool serial_pad)
{
	static struct encoder_state s;
	static bool first_run = true;
	static int buf_left = 0; // Bytes left to send
	static int buf_i = 0; // Bytes position of next unsent byte

	if (first_run) {
		encoder_state_init(&s);
		first_run = false;
	}

	gint queued = heap_size(&st->send_queue);

	if (!buf_left && queued) {
		// Try to fill send buffer
		struct msg *m = bitcoin_dequeue(st);

		// Should not happen
		if (m == NULL) errx(6,"Send queue handling error");

		// Do not retransmit if it is already sent.
		if (m->sent) {
			printf("Already sent %s %s, skipping\n",
			       bitcoin_type_str(m),
			       hex256(bitcoin_inv_hash(m)));
			return true;
		}

		// Mark message as sent
		m->sent = true;

		// Calculate signature. FIXME: Include type in calculation!
		
		// Bitcoin message header in unidirectional
		// transfer. The signature is used to verify the
		// transmitter. Transactions have their own signature
		// inside message body, too.
		
		unsigned char sig[72];
		int siglen;
		secp256k1_ecdsa_sign(m->payload,m->length,sig,&siglen,NULL,NULL);

		encode_start(&s);
		encode(&s,&siglen,1); // FIXME doesn't work on big endian archs
		encode(&s,&sig,siglen);
		encode(&s,&m->type,1); // FIXME doesn't work on big endian archs
		encode(&s,m->payload,m->length);

		// Finishing encoding and updating send buffer
		buf_left = encode_end(&s);
		buf_i = 0;

		// Debugging
		char height_buf[20] = "";
		if (m->height != UNCONFIRMED) {
			snprintf(height_buf,sizeof(height_buf),
				 " @ %d",m->height);
		}
		printf("Sending %s %s%s, %d bytes, %d items left\n",
		       bitcoin_type_str(m),
		       hex256(bitcoin_inv_hash(m)),
		       height_buf,
		       m->length,
		       queued);
	}

	if (buf_left) {
		// Consume buffer as much as possible
		const int wrote = write(devfd, s.buf+buf_i, buf_left);
		if (wrote == 0) {
			errx(3,"Weird behaviour on serial port");
		} else if (wrote == -1) {
			err(4,"Unable to write to serial port");
		}
		buf_i += wrote;
		buf_left -= wrote;
	} else {
		if (!serial_pad) {
			// All is sent, do not come back until there
			// is more data availableq
			printf("Serial device idle\n");
			return false;
		}
		// Send padding and go back to waiting loop.
		guint8 buf[PAD_COUNT*5];
		int i = 0;
		while (i < sizeof(buf)) {
			// Z_SYNC_FLUSH is 5 bytes long:
			buf[i++] = 0x00;
			buf[i++] = 0x00;
			buf[i++] = 0x00;
			buf[i++] = 0xFF;
			buf[i++] = 0xFF;
		}

		const int ret = write(devfd,buf,sizeof(buf));
		if (ret < 1) err(4,"Unable to write to serial port");
		if (ret != sizeof(buf)) err(10,"Too large padding buffer or non-linuxy system");
		printf("Sending %d bytes of padding\n",ret);
	}
	return true;
}