Solved

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

Posted on 2011-03-20
20
536 Views
Last Modified: 2012-05-11
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

0
Comment
Question by:logicallayer
  • 7
  • 5
  • 4
  • +2
20 Comments
 
LVL 32

Assisted Solution

by:sarabande
sarabande earned 50 total points
ID: 35179961
in case of udp you have connection-less sockets where youself need to do all synchronisation. that means some packets may come in wrong order or got lost and you must get aware of that and have code to handle that accordingly. also you need to handle the case where a new client connects to the server differently from following communication to that client. also if you make the socket non-blocking you would get error for almost any call to recvfrom and you have to handle the would-block errors differently from real errors.

in your code i couldn't detect any of these considerations though i may not have analysed it thoroughly enough.

i generally have a different design for tasks like yours. i firstly have a 'normal' tcpip connection where a server listens to a socket in order to accept new clients. if a client connected i open two more sockets (and threads to handle them), one is tcpip and one is udp. the udp now is for fast transfer and the tcpip is for lost packets or other hand-shake things.

Sara
0
 
LVL 12

Expert Comment

by:trinitrotoluene
ID: 35186182
take a look at this sample application here

http://www.codeproject.com/KB/IP/client_server_socket.aspx
0
 
LVL 12

Expert Comment

by:trinitrotoluene
ID: 35186187
it uses WinSock though, but you should be able to extend it to Unix as well
0
 

Author Comment

by:logicallayer
ID: 35186426
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?
0
 

Author Comment

by:logicallayer
ID: 35186428
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
0
 
LVL 32

Expert Comment

by:sarabande
ID: 35187095
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
0
 
LVL 34

Expert Comment

by:Duncan Roe
ID: 35187619
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).
0
 
LVL 32

Expert Comment

by:sarabande
ID: 35187758
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
0
 
LVL 34

Expert Comment

by:Duncan Roe
ID: 35188000
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
0
 
LVL 34

Expert Comment

by:Duncan Roe
ID: 35188060
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
0
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 
LVL 32

Expert Comment

by:sarabande
ID: 35188249
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
0
 
LVL 34

Accepted Solution

by:
Duncan Roe earned 350 total points
ID: 35189553
Easy - the man page says
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
Here one should supply a pointer to a struct sockaddr_in cast to a pointer to struct_sockaddr with addrlen being sizeof the preceding argument. On receipt of a datagram,  src_addr is filled in to be the source of the datagram - a responding sendto() should give that as its dest_addr.

See man 2 recvfrom and man 2 sendto
0
 
LVL 32

Assisted Solution

by:phoffric
phoffric earned 100 total points
ID: 35190511
>> if you want the ip address of the sender when using udp socket you need to pass the ip address with the message
   Assuming UDP over IPv4, then that is being done implicitly. Image taken from
       http://learn-networking.com/tcp-ip/how-the-internet-layer-works

>> On receipt of a datagram,  src_addr is filled in to be the source of the datagram
So, src_addr should be the the value of the circled item in the image.
IP-Packet.PNG
0
 

Author Comment

by:logicallayer
ID: 35195588
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
0
 
LVL 34

Expert Comment

by:Duncan Roe
ID: 35202495
Why is bzero commented out? You want INADDR_ANY (zero) if doing a bind. bzero (or memset) would achieve that.
0
 

Author Comment

by:logicallayer
ID: 35203240
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

0
 

Author Comment

by:logicallayer
ID: 35203553
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?
0
 
LVL 32

Expert Comment

by:phoffric
ID: 35204155
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).
0
 

Author Comment

by:logicallayer
ID: 35204251
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
0
 

Author Closing Comment

by:logicallayer
ID: 35209592
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,
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
Note: for this to work properly you need to use a Cross-Over network cable. 1. Connect both servers S1 and S2 on the second network slots respectively. Note that you can use the 1st slots but usually these would be occupied by the Service Provide…
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use nested-loops in the C programming language.
The goal of this video is to provide viewers with basic examples to understand how to create, access, and change arrays in the C programming language.

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now