加载中…
个人资料
小石头
小石头
  • 博客等级:
  • 博客积分:0
  • 博客访问:107,638
  • 关注人气:26
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
相关博文
推荐博文
谁看过这篇博文
加载中…
正文 字体大小:

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

(2013-04-16 10:16:57)
标签:

it

osip

exosip

sip

分类: 音视频
这个测试程序是从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:de: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,之后注册成功

0

阅读 评论 收藏 转载 喜欢 打印举报/Report
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 电话:4000520066 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有