1 #include "sip_client.h"
4 #include <sys/socket.h>
7 #include <netinet/in.h>
10 #include <sys/epoll.h>
15 #include <sys/ioctl.h>
18 #include "sip_agent.h"
22 static inline struct sip_agent
*agent_to_sip_agent(struct agent
*agent
)
24 return container_of(agent
, struct sip_agent
, agent
);
27 static int iface_get_addr(const char *iface
, struct sockaddr_storage
*addr
)
33 fd
= socket(AF_INET
, SOCK_DGRAM
, 0);
35 ifr
.ifr_addr
.sa_family
= AF_INET
;
36 strncpy(ifr
.ifr_name
, iface
, IFNAMSIZ
-1);
37 ret
= ioctl(fd
, SIOCGIFADDR
, &ifr
);
39 perror("Failed to get interface address");
44 memcpy(addr
, &ifr
.ifr_addr
, sizeof(ifr
.ifr_addr
));
50 static bool sockaddr_is_local(struct sockaddr_storage
*addr
)
53 bool is_local
= false;
55 switch (addr
->ss_family
) {
57 s_addr
= ((struct sockaddr_in
*)addr
)->sin_addr
.s_addr
;
58 if ((s_addr
& 0xff000000) == 0x10000000)
60 else if ((s_addr
& 0xfff00000) == 0xac100000)
62 else if ((s_addr
& 0xffff0000) == 0xc0a80000)
73 static uint16_t sockaddr_get_port(struct sockaddr_storage
*addr
)
77 switch (addr
->ss_family
) {
79 port
= ((struct sockaddr_in
*)addr
)->sin_port
;
82 port
= ((struct sockaddr_in6
*)addr
)->sin6_port
;
92 static void sockaddr_set_port(struct sockaddr_storage
*addr
, uint16_t port
)
94 switch (addr
->ss_family
) {
96 ((struct sockaddr_in
*)addr
)->sin_port
= port
;
99 ((struct sockaddr_in6
*)addr
)->sin6_port
= port
;
106 static void *sockaddr_get_addr(struct sockaddr_storage
*addr
)
109 switch (addr
->ss_family
) {
111 a
= &((struct sockaddr_in
*)addr
)->sin_addr
.s_addr
;
114 a
= ((struct sockaddr_in6
*)addr
)->sin6_addr
.s6_addr
;
124 static int sockaddr_to_string(struct sockaddr_storage
*addr
, char *s
, size_t n
)
126 return inet_ntop(addr
->ss_family
, sockaddr_get_addr(addr
), s
, n
) == NULL
? -1 : 0;
129 static pjsip_module mod_siprtp
;
130 static struct sip_client
*global_client
;
132 /* Creates a datagram socket and binds it to a port in the range of
133 * start_port-end_port */
134 static int sip_client_create_socket(struct sip_client
*client
,
135 struct sockaddr_storage
*sockaddr
, uint16_t start_port
,
141 sockfd
= socket(AF_INET
, SOCK_DGRAM
, 0);
145 memcpy(sockaddr
, &client
->local_addr
, sizeof(client
->local_addr
));
147 sockaddr_set_port(sockaddr
, start_port
);
148 ret
= bind(sockfd
, (struct sockaddr
*)sockaddr
, sizeof(*sockaddr
));
150 } while (ret
== -1 && start_port
< end_port
);
158 static int sip_worker_thread(void *arg
)
160 struct sip_client
*client
= arg
;
163 pj_time_val timeout
= {0, 10};
164 pjsip_endpt_handle_events(client
->sip_endpt
, &timeout
);
170 static bool sip_agent_stream_recv_callback(int events
, void *data
)
172 struct sip_agent
*agent
= data
;
177 len
= read(agent
->stream
->fd
, buf
, 512);
181 ret
= sendto(agent
->rtp_sockfd
, buf
, len
, 0,
182 (struct sockaddr
*)&agent
->remote_addr
, sizeof(agent
->remote_addr
));
185 printf("failed to send rtp data: %d\n", errno
);
191 static bool sip_agent_rtp_recv_callback(int events
, void *data
)
193 struct sip_agent
*agent
= data
;
197 len
= recvfrom(agent
->rtp_sockfd
, buf
, 512, 0, NULL
, NULL
);
199 write(agent
->stream
->fd
, buf
, len
);
204 static pj_status_t
sip_client_create_sdp(struct sip_client
*client
, pj_pool_t
*pool
,
205 struct sip_agent
*agent
,
206 pjmedia_sdp_session
**p_sdp
)
209 pjmedia_sdp_session
*sdp
;
210 pjmedia_sdp_media
*m
;
211 pjmedia_sdp_attr
*attr
;
212 struct sockaddr_storage rtp_addr
;
213 char addr
[INET6_ADDRSTRLEN
];
215 PJ_ASSERT_RETURN(pool
&& p_sdp
, PJ_EINVAL
);
217 agent
->rtp_sockfd
= sip_client_create_socket(client
, &rtp_addr
, 4000, 5000);
219 stun_client_resolve(client
->stun
, agent
->rtp_sockfd
,
220 (struct sockaddr
*)&rtp_addr
);
222 agent
->rtp_recv_callback
.callback
= sip_agent_rtp_recv_callback
;
223 agent
->rtp_recv_callback
.data
= agent
;
224 event_register(agent
->rtp_sockfd
, EPOLLIN
, &agent
->rtp_recv_callback
);
226 /* Create and initialize basic SDP session */
227 sdp
= pj_pool_zalloc (pool
, sizeof(pjmedia_sdp_session
));
229 pj_gettimeofday(&tv
);
230 sdp
->origin
.user
= pj_str("pjsip-siprtp");
231 sdp
->origin
.version
= sdp
->origin
.id
= tv
.sec
+ 2208988800UL;
232 sdp
->origin
.net_type
= pj_str("IN");
233 sdp
->origin
.addr_type
= pj_str("IP4");
234 sdp
->origin
.addr
= *pj_gethostname();
235 sdp
->name
= pj_str("pjsip");
237 /* Since we only support one media stream at present, put the
238 * SDP connection line in the session level.
240 sdp
->conn
= pj_pool_zalloc(pool
, sizeof(pjmedia_sdp_conn
));
241 sdp
->conn
->net_type
= pj_str("IN");
242 sdp
->conn
->addr_type
= pj_str("IP4");
243 sockaddr_to_string(&rtp_addr
, addr
, sizeof(addr
));
244 pj_strdup2_with_null(pool
, &sdp
->conn
->addr
, addr
);
246 /* SDP time and attributes. */
247 sdp
->time
.start
= sdp
->time
.stop
= 0;
250 /* Create media stream 0: */
252 sdp
->media_count
= 1;
253 m
= pj_pool_zalloc(pool
, sizeof(pjmedia_sdp_media
));
256 /* Standard media info: */
257 m
->desc
.media
= pj_str("audio");
258 m
->desc
.port
= sockaddr_get_port(&rtp_addr
);
259 m
->desc
.port_count
= 1;
260 m
->desc
.transport
= pj_str("RTP/AVP");
262 /* Add format and rtpmap for each codec. */
263 m
->desc
.fmt_count
= 1;
267 pjmedia_sdp_rtpmap rtpmap
;
270 sprintf(ptstr
, "%d", 0);
271 pj_strdup2_with_null(pool
, &m
->desc
.fmt
[0], ptstr
);
272 rtpmap
.pt
= m
->desc
.fmt
[0];
273 rtpmap
.clock_rate
= 64000;
274 rtpmap
.enc_name
= pj_str("PCMU");
275 rtpmap
.param
.slen
= 0;
279 /* Add sendrecv attribute. */
280 attr
= pj_pool_zalloc(pool
, sizeof(pjmedia_sdp_attr
));
281 attr
->name
= pj_str("sendrecv");
282 m
->attr
[m
->attr_count
++] = attr
;
290 static int sip_agent_invite(struct agent
*agent
, struct session
*session
)
292 struct sip_agent
*sip_agent
= agent_to_sip_agent(agent
);
293 struct sip_client
*client
= sip_agent
->client
;
295 pjmedia_sdp_session
*sdp
;
296 pjsip_tx_data
*tdata
;
300 sip_agent
->session
= session
;
302 dst_uri
= pj_str((char *)sip_agent
->identifier
);
304 /* Create UAC dialog */
305 status
= pjsip_dlg_create_uac(pjsip_ua_instance(),
306 &client
->local_contact
, /* local URI */
307 &client
->local_contact
, /* local Contact */
308 &dst_uri
, /* remote URI */
309 &dst_uri
, /* remote target */
311 if (status
!= PJ_SUCCESS
) {
312 fprintf(stderr
, "Failed to create uac dialog\n");
316 pjsip_auth_clt_set_credentials(&dlg
->auth_sess
, 1, &client
->cred
);
319 sip_client_create_sdp(client
, dlg
->pool
, sip_agent
, &sdp
);
321 /* Create the INVITE session. */
322 status
= pjsip_inv_create_uac(dlg
, sdp
, 0, &sip_agent
->inv
);
323 if (status
!= PJ_SUCCESS
) {
324 fprintf(stderr
, "Failed to create invite session\n");
325 pjsip_dlg_terminate(dlg
);
330 /* Attach call data to invite session */
331 sip_agent
->inv
->mod_data
[mod_siprtp
.id
] = sip_agent
;
333 /* Create initial INVITE request.
334 * This INVITE request will contain a perfectly good request and
335 * an SDP body as well.
337 status
= pjsip_inv_invite(sip_agent
->inv
, &tdata
);
338 PJ_ASSERT_RETURN(status
== PJ_SUCCESS
, -1); /*TODO*/
340 /* Send initial INVITE request.
341 * From now on, the invite session's state will be reported to us
342 * via the invite session callbacks.
344 status
= pjsip_inv_send_msg(sip_agent
->inv
, tdata
);
345 PJ_ASSERT_RETURN(status
== PJ_SUCCESS
, -1); /*TODO*/
350 static int sip_agent_hangup(struct agent
*agent
, struct session
*session
)
352 struct sip_agent
*sip_agent
= agent_to_sip_agent(agent
);
353 pjsip_tx_data
*tdata
;
356 printf("hangup %p\n", sip_agent
->inv
);
358 status
= pjsip_inv_end_session(sip_agent
->inv
, 603, NULL
, &tdata
);
359 if (status
== PJ_SUCCESS
&& tdata
!= NULL
)
360 pjsip_inv_send_msg(sip_agent
->inv
, tdata
);
362 if (sip_agent
->rtp_sockfd
) {
363 event_unregister(sip_agent
->rtp_sockfd
);
364 close(sip_agent
->rtp_sockfd
);
366 if (sip_agent
->stream
) {
367 event_unregister(sip_agent
->stream
->fd
);
368 tapi_stream_free(sip_agent
->stream
);
371 sip_agent
->inv
->mod_data
[mod_siprtp
.id
] = NULL
;
377 static int sip_agent_alloc_stream(struct sip_agent
*agent
)
382 printf("BUG!!!! %s:%s[%d]\n", __FILE__
, __func__
, __LINE__
);
384 agent
->stream
= tapi_stream_alloc(agent
->client
->tdev
);
385 agent
->stream_recv_callback
.callback
= sip_agent_stream_recv_callback
;
386 agent
->stream_recv_callback
.data
= agent
;
388 flags
= fcntl(agent
->stream
->fd
, F_GETFL
, 0);
389 fcntl(agent
->stream
->fd
, F_SETFL
, flags
| O_NONBLOCK
);
391 event_register(agent
->stream
->fd
, EPOLLIN
, &agent
->stream_recv_callback
);
396 static void sip_agent_free_stream(struct sip_agent
*agent
)
401 event_unregister(agent
->stream
->fd
);
402 tapi_stream_free(agent
->stream
);
403 agent
->stream
= NULL
;
406 static int sip_agent_accept(struct agent
*agent
, struct session
*session
)
408 struct sip_agent
*sip_agent
= agent_to_sip_agent(agent
);
410 pjsip_tx_data
*tdata
;
412 /* Create 200 response .*/
413 status
= pjsip_inv_answer(sip_agent
->inv
, 200,
415 if (status
!= PJ_SUCCESS
) {
416 status
= pjsip_inv_answer(sip_agent
->inv
,
417 PJSIP_SC_NOT_ACCEPTABLE
,
419 if (status
== PJ_SUCCESS
)
420 pjsip_inv_send_msg(sip_agent
->inv
, tdata
);
422 pjsip_inv_terminate(sip_agent
->inv
, 500, PJ_FALSE
);
426 /* Send the 200 response. */
427 status
= pjsip_inv_send_msg(sip_agent
->inv
, tdata
);
428 PJ_ASSERT_ON_FAIL(status
== PJ_SUCCESS
, return -1);
430 sip_agent_alloc_stream(sip_agent
);
435 static int sip_agent_get_endpoint(struct agent
*agent
, struct session
*session
)
437 struct sip_agent
*sip_agent
= agent_to_sip_agent(agent
);
438 return tapi_stream_get_endpoint(sip_agent
->stream
);
441 static const struct agent_ops sip_agent_ops
= {
442 .invite
= sip_agent_invite
,
443 .accept
= sip_agent_accept
,
444 .hangup
= sip_agent_hangup
,
445 .get_endpoint
= sip_agent_get_endpoint
,
448 struct sip_agent
*sip_client_alloc_agent(struct sip_client
*client
,
449 const char *identifier
)
451 struct sip_agent
*agent
;
453 agent
= malloc(sizeof(*agent
));
454 memset(agent
, 0, sizeof(*agent
));
456 agent
->agent
.ops
= &sip_agent_ops
;
457 agent
->identifier
= identifier
;
458 agent
->client
= client
;
464 * Receive incoming call
466 static void process_incoming_call(struct sip_client
*client
, pjsip_rx_data
*rdata
)
469 struct sip_agent
*agent
;
470 pjsip_tx_data
*tdata
;
473 pjmedia_sdp_session
*sdp
;
475 agent
= sip_client_alloc_agent(client
, "extern");
477 /* Verify that we can handle the request. */
479 status
= pjsip_inv_verify_request(rdata
, &options
, NULL
, NULL
,
480 client
->sip_endpt
, &tdata
);
481 if (status
!= PJ_SUCCESS
) {
483 * No we can't handle the incoming INVITE request.
486 pjsip_response_addr res_addr
;
487 pjsip_get_response_addr(tdata
->pool
, rdata
, &res_addr
);
488 pjsip_endpt_send_response(client
->sip_endpt
, &res_addr
, tdata
,
491 /* Respond with 500 (Internal Server Error) */
492 pjsip_endpt_respond_stateless(client
->sip_endpt
, rdata
, 500, NULL
,
499 /* Create UAS dialog */
500 status
= pjsip_dlg_create_uas(pjsip_ua_instance(), rdata
,
501 &client
->local_contact
, &dlg
);
502 if (status
!= PJ_SUCCESS
) {
503 const pj_str_t reason
= pj_str("Unable to create dialog");
504 pjsip_endpt_respond_stateless(client
->sip_endpt
, rdata
,
511 sip_client_create_sdp(client
, dlg
->pool
, agent
, &sdp
);
513 /* Create UAS invite session */
514 status
= pjsip_inv_create_uas(dlg
, rdata
, sdp
, 0, &agent
->inv
);
515 if (status
!= PJ_SUCCESS
) {
516 pjsip_dlg_create_response(dlg
, rdata
, 500, NULL
, &tdata
);
517 pjsip_dlg_send_response(dlg
, pjsip_rdata_get_tsx(rdata
), tdata
);
521 /* Attach call data to invite session */
522 agent
->inv
->mod_data
[mod_siprtp
.id
] = agent
;
524 /* Create 180 response .*/
525 status
= pjsip_inv_initial_answer(agent
->inv
, rdata
, 180,
527 if (status
!= PJ_SUCCESS
) {
528 status
= pjsip_inv_initial_answer(agent
->inv
, rdata
,
529 PJSIP_SC_NOT_ACCEPTABLE
,
531 if (status
== PJ_SUCCESS
)
532 pjsip_inv_send_msg(agent
->inv
, tdata
);
534 pjsip_inv_terminate(agent
->inv
, 500, PJ_FALSE
);
538 /* Send the 180 response. */
539 status
= pjsip_inv_send_msg(agent
->inv
, tdata
);
540 PJ_ASSERT_ON_FAIL(status
== PJ_SUCCESS
, return);
542 if (client
->incoming_call_cb
)
543 client
->incoming_call_cb(client
, agent
);
546 /* Callback to be called to handle incoming requests outside dialogs: */
547 static pj_bool_t
on_rx_request(pjsip_rx_data
*rdata
)
549 struct sip_client
*client
= global_client
;
551 /* Ignore strandled ACKs (must not send respone */
552 if (rdata
->msg_info
.msg
->line
.req
.method
.id
== PJSIP_ACK_METHOD
)
555 /* Respond (statelessly) any non-INVITE requests with 500 */
556 if (rdata
->msg_info
.msg
->line
.req
.method
.id
!= PJSIP_INVITE_METHOD
) {
557 pj_str_t reason
= pj_str("Unsupported Operation");
558 pjsip_endpt_respond_stateless(client
->sip_endpt
, rdata
,
564 /* Handle incoming INVITE */
565 process_incoming_call(client
, rdata
);
571 static pjsip_module sip_client_mod
= {
572 NULL
, NULL
, /* prev, next. */
573 { "mod-tapisip", 13 }, /* Name. */
575 PJSIP_MOD_PRIORITY_APPLICATION
, /* Priority */
580 &on_rx_request
, /* on_rx_request() */
581 NULL
, /* on_rx_response() */
582 NULL
, /* on_tx_request. */
583 NULL
, /* on_tx_response() */
584 NULL
, /* on_tsx_state() */
587 /* Callback to be called when dialog has forked: */
588 static void call_on_forked(pjsip_inv_session
*inv
, pjsip_event
*e
)
594 /* Callback to be called when invite session's state has changed: */
595 static void call_on_state_changed(pjsip_inv_session
*inv
, pjsip_event
*e
)
597 struct sip_agent
*agent
= inv
->mod_data
[mod_siprtp
.id
];
599 printf("state changed: %d\n", inv
->state
);
604 switch (inv
->state
) {
605 case PJSIP_INV_STATE_DISCONNECTED
:
606 printf("Disconnected\n");
608 session_hangup(agent
->session
, &agent
->agent
);
609 if (agent
->rtp_sockfd
) {
610 event_unregister(agent
->rtp_sockfd
);
611 close(agent
->rtp_sockfd
);
613 sip_agent_free_stream(agent
);
615 inv
->mod_data
[mod_siprtp
.id
] = NULL
;
617 case PJSIP_INV_STATE_CONFIRMED
:
618 printf("Connected: %p\n", agent
->stream
);
621 sip_agent_alloc_stream(agent
);
622 session_accept(agent
->session
, &agent
->agent
);
629 static void call_on_media_update(pjsip_inv_session
*inv
, pj_status_t status
)
631 struct sip_agent
*agent
;
633 const pjmedia_sdp_session
*local_sdp
, *remote_sdp
;
638 printf("media updte\n");
640 agent
= inv
->mod_data
[mod_siprtp
.id
];
641 pool
= inv
->dlg
->pool
;
643 /* Do nothing if media negotiation has failed */
644 if (status
!= PJ_SUCCESS
)
646 /* Capture stream definition from the SDP */
647 pjmedia_sdp_neg_get_active_local(inv
->neg
, &local_sdp
);
648 pjmedia_sdp_neg_get_active_remote(inv
->neg
, &remote_sdp
);
650 strlcpy(local
, local_sdp
->conn
->addr
.ptr
, local_sdp
->conn
->addr
.slen
+ 1);
651 printf("local media count: %d\n", local_sdp
->media_count
);
652 printf("local: %s %d\n", local
,
653 ntohs(local_sdp
->media
[0]->desc
.port
));
654 strlcpy(remote
, remote_sdp
->conn
->addr
.ptr
, remote_sdp
->conn
->addr
.slen
+ 1);
655 printf("remote media count: %d\n", remote_sdp
->media_count
);
656 printf("remote: %s %d\n", remote
,
657 ntohs(remote_sdp
->media
[0]->desc
.port
));
659 agent
->remote_addr
.ss_family
= AF_INET
;
660 inet_pton(AF_INET
, remote
,
661 sockaddr_get_addr(&agent
->remote_addr
));
662 sockaddr_set_port(&agent
->remote_addr
, remote_sdp
->media
[0]->desc
.port
);
664 printf("attributes: %d\n", remote_sdp
->attr_count
);
665 for (i
= 0; i
< remote_sdp
->attr_count
; ++i
)
666 printf("%s: %s\n", remote_sdp
->attr
[i
]->name
.ptr
,
667 remote_sdp
->attr
[i
]->value
.ptr
);
671 static int sip_client_init_sip_endpoint(struct sip_client
*client
)
674 pjsip_host_port addrname
;
675 pjsip_inv_callback inv_cb
;
677 char public_addr
[INET6_ADDRSTRLEN
];
679 global_client
= client
;
681 pj_caching_pool_init(&client
->cp
, &pj_pool_factory_default_policy
, 0);
682 client
->pool
= pj_pool_create(&client
->cp
.factory
, "tapi sip", 1000, 1000, NULL
);
684 status
= pjsip_endpt_create(&client
->cp
.factory
, NULL
,
687 client
->sockfd
= sip_client_create_socket(client
, &client
->public_addr
, 5060, 5100);
689 stun_client_resolve(client
->stun
, client
->sockfd
, (struct sockaddr
*)&client
->public_addr
);
691 sockaddr_to_string(&client
->public_addr
, public_addr
, sizeof(public_addr
));
693 addrname
.host
= pj_str(public_addr
);
694 addrname
.port
= sockaddr_get_port(&client
->public_addr
);
696 pjsip_udp_transport_attach(client
->sip_endpt
, client
->sockfd
, &addrname
, 1, &tp
);
698 status
= pjsip_tsx_layer_init_module(client
->sip_endpt
);
699 PJ_ASSERT_RETURN(status
== PJ_SUCCESS
, status
);
701 status
= pjsip_ua_init_module(client
->sip_endpt
, NULL
);
702 PJ_ASSERT_RETURN(status
== PJ_SUCCESS
, status
);
704 status
= pjsip_100rel_init_module(client
->sip_endpt
);
705 PJ_ASSERT_RETURN(status
== PJ_SUCCESS
, status
);
707 pj_bzero(&inv_cb
, sizeof(inv_cb
));
708 inv_cb
.on_state_changed
= &call_on_state_changed
;
709 inv_cb
.on_new_session
= &call_on_forked
;
710 inv_cb
.on_media_update
= &call_on_media_update
;
712 status
= pjsip_inv_usage_init(client
->sip_endpt
, &inv_cb
);
713 PJ_ASSERT_RETURN(status
== PJ_SUCCESS
, 1);
715 status
= pjsip_endpt_register_module(client
->sip_endpt
, &sip_client_mod
);
717 pj_thread_create(client
->pool
, "sip client", &sip_worker_thread
, client
,
718 0, 0, &client
->sip_thread
);
723 static void sip_client_register_callback(struct pjsip_regc_cbparam
*param
)
725 if (param
->status
!= PJ_SUCCESS
|| param
->code
/ 100 != 2)
726 printf("Failed to register: %d %d", param
->status
, param
->code
);
729 void sip_client_free(struct sip_client
*client
)
731 pjsip_regc_destroy(client
->regc
);
732 pjsip_endpt_destroy(client
->sip_endpt
);
735 void sip_client_register(struct sip_client
*client
)
737 pjsip_tx_data
*tdata
;
739 pjsip_regc_register(client
->regc
, true, &tdata
);
740 pjsip_regc_send(client
->regc
, tdata
);
743 void sip_client_set_cred(struct sip_client
*client
)
745 char local_contact
[100];
746 char server_uri
[100];
747 char s
[INET6_ADDRSTRLEN
];
748 char contact_addr
[INET6_ADDRSTRLEN
+ 10];
749 pj_str_t pj_contact_addr
;
751 sockaddr_to_string(&client
->public_addr
, s
, sizeof(s
));
753 snprintf(contact_addr
, sizeof(contact_addr
), "sip:%s:%d", s
,
754 sockaddr_get_port(&client
->public_addr
));
755 pj_contact_addr
= pj_str(contact_addr
);
757 client
->cred
.realm
= pj_str((char *)client
->config
->host
);
758 client
->cred
.scheme
= pj_str("digest");
759 client
->cred
.username
= pj_str((char *)client
->config
->username
);
760 client
->cred
.data_type
= PJSIP_CRED_DATA_PLAIN_PASSWD
;
761 client
->cred
.data
= pj_str((char *)client
->config
->password
);
763 snprintf(local_contact
, sizeof(local_contact
), "sip:%s@%s",
764 client
->config
->username
, client
->config
->host
);
765 pj_strdup2_with_null(client
->pool
, &client
->local_contact
, local_contact
);
767 snprintf(server_uri
, sizeof(server_uri
), "sip:%s\n", client
->config
->host
);
768 pj_strdup2_with_null(client
->pool
, &client
->server_uri
, server_uri
);
770 pjsip_regc_init(client
->regc
, &client
->server_uri
, &client
->local_contact
,
771 &client
->local_contact
, 1, &pj_contact_addr
, 3600);
772 pjsip_regc_set_credentials(client
->regc
, 1, &client
->cred
);
774 sip_client_register(client
);
777 void sip_client_init(struct sip_client
*client
, struct tapi_device
*tdev
,
778 const struct sip_client_config
*config
)
780 global_client
= client
;
781 client
->config
= config
;
785 iface_get_addr(config
->iface
, &client
->local_addr
);
787 if (config
->stun_host
&& config
->stun_port
)
788 client
->stun
= stun_client_alloc(config
->stun_host
, config
->stun_port
);
792 sip_client_init_sip_endpoint(client
);
794 pjsip_regc_create(client
->sip_endpt
, client
, sip_client_register_callback
,
797 sip_client_set_cred(client
);