?? voip.c
字號:
/**************************************************************************
* voip.c - Main real time code for VOIP final project.
*
* Author - Ed Hursey
* Date - December 2005
*
* Description - This file includes tasks for recording
* and playing audio. Tasks for sending and
* receiving messages (audio) across a netowrk.
* Tasks for encrypting and decrypting the audio.
* It also has the main start up function and utility
* functions for running the code.
*
* Instructions:
* 1. To start voip, run startVoip(machineIndex), where
* machineIndex can either be 1 or 2 for a 2 system
* voip setup. Index 1 corresponds to the machine
* that has server1IP below and Index 2 corresponds
* to the machine that has server2IP below.
* 2. To switch modes (i.e. from 8-bit mono (1) to 8-bit stereo (2)
* to 16-bit stereo (3) use the switchMode(mode) function.
* Pass in the mode number (1,2, or 3). This only needs
* run on one machine and the other machine will
* automatically switch modes. The code starts up by
* default in 8-bit mono mode.
* 3. To stop VOIP call stopVOIP().
* 4. After calling stop, don't call startVOIP again (the
* card can't be re-initialized that way. Instead call
* resumeVOIP().
* 5. To stop encryption (to prove that encrypt/decrypt are
* working set enable_encryption to 0. To stop decryption
* set enable_decryption to 0. This doesn't switch the other
* machinie automatically because I wanted to prove that
* the audio was being encrypted/decrypted.
**************************************************************************/
#include "voip.h"
#include "cs4281Registers.h"
extern STATUS udpServer (void);
/*semaphores for task and buffer syncronization*/
SEM_ID SEM_OK_TRANSMIT,SEM_ENCRYPT,SEM_DECRYPTED;
/*task loop control variables*/
int enable_play = 1;
int enable_record = 1;
int enable_transmit = 1;
int enable_encryption_task = 1;
int enable_decryption_task = 1;
int enable_encryption = 1;
int enable_decryption = 1;
/*server IP addresses so we know where to send packets*/
char* server1IP = "10.0.1.27";
char* server2IP = "10.0.1.28";
char* transmitToIp = "10.0.1.27";
/*variables used to determine when we missed a packet*/
int transmit_sync_packet_number = 0;
int recieve_sync_packet_number = 0;
int lost_packet = 0;
int first_packet = 1;
/*rc4 encryption/decription key stuff*/
rc4_key encrypt_key;
rc4_key decrypt_key;
unsigned char rc4_key_data[RC4_KEY_DATA_LEN] = {23,82,107,6,35,78,88,7};
/**************************************************************************
* Function - getRecordBufferTask
* Parameters - none
* Returns - void
* Purpose - Records audio.
* Task that loops as long as enable_record = 1.
* Waits for SEM_DMA_Record semaphore, which is given when DMA1 (ADC)
* buffer is half full or all the way full. Then moves appropriate
* half of DMA buffer to transmitRequest.message and signfies that
* data is available to be encrypted (i.e. does a semGive of
* SEM_ENCRYPT semaphore).
/**************************************************************************/
void getRecordBufferTask()
{
while(enable_record)
{
/*wait for DMA1 buffer to have data*/
semTake(SEM_DMA_Record, WAIT_FOREVER);
/*which part of the buffer to move? TC (second half), HTC (first half)*/
if(DTC_DMA_Record)
memmove(transmitRequest.message,ADC_BUFFER+ADC_BUFFER_SIZE/2, ADC_BUFFER_SIZE/2);
else
memmove(transmitRequest.message,ADC_BUFFER, ADC_BUFFER_SIZE/2);
/*do encryption*/
semGive(SEM_ENCRYPT);
}
}
/**************************************************************************
* Function - encryptionTask
* Parameters - none
* Returns - void
* Purpose - Encrypts audio.
* Task that loops as long as enable_encryption_task = 1.
* It should be noted that encryption can be shutoff
* (set enable_encryption = 0) without shuting down the encryption
* task. Waits for SEM_ENCRYPT semaphore, which is given after
* data has been moved from the DMA1 buffer to transmitRequest.message
* It then encrypts the audio and signifies that data is ready to be
* transmitted (i.e does a semGive of SEM_OK_TRANSMIT).
/**************************************************************************/
void encryptionTask()
{
while(enable_encryption_task)
{
/*wait for data to be ready to encrypt*/
semTake(SEM_ENCRYPT, WAIT_FOREVER);
/*have ability not to encrypt so can hear non encrypted value*/
if(enable_encryption)
{
/*get a local copy of the rc4 key*/
encrypt_key.x = perm_key.x;
encrypt_key.y = perm_key.y;
memmove(encrypt_key.state,perm_key.state, 256);
rc4_crypt(&encrypt_key,transmitRequest.message,transmitRequest.message,REQUEST_MSG_SIZE);
}
/*now do a semGive to signfy that the buffer can be transmitted*/
semGive(SEM_OK_TRANSMIT);
}
}
/**************************************************************************
* Function - decryptionTask
* Parameters - none
* Returns - void
* Purpose - Decrypts audio.
* Task that loops as long as enable_decryption_task = 1.
* It should be noted that decryption can be shutoff
* (set enable_decryption = 0) without shuting down the decryption
* task. Waits for SEM_RECEIVED semaphore, which is given after
* the udpServer has receivied a new packet.
* It then decrypts the audio and signifies that data is ready to be
* played (i.e does a semGive of SEM_DECRYPTED).
/**************************************************************************/
void decryptionTask()
{
while(enable_decryption_task)
{
/*wait until udpServer has something to decrypt*/
semTake(SEM_RECEIVED, WAIT_FOREVER);
/*have ability not to decrypt so can hear non decrypted value*/
if(enable_decryption)
{
/*get a local copy of the rc4 key*/
decrypt_key.x = perm_key.x;
decrypt_key.y = perm_key.y;
memmove(decrypt_key.state,perm_key.state, 256);
rc4_crypt(&decrypt_key,receivedRequest.message,receivedRequest.message,REQUEST_MSG_SIZE);
}
/*tell play that something has been decrypted and can be played*/
semGive(SEM_DECRYPTED);
}
}
/**************************************************************************
* Function - setPlayBufferTask
* Parameters - none
* Returns - void
* Purpose - Plays audio.
* Task that loops as long as enable_play = 1.
* Waits for SEM_DECRYPTED semaphore, which is given when receivied
* data has been decrypted. Then waits for the play buffer to signify
* that it has room for more data (i.e. SEM_DMA_PLAYBACK).
* It then checks the received message to make sure the packet number
* is the packet we are expecting. If it is not then we play the old
* buffer again (this is mainly done so that undecrypted audio doesn't
* get played which would cause an awful noise in the speaker).
* Then moves receivedRequest.message to the appropriate half of the
* DMA buffer.
/**************************************************************************/
void setPlayBufferTask()
{
while(enable_play)
{
/*wait until buffer has been decrypted*/
semTake(SEM_DECRYPTED, WAIT_FOREVER);
/*also must wait until play buffer has room for us to put data */
semTake(SEM_DMA_Playback, WAIT_FOREVER);
/*increment packet number so we know if this packet is the one we
were expecting*/
recieve_sync_packet_number++;
/*sync the numbers the first time we get a packet*/
if( first_packet == 1 )
{
recieve_sync_packet_number = receivedRequest.message_number;
first_packet = 0;
}
/*make sure packet number is what we think it should be*/
if( recieve_sync_packet_number != receivedRequest.message_number )
{
logMsg("Must have lost a packet\n");
lost_packet = 1;
/*resync packet numbers so that we aren't off for the rest of time*/
recieve_sync_packet_number = receivedRequest.message_number;
}
/*if lost packet, don't move into buffer because it could be encrypted which would cause static*/
if( lost_packet )
{
lost_packet=0;
}
else
{
/*which part of the buffer to right to? TC (second half), HTC (first half)*/
if(DTC_DMA_Playback)
memmove(DAC_BUFFER+DAC_BUFFER_SIZE/2, receivedRequest.message, DAC_BUFFER_SIZE/2);
else
memmove(DAC_BUFFER, receivedRequest.message, DAC_BUFFER_SIZE/2);
}
}
}
/**************************************************************************
* Function - transmitTask
* Parameters - none
* Returns - void
* Purpose - Builds a request object and transmits it to another machine.
* Task that loops as long as enable_transmit = 1.
* Waits for SEM_OK_TRANSMIT semaphore, which is given when after
* audion has been encrypted. Calls the udp client so it can send
* a message.
/**************************************************************************/
void transmitTask()
{
while(enable_transmit)
{
semTake(SEM_OK_TRANSMIT, WAIT_FOREVER);
/*set the display to 1, this is no longer used, it was used for debugging
at first, then a 1 meant to display debugging info on the receivied side*/
transmitRequest.display = 1;
/*we increment the packet number each time we send a message so that
we can tell on the receivied side if we miss a message*/
transmit_sync_packet_number++;
transmitRequest.message_number = transmit_sync_packet_number;
/*we set the request type to 3, which means it is an audio message,
other types of messages can be used to perform other features*/
transmitRequest.request_type = 3;
/*we set the mode to the current mode (8-bit mono, 8-bit stereo
or 16-bit stereo so the receiving side knows if it has to change
modes to play the data*/
transmitRequest.mode = current_mode;
/*send the message*/
udpSendRequest();
}
}
/**************************************************************************
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -