一个简单的eXosip的register注册例子

这个测试程序是从eXosip原有的测试程序改造的。原程序是tools 目录下的 sip_reg.c

 

本程序主要改造了这几个地方:

1) eXosip_event_wait() 函数的超时时间,从原来的1ms 修改为50ms

2) 对于初次注册时,服务器返回401的情况。  调用函数 eXosip_add_authentication_info()发送鉴权信息。

其余的内容基本没改,在我们的sipserver 上面注册成功了。

 

从这个例程中 我们可以看出sip鉴权的基本流程

从sip角度看, 注册过程是这样的:

        客户端                        server  

          |   --------regester --->      |

          |   <----------401------       |

          |   ---regester + nonce -》    |

          |  《----------200--------     |

其中 nonce中带有鉴权信息。形如:

Authorization: Digest username="buxiangyi", realm="Yate",  nonce="143e882c902a9c38a3286e9043c35d40.1366083396", uri="sip:172.16.50.189:5060", response="8119330abd3ff5e4e26d2fa87b563b39", algorithm=MD5

 

 

对于 eXosip, 其处理过程如下:

1)eXosip_init                            (初始化)

     |     

     v     

2)eXosip_listen_addr                     (监听sip端口)

     |     

     v     

3)eXosip_register_build_initial_register (构建一个register)

     |     

     v     

4)eXosip_register_send_register          (发送register)

     |     

     v     

5)eXosip_event_wait                      (等待对端事件)

     |     

     v     

6)eXosip_execute                         (处理事件,调整内部状态)

     |     

     v     

7)eXosip_automatic_action                (根据当前状况,发出响应消息)

之后应循环执行 5)-》 7)

 

 

主程序如下: 

#if defined(__arc__)

#define LOG_PERROR 1

#include <includes_api.h>

#include <os_cfg_pub.h>

#endif

 

#if !defined(WIN32) && !defined(_WIN32_WCE)

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <netdb.h>

#include <syslog.h>

#ifdef OSIP_MT

#include <pthread.h>

#endif

#endif

 

#ifdef _WIN32_WCE

#include <winsock2.h>

#endif

 

#include <osip2/osip_mt.h>

#include <eXosip2/eXosip.h>

 

#if !defined(WIN32) && !defined(_WIN32_WCE) && !defined(__arc__)

#define _GNU_SOURCE

#include <getopt.h>

#endif

 

#define PROG_NAME "sipreg"

#define PROG_VER  "1.0"

#define UA_STRING "SipReg v" PROG_VER

#define SYSLOG_FACILITY LOG_DAEMON

 

#ifdef ANDROID

#include <android/log.h>

#define LOGI(format,...)  //__android_log_print(ANDROID_LOG_INFO ,"hello_hl","file[%s] line[%d] "format"",__FILE__, __LINE__ ,##__VA_ARGS__)

#define LOGE(format,...)  __android_log_print(ANDROID_LOG_ERROR,"hello_hl","file[%s] line[%d] "format"",__FILE__, __LINE__ ,##__VA_ARGS__)

#else

#include <stdio.h>

#define LOGI(format,...)  // printf("file[%s] line[%d] "format"\n",__FILE__, __LINE__ ,##__VA_ARGS__)

#define LOGE(format,...)  printf("file[%s] line[%d] "format"\n",__FILE__, __LINE__ ,##__VA_ARGS__)

#endif

 

 

#if defined(WIN32) || defined(_WIN32_WCE)

static void syslog_wrapper(int a, const char *fmt, ...)

{

  va_list args;

  va_start (args, fmt);

  vfprintf (stdout, fmt, args);

  va_end (args);

}

#define LOG_INFO 0

#define LOG_ERR 0

#define LOG_WARNING 0

#define LOG_DEBUG 0

 

#elif defined(LOG_PERROR)

#define syslog_wrapper    syslog

#else

#define syslog_wrapper(a,b...) fprintf(stderr,b);fprintf(stderr,"\n")

#endif

 

 

static void usage (void);

#ifdef OSIP_MT

static void *register_proc (void *arg);

#endif

 

static void

usage (void)

{

  printf ("Usage: " PROG_NAME " [required_options] [optional_options]\n"

          "\n\t[required_options]\n"

          "\t-r --proxy\tsip:proxyhost[:port]\n"

          "\t-u --from\tsip:user@host[:port]\n"

          "\n\t[optional_options]\n"

          "\t-c --contact\tsip:user@host[:port]\n"

          "\t-d --debug (log to stderr and do not fork)\n"

          "\t-e --expiry\tnumber (default 3600)\n"

          "\t-f --firewallip\tN.N.N.N\n"

          "\t-h --help\n"

          "\t-l --localip\tN.N.N.N (force local IP address)\n"

          "\t-p --port\tnumber (default 5060)\n"

          "\t-U --username\tauthentication username\n"

          "\t-P --password\tauthentication password\n");

}

 

typedef struct regparam_t

{

  int regid;

  int expiry;

  int auth;

} regparam_t;

 

#ifdef OSIP_MT

static void *

register_proc (void *arg)

{

  struct regparam_t *regparam = arg;

  int reg;

 

  for (;;)

    {

#ifdef _WIN32_WCE

      Sleep ((regparam->expiry / 2)*1000);

#else

      sleep (regparam->expiry / 2);

#endif

      eXosip_lock ();

      reg = eXosip_register_send_register (regparam->regid, NULL);

      if (0 > reg)

        {

#ifdef _WIN32_WCE

          fprintf(stdout, "eXosip_register: error while registring");

#else

          perror ("eXosip_register");

#endif

          exit (1);

 }

      regparam->auth = 0;

      eXosip_unlock ();

    }

  return NULL;

}

#endif

 

#ifdef _WIN32_WCE

int WINAPI WinMain( HINSTANCE hInstance,

HINSTANCE hPrevInstance,

LPTSTR    lpCmdLine,

int       nCmdShow)

#else

int main (int argc, char *argv[])

#endif

{

  int c;

  int port = 5060;

  char *contact = NULL;

  char *fromuser = NULL;

  const char *localip = NULL;

  const char *firewallip = NULL;

  char *proxy = NULL;

#if !defined(__arc__)

  struct servent *service;

#endif

  char *username = NULL;

  char *password = NULL;

  struct regparam_t regparam = { 0, 3600, 0 };

#ifdef OSIP_MT

  struct osip_thread *register_thread;

#endif

  int debug = 0;

  int nofork = 0;

 

#ifdef _WIN32_WCE

  proxy = osip_strdup("sip:sip.antisip.com");

  fromuser = osip_strdup("sip:jack@sip.antisip.com");

 

#else

  for (;;)

    {

#define short_options "c??f:hl:p:r:u:U:P:"

#ifdef _GNU_SOURCE

      int option_index = 0;

      static struct option long_options[] = {

        {"contact", required_argument, NULL, 'c'},

        {"debug", no_argument, NULL, 'd'},

        {"expiry", required_argument, NULL, 'e'},

        {"firewallip", required_argument, NULL, 'f'},

        {"from", required_argument, NULL, 'u'},

        {"help", no_argument, NULL, 'h'},

        {"localip", required_argument, NULL, 'l'},

        {"port", required_argument, NULL, 'p'},

        {"proxy", required_argument, NULL, 'r'},

        {"username", required_argument, NULL, 'U'},

        {"password", required_argument, NULL, 'P'},

        {NULL, 0, NULL, 0}

      };

 

      c = getopt_long (argc, argv, short_options, long_options, &option_index);

#else

      c = getopt (argc, argv, short_options);

#endif

      if (c == -1)

        break;

 

      switch (c)

        {

          case 'c':

            contact = optarg;

            break;

          case 'd':

            nofork = 1;

#ifdef LOG_PERROR

            debug = LOG_PERROR;

#endif

            break;

          case 'e':

            regparam.expiry = atoi (optarg);

            break;

          case 'f':

            firewallip = optarg;

            break;

          case 'h':

            usage ();

            exit (0);

          case 'l':

            localip = optarg;

            break;

          case 'p':

#if !defined(__arc__)

            service = getservbyname (optarg, "udp");

            if (service)

              port = ntohs(service->s_port);

            else

              port = atoi (optarg);

#else

   port = atoi (optarg);

#endif

            break;

          case 'r':

            proxy = optarg;

            break;

          case 'u':

            fromuser = optarg;

            break;

          case 'U':

   username = optarg;

            break;

          case 'P':

   password = optarg;

            break;

          default:

            break;

        }

    }

#endif

 

  LOGE("111111");

  if (!proxy || !fromuser)

    {

      usage ();

      exit (1);

    }

 

#ifndef _WIN32_WCE

  if (!nofork)

    {

      int cpid = fork ();

 

      if (cpid)                

        exit (0);

     

      LOGE("22222");

      close (0);

      close (1);

      close (2);

 

    }

#endif

 

#if 0

  openlog (PROG_NAME, LOG_PID | debug, SYSLOG_FACILITY);

#endif

 

  LOGE(" up and running");

  LOGE( "proxy: %s", proxy);

  LOGE( "fromuser: %s", fromuser);

  LOGE( "contact: %s", contact);

  LOGE( "expiry: %d", regparam.expiry);

  LOGE( "local port: %d", port);

  LOGE( "passwd :%s",password );

 

  if (debug>0)

    TRACE_INITIALIZE (6, NULL);

 

  if (eXosip_init ())

    {

      syslog_wrapper (LOG_ERR, "eXosip_init failed");

      exit (1);

    }

  if (eXosip_listen_addr (IPPROTO_UDP, NULL, port, AF_INET, 0))

    {

      syslog_wrapper (LOG_ERR, "eXosip_listen_addr failed");

      exit (1);

    }

 

  if (localip)

    {

      syslog_wrapper (LOG_INFO, "local address: %s", localip);

      eXosip_masquerade_contact (localip, port);

    }

 

  if (firewallip)

    {

      syslog_wrapper (LOG_INFO, "firewall address: %s:%i", firewallip, port);

      eXosip_masquerade_contact (firewallip, port);

    }

 

  eXosip_set_user_agent (UA_STRING);

 

  if (username && password)

    {

      syslog_wrapper (LOG_INFO, "username: %s", username);

      syslog_wrapper (LOG_INFO, "password: [removed]");

      if (eXosip_add_authentication_info

          (username, username, password, NULL, NULL))

        {

          syslog_wrapper (LOG_ERR, "eXosip_add_authentication_info failed");

          exit (1);

        }

    }

 

{

osip_message_t *reg = NULL;

int i;

 

regparam.regid = eXosip_register_build_initial_register(fromuser, proxy,

contact, regparam.expiry * 2, &reg);

LOGE("33333 regid[%d] ",regparam.regid);

if (regparam.regid < 1) {

syslog_wrapper(LOG_ERR,

"eXosip_register_build_initial_register failed");

LOGE("66666");

exit(1);

}

i = eXosip_register_send_register(regparam.regid, reg);

if (i != 0) {

syslog_wrapper(LOG_ERR, "eXosip_register_send_register failed");

LOGE("55555");

exit(1);

}

LOGE("44444");

}

 

#ifdef OSIP_MT

  register_thread = osip_thread_create (20000, register_proc, &regparam);

  if (register_thread==NULL)

    {

      syslog_wrapper (LOG_ERR, "pthread_create failed");

      exit (1);

    }

#endif

 

  for (;;)

    {

      eXosip_event_t *event;

 

     

      if (!(event = eXosip_event_wait(0, 50)))

      {

#ifndef OSIP_MT

      LOGE("77777");

 eXosip_execute();

 eXosip_automatic_action ();

#endif

          osip_usleep (10000);

          continue;

      }

 

#ifndef OSIP_MT

      eXosip_execute();

#endif

 

      LOGE("88888");

 

      eXosip_automatic_action ();

      switch (event->type)

      {

       int res;

          case EXOSIP_REGISTRATION_NEW:

            LOGE("received new registration");

            break;

          case EXOSIP_REGISTRATION_SUCCESS:

         LOGE( "registrered successfully");

            break;

          case EXOSIP_REGISTRATION_FAILURE:

            regparam.auth = 1;

            //注册收到401之后,再次提交授权信息

            //res = eXosip_add_authentication_info(username,username,password, NULL, NULL);

            LOGE("401!!!!");

            break;

          case EXOSIP_REGISTRATION_TERMINATED:

        LOGE("Registration terminated\n");

            break;

          default:

         LOGE("recieved unknown eXosip event (type, did, cid) = (%d, %d, %d)",

                event->type, event->did, event->cid);

      }

      eXosip_event_free (event);

    }

}

 

 

执行结果

写脚本reg.sh(buxiangyi是我们测试用账号):

./sip_reg  \

-r sip:172.16.50.189:5060 \

-u sip:buxiangyi@172.16.50.189 \

-c sip:buxiangyi@172.16.50.189:5060 \

-U buxiangyi \

-P buxiangyi  \

-p 5060 \

-e 1800 \

-d

 

 

执行脚本:

hl@hl-VirtualBox:~/linphone/test_osip_linux$ ./reg.sh 

file[sip_reg.c] line[274] 111111

file[sip_reg.c] line[301]  up and running

file[sip_reg.c] line[302] proxy: sip:172.16.50.189:5060

file[sip_reg.c] line[303] fromuser: sip:buxiangyi@172.16.50.189

file[sip_reg.c] line[304] contact: sip:buxiangyi@172.16.50.189:5060

file[sip_reg.c] line[305] expiry: 1800

file[sip_reg.c] line[306] local port: 5060

file[sip_reg.c] line[307] passwd :buxiangyi

file[sip_reg.c] line[355] 33333 regid[1] 

file[sip_reg.c] line[368] 44444

file[sip_reg.c] line[388] 77777

file[sip_reg.c] line[388] 77777

file[sip_reg.c] line[400] 88888

file[sip_reg.c] line[416] 401!!!!

file[sip_reg.c] line[388] 77777

file[sip_reg.c] line[400] 88888

file[sip_reg.c] line[410] registrered successfully

file[sip_reg.c] line[388] 77777

file[sip_reg.c] line[388] 77777

file[sip_reg.c] line[388] 77777

。。。

 

可以看到客户端收到401之后, eXosip可以自动处理,向server继续发送带nonce的register,之后注册成功

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值