0

I am trying to make simple SIP client (UDP, BSD sockets), but I am stucked with REGISTER message. I manage to send the REGISTER message to asterisk, he will then respond, but client doesn't catch the response so he waits forever.

#include <stdio.h> //printf
#include <string.h> //memset
#include <stdlib.h> //exit(0);
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <ctype.h>
#include <netinet/in.h>
#include <unistd.h>
#include <netdb.h>

#define SERVER "127.0.0.1"
#define BUFLEN 1024  //Max length of buffer
#define PORT 5060   //The port on which to send data


int main(int argc, char **argv)
{
  struct sockaddr_in si_other;
  int s,slen=sizeof(si_other);
  char buf[BUFLEN];
  char message[]= "REGISTER sip:127.0.0.1 SIP/2.0\r\nVia: SIP/2.0/UDP 127.0.0.1:5060;branch=z9hG4bKnashds7\r\nFrom: <sip:bob@127.0.0.1>;tag=as58f4201b\r\nCall-ID: 843817637684230@hefrst\r\nTo: <sip:bob@127.0.0.1>\r\nCSeq: 1 REGISTER\r\nContact: <sip:bob@127.10.10.1>\r\nAllow: INVITE,ACK,OPTIONS,BYE,CANCEL,SUBSCRIBE,NOTIFY,REFER,MESSAGE,INFO,PING\r\nExpires: 3600\r\n\r\n";  

  if ( (s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
{
   fprintf(stderr, "socket failed");
   exit(1);
}

  memset((char *) &si_other, 0, sizeof(si_other));
  si_other.sin_family = AF_INET;
  si_other.sin_port = htons(PORT);

 if (inet_aton(SERVER , &si_other.sin_addr) == 0) 
{
    fprintf(stderr, "inet_aton() failed\n");
    exit(1);
}
while(1){
 if (sendto(s, message, strlen(message) , 0 , (struct sockaddr *) &si_other, slen)==-1)
    {
        fprintf(stderr, "sendto failed");
        exit(1);
    }
memset(buf,'\0', BUFLEN);
if (recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen) == -1)
    {
        fprintf(stderr, "recvfrom() failed");
        exit(1);
    }
  }
}

This is just the part of code that seems to be failing to receive the data.

Croolman
  • 1,103
  • 13
  • 40
  • I don't know SIP, but 1. aren't you expected to send the message before hearing (receiving)? 2. Is it right to use `\n`, not \r\n`, in the middle of the `message`? – MikeCAT Nov 21 '15 at 13:50
  • Yop, I am sending message before recieving, I ve just didnt include it in the example. And 2, I have to put newline after evey header in the message. – Croolman Nov 21 '15 at 14:01
  • s result uninitialised in the call to recvfrom. If there is more code, please post it. – terence hill Nov 21 '15 at 14:04
  • Using `\n` instead of `\r\n` as the separator of lines is **wrong**. Quote from [SIP: Session Initiation Protocol](http://www.ietf.org/rfc/rfc3261.txt) 7 SIP Messages (Page 26): "The start-line, each message-header line, and the empty line MUST be terminated by a carriage-return line-feed sequence (CRLF)." – MikeCAT Nov 21 '15 at 14:10
  • @terencehill updated question – Croolman Nov 21 '15 at 14:18
  • @MikeCAT Thank you, still the same problem though – Croolman Nov 21 '15 at 14:19

2 Answers2

0

You forgot to bind to the socket:

   if( bind(s , (struct sockaddr*)&si_other, sizeof(si_other) ) == -1)
    {
        fprintf(stderr, "bind failed\n");
        exit(1);
    }
terence hill
  • 3,354
  • 18
  • 31
  • It is UDP client, it doesn't have to bind. – Croolman Nov 21 '15 at 14:51
  • I have tried the code with bind and works. Plus: with UDP, you have to bind() the socket in the client because UDP is connectionless, so there is no other way for the stack to know which program to deliver datagrams to for a particular port. See (http://stackoverflow.com/questions/3057029/do-i-have-to-bind-an-udp-socket-in-my-client-program-to-receive-data-i-always) – terence hill Nov 21 '15 at 14:57
0

The problem was in the message header. The part Via has to end with ;rport, so asterisk does actually report.

Croolman
  • 1,103
  • 13
  • 40