Link to home
Start Free TrialLog in
Avatar of logicallayer
logicallayer

asked on

two ways voice chat using recvfrom() sendto() not working probably...

Hi,
I have the following code for two ways chat using UDP, recvfrom() and sendto() in sys/socket.h but for some reason my client can only talk but not listen and my server can only listen but not talk can someone take a look at the code please.

I did use pthread, and check it's validity using printing messages and I think my mutex being applied right as well, I fiind it weird that both my server and client have pretty much the same code except that one of them wait for connection as a server while the other establish the connection(not much of establishing considering im using UDP) any ideas what's wrong with my mechanism?


thanks,
             
////////////////////////SERVER////////////////

#include	"voip.h"
#include <pthread.h>
#include <fcntl.h>

int  			sockfd;
	struct sockaddr_in	serv_sock, cli_sock;
	char                    packet[PACKETSIZE];
	int fd,num, sum=0;

char *message1 = "this is thread two, being tested with recieving as thread";

pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t condition_var = PTHREAD_COND_INITIALIZER;
int recvalue = 0;
///////////////////////prototype//////////////

void *writespeaker();
void *print_message(void *ptr);
void *readmic();

////////////////////////////////////////////


int
main(int argc, char **argv)
{
	
	
	/* Open  a UDP SOCKET */
	
	if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
	  perror("Socket()");
	  exit(1);
	}
	
	fcntl(sockfd,F_SETFL,O_NONBLOCK); //make it non-blocking so it returns an error if no message to be read
	/* Set some params */
	audio_paras.speed = 8000;
	audio_paras.stereo = 0;
	audio_paras.PCM  = AFMT_U8; 

       	if (SetupAudio(devicename, &audio_paras)!=0) {
	    perror("Error in Initializing Audio Device!");
	    exit(-1);
	}
	else 
	puts("Audio Device is setup"); 	

	/* Set the socket parameters */
	bzero(&serv_sock, sizeof(serv_sock));
	serv_sock.sin_family      = AF_INET;
	serv_sock.sin_addr.s_addr = htonl(INADDR_ANY);
	serv_sock.sin_port        = htons(SERV_PORT);
 
	if (bind(sockfd,  &serv_sock, sizeof(serv_sock))<0)
	  perror(" Failed in binding the Server sock!");
   


pthread_t thread1,thread2;

pthread_create(&thread1,NULL, writespeaker,NULL);
pthread_create(&thread2,NULL, readmic,NULL);


pthread_join(thread1,NULL);
pthread_join(thread2,NULL);


}


int Transmitter(int sockfd, struct sockaddr_in *serv_sock, char *packet,int read_size, socklen_t servlen)
{
  int n;
  n = sendto(sockfd, packet, read_size, 0, serv_sock, servlen);
  //printf("%d ",n);
  return(n);
}

int Receiver(int sockfd, struct sockaddr_in *cli_sock, char *packet, int write_size, socklen_t clilen)
{
  int len;
  len = clilen;
  /* Here using polling to avoid too block - 10ms is good? */
  write_size = recvfrom(sockfd, packet, PACKETSIZE, 0, cli_sock, &len );
  //printf("write_size is %d\n",write_size);
  if (write_size > 0)
     return(0);
  else
     return (-1);
}

void Playback( char *packet, int write_size)
{
  write(devfd, packet, PACKETSIZE);	
}

int SetupAudio( char *devicename, struct Audio_Para *audio_paras)
{
    int format  = AFMT_QUERY;  
    printf("%s\n",devicename);
    devfd=-1;
    /* Open /dev/audio */
    if((devfd = open(devicename, O_RDWR)) < 0) {
	if(errno == EBUSY) {
	    fprintf(stderr, "%s in use\n", devicename);
	}
	printf(stderr, "%s: %s\n", devicename, strerror(errno));
	return(-1);
    }

    /* Set the format PCM: 8 unsigned bits */
    if((ioctl(devfd, SNDCTL_DSP_SETFMT, &audio_paras->PCM)) < 0) {
	perror("SNDCTL_DSP_GETFMTS");
	return(-1);
    }

    if((ioctl(devfd, SNDCTL_DSP_GETFMTS, &format)) < 0) {
      perror("SNDCTL");
      return(-1);
    }

    /* Set the number of channels */
    if((ioctl(devfd, SNDCTL_DSP_STEREO, &audio_paras->stereo)) < 0) {
	perror("SNDCTL_DSP_STEREO");
	return(-1);
    }
    printf("\tSet %s mode\n", (audio_paras->stereo) ? "STEREO" : "MONO");

    /* Set the sample speed */
    if((ioctl(devfd, SNDCTL_DSP_SPEED, &audio_paras->speed)) < 0) {
	perror("SNDCTL_DSP_SPEED");
	return(-1);
    }
    printf("\tSPEED %d Hz\n", audio_paras->speed);

    return(0);printf( "\n condition met\n");
}

void *writespeaker()
{

//pay attention that pthread mutex examole website uses one function only in both threads,
//here we have two functions that are trying to access the same variable
//we shouldn't allow one function to access the variable unless the other function is done with it
//notice we are talking about sockfd in receiver() and transmitter() 	

for(;;)
{
pthread_mutex_lock(&count_mutex);
recvalue = Receiver(sockfd, &cli_sock, packet, write_size, sizeof(cli_sock));
if(recvalue == 0)	        
{		
		 Playback( packet, write_size);
}
else if(recvalue == -1)
{

pthread_cond_signal(&condition_var); //signal to release the mutex
}


pthread_mutex_unlock(&count_mutex);
}
}

void *readmic()
{

for(;;)
{
read_size = read (devfd, packet, PACKETSIZE);
pthread_mutex_lock(&count_mutex);
pthread_cond_wait(&condition_var,&count_mutex);
//printf( "\n condition met holla!\n");
num = Transmitter(sockfd, &serv_sock, packet, read_size, sizeof(serv_sock));
if(num > 0)
{	
 write(fd, packet, PACKETSIZE);	
}
pthread_mutex_unlock(&count_mutex);
}

		
}

Open in new window

////////////////CLIENT//////////////////////

#include "voip.h"
#include <pthread.h>
#include <fcntl.h>

	int  sockfd;
	struct sockaddr_in  serv_sock, cli_sock;
	socklen_t len;
	char hostname[MAXHOSTNAMELEN];
	char packet[PACKETSIZE];
	int fd, num, sum=0;
	int recvalue = 0;

pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t condition_var = PTHREAD_COND_INITIALIZER;
///////////////////////prototype//////////////

void *writespeaker();
void *readmic();

////////////////////////////////////////////


int main(int argc, char **argv )
{
		 
	if ( argc != 3){
	  puts("Usage: Name Server Port");
	  exit(0);
	}

	/* Get the Server Parameters from the input*/  
	serv_addr.name = argv[1];
	serv_addr.port = atoi(argv[2]);
	
	printf(" Serv_addr is %s Serv_port is %d\n", serv_addr.name, serv_addr.port);

	
	/* Set some params */
	audio_paras.speed = 8000;
	audio_paras.stereo = 0;
	audio_paras.PCM  = AFMT_U8; 

	if (SetupAudio(devicename, &audio_paras)!=0) {
	    perror("Error in Initializing Audio Device!");
	    exit(-1);
	}
	else 
	  puts("Audio Device is setup");
	
	/* Get the Client Parameters */
        if ( gethostname(hostname, MAXHOSTNAMELEN) <0 )
	  perror("Couldn't get the hostname!");
        
	printf("hostname is %s\n",hostname);

	bzero(&serv_sock, sizeof(serv_sock));
	serv_sock.sin_family = AF_INET;
	serv_sock.sin_port = htons(serv_addr.port);
	inet_pton(AF_INET, serv_addr.name, &serv_sock.sin_addr);
 
    	/* Open  a UDP SOCKET - This is the only SOCKET opened in Daemon Server */
	if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
	  perror("Socket()");
	 exit(1);
	}
	fcntl(sockfd,F_SETFL,O_NONBLOCK); //make it non-blocking so it returns an error if no message to be read
        

pthread_t thread1,thread2;

pthread_create(&thread1,NULL, writespeaker,NULL);
pthread_create(&thread2,NULL, readmic,NULL);


pthread_join(thread1,NULL);
pthread_join(thread2,NULL);


}

int Transmitter(int sockfd, struct sockaddr_in *serv_sock, char *packet,int read_size, socklen_t servlen)
{
  int n;
  n = sendto(sockfd, packet, read_size, 0, serv_sock, servlen);
  //printf("%d ",n);
  return(n);
}

int Receiver(int sockfd, struct sockaddr_in *cli_sock, char *packet, int write_size, socklen_t clilen)
{
  int len;
  len = clilen;
  /* Here using polling to avoid too block - 10ms is good? */
  write_size = recvfrom(sockfd, packet, PACKETSIZE, 0, cli_sock, &len );
  //printf("write_size is %d\n",write_size);
  if (write_size > 0)
     return(0);
  else
     return (-1);
}

int SetupAudio( char *devicename, struct Audio_Para *audio_paras)
{
    int format  = AFMT_QUERY;  
    printf("%s\n",devicename);
    devfd=-1;
    /* Open /dev/audio */
    if((devfd = open(devicename, O_RDWR)) < 0) {
	if(errno == EBUSY) {
	    printf(stderr, "%s in use\n", devicename);
	}
	printf(stderr, "%s: %s\n", devicename, strerror(errno));
	return(-1);
    }

    /* Set the format PCM: 8 unsigned bits */
    if((ioctl(devfd, SNDCTL_DSP_SETFMT, &audio_paras->PCM)) < 0) {
	perror("SNDCTL_DSP_GETFMTS");
	return(-1);
    }

    if((ioctl(devfd, SNDCTL_DSP_GETFMTS, &format)) < 0) {
      perror("SNDCTL");
      return(-1);
    }

    /* Set the number of channels */
    if((ioctl(devfd, SNDCTL_DSP_STEREO, &audio_paras->stereo)) < 0) {
	perror("SNDCTL_DSP_STEREO");
	return(-1);
    }
    printf("\tSet %s mode\n", (audio_paras->stereo) ? "STEREO" : "MONO");

    /* Set the sample speed */
    if((ioctl(devfd, SNDCTL_DSP_SPEED, &audio_paras->speed)) < 0) {
	perror("SNDCTL_DSP_SPEED");
	return(-1);
    }
    printf("\tSPEED %d Hz\n", audio_paras->speed);

    return(0);
}
void Playback( char *packet, int write_size)
{

  write(devfd, packet, PACKETSIZE);	
}



void *writespeaker()
{

//pay attention that pthread mutex examole website uses one function only in both threads,
//here we have two functions that are trying to access the same variable
//we shouldn't allow one function to access the variable unless the other function is done with it
//notice we are talking about sockfd in receiver() and transmitter() 	

for(;;)
{
pthread_mutex_lock(&count_mutex);

recvalue = Receiver(sockfd, &cli_sock, packet, write_size, sizeof(cli_sock));
if(recvalue == 0)	        
{		
		 Playback( packet, write_size);
}
else if(recvalue == -1)
{
//printf("\n it is -1 now \n");

pthread_cond_signal(&condition_var); //signal to release the mutex
}

pthread_mutex_unlock(&count_mutex);
}
}

void *readmic()
{

for(;;)
{
read_size = read (devfd, packet, PACKETSIZE);
pthread_mutex_lock(&count_mutex);
pthread_cond_wait(&condition_var,&count_mutex);
printf( "\n condition met holla!\n");
num = Transmitter(sockfd, &serv_sock, packet, read_size, sizeof(serv_sock));
if(num > 0)
{	
 write(fd, packet, PACKETSIZE);	
}
pthread_mutex_unlock(&count_mutex);
}
 
		
}

Open in new window

/////////////////////header/////////////////
/* Header File */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <fcntl.h> 
#include <sys/ioctl.h>
#include <sys/soundcard.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>		/* for strerror */
#include <errno.h>		/* for errno */


#define PACKETSIZE  512
#define MAXHOSTNAMELEN  32
#define SERV_PORT 12000

/* Define the Server's Hostname and UDP port number */
 struct SERV_INFO {
          char *name;              
          int  port;               
 } ;

 struct SERV_INFO  cli_addr, serv_addr;  

 struct Audio_Para {
    int speed;
    int stereo;
    int PCM;
 } ; 
 
 struct Audio_Para  audio_paras;

int SetupAudio( char *devicename, struct Audio_Para *audio_paras);
int Transmitter(int sockfd, struct sockaddr_in *serv_sock, char *packet,int read_size, socklen_t servlen);
int Receiver(int sockfd, struct sockaddr_in *cli_addr, char *packet, int write_size, socklen_t clilen);
void Playback( char *packet, int write_size);

int   devfd, read_size, write_size;
char *devicename = "/dev/audio";

Open in new window

SOLUTION
Avatar of sarabande
sarabande
Flag of Luxembourg image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
it uses WinSock though, but you should be able to extend it to Unix as well
Avatar of logicallayer
logicallayer

ASKER

thanks everyone for the comments, here is where I'm at right now.

ok I found out that my problem is that my server isn't establishing a connection to the client which is has to be done by extracting the IP address of the UDP packet and then use it with proper port number (let's say I know it in advance) to send packets to the client side....


so my question how can I extract the ip address of a upd packet being received and then use that IP address to send data back to the client...

all I could find on the net is by using IP_PKTINFO inside setpacketopt()

but I couldn't figure out how to use it to extract the IP address of the header...

any ideas?
thanks everyone for the comments, here is where I'm at right now.

ok I found out that my problem is that my server isn't establishing a connection to the client which is has to be done by extracting the IP address of the UDP packet and then use it with proper port number (let's say I know it in advance) to send packets to the client side....


so my question how can I extract the ip address of a upd packet being received and then use that IP address to send data back to the client...

all I could find on the net is by using IP_PKTINFO inside setpacketopt()

but I couldn't figure out how to use it to extract the IP address of the header...

any ideas?

regard the link I prefer not use winsock, but thanks it's a neat article
as told the udp is a connectionless socket communication. you ask for service which is part of a tcpip connection. here the tcpip would provide information about sender, number of packages, and more and would guarantee that packages were transfered in the right order without losses. all that is missing when using udp and you would need to put the information into the packages yourself and establish mechanism to reorder packages, to request lost packages and so on.

by the way, winsock and linux sockets are nearly same beside of few exceptions which easily can be handled, for example error constants.

Sara
I wouldn't worry about out_of_sequence packets it's really quite rare and wouldn't be especially  serious even if it did happen.
I think you have to have a bit of a rethink regarding your design. What is the difference between a server and a client? Can the server handle multiple conversations? If not, they are peers and should both run the same code.
Also I really dislike "polling" - I very strongly recommend you use select() or poll() (ironic name poll() - it doesn't mean try every interval but instead is an alternative multi-channel interface to select()). You need one function to handle all socket transactions. If you want to write something, add your socket to the list of entities wanting to write. If you want to read something, add your socket to the list of entities wanting to read. In either case, select() or poll() will tell you when you can go ahead - there's no need to be non-blocking.
Sticking with select() (with which I'm slightly more familiar although I've used both), you are faced with the problem of how do you wake up select() when you have a new item to write ?
Luckily there's an easy solution. You open a loopback Tcp socket and write a byte to it, thus waking the select(). In previous projects I have only written a zero byte, but I can see future applications where the value of the byte might be nonzero and have some special meaning (like go and check a queue somewhere for,say, freshly completed connection requests).
lost or disordered udp packages might be a rare thing especially on one machine but if they happen they would lead to unacceptable errors in most cases. you may think of a simple file transfer where a wrong or missing package would spoil the whole file at the receiver side. generally udp is not recommended for wan or for lan's which have more than one router.
 
if you want the ip address of the sender when using udp socket you need to pass the ip address with the message.

Sara
With audio though, there would be some garbled sound then you'd carry on. Although on first reading the Q I did think that sound usually went over some other protocol, the name of which escapes me for no
Actually the possibility of mis-ordered packets is a complete irrelevancy at this stage. The problem is no communication at all in one direction - that is what we need to address
it is not irrelevant cause udp is the wrong decision in my opinion. also communication works - if i understood the author's last post correctly - and the last q. was 'how to gain ip address of sender when using udp' .

Sara
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I really appreciate everyone effort on this, you guys helping me alot going through this

sarabande,
thanks for your insight , regard using tcp instead of udp I have to say I don't agree with you for the following reason
first we know that udp does have less over head which quite important in video and audio streaming
second what's the probabilty of error in coaxial cable, I think 10^-9 , considering losing a packet or two you would still make out of what you are hearing as you are missng with a spectrum level, well it's digital but still...i prefer to work on the problem before I try to find a room for improvement but thanks though

duncane and  phoffric this exaclty what I'm looking for, I made adjustment to the code can you please check it out to see I'm passing the value of my pointer correctly, I think I'm missing it up some how but your suggestion totatally make sense, I almost gave up and was going to try to open a new socket to pass the ip address of the client then use it on the server to connect back to the client but you guys saved me quite some work


my problem i n my code is with first how to pass the ip is it as pointer or reference, I'm not really sure
and second how to assign a port to that ip address which is of type stuct sockaddr_in, I tried something here you can check in the code but I have a feeling it's not the way to  do it

      




//here is the part of trying to assign ip address

//here we are assigning the socket information for the client (that is going to be transmitted to)
	ip_sock = *cli_sock;	
	//bzero(&ip_sock, sizeof(ip_sock));
	ip_sock.sin_family = AF_INET;
	ip_sock.sin_port = htons(12001);

//we bind it (although we are sending so it might be not neccssary)	
if (bind(sockmd,  &ip_sock, sizeof(ip_sock))<0)
	  perror(" Failed in binding the Server sock!");

Open in new window

recv.c
connect.c
voip.h
Why is bzero commented out? You want INADDR_ANY (zero) if doing a bind. bzero (or memset) would achieve that.
actually I decided to not bother with getting the ip of the client but instead make the two programs identical except each one is listening on a different port, the only problem I'm facing now is that I'm getting echo sound that stays in there and doesn't stop, I have tried different methods but all failed, do you mind taking one more look please

the other frustrating thing that might be behind the problem is
my read_size = read(devfd, packet, PACKETSIZE); always returning size
while I thought by calling the following function, it should return -1 when there is no DATA to be read
fcntl(devfd,F_SETFL,O_NONBLOCK);

actually it did return -1 at some point in my code, then I did something that took that away... do you think that you can put your hands on it?

I really appreciate your help as my head is spinning...

#include	"voip.h"
#include <pthread.h>
#include <fcntl.h>

int  			sockfd,sockmd;
	struct sockaddr_in	serv_sock, cli_sock,ip_sock;
	char                    packet[PACKETSIZE];
	int fd,devfd2,num, sum=0;

pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t condition_var = PTHREAD_COND_INITIALIZER;
int recvalue = 0;
///////////////////////prototype//////////////

void *writespeaker();
void *readmic();

////////////////////////////////////////////


int main(int argc, char **argv)
{
	
	/* Open  a UDP SOCKET */
	
	if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
	  perror("Socket()");
	  exit(1);
	}

if ((sockmd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
	  perror("Socket()");
	  exit(1);
	}	
	
	//fcntl(sockfd,F_SETFL,O_NONBLOCK); //make it non-blocking so it returns an error if no message to be read


//make it no blocking to return error
	fcntl(sockmd,F_SETFL,O_NONBLOCK);
	fcntl(devfd,F_SETFL,O_NONBLOCK);	


	/* Set some params */
	audio_paras.speed = 8000;
	audio_paras.stereo = 0;
	audio_paras.PCM  = AFMT_U8; 

       	if (SetupAudio(devicename, &audio_paras)!=0) {
	    perror("Error in Initializing Audio Device!");
	    exit(-1);
	}
	else 
	puts("Audio Device is setup"); 	


	/* Set the socket parameters for the recieving*/
	bzero(&serv_sock, sizeof(serv_sock));
	serv_sock.sin_family      = AF_INET;
	serv_sock.sin_addr.s_addr = htonl(INADDR_ANY);
	serv_sock.sin_port        = htons(SERV_PORT);
 
	if (bind(sockfd,  &serv_sock, sizeof(serv_sock))<0)
	  perror(" Failed in binding the Server sock!");




/* Get the Server Parameters from the input*/  

	cli_addr.name = argv[1];
	cli_addr.port = atoi(argv[2]);

bzero(&cli_sock, sizeof(cli_sock));
	cli_sock.sin_family = AF_INET;
	cli_sock.sin_port = htons(cli_addr.port);
	inet_pton(AF_INET, cli_addr.name, &cli_sock.sin_addr);




 

	

pthread_t thread1,thread2;

pthread_create(&thread1,NULL, writespeaker,NULL);
pthread_create(&thread2,NULL, readmic,NULL);

pthread_join(thread1,NULL);
pthread_join(thread2,NULL);

}


int Transmitter(int sockmd, struct sockaddr_in *cli_sock, char *packet,int read_size, socklen_t servlen)
{
  int n;
  n = sendto(sockmd, packet, read_size, 0, cli_sock,servlen);
  //printf("%d ",n);
  return(n);
}

int Receiver(int sockfd, struct sockaddr_in *serv_sock, char *packet, int write_size, socklen_t clilen)
{
  int len;
  len = clilen;
  /* Here using polling to avoid too block - 10ms is good? */
  write_size = recvfrom(sockfd, packet, PACKETSIZE, 0, serv_sock, &len ); //cli_sock length was &len changed to sizeof(cli_sock)
  //printf("write_size is %d\n",write_size);
  if (write_size > 0)
     return(0);
  else
     return (-1);
}

void Playback( char *packet, int write_size)
{
  write(devfd, packet, PACKETSIZE);	
}

int SetupAudio( char *devicename, struct Audio_Para *audio_paras)
{
    int format  = AFMT_QUERY;  
    printf("%s\n",devicename);
    devfd=-1;
	
    /* Open /dev/audio */
    if((devfd = open(devicename, O_RDWR)) < 0) {
	if(errno == EBUSY) {
	    fprintf(stderr, "%s in use\n", devicename);
	}
	printf(stderr, "%s: %s\n", devicename, strerror(errno));
	return(-1);
    }

    /* Set the format PCM: 8 unsigned bits */
    if((ioctl(devfd, SNDCTL_DSP_SETFMT, &audio_paras->PCM)) < 0) {
	perror("SNDCTL_DSP_GETFMTS");
	return(-1);
    }

    if((ioctl(devfd, SNDCTL_DSP_GETFMTS, &format)) < 0) {
      perror("SNDCTL");
      return(-1);
    }

    /* Set the number of channels */
    if((ioctl(devfd, SNDCTL_DSP_STEREO, &audio_paras->stereo)) < 0) {
	perror("SNDCTL_DSP_STEREO");
	return(-1);
    }
    printf("\tSet %s mode\n", (audio_paras->stereo) ? "STEREO" : "MONO");

    /* Set the sample speed */
    if((ioctl(devfd, SNDCTL_DSP_SPEED, &audio_paras->speed)) < 0) {
	perror("SNDCTL_DSP_SPEED");
	return(-1);
    }
    printf("\tSPEED %d Hz\n", audio_paras->speed);

    return(0);printf( "\n condition met\n");
}



void *writespeaker()
{

//pay attention that pthread mutex examole website uses one function only in both threads,
//here we have two functions that are trying to access the same variable
//we shouldn't allow one function to access the variable unless the other function is done with it
//notice we are talking about sockfd in receiver() and transmitter() 	

for(;;)
{
//pthread_mutex_lock(&count_mutex);
//printf("reciver GOT NOTHING");
recvalue = Receiver(sockfd, &serv_sock, packet, write_size, sizeof(serv_sock));
if(recvalue == 0)	        
{		
printf("reciver GOT SOMETHING!!!!!!");
		 Playback( packet, write_size);
}
else if(recvalue == -1)
{
//pthread_cond_signal(&condition_var); //signal to release the mutex
}


//pthread_mutex_unlock(&count_mutex);
}
}

void *readmic()
{
for(;;)
{

//pthread_cond_wait(&condition_var,&count_mutex);
//pthread_mutex_lock(&count_mutex);
//printf("before cond");
//wait here until the writespeaker signal to continue

//printf("after cond");
read_size = read(devfd, packet, PACKETSIZE);
printf("\n read size is: %d",read_size);
if(read_size > 0)
{
printf( "\n condition met holla!\n");

num = Transmitter(sockmd, &cli_sock, packet, read_size, sizeof(cli_sock));
//if(num > 0)
//{	
// write(fd, packet, PACKETSIZE);	
//}
//pthread_mutex_unlock(&count_mutex);
}		
}
}

Open in new window

#include	"voip.h"
#include <pthread.h>
#include <fcntl.h>

int  			sockfd,sockmd;
	struct sockaddr_in	serv_sock, cli_sock,ip_sock;
	char                    packet[PACKETSIZE];
	int fd,devfd2,num, sum=0;

pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t condition_var = PTHREAD_COND_INITIALIZER;
int recvalue = 0;
///////////////////////prototype//////////////

void *writespeaker();
void *readmic();

////////////////////////////////////////////


int main(int argc, char **argv)
{
	
	/* Open  a UDP SOCKET */
	
	if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
	  perror("Socket()");
	  exit(1);
	}

if ((sockmd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
	  perror("Socket()");
	  exit(1);
	}	
	
	//fcntl(sockfd,F_SETFL,O_NONBLOCK); //make it non-blocking so it returns an error if no message to be read


//make it no blocking to return error
	fcntl(sockmd,F_SETFL,O_NONBLOCK);
	fcntl(devfd,F_SETFL,O_NONBLOCK);	


	/* Set some params */
	audio_paras.speed = 8000;
	audio_paras.stereo = 0;
	audio_paras.PCM  = AFMT_U8; 

       	if (SetupAudio(devicename, &audio_paras)!=0) {
	    perror("Error in Initializing Audio Device!");
	    exit(-1);
	}
	else 
	puts("Audio Device is setup"); 	


	/* Set the socket parameters for the recieving*/
	bzero(&serv_sock, sizeof(serv_sock));
	serv_sock.sin_family      = AF_INET;
	serv_sock.sin_addr.s_addr = htonl(INADDR_ANY);
	serv_sock.sin_port        = htons(12001);
 
	if (bind(sockfd,  &serv_sock, sizeof(serv_sock))<0)
	  perror(" Failed in binding the Server sock!");



/* Get the Server Parameters from the input*/  

	cli_addr.name = argv[1];
	cli_addr.port = atoi(argv[2]);

bzero(&cli_sock, sizeof(cli_sock));
	cli_sock.sin_family = AF_INET;
	cli_sock.sin_port = htons(cli_addr.port);
	inet_pton(AF_INET, cli_addr.name, &cli_sock.sin_addr);



	

pthread_t thread1,thread2;



pthread_create(&thread1,NULL, writespeaker,NULL);
pthread_create(&thread2,NULL, readmic,NULL);

pthread_join(thread1,NULL);
pthread_join(thread2,NULL);

}


int Transmitter(int sockmd, struct sockaddr_in *cli_sock, char *packet,int read_size, socklen_t servlen)
{
  int n;
  n = sendto(sockmd, packet, read_size, 0, cli_sock,servlen);
  //printf("%d ",n);
  return(n);
}

int Receiver(int sockfd, struct sockaddr_in *serv_sock, char *packet, int write_size, socklen_t clilen)
{
  int len;
  len = clilen;
  /* Here using polling to avoid too block - 10ms is good? */
  write_size = recvfrom(sockfd, packet, PACKETSIZE, 0, serv_sock, &len ); //cli_sock length was &len changed to sizeof(cli_sock)
  //printf("write_size is %d\n",write_size);
  if (write_size > 0)
     return(0);
  else
     return (-1);
}

void Playback( char *packet, int write_size)
{
  write(devfd, packet, PACKETSIZE);	
}

int SetupAudio( char *devicename, struct Audio_Para *audio_paras)
{
    int format  = AFMT_QUERY;  
    printf("%s\n",devicename);
    devfd=-1;
	
    /* Open /dev/audio */
    if((devfd = open(devicename, O_RDWR)) < 0) {
	if(errno == EBUSY) {
	    fprintf(stderr, "%s in use\n", devicename);
	}
	printf(stderr, "%s: %s\n", devicename, strerror(errno));
	return(-1);
    }

    /* Set the format PCM: 8 unsigned bits */
    if((ioctl(devfd, SNDCTL_DSP_SETFMT, &audio_paras->PCM)) < 0) {
	perror("SNDCTL_DSP_GETFMTS");
	return(-1);
    }

    if((ioctl(devfd, SNDCTL_DSP_GETFMTS, &format)) < 0) {
      perror("SNDCTL");
      return(-1);
    }

    /* Set the number of channels */
    if((ioctl(devfd, SNDCTL_DSP_STEREO, &audio_paras->stereo)) < 0) {
	perror("SNDCTL_DSP_STEREO");
	return(-1);
    }
    printf("\tSet %s mode\n", (audio_paras->stereo) ? "STEREO" : "MONO");

    /* Set the sample speed */
    if((ioctl(devfd, SNDCTL_DSP_SPEED, &audio_paras->speed)) < 0) {
	perror("SNDCTL_DSP_SPEED");
	return(-1);
    }
    printf("\tSPEED %d Hz\n", audio_paras->speed);

    return(0);printf( "\n condition met\n");
}



void *writespeaker()
{

//pay attention that pthread mutex examole website uses one function only in both threads,
//here we have two functions that are trying to access the same variable
//we shouldn't allow one function to access the variable unless the other function is done with it
//notice we are talking about sockfd in receiver() and transmitter() 	

for(;;)
{
//pthread_mutex_lock(&count_mutex);
//printf("reciver GOT NOTHING");
recvalue = Receiver(sockfd, &serv_sock, packet, write_size, sizeof(serv_sock));
if(recvalue == 0)	        
{		
printf("reciver GOT SOMETHING!!!!!!");
		 Playback( packet, write_size);
}
else if(recvalue == -1)
{
//pthread_cond_signal(&condition_var); //signal to release the mutex
}


//pthread_mutex_unlock(&count_mutex);
}
}

void *readmic()
{
for(;;)
{

//pthread_cond_wait(&condition_var,&count_mutex);
//pthread_mutex_lock(&count_mutex);
printf("before cond");
//wait here until the writespeaker signal to continue

//printf("after cond");
read_size = read(devfd, packet, PACKETSIZE);
printf("\n read size is: %d",read_size);
if(read_size > 0)
{
printf( "\n condition met holla!\n");

num = Transmitter(sockmd, &cli_sock, packet, read_size, sizeof(cli_sock));
//if(num > 0)
//{	
// write(fd, packet, PACKETSIZE);	
//}
//pthread_mutex_unlock(&count_mutex);
}		
}
}

Open in new window

for the problem of fcntl(devfd,F_SETFL,O_NONBLOCK); not working I found out my mistake was I had this function before I initialize the value of devfd and open the file so I fixed this now it's non-blocking but still when the peer1 take peer2 hear echo on the voice, what I noticed it seems that peer2 transmitting the packet back to peer1 and peer1 doing the same (indefinitely)

I figured that using one headset one plug on the mic of peer1 and the earphone on the plug of peer2 then once I talk and hear echo I switch the earphone to peer1 and I still hear the echo...so that does prove the retransmition indefinitely but why?
I'm not able to run this app, but I just wonder whether you have the echo and oscillation problem if you test on two platforms and two headsets (that are not near each other).
Im testing with one headset that earphone are not loud one connected to one pc mic and the other to the earphone on the other pc, I think my problem has to do with either devfd which only open one file for read and write but im not sure how read and write exactly behave, also I suspect using the same variable for read and write which is int packet, athough I tried to change this variable but it didnt fix the problem
nevermind , I found out that using only one headest seems that it created some polarity that cause the echo, I brought two headset and there is no echo, which is great


thanks everyone,