bzrtpPacket_t *bzrtp_createZrtpPacket(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext, uint32_t messageType, int *exitCode) {
	/* allocate packet */
	bzrtpPacket_t *zrtpPacket = (bzrtpPacket_t *)malloc(sizeof(bzrtpPacket_t));
	memset(zrtpPacket, 0, sizeof(bzrtpPacket_t));
	zrtpPacket->messageData = NULL;
	zrtpPacket->packetString = NULL;

	/* initialise it */
	switch(messageType) {
		case MSGTYPE_HELLO:
			{
				int i;
				bzrtpHelloMessage_t *zrtpHelloMessage = (bzrtpHelloMessage_t *)malloc(sizeof(bzrtpHelloMessage_t));
				memset(zrtpHelloMessage, 0, sizeof(bzrtpHelloMessage_t));
				/* initialise some fields using zrtp context data */
				memcpy(zrtpHelloMessage->version, ZRTP_VERSION, 4);
				strncpy((char*)zrtpHelloMessage->clientIdentifier, ZRTP_CLIENT_IDENTIFIER, 16);
				memcpy(zrtpHelloMessage->H3, zrtpChannelContext->selfH[3], 32);
				memcpy(zrtpHelloMessage->ZID, zrtpContext->selfZID, 12);
				/* set all S,M,P flags to zero as we're not able to verify signatures, we're not a PBX(TODO: implement?), we're not passive */
				zrtpHelloMessage->S = 0;
				zrtpHelloMessage->M = 0;
				zrtpHelloMessage->P = 0;

				/* get the algorithm availabilities from the context */
				zrtpHelloMessage->hc = zrtpContext->hc;
				zrtpHelloMessage->cc = zrtpContext->cc;
				zrtpHelloMessage->ac = zrtpContext->ac;
				zrtpHelloMessage->kc = zrtpContext->kc;
				zrtpHelloMessage->sc = zrtpContext->sc;

				for (i=0; i<zrtpContext->hc; i++) {
					zrtpHelloMessage->supportedHash[i] = zrtpContext->supportedHash[i];
				}
				for (i=0; i<zrtpContext->cc; i++) {
					zrtpHelloMessage->supportedCipher[i] = zrtpContext->supportedCipher[i];
				}
				for (i=0; i<zrtpContext->ac; i++) {
					zrtpHelloMessage->supportedAuthTag[i] = zrtpContext->supportedAuthTag[i];
				}
				for (i=0; i<zrtpContext->kc; i++) {
					zrtpHelloMessage->supportedKeyAgreement[i] = zrtpContext->supportedKeyAgreement[i];
				}
				for (i=0; i<zrtpContext->sc; i++) {
					zrtpHelloMessage->supportedSas[i] = zrtpContext->supportedSas[i];
				}

				/* attach the message data to the packet */
				zrtpPacket->messageData = zrtpHelloMessage;
			}
			break; /* MSGTYPE_HELLO */

		case MSGTYPE_HELLOACK :
			{
				/* nothing to do for the Hello ACK packet as it just contains it's type */
			}
			break; /* MSGTYPE_HELLOACK */
		/* In case of DH commit, this one must be called after the DHPart build and the self DH message and peer Hello message are stored in the context */
		case MSGTYPE_COMMIT :
			{
				bzrtpCommitMessage_t *zrtpCommitMessage = (bzrtpCommitMessage_t *)malloc(sizeof(bzrtpCommitMessage_t));
				memset(zrtpCommitMessage, 0, sizeof(bzrtpCommitMessage_t));
				
				/* initialise some fields using zrtp context data */
				memcpy(zrtpCommitMessage->H2, zrtpChannelContext->selfH[2], 32);
				memcpy(zrtpCommitMessage->ZID, zrtpContext->selfZID, 12);
				zrtpCommitMessage->hashAlgo = zrtpChannelContext->hashAlgo;
				zrtpCommitMessage->cipherAlgo = zrtpChannelContext->cipherAlgo;
				zrtpCommitMessage->authTagAlgo = zrtpChannelContext->authTagAlgo;
				zrtpCommitMessage->keyAgreementAlgo = zrtpChannelContext->keyAgreementAlgo;
				zrtpCommitMessage->sasAlgo = zrtpChannelContext->sasAlgo;

				/* if it is a multistream or preshared commit create a 16 random bytes nonce */
				if ((zrtpCommitMessage->keyAgreementAlgo == ZRTP_KEYAGREEMENT_Prsh) || (zrtpCommitMessage->keyAgreementAlgo == ZRTP_KEYAGREEMENT_Mult)) {
					bctoolbox_rng_get(zrtpContext->RNGContext, zrtpCommitMessage->nonce, 16);

					/* and the keyID for preshared commit only */
					if (zrtpCommitMessage->keyAgreementAlgo == ZRTP_KEYAGREEMENT_Prsh) {
						/* TODO at this point we must first compute the preShared key - make sure at least rs1 is present */
						/* preshared_key = hash(len(rs1) || rs1 || len(auxsecret) || auxsecret ||
                       len(pbxsecret) || pbxsecret) using the agreed hash and store it into the env */
						/* and then the keyID : MAC(preshared_key, "Prsh") truncated to 64 bits using the agreed MAC */
					}
				} else { /* it's a DH commit message, set the hvi */
					/* hvi = hash(initiator's DHPart2 message || responder's Hello message) using the agreed hash function truncated to 256 bits */
					/* create a string with the messages concatenated */
					uint16_t DHPartMessageLength = zrtpChannelContext->selfPackets[DHPART_MESSAGE_STORE_ID]->messageLength;
					uint16_t HelloMessageLength = zrtpChannelContext->peerPackets[HELLO_MESSAGE_STORE_ID]->messageLength;
					uint16_t DHPartHelloMessageStringLength = DHPartMessageLength + HelloMessageLength;

					uint8_t *DHPartHelloMessageString = (uint8_t *)malloc(DHPartHelloMessageStringLength*sizeof(uint8_t));
					
					memcpy(DHPartHelloMessageString, zrtpChannelContext->selfPackets[DHPART_MESSAGE_STORE_ID]->packetString+ZRTP_PACKET_HEADER_LENGTH, DHPartMessageLength);
					memcpy(DHPartHelloMessageString+DHPartMessageLength, zrtpChannelContext->peerPackets[HELLO_MESSAGE_STORE_ID]->packetString+ZRTP_PACKET_HEADER_LENGTH, HelloMessageLength);

					zrtpChannelContext->hashFunction(DHPartHelloMessageString, DHPartHelloMessageStringLength, 32, zrtpCommitMessage->hvi);

					free(DHPartHelloMessageString);
				}

				/* attach the message data to the packet */
				zrtpPacket->messageData = zrtpCommitMessage;
			}
			break; /* MSGTYPE_COMMIT */

		/* this one is called after the exchange of Hello messages when the crypto algo agreement have been performed */
		case MSGTYPE_DHPART1 :
		case MSGTYPE_DHPART2 :
			{
				uint8_t secretLength; /* is in bytes */
				uint8_t bctoolbox_keyAgreementAlgo = BCTOOLBOX_DHM_UNSET;
				bzrtpDHPartMessage_t *zrtpDHPartMessage = (bzrtpDHPartMessage_t *)malloc(sizeof(bzrtpDHPartMessage_t));
				memset(zrtpDHPartMessage, 0, sizeof(bzrtpDHPartMessage_t));
				/* initialise some fields using zrtp context data */
				memcpy(zrtpDHPartMessage->H1, zrtpChannelContext->selfH[1], 32);
				/* get the retained secret from context, we anyway create a DHPart2 packet that we may turn into a DHPart1 packet if we end to 
				 * be the responder and not the initiator, use the initiator retained secret hashes */
				memcpy(zrtpDHPartMessage->rs1ID, zrtpContext->initiatorCachedSecretHash.rs1ID, 8);
				memcpy(zrtpDHPartMessage->rs2ID, zrtpContext->initiatorCachedSecretHash.rs2ID, 8);
				memcpy(zrtpDHPartMessage->auxsecretID, zrtpChannelContext->initiatorAuxsecretID, 8);
				memcpy(zrtpDHPartMessage->pbxsecretID, zrtpContext->initiatorCachedSecretHash.pbxsecretID, 8);
				
				/* compute the public value and insert it in the message, will then be used whatever role - initiator or responder - we assume */
				/* initialise the dhm context, secret length shall be twice the size of cipher block key length - rfc section 5.1.5 */
				switch (zrtpChannelContext->cipherAlgo) {
					case ZRTP_CIPHER_AES3:
					case ZRTP_CIPHER_2FS3:
						secretLength = 64;
						break;
					case ZRTP_CIPHER_AES2:
					case ZRTP_CIPHER_2FS2:
						secretLength = 48;
						break;
					case ZRTP_CIPHER_AES1:
					case ZRTP_CIPHER_2FS1:
					default:
						secretLength = 32;
						break;
				}

				switch (zrtpChannelContext->keyAgreementAlgo) {
					case ZRTP_KEYAGREEMENT_DH2k:
						bctoolbox_keyAgreementAlgo = BCTOOLBOX_DHM_2048;
						break;
					case ZRTP_KEYAGREEMENT_DH3k:
						bctoolbox_keyAgreementAlgo = BCTOOLBOX_DHM_3072;
						break;
					default:
						free(zrtpPacket);
						free(zrtpDHPartMessage);
						*exitCode = BZRTP_CREATE_ERROR_UNABLETOCREATECRYPTOCONTEXT;
						return NULL;
						break;
				}
				zrtpContext->DHMContext = bctoolbox_CreateDHMContext(bctoolbox_keyAgreementAlgo, secretLength);
				if (zrtpContext->DHMContext == NULL) {
					free(zrtpPacket);
					free(zrtpDHPartMessage);
					*exitCode = BZRTP_CREATE_ERROR_UNABLETOCREATECRYPTOCONTEXT;
					return NULL;
				}

				/* now compute the public value */
				bctoolbox_DHMCreatePublic(zrtpContext->DHMContext, (int (*)(void *, uint8_t *, size_t))bctoolbox_rng_get, zrtpContext->RNGContext);
				zrtpDHPartMessage->pv = (uint8_t *)malloc((zrtpChannelContext->keyAgreementLength)*sizeof(uint8_t));
				memcpy(zrtpDHPartMessage->pv, zrtpContext->DHMContext->self, zrtpChannelContext->keyAgreementLength);

				/* attach the message data to the packet */
				zrtpPacket->messageData = zrtpDHPartMessage;
			}
			break; /* MSGTYPE_DHPART1 and MSGTYPE_DHPART2 */

		case MSGTYPE_CONFIRM1:
		case MSGTYPE_CONFIRM2:
			{
				bzrtpConfirmMessage_t *zrtpConfirmMessage = (bzrtpConfirmMessage_t *)malloc(sizeof(bzrtpConfirmMessage_t));
				memset(zrtpConfirmMessage, 0, sizeof(bzrtpConfirmMessage_t));
				/* initialise some fields using zrtp context data */
				memcpy(zrtpConfirmMessage->H0, zrtpChannelContext->selfH[0], 32);
				zrtpConfirmMessage->sig_len = 0; /* signature is not supported */
				zrtpConfirmMessage->cacheExpirationInterval = 0xFFFFFFFF; /* expiration interval is set to unlimited as recommended in rfc section 4.9 */
				zrtpConfirmMessage->E = 0; /* we are not a PBX and then will never signal an enrollment - rfc section 7.3.1 */
				zrtpConfirmMessage->V = zrtpContext->cachedSecret.previouslyVerifiedSas;
				zrtpConfirmMessage->A = 0; /* Go clear message is not supported - rfc section 4.7.2 */
				zrtpConfirmMessage->D = 0; /* The is no backdoor in our implementation of ZRTP - rfc section 11 */

				/* generate a random CFB IV */
				bctoolbox_rng_get(zrtpContext->RNGContext, zrtpConfirmMessage->CFBIV, 16);

				/* attach the message data to the packet */
				zrtpPacket->messageData = zrtpConfirmMessage;
			}
			break; /* MSGTYPE_CONFIRM1 and MSGTYPE_CONFIRM2 */

		case MSGTYPE_CONF2ACK :
			{
				/* nothing to do for the conf2ACK packet as it just contains it's type */
			}
			break; /* MSGTYPE_CONF2ACK */
		case MSGTYPE_PINGACK:
			{
				bzrtpPingMessage_t *pingMessage;
				bzrtpPingAckMessage_t *zrtpPingAckMessage;

				/* to create a pingACK we must have a ping packet in the channel context, check it */
				bzrtpPacket_t *pingPacket = zrtpChannelContext->pingPacket;
				if (pingPacket == NULL) {
					*exitCode = BZRTP_CREATE_ERROR_INVALIDCONTEXT;
					return NULL;
				}
				pingMessage = (bzrtpPingMessage_t *)pingPacket->messageData;

				/* create the message */
				zrtpPingAckMessage = (bzrtpPingAckMessage_t *)malloc(sizeof(bzrtpPingAckMessage_t));
				memset(zrtpPingAckMessage, 0, sizeof(bzrtpPingAckMessage_t));

				/* initialise all fields using zrtp context data and the received ping message */
				memcpy(zrtpPingAckMessage->version,ZRTP_VERSION , 4); /* we support version 1.10 only, so no need to even check what was sent in the ping */
				memcpy(zrtpPingAckMessage->endpointHash, zrtpContext->selfZID, 8); /* as suggested in rfc section 5.16, use the truncated ZID as endPoint hash */
				memcpy(zrtpPingAckMessage->endpointHashReceived, pingMessage->endpointHash, 8);
				zrtpPingAckMessage->SSRC = pingPacket->sourceIdentifier;

				/* attach the message data to the packet */
				zrtpPacket->messageData = zrtpPingAckMessage;
			} /* MSGTYPE_PINGACK */
			break;

		default:
			free(zrtpPacket);
			*exitCode = BZRTP_CREATE_ERROR_INVALIDMESSAGETYPE;
			return NULL;
			break;
	}

	zrtpPacket->sequenceNumber = 0; /* this field is not used buy the packet creator, sequence number is given as a parameter when converting
	the message to a packet string(packet build). Used only when parsing a string into a packet struct */
	zrtpPacket->messageType = messageType;
	zrtpPacket->sourceIdentifier = zrtpChannelContext->selfSSRC;
	zrtpPacket->messageLength = 0; /* length will be computed at packet build */
	zrtpPacket->packetString = NULL;

	*exitCode=0;
	return zrtpPacket;
}
bzrtpPacket_t *bzrtp_createZrtpPacket(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext, uint32_t messageType, int *exitCode) {
	 
	bzrtpPacket_t *zrtpPacket = (bzrtpPacket_t *)malloc(sizeof(bzrtpPacket_t));
	memset(zrtpPacket, 0, sizeof(bzrtpPacket_t));
	zrtpPacket->messageData = NULL;
	zrtpPacket->packetString = NULL;

	 
	switch(messageType) {
		case MSGTYPE_HELLO:
			{
				int i;
				bzrtpHelloMessage_t *zrtpHelloMessage = (bzrtpHelloMessage_t *)malloc(sizeof(bzrtpHelloMessage_t));
				memset(zrtpHelloMessage, 0, sizeof(bzrtpHelloMessage_t));
				 
				memcpy(zrtpHelloMessage->version, ZRTP_VERSION, 4);
				strncpy((char*)zrtpHelloMessage->clientIdentifier, ZRTP_CLIENT_IDENTIFIER, 16);
				memcpy(zrtpHelloMessage->H3, zrtpChannelContext->selfH[3], 32);
				memcpy(zrtpHelloMessage->ZID, zrtpContext->selfZID, 12);
				 
				zrtpHelloMessage->S = 0;
				zrtpHelloMessage->M = 0;
				zrtpHelloMessage->P = 0;

				 
				zrtpHelloMessage->hc = zrtpContext->hc;
				zrtpHelloMessage->cc = zrtpContext->cc;
				zrtpHelloMessage->ac = zrtpContext->ac;
				zrtpHelloMessage->kc = zrtpContext->kc;
				zrtpHelloMessage->sc = zrtpContext->sc;

				for (i=0; i<zrtpContext->hc; i++) {
					zrtpHelloMessage->supportedHash[i] = zrtpContext->supportedHash[i];
				}
				for (i=0; i<zrtpContext->cc; i++) {
					zrtpHelloMessage->supportedCipher[i] = zrtpContext->supportedCipher[i];
				}
				for (i=0; i<zrtpContext->ac; i++) {
					zrtpHelloMessage->supportedAuthTag[i] = zrtpContext->supportedAuthTag[i];
				}
				for (i=0; i<zrtpContext->kc; i++) {
					zrtpHelloMessage->supportedKeyAgreement[i] = zrtpContext->supportedKeyAgreement[i];
				}
				for (i=0; i<zrtpContext->sc; i++) {
					zrtpHelloMessage->supportedSas[i] = zrtpContext->supportedSas[i];
				}

				 
				zrtpPacket->messageData = zrtpHelloMessage;
			}
			break;  

		case MSGTYPE_HELLOACK :
			{
				 
			}
			break;  
		 
		case MSGTYPE_COMMIT :
			{
				bzrtpCommitMessage_t *zrtpCommitMessage = (bzrtpCommitMessage_t *)malloc(sizeof(bzrtpCommitMessage_t));
				memset(zrtpCommitMessage, 0, sizeof(bzrtpCommitMessage_t));
				
				 
				memcpy(zrtpCommitMessage->H2, zrtpChannelContext->selfH[2], 32);
				memcpy(zrtpCommitMessage->ZID, zrtpContext->selfZID, 12);
				zrtpCommitMessage->hashAlgo = zrtpChannelContext->hashAlgo;
				zrtpCommitMessage->cipherAlgo = zrtpChannelContext->cipherAlgo;
				zrtpCommitMessage->authTagAlgo = zrtpChannelContext->authTagAlgo;
				zrtpCommitMessage->keyAgreementAlgo = zrtpChannelContext->keyAgreementAlgo;
				zrtpCommitMessage->sasAlgo = zrtpChannelContext->sasAlgo;

				 
				if ((zrtpCommitMessage->keyAgreementAlgo == ZRTP_KEYAGREEMENT_Prsh) || (zrtpCommitMessage->keyAgreementAlgo == ZRTP_KEYAGREEMENT_Mult)) {
					bctoolbox_rng_get(zrtpContext->RNGContext, zrtpCommitMessage->nonce, 16);

					 
					if (zrtpCommitMessage->keyAgreementAlgo == ZRTP_KEYAGREEMENT_Prsh) {
						 
						 
						 
					}
				} else {  
					 
					 
					uint16_t DHPartMessageLength = zrtpChannelContext->selfPackets[DHPART_MESSAGE_STORE_ID]->messageLength;
					uint16_t HelloMessageLength = zrtpChannelContext->peerPackets[HELLO_MESSAGE_STORE_ID]->messageLength;
					uint16_t DHPartHelloMessageStringLength = DHPartMessageLength + HelloMessageLength;

					uint8_t *DHPartHelloMessageString = (uint8_t *)malloc(DHPartHelloMessageStringLength*sizeof(uint8_t));
					
					memcpy(DHPartHelloMessageString, zrtpChannelContext->selfPackets[DHPART_MESSAGE_STORE_ID]->packetString+ZRTP_PACKET_HEADER_LENGTH, DHPartMessageLength);
					memcpy(DHPartHelloMessageString+DHPartMessageLength, zrtpChannelContext->peerPackets[HELLO_MESSAGE_STORE_ID]->packetString+ZRTP_PACKET_HEADER_LENGTH, HelloMessageLength);

					zrtpChannelContext->hashFunction(DHPartHelloMessageString, DHPartHelloMessageStringLength, 32, zrtpCommitMessage->hvi);

					free(DHPartHelloMessageString);
				}

				 
				zrtpPacket->messageData = zrtpCommitMessage;
			}
			break;  

		 
		case MSGTYPE_DHPART1 :
		case MSGTYPE_DHPART2 :
			{
				uint8_t secretLength;  
				uint8_t bctoolbox_keyAgreementAlgo = BCTOOLBOX_DHM_UNSET;
				bzrtpDHPartMessage_t *zrtpDHPartMessage = (bzrtpDHPartMessage_t *)malloc(sizeof(bzrtpDHPartMessage_t));
				memset(zrtpDHPartMessage, 0, sizeof(bzrtpDHPartMessage_t));
				 
				memcpy(zrtpDHPartMessage->H1, zrtpChannelContext->selfH[1], 32);
				 
				memcpy(zrtpDHPartMessage->rs1ID, zrtpContext->initiatorCachedSecretHash.rs1ID, 8);
				memcpy(zrtpDHPartMessage->rs2ID, zrtpContext->initiatorCachedSecretHash.rs2ID, 8);
				memcpy(zrtpDHPartMessage->auxsecretID, zrtpChannelContext->initiatorAuxsecretID, 8);
				memcpy(zrtpDHPartMessage->pbxsecretID, zrtpContext->initiatorCachedSecretHash.pbxsecretID, 8);
				
				 
				 
				switch (zrtpChannelContext->cipherAlgo) {
					case ZRTP_CIPHER_AES3:
					case ZRTP_CIPHER_2FS3:
						secretLength = 64;
						break;
					case ZRTP_CIPHER_AES2:
					case ZRTP_CIPHER_2FS2:
						secretLength = 48;
						break;
					case ZRTP_CIPHER_AES1:
					case ZRTP_CIPHER_2FS1:
					default:
						secretLength = 32;
						break;
				}

				switch (zrtpChannelContext->keyAgreementAlgo) {
					case ZRTP_KEYAGREEMENT_DH2k:
						bctoolbox_keyAgreementAlgo = BCTOOLBOX_DHM_2048;
						break;
					case ZRTP_KEYAGREEMENT_DH3k:
						bctoolbox_keyAgreementAlgo = BCTOOLBOX_DHM_3072;
						break;
					default:
						free(zrtpPacket);
						free(zrtpDHPartMessage);
						*exitCode = BZRTP_CREATE_ERROR_UNABLETOCREATECRYPTOCONTEXT;
						return NULL;
						break;
				}
				zrtpContext->DHMContext = bctoolbox_CreateDHMContext(bctoolbox_keyAgreementAlgo, secretLength);
				if (zrtpContext->DHMContext == NULL) {
					free(zrtpPacket);
					free(zrtpDHPartMessage);
					*exitCode = BZRTP_CREATE_ERROR_UNABLETOCREATECRYPTOCONTEXT;
					return NULL;
				}

				 
				bctoolbox_DHMCreatePublic(zrtpContext->DHMContext, (int (*)(void *, uint8_t *, size_t))bctoolbox_rng_get, zrtpContext->RNGContext);
				zrtpDHPartMessage->pv = (uint8_t *)malloc((zrtpChannelContext->keyAgreementLength)*sizeof(uint8_t));
				memcpy(zrtpDHPartMessage->pv, zrtpContext->DHMContext->self, zrtpChannelContext->keyAgreementLength);

				 
				zrtpPacket->messageData = zrtpDHPartMessage;
			}
			break;  

		case MSGTYPE_CONFIRM1:
		case MSGTYPE_CONFIRM2:
			{
				bzrtpConfirmMessage_t *zrtpConfirmMessage = (bzrtpConfirmMessage_t *)malloc(sizeof(bzrtpConfirmMessage_t));
				memset(zrtpConfirmMessage, 0, sizeof(bzrtpConfirmMessage_t));
				 
				memcpy(zrtpConfirmMessage->H0, zrtpChannelContext->selfH[0], 32);
				zrtpConfirmMessage->sig_len = 0;  
				zrtpConfirmMessage->cacheExpirationInterval = 0xFFFFFFFF;  
				zrtpConfirmMessage->E = 0;  
				zrtpConfirmMessage->V = zrtpContext->cachedSecret.previouslyVerifiedSas;
				zrtpConfirmMessage->A = 0;  
				zrtpConfirmMessage->D = 0;  

				 
				bctoolbox_rng_get(zrtpContext->RNGContext, zrtpConfirmMessage->CFBIV, 16);

				 
				zrtpPacket->messageData = zrtpConfirmMessage;
			}
			break;  

		case MSGTYPE_CONF2ACK :
			{
				 
			}
			break;  
		case MSGTYPE_PINGACK:
			{
				bzrtpPingMessage_t *pingMessage;
				bzrtpPingAckMessage_t *zrtpPingAckMessage;

				 
				bzrtpPacket_t *pingPacket = zrtpChannelContext->pingPacket;
				if (pingPacket == NULL) {
					*exitCode = BZRTP_CREATE_ERROR_INVALIDCONTEXT;
					return NULL;
				}
				pingMessage = (bzrtpPingMessage_t *)pingPacket->messageData;

				 
				zrtpPingAckMessage = (bzrtpPingAckMessage_t *)malloc(sizeof(bzrtpPingAckMessage_t));
				memset(zrtpPingAckMessage, 0, sizeof(bzrtpPingAckMessage_t));

				 
				memcpy(zrtpPingAckMessage->version,ZRTP_VERSION , 4);  
				memcpy(zrtpPingAckMessage->endpointHash, zrtpContext->selfZID, 8);  
				memcpy(zrtpPingAckMessage->endpointHashReceived, pingMessage->endpointHash, 8);
				zrtpPingAckMessage->SSRC = pingPacket->sourceIdentifier;

				 
				zrtpPacket->messageData = zrtpPingAckMessage;
			}  
			break;

		default:
			free(zrtpPacket);
			*exitCode = BZRTP_CREATE_ERROR_INVALIDMESSAGETYPE;
			return NULL;
			break;
	}

	zrtpPacket->sequenceNumber = 0;  
	zrtpPacket->messageType = messageType;
	zrtpPacket->sourceIdentifier = zrtpChannelContext->selfSSRC;
	zrtpPacket->messageLength = 0;  
	zrtpPacket->packetString = NULL;

	*exitCode=0;
	return zrtpPacket;
}