感谢网友整理得sip ua示例,至少为我节约了1~2天时间 !
ua.c
/* SIP User Agent Sample -- by [email protected] This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 1.Architecture: UA ==command==> eXosip2 UA <==notify== eXosip2 2.Requires: libosip2-5.0.0 libeXosip2-5.0.0 3.Compile:(assumed that osip2 & eXosip2 are installed in /usr/local) gcc -I/usr/local/include -L/usr/local/lib ua.c -o ua -leXosip2 \ -losip2 -losipparser2 -lpthread 4.Run: export LD_LIBRARY_PATH+=/usr/local/lib: ./ua -r sip:DOMAIN-OR-IP -R sip:X.X.X.X:5060 -f sip:FROM-USER@DOMAIN \ -t sip:TO-USER@DOMAIN -U AUTH-USER -P AUTH-PASSWORD 5.Register: UAC/UAS PROXY 1 -REGISTER-> <-401- -REGISTER(auth)-> <-200- 6.Call: UAC (PROXY) UAS 2 -INVITE-> <-407- -INVITE(auth)-> <-180- <-200- 3 -ACK-> 4 -reINVITE-> <-200- -ACK-> 5 -BYE-> <-200- */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <netdb.h> #include <string.h> #include <signal.h> #include <pthread.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <osip2/osip_mt.h> #include <eXosip2/eXosip.h> #define ualog(a,b...) fprintf(stderr,b);fprintf(stderr,"\n>") #define null_if_empty(s) (((s)!=NULL&&(s)[0]!='\0')?(s):NULL) #define UA_VERSION "SipUAv0.1" #define BUFFER_LEN (1024) #define UA_CMD_REGISTER ('1') #define UA_CMD_CALL_START ('2') #define UA_CMD_CALL_ANSWER ('3') #define UA_CMD_CALL_KEEP ('4') #define UA_CMD_CALL_STOP ('5') #define UA_CMD_UNREGISTER ('6') #define UA_CMD_HELP ('h') #define UA_CMD_QUIT ('q') typedef struct ua_core{ /* config */ int expiry; int localport; int calltimeout; char *proxy; char *outboundproxy; char *username; char *password; char *from; char *to; char *contact; char *localip; char *firewallip; char *transport; /* dynamic */ struct eXosip_t *context; pthread_t notifythread; int running; int regid; int callid; int dialogid; int transactionid; int cmd; } uacore; uacore g_core; char g_test_sdp[] = "v=0\r\n" "o=1 2 3 IN IP4 0.0.0.0\r\n" "s=Talk\r\n" "c=IN IP4 0.0.0.0\r\n" "t=0 0\r\n" "m=audio 8288 RTP/AVP 0\r\n" "a=rtpmap:0 PCMU/8000\r\n" "a=ptime:20\r\n"; static int ua_add_outboundproxy(osip_message_t *msg, const char *outboundproxy); int ua_cmd_register(uacore *core); int ua_cmd_unregister(uacore *core); int ua_cmd_callstart(uacore *core); int ua_cmd_callring(uacore *core); int ua_cmd_callanswer(uacore *core); int ua_cmd_callkeep(uacore *core); int ua_cmd_callstop(uacore *core); int ua_notify_callack(uacore *core, eXosip_event_t *je); int ua_notify_callkeep(uacore *core, eXosip_event_t *je); void *ua_notify_thread(void *arg); void ua_stop(int signum); void usage(void); void ua_stop(int signum){ g_core.running = 0; } void usage(void){ #define short_options "r:f:t:k:U:P:T:e:p:c:l:F:R:hv" printf("Usage: " UA_VERSION " [required] [optional]\n" "\n\t[required]\n" "\t-r --proxy\tsip:proxyhost[:port]\n" "\t-f --fromuser\tsip:fromuser@host[:port]\n" "\n\t[optional]\n" "\t-t --touser\tsip:touser@host[:port]\n" "\t-U --username\tauthentication username\n" "\t-P --password\tauthentication password\n" "\t-T --transport\tUDP|TCP|TLS|DTLS(default UDP)\n" "\t-e --expiry\tnumber(default 3600)\n" "\t-p --port\tnumber(default 5060)\n" "\t-c --contact\tsip:user@host[:port]\n" "\t-l --localip\tX.X.X.X(force local IP address)\n" "\t-k --keep\tcall keep timeout(default 1800)\n" "\t-F --firewallip\tX.X.X.X\n" "\t-R --route\toutboundproxy or SBC or P-CSCF(sip:outboundproxyhost[:port])\n" "\n\t[help]\n" "\t-v --version\n" "\t-h --help\n" "\n\t[uas example]\n" "\tua -r sip:192.168.1.X:5060 -f sip:[email protected]" " -U 1001 -P 1001 -p 5080\n" "\n\t[uac example]\n" "\tua -r sip:domain.com -R sip:192.168.1.X:5060 -f sip:[email protected]" " -t sip:[email protected] -U 1002 -P 1002\n" "\n\t[ims uac example]\n" "\tua -r sip:domain.com -R sip:192.168.1.X:5060 -f sip:[email protected]" " -t sip:[email protected] -U [email protected] -P 1002\n\n" ); } void ua_cmd_usage(void){ printf("please select:\n" "\t1: register\n" "\t2: call start\n" "\t3: call answer\n" "\t4: call keep\n" "\t5: call stop\n" "\t6: unregister\n" "\th: help\n" "\tq: quit\n"); } int ua_quit(uacore *core){ if (NULL != core->proxy) free(core->proxy); if (NULL != core->from) free(core->from); if (NULL != core->to) free(core->to); if (NULL != core->contact) free(core->contact); if (NULL != core->localip) free(core->localip); if (NULL != core->username) free(core->username); if (NULL != core->password) free(core->password); if (NULL != core->outboundproxy) free(core->outboundproxy); if (NULL != core->firewallip) free(core->firewallip); if (NULL != core->transport) free(core->transport); return 0; } /***************************** command *****************************/ static int ua_add_outboundproxy(osip_message_t *msg, const char *outboundproxy) { int ret = 0; char head[BUFFER_LEN] = { 0 }; if (NULL == null_if_empty(outboundproxy)){ return 0; } snprintf(head, sizeof(head)-1, "<%s;lr>", outboundproxy); osip_list_special_free(&msg->routes, (void(*)(void*))osip_route_free); ret = osip_message_set_route(msg, head); return ret; } int ua_cmd_register(uacore *core) { int ret = -1; osip_message_t *msg = NULL; if (core->regid > 0){ // refresh register ret = eXosip_register_build_register(core->context, core->regid, core->expiry, &msg); if (0 != ret){ ualog(LOG_ERR, "register %d refresh build failed %d", core->regid, ret); return -1; } } else{ // new register core->regid = eXosip_register_build_initial_register(core->context, core->from, core->proxy, core->contact, core->expiry, &msg); if (core->regid <= 0){ ualog(LOG_ERR, "register build failed %d", core->regid); return -1; } ua_add_outboundproxy(msg, core->outboundproxy); } ret = eXosip_register_send_register(core->context, core->regid, msg); if (0 != ret){ ualog(LOG_ERR, "register %d send failed", core->regid); return ret; } return ret; } int ua_cmd_unregister(uacore *core) { int ret = -1; osip_message_t *msg = NULL; int expiry = 0; //unregister ret = eXosip_register_build_register(core->context, core->regid, expiry, &msg); if (0 != ret){ ualog(LOG_ERR, "unregister %d build failed %d", core->regid, ret); return -1; } ret = eXosip_register_send_register(core->context, core->regid, msg); if (0 != ret){ ualog(LOG_ERR, "register %d send failed %d", core->regid, ret); return ret; } core->regid = 0; return ret; } int ua_cmd_callstart(uacore *core) { int ret = -1; char session_exp[BUFFER_LEN] = { 0 }; osip_message_t *msg = NULL; ret = eXosip_call_build_initial_invite(core->context, &msg, core->to, core->from, NULL, NULL); if (0 != ret){ ualog(LOG_ERR, "call build failed", core->from, core->to); return -1; } ua_add_outboundproxy(msg, core->outboundproxy); osip_message_set_body(msg, g_test_sdp, strlen(g_test_sdp)); osip_message_set_content_type(msg, "application/sdp"); /* UAC call timeout */ snprintf(session_exp, sizeof(session_exp)-1, "%i;refresher=uac", core->calltimeout); osip_message_set_header(msg, "Session-Expires", session_exp); osip_message_set_supported(msg, "timer"); core->callid = eXosip_call_send_initial_invite(core->context, msg); ret = (core->callid > 0) ? 0 : -1; return ret; } int ua_cmd_callring(uacore *core) { int ret = 0; int code = 180; osip_message_t *msg = NULL; ret = eXosip_call_build_answer(core->context, core->transactionid, code, &msg); if (0 != ret){ ualog(LOG_ERR, "call %d build ring failed", core->callid); return ret; } ret = eXosip_call_send_answer(core->context, core->transactionid, code, msg); if (0 != ret){ ualog(LOG_ERR, "call %d send ring failed", core->callid); return ret; } return ret; } int ua_cmd_callanswer(uacore *core) { int ret = 0; int code = 200; osip_message_t *msg = NULL; ret = eXosip_call_build_answer(core->context, core->transactionid, code, &msg); if (0 != ret){ ualog(LOG_ERR, "call %d build answer failed", core->callid); return ret; } /* UAS call timeout */ osip_message_set_supported(msg, "timer"); osip_message_set_body(msg, g_test_sdp, strlen(g_test_sdp)); osip_message_set_content_type(msg, "application/sdp"); ret = eXosip_call_send_answer(core->context, core->transactionid, code, msg); if (0 != ret){ ualog(LOG_ERR, "call %d send answer failed", core->callid); return ret; } return ret; } int ua_cmd_callkeep(uacore *core) { int ret = -1; char session_exp[BUFFER_LEN] = { 0 }; osip_message_t *msg = NULL; ret = eXosip_call_build_request(core->context, core->dialogid, "INVITE", &msg); if (NULL == msg){ ualog(LOG_ERR, "call %d build keep failed", core->callid); return ret; } ret = eXosip_call_send_request(core->context, core->dialogid, msg); if (0 != ret){ ualog(LOG_ERR, "call %d send keep failed", core->callid); return ret; } return ret; } int ua_cmd_callstop(uacore *core) { int ret = 0; ret = eXosip_call_terminate(core->context, core->callid, core->dialogid); if (0 != ret){ ualog(LOG_ERR, "call %d send stop failed", core->callid); return ret; } return ret; } /***************************** notify *****************************/ int ua_notify_callack(uacore *core, eXosip_event_t *je) { int ret = 0; osip_message_t *msg = NULL; ret = eXosip_call_build_ack(core->context, je->did, &msg); if (0 != ret){ ualog(LOG_ERR, "call %d build ack failed", je->cid); return ret; } ua_add_outboundproxy(msg, core->outboundproxy); ret = eXosip_call_send_ack(core->context, je->did, msg); if (0 != ret){ ualog(LOG_ERR, "call %d send ack failed", je->cid); return ret; } return ret; } int ua_notify_callkeep(uacore *core, eXosip_event_t *je) { int ret = 0; int code = 200; osip_message_t *msg = NULL; eXosip_call_build_answer(core->context, je->tid, code, &msg); if (NULL == msg){ ualog(LOG_ERR, "call %d send keep answer failed", je->cid); } ret = eXosip_call_send_answer(core->context, je->tid, code, msg); if (0 != ret){ ualog(LOG_ERR, "call %d send keep answer failed", je->cid); return ret; } return ret; } int ua_notidy_callid(uacore *core, eXosip_event_t *je) { core->callid = je->cid; core->dialogid = je->did; core->transactionid = je->tid; return 0; } /* event notify loop */ void * ua_notify_thread(void *arg) { uacore *core = (uacore *)arg; int ret = 0; int code = -1; while (core->running){ osip_message_t *msg = NULL; eXosip_event_t *je = eXosip_event_wait(core->context, 0, 1); if (NULL == je){ /* auto process,such as:register refresh,auth,call keep... */ eXosip_automatic_action(core->context); osip_usleep(100000); continue; } eXosip_lock(core->context); eXosip_automatic_action(core->context); switch (je->type){ case EXOSIP_REGISTRATION_SUCCESS: if (UA_CMD_REGISTER == core->cmd){ ualog(LOG_INFO, "register %d sucess", je->rid); } else { ualog(LOG_INFO, "unregister %d sucess", je->rid); } break; case EXOSIP_REGISTRATION_FAILURE: if (UA_CMD_REGISTER == core->cmd){ ualog(LOG_INFO, "register %d failure", je->rid); } else{ ualog(LOG_INFO, "unregister %d failure", je->rid); } break; case EXOSIP_CALL_INVITE: ua_notidy_callid(core, je); ua_cmd_callring(core); ualog(LOG_INFO, "call %d incoming,please answer...", je->cid); break; case EXOSIP_CALL_REINVITE: ua_notidy_callid(core, je); ualog(LOG_INFO, "call %d keep", je->cid); ua_notify_callkeep(core, je); break; case EXOSIP_CALL_RINGING: ua_notidy_callid(core, je); ualog(LOG_INFO, "call %d ring", je->cid); break; case EXOSIP_CALL_ANSWERED: ua_notidy_callid(core, je); if (je->response) code = osip_message_get_status_code(je->response); ualog(LOG_INFO, "call %d answer %d", je->cid, code); ua_notify_callack(core, je); break; case EXOSIP_CALL_NOANSWER: ua_notidy_callid(core, je); ualog(LOG_INFO, "call %d noanswer", je->cid); break; case EXOSIP_CALL_REQUESTFAILURE: case EXOSIP_CALL_GLOBALFAILURE: case EXOSIP_CALL_SERVERFAILURE: ua_notidy_callid(core, je); if (je->response) code = osip_message_get_status_code(je->response); ualog(LOG_INFO, "call %d failture %d", je->cid, code); break; case EXOSIP_CALL_ACK: ua_notidy_callid(core, je); ualog(LOG_INFO, "call %d ack", je->cid); break; case EXOSIP_CALL_CLOSED: ualog(LOG_INFO, "call %d stop", je->cid); break; case EXOSIP_CALL_CANCELLED: ualog(LOG_INFO, "call %d cancel", je->cid); break; case EXOSIP_CALL_RELEASED: ualog(LOG_INFO, "call %d release", je->cid); break; default: break; } eXosip_unlock(core->context); eXosip_event_free(je); } eXosip_quit(core->context); osip_free(core->context); pthread_detach(pthread_self()); return 0; } /***************************** main *****************************/ int main(int argc, char *argv[]) { int ret = 0; struct servent *service = NULL; /* init */ signal(SIGINT, ua_stop); memset(&g_core, 0, sizeof(uacore)); g_core.running = 1; g_core.expiry = 3600; g_core.localport = 5060; g_core.calltimeout = 1800; /* config */ for (;;){ int c = getopt(argc, argv, short_options); if (-1 == c) break; switch (c){ case 'r': g_core.proxy = strdup(optarg); break; case 'f': g_core.from = strdup(optarg); break; case 't': g_core.to = strdup(optarg); break; case 'c': g_core.contact = strdup(optarg); break; case 'e': g_core.expiry = atoi(optarg); break; case 'l': g_core.localip = strdup(optarg); break; case 'p': service = getservbyname(optarg, "udp"); if (service) g_core.localport = ntohs(service->s_port); else g_core.localport = atoi(optarg); break; case 'k': g_core.calltimeout = atoi(optarg); break; case 'U': g_core.username = strdup(optarg); break; case 'P': g_core.password = strdup(optarg); break; case 'R': g_core.outboundproxy = strdup(optarg); break; case 'F': g_core.firewallip = strdup(optarg); break; case 'T': g_core.transport = strdup(optarg); break; case 'v': printf("%s\n", UA_VERSION); return 0; case 'h': default: usage(); return 0; } } if (!g_core.proxy || !g_core.from){ usage(); return -1; } if (NULL == g_core.transport) g_core.transport = strdup("UDP"); ualog(LOG_INFO, "proxy: %s", g_core.proxy); ualog(LOG_INFO, "outboundproxy: %s", g_core.outboundproxy); ualog(LOG_INFO, "from: %s", g_core.from); ualog(LOG_INFO, "to: %s", g_core.to); ualog(LOG_INFO, "contact: %s", g_core.contact); ualog(LOG_INFO, "expiry: %d", g_core.expiry); ualog(LOG_INFO, "localport: %d", g_core.localport); ualog(LOG_INFO, "transport: %s", g_core.transport); ualog(LOG_INFO, "calltimeout: %d", g_core.calltimeout); g_core.context = eXosip_malloc(); if (eXosip_init(g_core.context)){ ualog(LOG_ERR, "init failed"); return -1; } if (osip_strcasecmp(g_core.transport, "UDP") == 0){ ret = eXosip_listen_addr(g_core.context, IPPROTO_UDP, NULL, g_core.localport, AF_INET, 0); } else if (osip_strcasecmp(g_core.transport, "TCP") == 0){ ret = eXosip_listen_addr(g_core.context, IPPROTO_TCP, NULL, g_core.localport, AF_INET, 0); } else if (osip_strcasecmp(g_core.transport, "TLS") == 0){ ret = eXosip_listen_addr(g_core.context, IPPROTO_TCP, NULL, g_core.localport, AF_INET, 1); } else if (osip_strcasecmp(g_core.transport, "DTLS") == 0){ ret = eXosip_listen_addr(g_core.context, IPPROTO_UDP, NULL, g_core.localport, AF_INET, 1); } else{ ret = -1; } if (ret){ ualog(LOG_ERR, "listen failed"); return -1; } if (g_core.localip){ ualog(LOG_INFO, "local address: %s", g_core.localip); eXosip_masquerade_contact(g_core.context, g_core.localip, g_core.localport); } if (g_core.firewallip){ ualog(LOG_INFO, "firewall address: %s:%i", g_core.firewallip, g_core.localport); eXosip_masquerade_contact(g_core.context, g_core.firewallip, g_core.localport); } eXosip_set_user_agent(g_core.context, UA_VERSION); if (g_core.username && g_core.password){ ualog(LOG_INFO, "username: %s", g_core.username); ualog(LOG_INFO, "password: ******"); if (eXosip_add_authentication_info(g_core.context, g_core.username, g_core.username, g_core.password, NULL, NULL)){ ualog(LOG_ERR, "add_authentication_info failed"); return -1; } } /* start */ pthread_create(&g_core.notifythread, NULL, ua_notify_thread, &g_core); ualog(LOG_INFO, UA_VERSION " start"); ua_cmd_usage(); printf(">"); while (g_core.running){ //command loop char c = getchar(); eXosip_lock(g_core.context); switch (c){ case UA_CMD_REGISTER: g_core.cmd = c; ua_cmd_register(&g_core); break; case UA_CMD_CALL_START: ua_cmd_callstart(&g_core); break; case UA_CMD_CALL_ANSWER: ua_cmd_callanswer(&g_core); break; case UA_CMD_CALL_KEEP: ua_cmd_callkeep(&g_core); break; case UA_CMD_CALL_STOP: ua_cmd_callstop(&g_core); break; case UA_CMD_UNREGISTER: g_core.cmd = c; ua_cmd_unregister(&g_core); break; case UA_CMD_HELP: ua_cmd_usage(); break; case UA_CMD_QUIT: g_core.running = 0; break; case '\n': printf(">"); break; default: ualog(LOG_ERR, "unknown '%c'", c); break; } eXosip_unlock(g_core.context); } /* stop */ ua_quit(&g_core); printf("%s stop\n", UA_VERSION); return 0; }
附件:
https://files.cnblogs.com/files/dong1/ua.tar.gz
转载自:
https://github.com/larkguo/SIP_UA/blob/master/ua.c
感谢:
https://github.com/staskobzar/sip_stacks_examples/blob/master/libexosip/sipua.c
https://github.com/staskobzar/sip_stacks_examples
https://github.com/hfreire/sipc/blob/master/src/rtp.c
https://github.com/Cashwini/PJSIPClient/blob/master/sip_client.c
https://github.com/larkguo/SIP_UA/blob/master/ua.c
https://github.com/larkguo/sip2rtsp