⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 soa.c

📁 this is simple sip stack.
💻 C
📖 第 1 页 / 共 4 页
字号:
}/* ======================================================================== */int soa_set_status(soa_session_t *ss, int status, char const *phrase){  if (ss) {    ss->ss_status = status, ss->ss_phrase = phrase;    ss->ss_wcode = 0, ss->ss_warning = NULL;  }  return -1;}int soa_set_warning(soa_session_t *ss, int code, char const *text){  if (ss)    ss->ss_wcode = code, ss->ss_warning = text;  return -1;}static inlineint soa_media_is_ready(soa_session_t const *ss){  XXX;  return 0;  /* return ss && ss->ss_session != NULL; */}void soa_set_activity(soa_session_t *ss,		      sdp_media_t const *m,		      int remote){  struct soa_media_activity *ma;  sdp_connection_t const *c;  int mode;  int ma_audio = SOA_ACTIVE_DISABLED;  int ma_video = SOA_ACTIVE_DISABLED;  int ma_chat = SOA_ACTIVE_DISABLED;  int ma_image = SOA_ACTIVE_DISABLED;  int *p;  remote = !!remote;  ma = remote ? ss->ss_remote_activity : ss->ss_local_activity;  for (; m; m = m->m_next) {    if (m->m_type == sdp_media_audio)      p = &ma_audio;    else if (m->m_type == sdp_media_video)      p = &ma_video;    else if (m->m_type == sdp_media_image)      p = &ma_image;    else if (strcasecmp(m->m_type_name, "message") == 0)      p = &ma_chat;    else      continue;    if (m->m_rejected) {      if (*p < 0)	*p = SOA_ACTIVE_REJECTED;      continue;    }    mode = m->m_mode;    c = sdp_media_connections((sdp_media_t *)m);    if (remote != (c && c->c_mcast))      mode = ((mode << 1) & 2) | ((mode >> 1) & 1);    if (*p < 0)      *p = mode;    else      *p |= mode;  }  ma->ma_audio = ma_audio;  ma->ma_video = ma_video;  ma->ma_image = ma_image;  ma->ma_chat = ma_chat;}/* ----------------------------------------------------------------------*//* Handle SDP *//** * Parses and stores session description *  * @param ss instance pointer * @param what caps, local or remote * @param sdp0 new sdp (parsed) * @param sdp_str new sdp (unparsed) * @param str_len length on unparsed data **/staticint soa_set_sdp(soa_session_t *ss, 		enum soa_sdp_kind what,		sdp_session_t const *sdp0,		char const *sdp_str, int str_len){  struct soa_description *ssd;  int flags, new_version, retval;  sdp_parser_t *parser = NULL;  sdp_session_t sdp[1];  switch (what) {  case soa_capability_sdp_kind:    ssd = ss->ss_caps;    flags = sdp_f_config;    break;  case soa_user_sdp_kind:    ssd = ss->ss_user;    flags = sdp_f_config;    break;  case soa_remote_sdp_kind:    ssd = ss->ss_remote;    flags = sdp_f_mode_0000;    break;  default:    return -1;  }  if (sdp0)    new_version = sdp_session_cmp(sdp0, ssd->ssd_sdp) != 0;  else if (sdp_str)    new_version = str0cmp(sdp_str, ssd->ssd_unparsed) != 0;  else    return (void)su_seterrno(EINVAL), -1;  if (sdp_str && str_len == -1)    str_len = strlen(sdp_str);  if (!new_version) {    if (what == soa_remote_sdp_kind) {      *sdp = *ssd->ssd_sdp;      /* XXX - should check changes by soa_set_remote_sdp */      return ss->ss_actions->soa_set_remote_sdp(ss, new_version, 						sdp, sdp_str, str_len);    }    return 0;  }   if (sdp0) {    /* note: case 1 - src in parsed form */    *sdp = *sdp0;  }   else /* if (sdp_str) */ {    /* note: case 2 - src in unparsed form */    parser = sdp_parse(ss->ss_home, sdp_str, str_len, flags | sdp_f_anynet);    if (sdp_parsing_error(parser)) {      sdp_parser_free(parser);      return soa_set_status(ss, 400, "Bad Session Description");    }    *sdp = *sdp_session(parser);  }   switch (what) {  case soa_capability_sdp_kind:    retval = ss->ss_actions->soa_set_capability_sdp(ss, sdp, sdp_str, str_len);    break;  case soa_user_sdp_kind:    retval =  ss->ss_actions->soa_set_user_sdp(ss, sdp, sdp_str, str_len);    break;  case soa_remote_sdp_kind:    retval = ss->ss_actions->soa_set_remote_sdp(ss, 1, sdp, sdp_str, str_len);    break;  default:    retval = soa_set_status(ss, 500, "Internal Error");    break;  }  if (parser)    sdp_parser_free(parser);  return retval;}/** Set session descriptions. */int soa_description_set(soa_session_t *ss,			struct soa_description *ssd,			sdp_session_t *sdp,			char const *sdp_str,			int str_len){  int retval = -1;  sdp_printer_t *printer = NULL;  sdp_session_t *sdp_new;  char *sdp_str_new;  char *sdp_str0_new;  void *tbf1, *tbf2, *tbf3, *tbf4;  /* Store description in three forms: unparsed, parsed and reprinted */  sdp_new = sdp_session_dup(ss->ss_home, sdp);  printer = sdp_print(ss->ss_home, sdp, NULL, 0, 0);  sdp_str_new = (char *)sdp_message(printer);  if (sdp_str)    sdp_str0_new = su_strndup(ss->ss_home, sdp_str, str_len);  else    sdp_str0_new = sdp_str_new;    if (sdp_new && printer && sdp_str_new && sdp_str0_new) {    tbf1 = ssd->ssd_sdp, tbf2 = ssd->ssd_printer;    tbf3 = (void *)ssd->ssd_str, tbf4 = (void *)ssd->ssd_unparsed;    ssd->ssd_sdp = sdp_new;    ssd->ssd_printer = printer;    ssd->ssd_str = sdp_str_new;    ssd->ssd_unparsed = sdp_str0_new;          retval = 1;  }  else {    tbf1 = sdp_new, tbf2 = printer, tbf3 = sdp_str_new, tbf4 = sdp_str0_new;  }    su_free(ss->ss_home, tbf1);  sdp_printer_free(tbf2);  if (tbf3 != tbf4)    su_free(ss->ss_home, tbf4);  return retval;}/** Duplicate a session descriptions. */int soa_description_dup(su_home_t *home, 			struct soa_description *ssd,			struct soa_description const *ssd0){  if (ssd0->ssd_sdp) {    ssd->ssd_sdp = sdp_session_dup(home, ssd0->ssd_sdp);    ssd->ssd_printer = sdp_print(home, ssd->ssd_sdp, NULL, 0, 0);    ssd->ssd_str = (char *)sdp_message(ssd->ssd_printer);    if (ssd0->ssd_str != ssd0->ssd_unparsed)      ssd->ssd_unparsed = su_strdup(home, ssd0->ssd_unparsed);    else      ssd->ssd_unparsed = ssd->ssd_str;  }  return 0;}/** Free session descriptions. */void soa_description_free(soa_session_t *ss, 			  struct soa_description *ssd){  void *tbf1, *tbf2, *tbf3, *tbf4;  tbf1 = ssd->ssd_sdp, tbf2 = ssd->ssd_printer;  tbf3 = (void *)ssd->ssd_str, tbf4 = (void *)ssd->ssd_unparsed;  memset(ssd, 0, sizeof *ssd);  su_free(ss->ss_home, tbf1);  sdp_printer_free(tbf2);  if (tbf3 != tbf4)    su_free(ss->ss_home, tbf4);}/** Initialize SDP o= line */intsoa_init_sdp_origin(soa_session_t *ss, sdp_origin_t *o, char buffer[64]){  sdp_connection_t *c;  if (ss == NULL || o == NULL)    return su_seterrno(EFAULT), -1;  assert(o->o_address);  if (!o->o_username)    o->o_username = "-";  if (o->o_id == 0)    su_randmem(&o->o_id, sizeof o->o_id);  o->o_id &= ((unsigned longlong)1 << 63) - 1;  if (o->o_version == 0)    su_randmem(&o->o_version, sizeof o->o_version);  o->o_version &= ((unsigned longlong)1 << 63) - 1;  c = o->o_address;  if (!c->c_nettype ||      !c->c_address ||      strcmp(c->c_address, "") == 0 ||      strcmp(c->c_address, "0.0.0.0") == 0 ||      strcmp(c->c_address, "::") == 0 ||      !host_is_local(c->c_address)) {    return soa_init_sdp_connection(ss, c, buffer);  }  return 0;}/** Search for an local address item from string provided by user */staticsu_localinfo_t *li_in_list(su_localinfo_t *li0, char const **llist){  char const *list = *llist;  int n;  if (!list)    return NULL;  while ((n = strcspn(list, ", "))) {    su_localinfo_t *li;    for (li = li0; li; li = li->li_next) {      if (strncasecmp(li->li_canonname, list, n) == 0 &&	  li->li_canonname[n] == '\0')	break;    }    list += n; while (list[0] == ' ' || list[0] == ',') list++;    *llist = list;    if (li)      return li;  }  return NULL;}/** Obtain a local address for SDP connection structure */intsoa_init_sdp_connection(soa_session_t *ss,			sdp_connection_t *c,			char buffer[64]){  su_localinfo_t *res, hints[1] = {{ LI_CANONNAME | LI_NUMERIC }};  su_localinfo_t *li, *li4, *li6;  char const *address;  int ip4, ip6, error;  if (ss == NULL || c == NULL)    return su_seterrno(EFAULT), -1;  address = ss->ss_address;  if (host_is_ip_address(address)) {    /* Use the application-specified address -     * do not check that it is found from the local address list */    c->c_nettype = sdp_net_in;        if (host_is_ip4_address(address))      c->c_addrtype = sdp_addr_ip4;    else      c->c_addrtype = sdp_addr_ip6;        if (!host_is_ip6_reference(address)) {      c->c_address = strcpy(buffer, address);    }    else {      /* Remove brackets [] around the reference */      size_t len = strlen(address + 1);      c->c_address = memcpy(buffer, address + 1, len - 1);      buffer[len - 1] = '\0';     }    return 0;  }  /* XXX - using LI_SCOPE_LINK requires some tweaking */  hints->li_scope = LI_SCOPE_GLOBAL | LI_SCOPE_SITE /* | LI_SCOPE_LINK */;  switch (ss->ss_af) {  case SOA_AF_IP4_ONLY:    hints->li_family = AF_INET, ip4 = 1, ip6 = 0;    break;#if HAVE_SIN6  case SOA_AF_IP6_ONLY:    hints->li_family = AF_INET6, ip6 = 1, ip4 = 0;    break;  case SOA_AF_IP4_IP6:    ip4 = 2, ip6 = 1;    break;  case SOA_AF_IP6_IP4:    ip4 = 1, ip6 = 2;    break;#endif  default:    ip4 = ip6 = 1;  }  for (res = NULL; res == NULL;) {    if ((error = su_getlocalinfo(hints, &res)) < 0 	&& error != ELI_NOADDRESS) {      SU_DEBUG_1(("%s: su_localinfo: %s\n", __func__,		  su_gli_strerror(error)));      return -1;    }    if (hints->li_scope & LI_SCOPE_HOST)      break;    hints->li_scope |= LI_SCOPE_HOST;  }  if (!(ip4 & ip6 && c->c_nettype == sdp_net_in))    /* Use ss_af preference */;  else if (c->c_addrtype == sdp_addr_ip4)    ip4 = 2, ip6 = 1;  else if (c->c_addrtype == sdp_addr_ip6)    ip6 = 2, ip4 = 1;  if (address)    SU_DEBUG_3(("%s: searching for %s from list \"%s\"\n",		__func__, ip6 && !ip4 ? "IP6 " : !ip6 && ip4 ? "IP4 " : "",		address));  li = res, li4 = NULL, li6 = NULL;  for (;;) {    if (address)      li = li_in_list(li, &address);    if (!li)      break;#if HAVE_SIN6    else if (li->li_family == AF_INET6) {      if (ip6 >= ip4)	break;      else if (!li6)	li6 = li;		/* Best IP6 address */    }#endif    else if (li->li_family == AF_INET) {      if (ip4 > ip6)	break;      else if (!li4)	li4 = li;		/* Best IP4 address */    }    if (!address)      li = li->li_next;  }  if (li == NULL)    li = li4;  if (li == NULL)    li = li6;  if (li == NULL)    ;  else if (li->li_family == AF_INET)    c->c_nettype = sdp_net_in,  c->c_addrtype = sdp_addr_ip4;#if HAVE_SIN6  else if (li->li_family == AF_INET6)    c->c_nettype = sdp_net_in,  c->c_addrtype = sdp_addr_ip6;#endif  if (li) {    assert(strlen(li->li_canonname) < 64);    c->c_address = strcpy(buffer, li->li_canonname);  }  su_freelocalinfo(res);  if (!li)    return -1;  else    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -