Esempio n. 1
0
/**
 * Creates a new operation object and stores it the list of
 * active operations for 'cli'.
 */
ssc_oper_t *ssc_oper_create(ssc_t *ssc,
                            sip_method_t method,
                            char const *name,
                            char const *address,
                            tag_type_t tag, tag_value_t value, ...)
{
    ssc_oper_t *op, *old;

    ta_list ta;

    enter;

    for (old = ssc->ssc_operations; old; old = old->op_next)
        if (!old->op_persistent)
            break;

    if (address) {
        int have_url = 1;
        sip_to_t *to;

        to = sip_to_make(ssc->ssc_home, address);

        if (to == NULL) {
            printf("%s: %s: invalid address: %s\n", ssc->ssc_name, name, address);
            return NULL;
        }

        /* Try to make sense out of the URL */
        if (url_sanitize(to->a_url) < 0) {
            printf("%s: %s: invalid address\n", ssc->ssc_name, name);
            return NULL;
        }

        if (!(op = su_zalloc(ssc->ssc_home, sizeof(*op)))) {
            printf("%s: %s: cannot create handle\n", ssc->ssc_name, name);
            return NULL;
        }

        op->op_next = ssc->ssc_operations;
        op->op_prev_state = -1;
        op->op_ssc = ssc;
        ssc->ssc_operations = op;

        if (method == sip_method_register)
            have_url = 0;

        ta_start(ta, tag, value);

        op->op_handle = nua_handle(ssc->ssc_nua, op,
                                   TAG_IF(have_url, NUTAG_URL(to->a_url)),
                                   SIPTAG_TO(to),
                                   ta_tags(ta));

        ta_end(ta);

        op->op_ident = sip_header_as_string(ssc->ssc_home, (sip_header_t *)to);

        ssc_oper_assign(op, method, name);

        if (!op->op_persistent) {
            ssc_oper_t *old_next;
            for (; old; old = old_next) {      /* Clean old handles */
                old_next = old->op_next;
                if (!old->op_persistent && !old->op_callstate)
                    ssc_oper_destroy(ssc, old);
            }
        }

        su_free(ssc->ssc_home, to);
    }
    else if (method || name)
        ssc_oper_assign(op = old, method, name);
    else
        return old;

    if (!op) {
        if (address)
            printf("%s: %s: invalid destination\n", ssc->ssc_name, name);
        else
            printf("%s: %s: no destination\n", ssc->ssc_name, name);
        return NULL;
    }

    return op;
}
Esempio n. 2
0
/**
 * Updates the modified copy of local SDP based
 * on application provided local SDP and remote SDP.
 */
static int offer_answer_step(soa_session_t *ss,
			     enum offer_answer_action action,
			     char const *by)
{
  soa_static_session_t *sss = (soa_static_session_t *)ss;

  sdp_session_t *local = ss->ss_local->ssd_sdp;
  sdp_session_t local0[1];

  sdp_session_t *user = ss->ss_user->ssd_sdp;
  unsigned user_version = ss->ss_user_version;

  sdp_session_t *remote = ss->ss_remote->ssd_sdp;
  unsigned remote_version = ss->ss_remote_version;

  int fresh = 0;

  sdp_origin_t o[1] = {{ sizeof(o) }};
  sdp_connection_t *c, c0[1] = {{ sizeof(c0) }};
  char c0_buffer[64];

  sdp_time_t t[1] = {{ sizeof(t) }};

  int *u2s = NULL, *s2u = NULL, *tbf;

  sdp_session_t *latest = NULL, *previous = NULL;

  char const *phrase = "Internal Media Error";

  su_home_t tmphome[SU_HOME_AUTO_SIZE(8192)];

  su_home_auto(tmphome, sizeof tmphome);

  SU_DEBUG_7(("soa_static_offer_answer_action(%p, %s): called\n",
	      (void *)ss, by));

  if (user == NULL)
    return soa_set_status(ss, 500, "No session set by user");

  if (action == generate_offer)
    remote = NULL;
  else if (remote == NULL)
    return soa_set_status(ss, 500, "No remote SDP");

  /* Pre-negotiation Step: Expand truncated remote SDP */
  if (local && remote) switch (action) {
  case generate_answer:
  case process_answer:
    if (sdp_media_count(remote, sdp_media_any, "*", (sdp_proto_e)0, (sdp_text_t)0) <
	sdp_media_count(local, sdp_media_any, "*", (sdp_proto_e)0, (sdp_text_t)0)) {
      SU_DEBUG_5(("%s: remote %s is truncated: expanding\n",
		  by, action == generate_answer ? "offer" : "answer"));
      remote = soa_sdp_expand_media(tmphome, remote, local);
      if (remote == NULL)
	return soa_set_status(ss, 500, "Cannot expand remote session");
    }
  default:
    break;
  }

  /* Step A: Create local SDP session (based on user-supplied SDP) */
  if (local == NULL) switch (action) {
  case generate_offer:
  case generate_answer:
    SU_DEBUG_7(("soa_static(%p, %s): %s\n", (void *)ss, by,
		"generating local description"));

    fresh = 1;
    local = local0;
    *local = *user, local->sdp_media = NULL;

    o->o_username = "******";
    o->o_address = c0;
    c0->c_address = c0_buffer;

    if (!local->sdp_origin)
      local->sdp_origin = o;
    break;

  case process_answer:
  default:
    goto internal_error;
  }

  /* Step B: upgrade local SDP (add m= lines to it)  */
  switch (action) {
  case generate_offer:
    /* Upgrade local SDP based on user SDP */
    if (local != local0 && ss->ss_local_user_version == user_version)
      break;
    if (local != local0)
      *local0 = *local, local = local0;
    SU_DEBUG_7(("soa_static(%p, %s): %s\n", (void *)ss, by,
		"upgrade with local description"));
    if (soa_sdp_upgrade(ss, tmphome, local, user, NULL, &u2s, &s2u) < 0)
      goto internal_error;
    break;
  case generate_answer:
    /* Upgrade local SDP based on remote SDP */
    if (ss->ss_local_user_version == user_version &&
	ss->ss_local_remote_version == remote_version)
      break;
    if (1) {
      if (local != local0)
	*local0 = *local, local = local0;
      SU_DEBUG_7(("soa_static(%p, %s): %s\n", (void *)ss, by,
		  "upgrade with remote description"));
      if (soa_sdp_upgrade(ss, tmphome, local, user, remote, &u2s, &s2u) < 0)
	goto internal_error;
    }
    break;
  case process_answer:
  default:
    break;
  }


  /* Step C: reject media */
  switch (action) {
  case generate_offer:
    /* Local media is marked as rejected already in upgrade phase */
    break;
  case generate_answer:
  case process_answer:
    if (ss->ss_local_remote_version == remote_version)
      break;
    if (soa_sdp_reject_is_needed(local, remote)) {
      if (local != local0) {
	*local0 = *local, local = local0;
#define DUP_LOCAL(local)					 \
	do {							 \
	  if (!local->sdp_media) break;				 \
	  local->sdp_media =					 \
	    sdp_media_dup_all(tmphome, local->sdp_media, local); \
	  if (!local->sdp_media)				 \
	    goto internal_error;				 \
	} while (0)
	DUP_LOCAL(local);
      }
      SU_DEBUG_7(("soa_static(%p, %s): %s\n", (void *)ss, by,
		  "marking rejected media"));
      soa_sdp_reject(tmphome, local, remote);
    }
    break;
  default:
    break;
  }

  /* Step D: Set media mode bits */
  switch (action) {
    int const *s2u_;

  case generate_offer:
  case generate_answer:
  case process_answer:
    s2u_ = s2u;

    if (!s2u_) s2u_ = sss->sss_s2u;

    if (soa_sdp_mode_set(user, s2u_, local, remote, ss->ss_hold, 1)) {
      if (local != local0) {
	*local0 = *local, local = local0;
	DUP_LOCAL(local);
      }

      soa_sdp_mode_set(user, s2u_, local, remote, ss->ss_hold, 0);
    }
    break;
  default:
    break;
  }

  /* Step E: Upgrade codecs by answer. */
  switch (action) {
  case process_answer:
    /* Upgrade local SDP based on remote SDP */
    if (ss->ss_local_remote_version == remote_version)
      break;
    if (1 /* We don't have good test for codecs */) {
      SU_DEBUG_7(("soa_static(%p, %s): %s\n", (void *)ss, by,
		  "upgrade codecs with remote description"));
      if (local != local0) {
	*local0 = *local, local = local0;
	DUP_LOCAL(local);
      }
      soa_sdp_session_upgrade_rtpmaps(ss, local, remote);
    }
    break;
  case generate_offer:
  case generate_answer:
  default:
    break;
  }

  /* Step F0: Initialize o= line */
  if (fresh) {
    if (user->sdp_origin) {
      o->o_username = user->sdp_origin->o_username;

      if (user->sdp_origin->o_address)
	o->o_address = user->sdp_origin->o_address;

      if (user->sdp_origin->o_id)
	o->o_id = user->sdp_origin->o_id;

      if (user->sdp_origin->o_version &&
	  user->sdp_origin->o_version != o->o_version) {
	o->o_version = user->sdp_origin->o_version;
	o->o_version--;
      }
    }

    if (soa_init_sdp_origin_with_session(ss, o, c0_buffer, local) < 0) {
      phrase = "Cannot Get IP Address for Session Description";
      goto internal_error;
    }

    local->sdp_origin = o;
  }

  /* Step F: Update c= line(s) */
  switch (action) {
    sdp_connection_t *user_c, *local_c;

  case generate_offer:
  case generate_answer:
    user_c = user->sdp_connection;
    if (!soa_check_sdp_connection(user_c))
      user_c = NULL;

    local_c = local->sdp_connection;
    if (!soa_check_sdp_connection(local_c))
      local_c = NULL;

    if (ss->ss_local_user_version != user_version ||
	local_c == NULL ||
	(user_c != NULL && sdp_connection_cmp(local_c, user_c))) {
      sdp_media_t *m;

      if (user_c)
	c = user_c;
      else
	c = local->sdp_origin->o_address;

      /* Every m= line (even rejected one) must have a c= line
       * or there must be a c= line at session level
       */
      for (m = local->sdp_media; m; m = m->m_next)
	if (m->m_connections == NULL)
	  break;

      if (m) {
	if (local != local0) {
	  *local0 = *local, local = local0;
	  DUP_LOCAL(local);
	}
	local->sdp_connection = c;
      }
    }
    break;

  default:
    break;
  }

  soa_description_free(ss, ss->ss_previous);
  su_free(ss->ss_home, sss->sss_previous.u2s), sss->sss_previous.u2s = NULL;
  su_free(ss->ss_home, sss->sss_previous.s2u), sss->sss_previous.s2u = NULL;

  if (u2s) {
    u2s = u2s_alloc(ss->ss_home, u2s);
    s2u = u2s_alloc(ss->ss_home, s2u);
    if (!u2s || !s2u)
      goto internal_error;
  }

  if (ss->ss_local->ssd_sdp != local &&
      sdp_session_cmp(ss->ss_local->ssd_sdp, local)) {
    int bump;

    switch (action) {
    case generate_offer:
      bump = sdp_session_cmp(local, sss->sss_latest);
      break;
    case generate_answer:
      bump = 1;
      break;
    case process_answer:
    default:
      bump = 0;
      break;
    }

    if (bump) {
      /* Upgrade the version number */
      if (local->sdp_origin != o)
	*o = *local->sdp_origin, local->sdp_origin = o;
      o->o_version++;
    }

    /* Do sanity checks for the created SDP */
    if (!local->sdp_subject)	/* s= is mandatory */
      local->sdp_subject = "-";
    if (!local->sdp_time)	/* t= is mandatory */
      local->sdp_time = t;

    if (action == generate_offer) {
      /* Keep a copy of previous session state */
      int *previous_u2s = u2s_alloc(ss->ss_home, sss->sss_u2s);
      int *previous_s2u = u2s_alloc(ss->ss_home, sss->sss_s2u);

      if ((sss->sss_u2s && !previous_u2s) || (sss->sss_s2u && !previous_s2u))
	goto internal_error;

      *ss->ss_previous = *ss->ss_local;
      memset(ss->ss_local, 0, (sizeof *ss->ss_local));
      ss->ss_previous_user_version = ss->ss_local_user_version;
      ss->ss_previous_remote_version = ss->ss_local_remote_version;
      sss->sss_previous.u2s = previous_u2s;
      sss->sss_previous.s2u = previous_s2u;
    }

    SU_DEBUG_7(("soa_static(%p, %s): %s\n", (void *)ss, by,
		"storing local description"));

    /* Update the unparsed and pretty-printed descriptions  */
    if (soa_description_set(ss, ss->ss_local, local, NULL, 0) < 0) {
      if (action == generate_offer) {
	/* Remove 2nd reference to local session state */
	memset(ss->ss_previous, 0, (sizeof *ss->ss_previous));
	ss->ss_previous_user_version = 0;
	ss->ss_previous_remote_version = 0;
	su_free(ss->ss_home, sss->sss_previous.u2s), sss->sss_previous.u2s = NULL;
	su_free(ss->ss_home, sss->sss_previous.s2u), sss->sss_previous.s2u = NULL;
      }

      su_free(ss->ss_home, u2s), su_free(ss->ss_home, s2u);

      goto internal_error;
    }

    if (bump) {
      latest = sdp_session_dup(ss->ss_home, ss->ss_local->ssd_sdp);
      previous = sss->sss_latest;
    }
  }

  if (u2s) {
    tbf = sss->sss_u2s, sss->sss_u2s = u2s, su_free(ss->ss_home, tbf);
    tbf = sss->sss_s2u, sss->sss_s2u = s2u, su_free(ss->ss_home, tbf);
  }

  /* Update version numbers */
  switch (action) {
  case generate_offer:
    ss->ss_local_user_version = user_version;
    sss->sss_latest = latest;
    break;
  case generate_answer:
    ss->ss_local_user_version = user_version;
    ss->ss_local_remote_version = remote_version;
    sss->sss_latest = latest;
    break;
  case process_answer:
    ss->ss_local_remote_version = remote_version;
  default:
    break;
  }

  if (previous)
    su_free(ss->ss_home, previous);

  su_home_deinit(tmphome);
  return 0;

 internal_error:
  su_home_deinit(tmphome);
  return soa_set_status(ss, 500, phrase);
}
Esempio n. 3
0
/** Initialize logging. */
int tport_open_log(tport_master_t *mr, tagi_t *tags)
{
  int n;
  int log_msg = mr->mr_log != 0;
  char const *dump = NULL;
  char const *capt = NULL;;
  
  if(mr->mr_capt_name) capt = mr->mr_capt_name;
  
  n = tl_gets(tags,
	      TPTAG_LOG_REF(log_msg),
	      TPTAG_DUMP_REF(dump),
	      TPTAG_CAPT_REF(capt),
	      TAG_END());

  if (getenv("MSG_STREAM_LOG") != NULL || getenv("TPORT_LOG") != NULL)
    log_msg = 1;
  mr->mr_log = log_msg ? MSG_DO_EXTRACT_COPY : 0;

  if (getenv("TPORT_CAPT"))
    capt = getenv("TPORT_CAPT");
  if (getenv("MSG_DUMP"))
    dump = getenv("MSG_DUMP");
  if (getenv("TPORT_DUMP"))
    dump = getenv("TPORT_DUMP");
 
  if(capt) {

        char *captname, *p, *host_s;
        char port[10];
        su_addrinfo_t *ai = NULL, hints[1] = {{ 0 }};
        unsigned len =0;

        if (mr->mr_capt_name && mr->mr_capt_sock && strcmp(capt, mr->mr_capt_name) == 0)                
              return n;

        captname = su_strdup(mr->mr_home, capt);
        if (captname == NULL)
              return n;
                           
        if(strncmp(captname, "udp:",4) != 0) {
              su_log("tport_open_log: capturing. Only udp protocol supported [%s]\n", captname);          
              return n;
        } 
        
        /* separate proto and host */
        p = captname+4;
        if( (*(p)) == '\0') {
                su_log("malformed ip address\n");
                return n;
        }
        host_s = p;

        if( (p = strrchr(p+1, ':')) == 0 ) {
                su_log("no host or port specified\n");
                return n;
        }
 
        /*the address contains a port number*/
        *p = '\0';
        p++;

        if (atoi(p) <1024  || atoi(p)>65536)
        {
                su_log("invalid port number; must be in [1024,65536]\n");
                return n;
        }

        strncpy(port, p, sizeof(port));
                        
        *p = '\0'; 
        
        /* check if we have [] */
        if (host_s[0] == '[') {
              len = strlen(host_s + 1) - 1;              
              if(host_s[len+1] != ']') {
                su_log("bracket not closed\n");
                return n;            
            }            
            memmove(host_s, host_s + 1, len);
            host_s[len] = '\0';
        }                              

        /* and again */
        captname = su_strdup(mr->mr_home, capt);
        if (captname == NULL) return n;
        
        su_free(mr->mr_home, mr->mr_capt_name);
        mr->mr_capt_name = captname;

        if (mr->mr_capt_sock)
          su_close(mr->mr_capt_sock), mr->mr_capt_sock = 0;        

        /* HINTS && getaddrinfo */
        hints->ai_flags = AI_NUMERICSERV;
        hints->ai_family = AF_UNSPEC; 
        hints->ai_socktype = SOCK_DGRAM;
        hints->ai_protocol = IPPROTO_UDP;
        

        if (su_getaddrinfo(host_s, port, hints, &ai)) {
            su_perror("capture: su_getaddrinfo()");
            return n;
        }
        
	mr->mr_capt_sock = su_socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
	if (mr->mr_capt_sock == INVALID_SOCKET) {
	    su_perror("capture: invalid socket");
	    return n;
	}

	su_setblocking(mr->mr_capt_sock, 0);         /* Don't block */

	if (connect(mr->mr_capt_sock, ai->ai_addr, (socklen_t)(ai->ai_addrlen)) == -1) {
	    if (errno != EINPROGRESS) {
		    su_perror("capture: socket connect");
		    return n;
	    }	                
	}
		
	su_freeaddrinfo(ai);        
  }
  else if(mr->mr_capt_sock) {
      /* close capture server*/
      su_close(mr->mr_capt_sock);
      mr->mr_capt_sock = 0;
  }

  if (dump) {
    time_t now;
    char *dumpname;
    
    if (mr->mr_dump && strcmp(dump, mr->mr_dump) == 0)
      return n;
    dumpname = su_strdup(mr->mr_home, dump);
    if (dumpname == NULL)
      return n;
    su_free(mr->mr_home, mr->mr_dump);
    mr->mr_dump = dumpname;

    if (mr->mr_dump_file && mr->mr_dump_file != stdout)
      fclose(mr->mr_dump_file), mr->mr_dump_file = NULL;

    if (strcmp(dumpname, "-"))
      mr->mr_dump_file = fopen(dumpname, "ab"); /* XXX */
    else
      mr->mr_dump_file = stdout;

    if (mr->mr_dump_file) {
      time(&now);
      fprintf(mr->mr_dump_file, "dump started at %s\n\n", ctime(&now));
    }
  }

  return n;
}
static int test_auto(void)
{
  BEGIN();

  int i;
  su_home_t tmphome[SU_HOME_AUTO_SIZE(8000)];
  char *b = NULL;
  su_home_stat_t hs[1];

  TEST_1(!su_home_auto(tmphome, sizeof tmphome[0]));
  TEST_1(su_home_auto(tmphome, sizeof tmphome));

  for (i = 0; i < 8192; i++)
    TEST_1(su_alloc(tmphome, 12));

  TEST_VOID(su_home_deinit(tmphome));

  TEST_1(su_home_auto(tmphome, sizeof tmphome));

  su_home_init_stats(tmphome);

  for (i = 1; i < 8192; i++) {
    TEST_1(b = su_realloc(tmphome, b, i));
    b[i - 1] = '\125';
  }

  for (i = 1; i < 8192; i++) {
    TEST(b[i - 1], '\125');
  }

  for (i = 1; i < 8192; i++) {
    TEST_1(b = su_realloc(tmphome, b, i));
    b[i - 1] = '\125';

    if ((i % 32) == 0)
      TEST_1(b = su_realloc(tmphome, b, 1));
  }

  su_home_get_stats(tmphome, 0, hs, sizeof *hs);

  TEST64(hs->hs_allocs.hsa_preload + hs->hs_allocs.hsa_number,
	  8191 + 8191 + 8191 / 32);
  TEST64(hs->hs_frees.hsf_preload + hs->hs_frees.hsf_number,
	 8191 + 8191 + 8191 / 32 - 1);
  /*
    This test depends on macro SU_HOME_AUTO_SIZE() calculating
    offsetof(su_block_t, sub_nodes[7]) correctly with

    ((3 * sizeof (void *) + 4 * sizeof(unsigned) +
      7 * (sizeof (long) + sizeof(void *)) + 7)
  */
  TEST_1(hs->hs_frees.hsf_preload == hs->hs_allocs.hsa_preload);

  su_free(tmphome, b);

  for (i = 1; i < 8192; i++)
    TEST_1(b = su_alloc(tmphome, 1));

  TEST_VOID(su_home_deinit(tmphome));

  END();
}
Esempio n. 5
0
/**@internal Store information from remote endpoint. */
void nua_dialog_store_peer_info(nua_owner_t *own,
				nua_dialog_state_t *ds,
				sip_t const *sip)
{
  nua_dialog_peer_info_t *nr = ds->ds_remote_ua;
  nua_dialog_usage_t *du;
  nua_dialog_peer_info_t old[1];

  *old = *nr;

  if (sip && sip->sip_status &&
      sip->sip_status->st_status >= 300 &&
      sip->sip_status->st_status <= 399)
    sip = NULL;			/* Redirected */

  if (sip == NULL) {
    nr->nr_allow = NULL, su_free(own, old->nr_allow);
    nr->nr_accept = NULL, su_free(own, old->nr_accept);
    nr->nr_require = NULL, su_free(own, old->nr_require);
    nr->nr_supported = NULL, su_free(own, old->nr_supported);
    nr->nr_user_agent = NULL, su_free(own, old->nr_user_agent);
    return;
  }

  if (sip->sip_allow) {
    nr->nr_allow = sip_allow_dup(own, sip->sip_allow);
    su_free(own, old->nr_allow);
  }

  if (sip->sip_accept) {
    nr->nr_accept = sip_accept_dup(own, sip->sip_accept);
    su_free(own, old->nr_accept);
  }

  if (sip->sip_require) {
    nr->nr_require = sip_require_dup(own, sip->sip_require);
    su_free(own, old->nr_require);
  }

  if (sip->sip_supported) {
    nr->nr_supported = sip_supported_dup(own, sip->sip_supported);
    su_free(own, old->nr_supported);
  }

  if (sip->sip_user_agent) {
    nr->nr_user_agent = sip_user_agent_dup(own, sip->sip_user_agent);
    su_free(own, old->nr_user_agent);
  }
  else if (sip->sip_server) {
    nr->nr_user_agent = sip_user_agent_dup(own, sip->sip_server);
    su_free(own, old->nr_user_agent);
  }

  for (du = ds->ds_usage; du; du = du->du_next) {
    if (du->du_class->usage_peer_info)
      du->du_class->usage_peer_info(du, ds, sip);
  }
}
Esempio n. 6
0
/**Update registered socket.
 *
 * @retval 0 if success
 * @retval -1 upon failure
 */
static int sres_sofia_update(sres_sofia_t *srs,
			     su_socket_t new_socket,
			     su_socket_t old_socket)
{
  char const *what = NULL;
  su_wait_t wait[1];
  sres_sofia_register_t *reg = NULL;
  sres_sofia_register_t *old_reg = NULL;
  int i, index = -1, error = 0;
  int N = SRES_MAX_NAMESERVERS;

  SU_DEBUG_9(("sres_sofia_update(%p, %d, %d)\n",
	      (void *)srs, (int)new_socket, (int)old_socket));

  if (srs == NULL)
    return 0;

  if (srs->srs_root == NULL)
    return -1;

  if (old_socket == new_socket) {
    if (old_socket == INVALID_SOCKET) {
      sres_resolver_set_async(srs->srs_resolver, sres_sofia_update, NULL, 0);
      /* Destroy srs */
      for (i = 0; i < N; i++) {
	if (!srs->srs_reg[i].reg_index)
	  continue;
	su_root_deregister(srs->srs_root, srs->srs_reg[i].reg_index);
	memset(&srs->srs_reg[i], 0, sizeof(srs->srs_reg[i]));
      }
      su_timer_destroy(srs->srs_timer), srs->srs_timer = NULL;
      su_free(NULL, srs);
    }
    return 0;
  }

  if (old_socket != INVALID_SOCKET)
    for (i = 0; i < N; i++)
      if ((srs->srs_reg + i)->reg_socket == old_socket) {
	old_reg = srs->srs_reg + i;
	break;
      }

  if (new_socket != INVALID_SOCKET) {
    if (old_reg == NULL) {
      for (i = 0; i < N; i++) {
	if (!(srs->srs_reg + i)->reg_ptr)
	  break;
      }
      if (i > N)
	return su_seterrno(ENOMEM);

      reg = srs->srs_reg + i;
    }
    else
      reg = old_reg;
  }

  if (reg) {
    if (su_wait_create(wait, new_socket, SU_WAIT_IN | SU_WAIT_ERR) == -1) {
      reg = NULL;
      what = "su_wait_create";
      error = su_errno();
    }

    if (reg)
      index = su_root_register(srs->srs_root, wait, sres_sofia_poll, reg, 0);

    if (index < 0) {
      reg = NULL;
      what = "su_root_register";
      error = su_errno();
      su_wait_destroy(wait);
    }
  }

  if (old_reg) {
    if (old_socket == srs->srs_socket)
      srs->srs_socket = INVALID_SOCKET;
    su_root_deregister(srs->srs_root, old_reg->reg_index);
    memset(old_reg, 0, sizeof *old_reg);
  }

  if (reg) {
    srs->srs_socket = new_socket;

    reg->reg_ptr = srs;
    reg->reg_socket = new_socket;
    reg->reg_index = index;
  }

  if (!what)
    return 0;		/* success */

  SU_DEBUG_3(("sres: %s: %s\n", what, su_strerror(error)));

  return su_seterrno(error);
}
static int test_strlst(void)
{
  su_home_t home[1] = { SU_HOME_INIT(home) };
  su_strlst_t *l, *l1, *l2;
  char *s;
  char foo[] = "foo";
  char bar[] = "bar";
  char baz[] = "baz";

  su_home_stat_t parent[1], kids[2];

  BEGIN();

  parent->hs_size = (sizeof parent);
  kids[0].hs_size = (sizeof kids[0]);
  kids[1].hs_size = (sizeof kids[1]);

  su_home_init_stats(home);

  /* Test API for invalid arguments */
  TEST_1(l = su_strlst_create(NULL));
  TEST_1(l2 = su_strlst_dup(home, l));
  TEST_VOID(su_strlst_destroy(l2));
  TEST_1(!su_strlst_dup(home, NULL));
  TEST_1(l1 = su_strlst_copy(home, l));
  TEST_VOID(su_strlst_destroy(l1));
  TEST_1(!su_strlst_copy(home, NULL));

  TEST_VOID(su_strlst_destroy(NULL));
  TEST_VOID(su_strlst_destroy(l));

  TEST_1(!su_strlst_dup_append(NULL, "aa"));
  TEST_1(!su_strlst_append(NULL, "bee"));
  TEST_1(!su_strlst_item(NULL, 1));
  TEST_1(!su_strlst_set_item(NULL, 1, "cee"));
  TEST_1(!su_strlst_remove(NULL, 1));
  TEST_S(s = su_strlst_join(NULL, home, "a"), "");
  TEST_VOID(su_free(home, s));

  TEST_1(!su_strlst_split(home, NULL, "."));

  TEST_1(s = su_strdup(home, "aaa"));
  TEST_1(l = su_strlst_split(home, s, NULL));
  TEST_S(su_strlst_item(l, 0), "aaa");
  TEST_VOID(su_strlst_destroy(l));

  TEST_VOID(su_free(home, s));

  TEST_1(!su_strlst_dup_split(home, NULL, "."));

  TEST_1(l1 = su_strlst_dup_split(home, "aaa", ""));
  TEST_S(su_strlst_item(l1, 0), "aaa");
  TEST_VOID(su_strlst_destroy(l1));

  TEST_SIZE(su_strlst_len(NULL), 0);
  TEST_1(!su_strlst_get_array(NULL));
  TEST_VOID(su_strlst_free_array(NULL, NULL));

  TEST_1(l = su_strlst_create(home));
  TEST_VOID(su_strlst_free_array(l, NULL));
  TEST_S(su_strlst_dup_append(l, "oh"), "oh");
  TEST_VOID(su_strlst_free_array(l, NULL));
  TEST_VOID(su_strlst_destroy(l));

  /* Test functionality */
  TEST_1(l = su_strlst_create(home));

  su_home_init_stats(su_strlst_home(l));

  TEST_S(su_strlst_join(l, home, "bar"), "");
  TEST_S(su_strlst_append(l, foo), "foo");
  TEST_S(su_strlst_dup_append(l, bar), "bar");
  TEST_S(su_strlst_append(l, baz), "baz");
  TEST_S((s = su_strlst_join(l, home, "!")), "foo!bar!baz");

  TEST_S(su_strlst_item(l, 0), foo);
  TEST_S(su_strlst_item(l, 1), bar);
  TEST_S(su_strlst_item(l, 2), baz);
  TEST_P(su_strlst_item(l, 3), NULL);
  TEST_P(su_strlst_item(l, (unsigned)-1), NULL);

  TEST_1(l1 = su_strlst_copy(su_strlst_home(l), l));
  TEST_1(l2 = su_strlst_dup(su_strlst_home(l), l));

  strcpy(foo, "hum"); strcpy(bar, "pah"); strcpy(baz, "hah");

  TEST_S(su_strlst_dup_append(l1, "kuik"), "kuik");
  TEST_S(su_strlst_dup_append(l2, "uik"), "uik");

  TEST_S((s = su_strlst_join(l, home, ".")), "hum.bar.hah");
  TEST_S((su_strlst_join(l1, home, ".")), "hum.bar.hah.kuik");
  TEST_S((su_strlst_join(l2, home, ".")), "foo.bar.baz.uik");

  su_strlst_destroy(l2);

  su_home_get_stats(su_strlst_home(l), 0, kids, sizeof kids);

  TEST_SIZE(kids->hs_clones, 2);
  TEST64(kids->hs_allocs.hsa_number, 3);
  TEST64(kids->hs_frees.hsf_number, 1);

  su_strlst_destroy(l);

  TEST_S(s, "hum.bar.hah");

  TEST_1(l = su_strlst_create(home));

  su_home_init_stats(su_strlst_home(l));

  TEST_S(su_strlst_join(l, home, "bar"), "");
  TEST_S(su_strlst_append(l, "a"), "a");
  TEST_S(su_strlst_append(l, "b"), "b");
  TEST_S(su_strlst_append(l, "c"), "c");
  TEST_S(su_strlst_append(l, "d"), "d");
  TEST_S(su_strlst_append(l, "e"), "e");
  TEST_S(su_strlst_append(l, "f"), "f");
  TEST_S(su_strlst_append(l, "g"), "g");
  TEST_S(su_strlst_append(l, "h"), "h");
  TEST_S(su_strlst_append(l, "i"), "i");
  TEST_S(su_strlst_append(l, "j"), "j");

  TEST_S((s = su_strlst_join(l, home, "")), "abcdefghij");
  TEST_S(su_strlst_append(l, "a"), "a");
  TEST_S(su_strlst_append(l, "b"), "b");
  TEST_S(su_strlst_append(l, "c"), "c");
  TEST_S(su_strlst_append(l, "d"), "d");
  TEST_S(su_strlst_append(l, "e"), "e");
  TEST_S(su_strlst_append(l, "f"), "f");
  TEST_S(su_strlst_append(l, "g"), "g");
  TEST_S(su_strlst_append(l, "h"), "h");
  TEST_S(su_strlst_append(l, "i"), "i");
  TEST_S(su_strlst_append(l, "j"), "j");

  TEST_S((s = su_strlst_join(l, home, "")), "abcdefghijabcdefghij");

  su_home_get_stats(su_strlst_home(l), 0, kids + 1, (sizeof kids[1]));
  su_home_stat_add(kids, kids + 1);

  su_strlst_destroy(l);

  su_home_get_stats(home, 1, parent, (sizeof parent));

  su_home_check(home);
  su_home_deinit(home);

  su_home_init(home);

  {
    char s[] = "foo\nfaa\n";
    TEST_1((l = su_strlst_split(home, s, "\n")));
    TEST_SIZE(su_strlst_len(l), 3);
    TEST_1(su_strlst_append(l, "bar"));
    TEST_S(su_strlst_join(l, home, "\n"), "foo\nfaa\n\nbar");
  }

  {
    char s[] = "foo";
    TEST_1((l = su_strlst_split(home, s, "\n")));
    TEST_SIZE(su_strlst_len(l), 1);
  }

  {
    char s[] = "\n\n";
    TEST_1((l = su_strlst_split(home, s, "\n")));
    TEST_SIZE(su_strlst_len(l), 3);
  }

  {
    char s[] = "";
    TEST_1((l = su_strlst_split(home, s, "\n")));
    TEST_SIZE(su_strlst_len(l), 1);
  }

  {
    int i;

#define S \
      "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\n" \
      "n\no\np\nq\nr\ns\nt\nu\nv\nw\nx\ny\nz\n" \
      "A\nB\nC\nD\nE\nF\nG\nH\nI\nJ\nK\nL\nM\n" \
      "N\nO\nP\nQ\nR\nS\nT\nU\nV\nW\nX\nY\nZ\n"

    char s[] = S;

    TEST_1((l = su_strlst_split(home, s, "\n")));
    TEST_SIZE(su_strlst_len(l), 53);
    TEST_1(su_strlst_append(l, "bar"));
    TEST_S(su_strlst_join(l, home, "\n"), S "\nbar");

    TEST_1(!su_strlst_remove(l, 54));

    for (i = 0; i < 54; i++) {
      TEST_1(su_strlst_remove(l, 0));
      TEST_1(!su_strlst_remove(l, 53 - i));
      TEST_SIZE(su_strlst_len(l), 53 - i);
    }

    TEST_1(!su_strlst_remove(l, 0));
    TEST_SIZE(su_strlst_len(l), 0);
  }

  {
    char const *s0;

    TEST_1(l = su_strlst_create_with(NULL, s0 = "a", "b", NULL));
    TEST_1(su_strlst_item(l, 0) == s0);
    TEST_S(su_strlst_item(l, 0), "a");
    TEST_S(su_strlst_item(l, 1), "b");
    TEST_1(su_strlst_item(l, 2) == NULL);

    TEST_S(su_slprintf(l, "1: %u", 1), "1: 1");
    TEST_S(su_slprintf(l, "1.0: %g", 1.0), "1.0: 1");

    TEST_1(su_strlst_append(l, ""));

    TEST_S(su_strlst_join(l, home, "\n"),
	   "a\n" "b\n" "1: 1\n" "1.0: 1\n");

    TEST_VOID(su_strlst_destroy(l));

    TEST_1(l2 = su_strlst_create_with_dup(NULL,
					  s0 = "0", "1", "2", "3",
					  "4", "5", "6", "7",
					  NULL));
    TEST_1(su_strlst_item(l2, 0) != s0);
    TEST_S(su_strlst_item(l2, 0), "0");
    TEST_S(su_strlst_item(l2, 1), "1");
    TEST_S(su_strlst_item(l2, 2), "2");
    TEST_S(su_strlst_item(l2, 3), "3");
    TEST_S(su_strlst_item(l2, 4), "4");
    TEST_S(su_strlst_item(l2, 5), "5");
    TEST_S(su_strlst_item(l2, 6), "6");
    TEST_S(su_strlst_item(l2, 7), "7");
    TEST_1(su_strlst_item(l2, 8) == NULL);

    TEST_S(su_strlst_join(l2, home, ""), "01234567");

    TEST_VOID(su_strlst_destroy(l2));
  }
  su_home_check(home);
  su_home_deinit(home);

  END();
}
Esempio n. 8
0
/** @internal Remove dialog usage.
 *
 * Zap dialog state (leg, tag and route) if no usages remain.
*/
static void
nua_dialog_usage_remove_at(nua_owner_t *own,
			   nua_dialog_state_t *ds,
			   nua_dialog_usage_t **at,
			   nua_client_request_t *cr0,
			   nua_server_request_t *sr0)
{
  if (*at) {
    nua_dialog_usage_t *du = *at;
    sip_event_t const *o = NULL;
    nua_client_request_t *cr, *cr_next;
    nua_server_request_t *sr, *sr_next;

    *at = du->du_next;

    o = du->du_event;

    SU_DEBUG_5(("nua(%p): removing %s usage%s%s\n",
		(void *)own, nua_dialog_usage_name(du),
		o ? " with event " : "", o ? o->o_type :""));
    du->du_class->usage_remove(own, ds, du, cr0, sr0);

    /* Clean reference to saved client request */
    if (du->du_cr)
      nua_client_bind(du->du_cr, NULL);

    /* Clean references from queued client requests */
    for (cr = ds->ds_cr; cr; cr = cr_next) {
      cr_next = cr->cr_next;
      if (cr->cr_usage == du)
	cr->cr_usage = NULL;
    }

    /* Clean references from queued server requests */
    for (sr = ds->ds_sr; sr; sr = sr_next) {
      sr_next = sr->sr_next;
      if (sr->sr_usage == du) {
	sr->sr_usage = NULL;
	if (sr != sr0)
	  nua_server_request_destroy(sr);
      }
    }

    if (du->du_refresh_timer)
      su_timer_destroy(du->du_refresh_timer);

    su_home_unref(own);
    su_free(own, du);
  }

  /* Zap dialog if there are no more usages */
  if (ds->ds_terminating)
    ;
  else if (ds->ds_usage == NULL) {
    nua_dialog_remove(own, ds, NULL);
    ds->ds_has_events = 0;
    return;
  }
  else {
    nua_dialog_log_usage(own, ds);
  }
}
Esempio n. 9
0
/** Read authentication database */
static
int auth_readdb_internal(auth_mod_t *am, int always)
{
    FILE *f;
    char *data, *s;
    size_t len, i, n, N;
    ssize_t slen;
    auth_passwd_t *apw;

    if (!am->am_stat)
        am->am_stat = su_zalloc(am->am_home, sizeof (*am->am_stat));

    f = fopen(am->am_db, "rb");

    if (f) {
        void *buffer = NULL;
        auth_passwd_t *fresh = NULL;

#if HAVE_FLOCK
        int locked;

        /* Obtain shared lock on the database file */
        if (flock(fileno(f), LOCK_SH | (always ? 0 : LOCK_NB)) == 0) {
            locked = 1;
        } else {
            locked = 0;

            if (errno == ENOLCK) {
                ;
            }
            else if (errno == EWOULDBLOCK) {
                SU_DEBUG_3(("auth(%s): user file \"%s\" is busy, trying again later\n",
                            am->am_scheme->asch_method, am->am_db));
                fclose(f);
                return always ? -1 : 0;
            }
            else {
                SU_DEBUG_3(("auth(%s): flock(\"%s\"): %s (%u)\n",
                            am->am_scheme->asch_method, am->am_db,
                            strerror(errno), errno));
                fclose(f);
                return always ? -1 : 0;
            }
        }
#endif
        if (am->am_stat)
            stat(am->am_db, am->am_stat); /* too bad if this fails */

        slen = readfile(am->am_home, f, &buffer, 1);

#if HAVE_FLOCK
        /* Release shared lock on the database file */
        if (locked && flock(fileno(f), LOCK_UN) == -1) {
            SU_DEBUG_0(("auth(%s): un-flock(\"%s\"): %s (%u)\n",
                        am->am_scheme->asch_method, am->am_db, strerror(errno), errno));
            fclose(f);
            return -1;
        }
#endif

        fclose(f);

        if (slen < 0)
            return -1;
        len = (size_t)slen;

        /* Count number of entries in new buffer */
        for (i = am->am_anonymous, s = data = buffer;
                s < data + len;
                s += n + strspn(s + n, "\r\n")) {
            n = strcspn(s, "\r\n");
            if (*s != '#' && *s != '\n' && *s != '\r')
                i++;
        }

        N = i, i = 0;

        if (N > 0) {
            size_t size = (N * 5 + 3) / 4;
            if (auth_htable_resize(am->am_home, am->am_users, size) < 0 ||
                    !(fresh = su_zalloc(am->am_home, sizeof(*fresh) * N))) {
                su_free(am->am_home, buffer);
                return -1;
            }
        }

        if (am->am_anonymous) {
            assert(i < N);

            apw = fresh + i++;

            apw->apw_index = msg_hash_string("anonymous");
            apw->apw_user = "******";
            apw->apw_pass = "";
            apw->apw_realm = "";

            am->am_anon_user = apw;

            if (auth_htable_is_full(am->am_users))
                auth_htable_resize(am->am_home, am->am_users, 0);

            auth_htable_append_local(am->am_users, apw);
        }

        apw = NULL;

        for (data = buffer, s = data;
                s < data + len && i < N;
                s += n + strspn(s + n, "\r\n")) {
            char *user, *pass, *realm, *ident;

            n = strcspn(s, "\r\n");
            if (*s == '#')
                continue;

            user = s;
            s[n++] = '\0';
            if (!(pass = strchr(user, ':')))
                continue;

            *pass++ = '\0';
            if (!*pass || !*user)
                continue;

            if ((realm = strchr(pass, ':')))
                *realm++ = '\0';
            else
                realm = "";

            if ((ident = strchr(realm, ':')))
                *ident++ = '\0';
            else
                ident = "";

            apw = fresh + i++;

            apw->apw_index = msg_hash_string(user);
            apw->apw_user = user;
            apw->apw_ident = ident;

            /* Check for htdigest format */
            if (span_hexdigit(realm) == 32 && realm[32] == '\0') {
                apw->apw_realm = pass;
                apw->apw_hash = realm;
            } else {
                apw->apw_pass = pass;
                apw->apw_realm = realm;
            }

            if (auth_htable_is_full(am->am_users))
                auth_htable_resize(am->am_home, am->am_users, 0);

            auth_htable_append_local(am->am_users, apw);
        }

        assert(i <= N);
        N = i;

        /* Remove from hash those entries that were read from old passwd file */
        for (i = 0; i < am->am_local_count; i++) {
            if (am->am_locals[i].apw_type == auth_apw_local)
                auth_htable_remove(am->am_users, &am->am_locals[i]);
        }

        if (am->am_locals)
            su_free(am->am_home, am->am_locals); /* Free old entries */
        if (am->am_buffer)
            su_free(am->am_home, am->am_buffer); /* Free old passwd file contents */

        SU_DEBUG_5(("auth(%s): read %u entries from \"%s\"\n",
                    am->am_scheme->asch_method, (unsigned)N, am->am_db));

        am->am_locals = fresh;
        am->am_local_count = N;
        am->am_buffer = buffer;

        return 0;
    }

    return -1;
}
Esempio n. 10
0
/**Free a string array.
 *
 * The function su_vector_free_array() discards a string array allocated
 * with su_vector_get_array().
 *
 * @param vector  pointer to a vector object
 * @param array  string array to be freed
 *
 */
void su_vector_free_array(su_vector_t *vector, void **array)
{
  su_free(vector->v_home, array);
}
/**Create a NTLM authorization header.
 *
 * Creates a ntlm authorization header from username @a user and password
 * @a pass, client nonce @a cnonce, client nonce count @a nc, request method
 * @a method, request URI @a uri and message body @a data. The authorization
 * header type is determined by @a hc - it can be either
 * sip_authorization_class or sip_proxy_authorization_class, as well as
 * http_authorization_class or http_proxy_authorization_class.
 *
 * @param home 	  memory home used to allocate memory for the new header
 * @param hc   	  header class for the header to be created
 * @param user 	  user name
 * @param pass 	  password
 * @param ac      challenge structure
 * @param cnonce  client nonce
 * @param nc      client nonce count
 * @param method  request method
 * @param uri     request uri
 * @param data    message body
 * @param dlen    length of message body
 *
 * @return
 * Returns a pointer to newly created authorization header, or NULL upon an
 * error.
 */
int auc_ntlm_authorization(auth_client_t *ca,
			     su_home_t *home,
			     char const *method,
			     url_t const *url,
			     msg_payload_t const *body,
			     msg_header_t **return_headers)
{
  auth_ntlm_client_t *ntlm = (auth_ntlm_client_t *)ca;
  msg_hclass_t *hc = ca->ca_credential_class;
  char const *user = ca->ca_user;
  char const *pass = ca->ca_pass;
  auth_challenge_t const *ac = ntlm->ntlm_ac;
  char const *cnonce = ntlm->ntlm_cnonce;
  unsigned nc = ++ntlm->ntlm_ncount;
  char *uri = url_as_string(home, url);
  void const *data = body ? body->pl_data : "";
  int dlen = body ? body->pl_len : 0;

  msg_header_t *h;
  auth_hexmd5_t sessionkey, response;
  auth_response_t ar[1] = {{ 0 }};
  char ncount[17];

  ar->ar_size = sizeof(ar);
  ar->ar_username = user;
  ar->ar_realm = ac->ac_realm;
  ar->ar_nonce = ac->ac_nonce;
  ar->ar_algorithm = NULL;
  ar->ar_md5 = ac->ac_md5;
  ar->ar_md5sess = ac->ac_md5sess;
  ar->ar_opaque = ac->ac_opaque;
  ar->ar_qop = NULL;
  ar->ar_auth = ac->ac_auth;
  ar->ar_auth_int = ac->ac_auth_int;
  ar->ar_uri = uri;

  /* If there is no qop, we MUST NOT include cnonce or nc */
  if (!ar->ar_auth && !ar->ar_auth_int)
    cnonce = NULL;

  if (cnonce) {
    snprintf(ncount, sizeof(ncount), "%08x", nc);
    ar->ar_cnonce = cnonce;
    ar->ar_nc = ncount;
  }

  auth_ntlm_sessionkey(ar, sessionkey, pass);
  auth_ntlm_response(ar, response, sessionkey, method, data, dlen);

  h = msg_header_format(home, hc,
			"NTLM "
			"username=\"%s\", "
			"realm=\"%s\", "
			"nonce=\"%s"
			"%s%s"
			"%s%s"
			"%s%s, "
			"uri=\"%s\", "
			"response=\"%s\""
			"%s%s"
			"%s%s",
			ar->ar_username,
			ar->ar_realm,
			ar->ar_nonce,
			cnonce ? "\",  cnonce=\"" : "",
			cnonce ? cnonce : "",
			ar->ar_opaque ? "\",  opaque=\"" : "",
			ar->ar_opaque ? ar->ar_opaque : "",
			ar->ar_algorithm ? "\", algorithm=" : "",
			ar->ar_algorithm ? ar->ar_algorithm : "",
			ar->ar_uri,
			response,
			ar->ar_auth || ar->ar_auth_int ? ", qop=" : "",
			ar->ar_auth_int ? "auth-int" :
			(ar->ar_auth ? "auth" : ""),
			cnonce ? ", nc=" : "",
			cnonce ? ncount : "");

  su_free(home, uri);

  if (!h)
    return -1;
  *return_headers = h;
  return 0;
}
Esempio n. 12
0
static int nua_notify_client_init_etag(nua_client_request_t *cr,
				       msg_t *msg, sip_t *sip,
				       tagi_t const *tags)
{
#if SU_HAVE_EXPERIMENTAL
  nua_handle_t *nh = cr->cr_owner;
  struct notifier_usage *nu = nua_dialog_usage_private(cr->cr_usage);
  nua_server_request_t *sr;

  if (nu->nu_tag)
    su_free(nh->nh_home, nu->nu_tag), nu->nu_tag = NULL;
    nu->nu_no_body = 0;

  if (sip->sip_etag) {
    nu->nu_appl_etags = 1;
    nu->nu_tag = su_strdup(nh->nh_home, sip->sip_etag->g_string);
  }
  else if (!nu->nu_appl_etags && nu->nu_etags) {
    su_md5_t md5[1];
    unsigned char digest[SU_MD5_DIGEST_SIZE];
    sip_payload_t pl[1] = { SIP_PAYLOAD_INIT() };
    char token[2 * 16];

    su_md5_init(md5);

    if (sip->sip_payload) *pl = *sip->sip_payload;

    if (pl->pl_len)
      su_md5_update(md5, pl->pl_data, pl->pl_len);
    su_md5_update(md5, &pl->pl_len, sizeof(pl->pl_len));

    if (sip->sip_content_type)
      su_md5_striupdate(md5, sip->sip_content_type->c_type);

    su_md5_digest(md5, digest);
    token64_e(token, sizeof token, digest, sizeof digest);
    token[(sizeof token) - 1] = '\0';
    nu->nu_tag = su_strdup(nh->nh_home, token);
  }

  if (!nu->nu_requested || !nu->nu_tag)
    return 0;

  /* Check if SUBSCRIBE had matching suppression */
  for (sr = nh->nh_ds->ds_sr; sr; sr = sr->sr_next)
    if (sr->sr_usage == cr->cr_usage && sr->sr_method == sip_method_subscribe)
      break;

  if (sr) {
    sip_t const *sip = sr->sr_request.sip;

    sip_suppress_body_if_match_t *sbim;
    sip_suppress_notify_if_match_t *snim;

    if (cr->cr_usage->du_ready) {
      snim = sip_suppress_notify_if_match(sip);

      if (snim && su_casematch(snim->snim_tag, nu->nu_tag)) {
	if (nu->nu_requested > nu->nu_expires)
	  nu->nu_expires = nu->nu_requested;
	nu->nu_requested = 0;
	return nua_client_return(cr, 202, "NOTIFY Suppressed", msg);
      }
    }

    sbim = sip_suppress_body_if_match(sip);
    if (sbim && su_casematch(sbim->sbim_tag, nu->nu_tag))
      nu->nu_no_body = 1;
  }
#endif

  return 0;
}
Esempio n. 13
0
tagi_t* luasofia_tags_table_to_taglist(lua_State *L, int index, su_home_t *home)
{
    int i = 0;
    int maxtags = TAGS_LIST_SIZE;
    tagi_t* tags = su_zalloc(home, sizeof(tagi_t) * maxtags);

    if(!lua_istable(L, index)) {
        tags[0].t_tag = NULL;
        tags[0].t_value = 0;
        return tags;
    }

    /* put the tag table at the stack */
    lua_rawgeti(L, LUA_REGISTRYINDEX, tag_table_ref);
    if (lua_isnil(L, -1)) {
        su_free(home, tags);
        luaL_error(L, "Failed to get tag table!");
    }

    if (index < 0)
        index--;

    /* first key */
    lua_pushnil(L);
    while(lua_next(L, index) != 0) {
        /* 'key' at index -2 and 'value' at index -1 */
        tag_type_t t_tag = NULL;
        tag_value_t return_value;
        char const *s = NULL;

        /* if 'value' is nil not use this tag */
        if(lua_isnil(L, -1)) {
            /* remove 'value' and 'key' is used on the next iteration */
            lua_pop(L, 1);
            continue;
        }
        s = lua_tostring(L, -1);

        /* lookup key in the tag table and push tag_type_t */
        lua_pushvalue(L, -2);
        lua_rawget(L, -4);
        t_tag = lua_touserdata(L, -1);
        lua_pop(L, 1);

        if(t_scan(t_tag, home, s, &return_value) == -1) {
            su_free(home, tags);
            luaL_error(L, "Tag '%s' doesn't exist!", lua_tostring(L, -2));
        }

        tags[i].t_tag = t_tag;
        tags[i++].t_value = return_value;

        if(i == maxtags - 1) {
            maxtags *= 2;
            tags = su_realloc(home, tags, sizeof(tagi_t) * maxtags);
        }

        /* remove 'value' and 'key' is used on the next iteration */
        lua_pop(L, 1);
    }
    /* remove tag table from stack */
    lua_pop(L, 1);

    tags[i].t_tag = NULL;
    tags[i].t_value = 0;
    return tags;
}
Esempio n. 14
0
/** Reallocate a memory block.
 *
 *   Allocates a memory block of @a size bytes.
 *   It copies the old block contents to the new block and frees the old
 *   block.
 *
 *   If @a home is NULL, this function behaves exactly like realloc().
 *
 *   @param home  pointer to memory pool object
 *   @param data  pointer to old memory block
 *   @param size  size of the memory block to be allocated
 *
 * @return
 *   A pointer to the allocated memory block or
 *   NULL if an error occurred.
 */
void *su_realloc(su_home_t *home, void *data, isize_t size)
{
  void *ndata;
  su_alloc_t *sua;
  su_block_t *sub;
  size_t p;
  size_t term = 0 - size;

  if (!home)
    return realloc(data, size);

  if (size == 0) {
    if (data)
      su_free(home, data);
    return NULL;
  }

  sub = MEMLOCK(home);
  if (!data) {
    data = sub_alloc(home, sub, size, (enum sub_zero)0);
    UNLOCK(home);
    return data;
  }

  sua = su_block_find(sub, data);

  if (!su_alloc_check(sub, sua))
    return UNLOCK(home);

  assert(!sua->sua_home);
  if (sua->sua_home)
    return UNLOCK(home);

  if (!su_is_preloaded(sub, data)) {
    ndata = realloc(data, size + MEMCHECK_EXTRA);
    if (ndata) {
      if (sub->sub_stats) {
	su_home_stats_free(sub, data, 0, sua->sua_size);
	su_home_stats_alloc(sub, data, 0, size, 1);
      }

#if MEMCHECK_EXTRA
      memcpy((char *)ndata + size, &term, sizeof (term));
#else
      (void)term;
#endif
      memset(sua, 0, sizeof *sua);
      sub->sub_used--;
      su_block_add(sub, ndata)->sua_size = (unsigned)size;
    }
    UNLOCK(home);

    return ndata;
  }

  p = (char *)data - home->suh_blocks->sub_preload;
  p += sua->sua_size + MEMCHECK_EXTRA;
  p = __ALIGN(p);

  if (p == sub->sub_prused) {
    size_t p2 = (char *)data - sub->sub_preload + size + MEMCHECK_EXTRA;
    p2 = __ALIGN(p2);
    if (p2 <= sub->sub_prsize) {
      /* Extend/reduce existing preload */
      if (sub->sub_stats) {
	su_home_stats_free(sub, data, data, sua->sua_size);
	su_home_stats_alloc(sub, data, data, size, 0);
      }

      sub->sub_prused = (unsigned)p2;
      sua->sua_size = (unsigned)size;

#if MEMCHECK_EXTRA
      memcpy((char *)data + size, &term, sizeof (term));
#endif
      UNLOCK(home);
      return data;
    }
  }
  else if (size < (size_t)sua->sua_size) {
    /* Reduce existing preload */
    if (sub->sub_stats) {
      su_home_stats_free(sub, data, data, sua->sua_size);
      su_home_stats_alloc(sub, data, data, size, 0);
    }
#if MEMCHECK_EXTRA
    memcpy((char *)data + size, &term, sizeof (term));
#endif
    sua->sua_size = (unsigned)size;
    UNLOCK(home);
    return data;
  }

  ndata = malloc(size + MEMCHECK_EXTRA);

  if (ndata) {
    if (p == sub->sub_prused) {
      /* Free preload */
      sub->sub_prused = (char *)data - home->suh_blocks->sub_preload;
      if (sub->sub_stats)
	su_home_stats_free(sub, data, data, sua->sua_size);
    }

    memcpy(ndata, data,
	   (size_t)sua->sua_size < size
	   ? (size_t)sua->sua_size
	   : size);
#if MEMCHECK_EXTRA
    memcpy((char *)ndata + size, &term, sizeof (term));
#endif

    if (sub->sub_stats)
      su_home_stats_alloc(sub, data, 0, size, 1);

    memset(sua, 0, sizeof *sua); sub->sub_used--;

    su_block_add(sub, ndata)->sua_size = (unsigned)size;
#ifdef DEBUG
    SU_DEBUG_9(("%s: block %p sub_used is %ld sub_n %ld used %d\n", __func__, sub, sub->sub_used, sub->sub_n, su_get_used_count(sub))) ;
#endif
  }

  UNLOCK(home);

  return ndata;
}