//SIGSEGV-SEGMENTATION FAULT
//BUT, WAIT, WHY? cause of so?
//3)
//funk! uint8_t is equal with char, 8 bits, well, obviously!
//4)
//when sending file_len, a SIGSEGV SIGNAL received
//an error is: use data_count as uint8_t
//5)
//NOTICE
//the add destination action, take care of it, I find something
//strange.
//I firstly guess it will add the source address automatically, but
//now it seems not, strangely, so I add it by my hand.
//6)
//if it's too fast to send the packet, the client will not
//receive the pakcets, so try to find how to wait
//but what if we bigger the packet size?
//this seem to work, bigger the packet size, longer the waiting
//time.
//7)
//sometime the EOF packet lost, the client keep sending RTCP packets, make sure
//he knows the EOF on RTCP received
//global value
static bool requ_received = false;
static bool file_name_received = false;
static bool receive_ready = false;
//say bye to the source
bool source_bye = false;
char *file_name;
uint8_t null_array[4];
char null_char[4];
//types of apppackets
typedef enum{
REQU = 0, SERVER_OK, SERVER_BUSY, FILENAME, FILEINFO, RECEIVE_READY
}apppacketT;
//check error
void checkerror(int rtperr)
{
if(rtperr < 0)
{
std::cout<<"ERROR:"<<RTPGetErrorString(rtperr)<<std::endl;
exit(-1);
}
}
//set rulers for apppackets
class MyRTPSession : public RTPSession
{
protected:
#ifdef _DEBUG
void OnNewSource(RTPSourceData *srcdat)
{
std::cout<<"test source"<<std::endl;
if(srcdat->IsOwnSSRC())
{
return;
}
uint32_t ip;
uint16_t port;
if(srcdat->GetRTCPDataAddress() != 0)
{
const RTPIPv4Address *addr =
(const RTPIPv4Address *)
(srcdat->
GetRTCPDataAddress());
ip = addr->GetIP();
port = addr->GetPort()-1;
RTPIPv4Address src_addr(ip, port);
AddDestination(src_addr);
}
return;
}
void OnRTPPacket(RTPPacket *pack,
const RTPTime &receivetime,
const RTPAddress *senderaddress)
{
std::cout<<"test rtppacket"<<std::endl;
RTPTime::Wait(RTPTime(1.0));
}
#endif
void OnRTCPCompoundPacket(RTCPCompoundPacket *pack,
const RTPTime &receivetime,
const RTPAddress *senderaddress)
{
#ifdef _DEBUG
//std::cout<<"test rtcp"<<std::endl;
#endif
if(source_bye == true)
{
//send the EOF
checkerror(SendPacket(NULL, 0));
}
}
void OnAPPPacket(RTCPAPPPacket *apppacket,
const RTPTime &receivetime,
const RTPAddress *senderaddress)
{
//get the subtype of apppacket
apppacketT subtype = (apppacketT)(apppacket->GetSubType());
switch(subtype)
{
case REQU:
if(requ_received == true)
{
//busy will be sent to every sourcem, also the serving
//one, but he can judge it's not his funk
SendRTCPAPPPacket((uint8_t)SERVER_BUSY, null_array, null_char, 4);
}
//the ok is sent in the main()
#ifdef _DEBUG
std::cout<<"test requ"<<std::endl;
#endif
requ_received = true;
break;
case FILENAME:
if(file_name_received == true)
{
break;
}
#ifdef _DEBUG
std::cout<<"test file_name"<<std::endl;
#endif
file_name =(char *)
(apppacket->GetAPPData());
file_name_received = true;
break;
case RECEIVE_READY:
if(receive_ready == true)
{
break;
}
#ifdef _DEBUG
std::cout<<"test received_ready"<<std::endl;
#endif
receive_ready = true;
break;
default:
break;
}
}
};
//wait for some seconds
void waiting(double seconds)
{
RTPTime::Wait(RTPTime(seconds));
}
//notice here, global sess
MyRTPSession sess;
//print the situation of the network
void *print_situation(void *)
{
RTPSourceData *source;
while(1)
{
if(source_bye == true)
{
return(NULL);
}
sess.BeginDataAccess();
sess.GotoFirstSource();
source = sess.GetCurrentSourceInfo();
//it's me
if(source->IsOwnSSRC())
{
sess.GotoNextSource();
source = sess.GetCurrentSourceInfo();
}
std::cout<<"FractionLost: "
<<source->RR_GetFractionLost()<<std::endl;
std::cout<<"PacketsLost: "
<<source->RR_GetPacketsLost()<<std::endl;
std::cout<<"Jitter: "
<<source->RR_GetJitter()<<std::endl;
sess.EndDataAccess();
waiting(1.0);
//sleep this thread
sleep(1);
}
return(NULL);
}
int main()
{
int status;
//set params
RTPSessionParams sessparams;
sessparams.SetOwnTimestampUnit(1.0/8000.0);
sessparams.SetAcceptOwnPackets(false);
//set transparams
RTPUDPv4TransmissionParams transparams;
#ifndef _DEBUG
uint16_t localport;
std::cout<<"Local Port: "<<std::endl;
std::cin>>localport;
transparams.SetPortbase(localport);
#else
transparams.SetPortbase(8000);
#endif
//create a session
status = sess.Create(sessparams, &transparams);
checkerror(status);
//set packet attribute
sess.SetDefaultPayloadType(96);
sess.SetDefaultMark(false);
sess.SetDefaultTimestampIncrement(160);
sess.SetMaximumPacketSize
((size_t)((DATA_EACH_PACKET*1.1)));
#ifdef _DEBUG
// uint8_t destip[]={192, 168, 0, 3};
// RTPIPv4Address addr(destip, 8000);
// status = sess.AddDestination(addr);
// checkerror(status);
#endif
//daemon
while(1)
{
//got a request
if(requ_received == true)
{
int fd;
int file_len;
//until we get the file name
while(!file_name_received)
{
status =
sess.SendRTCPAPPPacket((uint8_t)SERVER_OK,
null_array, null_char, 4);
checkerror(status);
waiting(1.0);
//hey, regularly poll!
sess.Poll();
if(file_name_received ==false)
{
continue;
}
//if it's a valid file name
fd = open(file_name, O_RDONLY);
//a valid name
if(fd < 0)
{
file_len = 0;
status =
sess.SendRTCPAPPPacket((uint8_t)FILEINFO,
(uint8_t*)&file_len, null_char, 4);
sess.Poll();
waiting(1.0);
file_name_received
= false;
}
else
{
//get the stat of file
struct stat st;
if(stat(file_name, &st) < 0)
{
std::cout
<<"Cannot get the stat of file"<<std::endl;
exit(-1);
}
file_len = st.st_size;
}
}
//open the file, get the information
//until he's ready
while(!receive_ready)
{
sess.SendRTCPAPPPacket((uint8_t)FILEINFO,
(uint8_t*)&file_len, null_char, 4);
waiting(1.0);
sess.Poll();
}
//now he's ok
if(status < 0)
{
std::cout<<"Error Thread"
<<std::endl;
}
RTPSourceData *source;
struct in_addr inaddr;
uint16_t port;
sess.BeginDataAccess();
if(sess.GotoFirstSource())
{
source = sess.GetCurrentSourceInfo();
//it's me
if(source->IsOwnSSRC())
{
sess.GotoNextSource();
source = sess.GetCurrentSourceInfo();
}
//get the client address
uint32_t ip;
const RTPIPv4Address *addr;
if(source->GetRTCPDataAddress() != 0)
{
addr = (const RTPIPv4Address *)
(source->GetRTCPDataAddress());
ip = addr->GetIP();
port = addr->GetPort()-1;
inaddr.s_addr = htonl(ip);
std::cout<<"Begin service for: "
<< std::string(inet_ntoa(inaddr))
<<"-"<<port<<std::endl;
std::cout<<"File Length: "
<<file_len<<std::endl;
}
}
sess.EndDataAccess();
//create a thread for printing situation
pthread_t thread_id;
status = pthread_create(&thread_id, NULL,
&print_situation, NULL);
//begin send data
void *file_memory;
char *index;
file_memory =
mmap(NULL, file_len, PROT_READ, MAP_SHARED,
fd, 0);
if(file_memory == MAP_FAILED)
{
std::cout<<"FiLe Map failed"<<std::endl;
exit(-1);
}
close(fd);
index = (char *)file_memory;
int data_count;
for(data_count = 0;
file_len > data_count + DATA_EACH_PACKET;
data_count += DATA_EACH_PACKET)
{
#ifdef _DEBUG
// std::cout<<"data_count: "
// <<data_count<<std::endl;
#endif
status = sess.SendPacket(index,
DATA_EACH_PACKET);
checkerror(status);
index += DATA_EACH_PACKET;
sess.Poll();
RTPTime::Wait(RTPTime(0, 800));
}
//send the reminded data
status =
sess.SendPacket(index, file_len-data_count);
checkerror(status);
//send the EOF
status = sess.SendPacket(NULL, 0);
checkerror(status);
//the source bye now
source_bye = true;
//join the thread
pthread_join(thread_id, NULL);
//end send data
munmap(file_memory, file_len);
std::cout<<"End service for: "<<
std::string(inet_ntoa(inaddr))
<<"-"<<port<<std::endl;
//wait for EOF received
for(int i = 0; i < 5; i++)
{
sess.Poll();
waiting(1.0);
}
//clear the last service
requ_received = false;
file_name_received = false;
receive_ready = false;
source_bye = false;
}
sess.Poll();
}
return(0);
}
|