Проблема регистрации SIP - PullRequest
0 голосов
/ 13 февраля 2012

В настоящее время я работаю над примером приложения SIP.

Я пытаюсь выполнить регистрацию, используя программирование сокетов на основе Си в Unix.Я успешно смог зарегистрироваться в PJSIP, но когда те же параметры я посылаю при обычном программировании сокетов, я не могу получить ответ от сервера.

Вот исходный код:

char *server = (char *)serverAddress; // First arg: server address/name
char *echoString = "Request msg REGISTER/cseq=46476 (tdta0x8857200)\r\nREGISTER sip:DOMAIN_NAME SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.1.120:51648;rport;branch=z9hG4bKPjwEt4VvIVdjIJKRmEJbkidYDAu-zQbIqv\r\nMax-Forwards: 70\r\nFrom: <sip:USER_NAME@DOMAIN_NAME>;tag=epCBN7JXsQE1nnI5d5SOZe9a5ujRyI67\r\nTo: <sip:USER_NAME@DOMAIN_NAME>\r\nCall-ID: .5yYCqh2jEYdy5T4kxhzxwDYEkCO1XlD\r\nCSeq: 46476 REGISTER\r\nContact: <sip:USER_NAME@192.168.1.120:51648;ob>\r\nExpires: 300\r\nAllow: PRACK, INVITE, ACK, BYE, CANCEL, UPDATE, SUBSCRIBE, NOTIFY, REFER, MESSAGE, OPTIONS\r\nAuthorization: Digest username=\"USER_NAME\", realm=\"asterisk\", nonce=\"3b63254c\", uri=\"sip:DOMAIN_NAME\", response=\"9e8fc78829d143a58fba5a79f6ad44fd\", algorithm=MD5\r\nContent-Length:  0"; 


size_t echoStringLen = strlen(echoString);


// Third arg (optional): server port/service
char *servPort = (char *)service;

// Tell the system what kind(s) of address info we want
struct addrinfo addrCriteria;                      // Criteria for address match
memset(&addrCriteria, 0, sizeof(addrCriteria));    // Zero out structure
addrCriteria.ai_family = AF_UNSPEC;                // For the following fields, a zero value means 
                                                   // Any address family "don't care"


addrCriteria.ai_socktype = SOCK_DGRAM; // Only datagram sockets
addrCriteria.ai_protocol = IPPROTO_UDP;         // Only UDP protocol
// Get address(es)
struct addrinfo *servAddr; // List of server addresses
int rtnVal = getaddrinfo(server, servPort, &addrCriteria, &servAddr);
if (rtnVal != 0)
    DieWithUserMessage("getaddrinfo() failed", gai_strerror(rtnVal));
// Create a datagram/UDP socket
int sock = socket(servAddr->ai_family, servAddr->ai_socktype,
                  servAddr->ai_protocol); // Socket descriptor for client
if (sock < 0)
    DieWithSystemMessage("socket() failed");
// Send the string to the server
ssize_t numBytes = sendto(sock, echoString, echoStringLen, 0,
                          servAddr->ai_addr, servAddr->ai_addrlen);
if (numBytes < 0)
    DieWithSystemMessage("sendto() failed");
else if (numBytes != echoStringLen)
    DieWithUserMessage("sendto() error", "sent unexpected number of bytes");
// Receive a response
struct sockaddr_storage fromAddr; // Source address of server
// Set length of from address structure (in-out parameter)
socklen_t fromAddrLen = sizeof(fromAddr);
char buffer[100 + 1]; // I/O buffer
numBytes = recvfrom(sock, buffer, 100, 0,
                    (struct sockaddr *) &fromAddr, &fromAddrLen);
if (numBytes < 0)
    DieWithSystemMessage("recvfrom() failed");
else if (numBytes != 100)
    DieWithUserMessage("recvfrom() error", "received unexpected number of bytes");
// Verify reception from expected source

int value = SockAddrsEqual(servAddr->ai_addr, (struct sockaddr *) &fromAddr);
if (value == 0)
    DieWithUserMessage("recvfrom()", "received a packet from unknown source");
freeaddrinfo(servAddr);
buffer[echoStringLen] = '\0';     // Null-terminate received data
printf("Received: %s\n", buffer); // Print the echoed string

close(sock);
exit(0);

Когда я пытаюсь отладить код, точка останова исчезает из вызова метода recvfrom следующим образом.

numBytes = recvfrom(sock, buffer, 100, 0, (struct sockaddr *) &fromAddr, &fromAddrLen);

Заранее благодарим за сотрудничество.

Ответы [ 3 ]

0 голосов
/ 14 февраля 2012

recvfrom() блокируется до получения ответа, если вы не установите сокет в неблокирующее состояние. Лучшим подходом было бы использовать select() с таймаутом (например, секунда или две). Еще лучше было бы поместить все это в цикл, который повторяется несколько раз (например, три или четыре).

Помните, что UDP не гарантирует, что ваша дейтаграмма будет доставлена: вам решать, когда вы достаточно долго ждали и вам нужно повторить попытку.

Также убедитесь, что значения, установленные в servAddr с помощью getaddrinfo(), имеют смысл. Если адрес или номер порта неверен, ваш пакет может молча исчезнуть.

0 голосов
/ 15 февраля 2012

Если вы подтвердите, что это проблема с сокетом, тогда лучше ее отследить.

Но если вы не уверены, что для решения этой проблемы используйте приложение сетевого анализа (wireshark) и посмотрите пакет, который вы отправляете и получаете. Затем посмотрите на проблему с сокетом.

0 голосов
/ 13 февраля 2012

Если вы не получаете ответ от сервера регистратора, скорее всего, он не может понять запрос REGISTER, который вы отправили, или отклонил его как дубликат.Скорее всего, вам понадобится немного сложнее понять, как вы строите свой запрос REGISTER, а не просто отправлять жестко закодированную строку.

Помимо этой очевидной вещи, которую вы можете попробовать, добавьте требуемый \r \ n \ r \ n в конце вашей эхо-строки.Все SIP-запросы требуются для завершения заголовочной части двойным переводом строки, который отсутствует в вашей строке.

...