#ifndef PIPE_CS_IIP1_H
#define PIPE_CS_IIP1_H

#include "misc/compat.h"
#include <stdlib.h>
#include "pipe/pipe.h"
#include "base/bignum.h"
#include "crypt/blowfish.h"
#include "pipe/c-stream.h"

#define KEY_LENGTH 16 //XTEA_BLOCK_LENGTH
#define BLOCK_LENGTH 8 //XTEA_KEY_LENGTH
#define BLOCK_LENGTH1 7 //XTEA_BLOCK_LENGTH1;

typedef struct CryptStreamIIP1{
	CryptStream cs;
	//Pipe *backPipe;
	//Pipe *thisPipe;

	int inShake;
	int outShake;
	BigNum *privkey; //local private key
	BigNum *localkey; //local public key
	BigNum *remotekey; //remote public key
	BigNum *sharedkey; //the shared key
	DataBlock *insessionkey; //session key from key exchange
	DataBlock *outsessionkey; //session key from key exchange

	int inNeeded;
	int outCount;

	BlowfishContext *blowfishin;
	BlowfishContext *blowfishout;

	BigNum *setremotekey;

	uint8 counterin[BLOCK_LENGTH];
	uint8 counterout[BLOCK_LENGTH];

} CryptStreamIIP1;

#define WRITES_TILL_ROTATE 52

#define BLANKCOUNTER {0, 0, 0, 0,  0, 0, 0, 0}
//#define BLANKCRYPTSTREAMIIP1 {{(CSWriteFunc) csiip1Write, (CSReadFunc) csiip1Read, (CSFreeFunc) csiip1Free}, NULL, 1, 1, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, NULL, NULL, NULL, BLANKCOUNTER, BLANKCOUNTER}
#define BLANKCRYPTSTREAMIIP1 {{(CSWriteFunc) csiip1Write, (CSReadFunc) csiip1Read, (CSFreeFunc) csiip1Free}, 1, 1, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, NULL, NULL, NULL, BLANKCOUNTER, BLANKCOUNTER}

#define CSIIP1_DH_LENGTH 1024
#define CSIIP1_DH_PRIV_LENGTH 512

CryptStream *csiip1Make(char *csname, char *options);
void csiip1Init(CryptStreamIIP1 *cs, Pipe *thispipe);//, Pipe *backpipe
void csiip1Free(CryptStreamIIP1 *cs);
void csiip1Decrypt(CryptStreamIIP1 *cs);
void csiip1Encrypt(CryptStreamIIP1 *cs);
void csiip1InHandshake(CryptStreamIIP1 *cs);
void csiip1Outhandshake(CryptStreamIIP1 *cs);
void csiip1Read(CryptStreamIIP1 *cs);
void csiip1Write(CryptStreamIIP1 *cs);



//private functions
void csiip1RotateSessionKey(DataBlock *key, DataBlock *rand);
void csiip1ApplyCounter(uint8 *data, uint8 *counter);
void csiip1Decode(CryptStreamIIP1 *cs, DataBlock *db);
void csiip1Encode(CryptStreamIIP1 *cs, DataBlock *db);
void csiip1EncryptWrite(CryptStreamIIP1 *cs, DataBlock *db);
void csiip1OutHandshake(CryptStreamIIP1 *cs);


#endif //PIPE_CS_IIP1_H

