示例#1
0
int forwarder_stream_peer(proxy_t *pr, forwarder_t *f_peer)
{
  forwarder_t *f;
  su_addrinfo_t *ai;

  assert(f_peer);

  f = forwarder_create(pr);
  if (!f) {
    SU_DEBUG_1(("%s: cannot allocate peer\n", __func__));
    goto error;
  }

  for (ai = pr->pr_addrinfo; ai; ai = ai->ai_next) {
    if (ai->ai_socktype == SOCK_STREAM)
      break;
  }

  if (!ai) {
    SU_DEBUG_1(("%s: no matching destination\n", __func__));
    goto error;
  }

  f->f_socket = su_socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
  if (f->f_socket == INVALID_SOCKET) {
    SU_DEBUG_1(("%s: socket: %s\n", __func__, su_strerror(su_errno())));
    goto error;
  }

  if (su_wait_create(f->f_wait, f->f_socket, SU_WAIT_IN) ||
      su_wait_create(f->f_wait + 1, f->f_socket, SU_WAIT_OUT)) {
    SU_DEBUG_1(("%s: cannot create wait objects\n", __func__));
    goto error;
  }

  /* Asynchronous connect */
  su_setblocking(f->f_socket, 0);
  su_seterrno(0);
  connect(f->f_socket, ai->ai_addr, ai->ai_addrlen);
  memcpy(f->f_dest, ai->ai_addr, ai->ai_addrlen);

  if (su_errno() != EINPROGRESS) {
    SU_DEBUG_1(("%s: connect: %s\n", __func__, su_strerror(su_errno())));
    goto error;
  }

  if (su_root_register(pr->pr_root, f->f_wait + 1,
		       forwarder_connected, f, 0) == -1) {
    SU_DEBUG_1(("%s: cannot register\n", __func__));
    goto error;
  }

  f->f_peer = f_peer;
  f_peer->f_peer = f;
  return 0;

 error:
  forwarder_destroy(f);
  return SOCKET_ERROR;
}
/** Test root initialization */
int init_test(root_test_t *rt)
{
  su_sockaddr_t su[1] = {{ 0 }};
  int i;

  BEGIN();

  su_init();

  su->su_family = rt->rt_family;

  TEST_1(rt->rt_root = su_root_osx_runloop_create(rt));

  for (i = 0; i < 5; i++) {
    test_ep_t *ep = rt->rt_ep[i];
    ep->i = i;
    ep->addrlen = su_sockaddr_size(su);
    TEST_1((ep->s = su_socket(su->su_family, SOCK_DGRAM, 0)) != -1);
    TEST_1(bind(ep->s, &su->su_sa, ep->addrlen) != -1);
    TEST_1(su_wait_create(ep->wait, ep->s, SU_WAIT_IN|SU_WAIT_ERR) != -1);
    TEST_1(getsockname(ep->s, &ep->addr->su_sa, &ep->addrlen) != -1);
    if (SU_HAS_INADDR_ANY(ep->addr)) {
      su_inet_pton(su->su_family,
		   su->su_family == AF_INET ? "127.0.0.1" : "::1",
		   SU_ADDR(ep->addr));
    }
  }

  END();
}
示例#3
0
int main(int argc, char *argv[])
{
  su_socket_t s;
  su_sockaddr_t su = { 0 };
  char *host = argv[1];
  char *port = host ? argv[2] : NULL;
  su_addrinfo_t *ai = NULL, hints[1] = {{ 0 }};
  int error;

  if (argv[1] && (strcmp(argv[1], "--help") == 0 ||
		  strcmp(argv[1], "-?") == 0))
    usage(argv[0]);

  if (!port) port = "echo";

  if ((error = su_getaddrinfo(host, port, hints, &ai))) {
    fprintf(stderr, "poll_test: su_getaddrinfo(): %s\n",
	    su_gai_strerror(error));
    exit(1);
  }

  memcpy(SU_ADDR(&su), ai->ai_addr, ai->ai_addrlen);

  s = su_socket(ai->ai_family, SOCK_STREAM, 0);
  if (s == INVALID_SOCKET) {
    su_perror("socket");
    exit(1);
  }

  su_freeaddrinfo(ai);

  su_setblocking(s, 0);		/* Don't block */

  if (connect(s, &su.su_sa, su_sockaddr_size(&su)) == -1) {
    if (errno != EINPROGRESS) {
      su_perror("connect");
      exit(1);
    }
  }

  {
    su_wait_t w;
    int n, err;

    su_wait_create(&w, s, SU_WAIT_OUT);

    n = su_wait(&w, 1, SU_WAIT_FOREVER);

    printf("su_wait returned %d\n", n);

    err = su_soerror(s);

    printf("connect: %s\n", su_strerror(err));
  }

  exit(0);
}
示例#4
0
/** Accept a connection. */
int forwarder_accept(proxy_t *pr, su_wait_t *w, forwarder_t *f0)
{
  forwarder_t *f;
  su_sockaddr_t *su;
  socklen_t  sulen;
  int events;

  events = su_wait_events(w, f0->f_socket);

  f = forwarder_create(pr);

  if (f) {
    su = f->f_dest;
    sulen = sizeof(f->f_dest);
    f->f_socket = accept(f0->f_socket, &su->su_sa, &sulen);
    f->f_upstream = 1;
    if (f->f_socket != INVALID_SOCKET) {
      char buf[SU_ADDRSIZE];

      SU_DEBUG_3(("accept: connection from %s:%u\n",
		  su_inet_ntop(su->su_family, SU_ADDR(su), buf, sizeof(buf)),
		  ntohs(su->su_port)));

      if (!su_wait_create(f->f_wait, f->f_socket, SU_WAIT_IN) &&
	  !su_wait_create(f->f_wait + 1, f->f_socket, SU_WAIT_OUT)) {
	if (forwarder_stream_peer(pr, f) != SOCKET_ERROR) {
	  /* success */
	  return 0;
	}
      }
      else {
	SU_DEBUG_1(("%s: cannot create wait objects\n", __func__));
      }
    }
  }

  forwarder_destroy(f);

  return 0;
}
示例#5
0
int forwarder_init_stream(forwarder_t *f)
{
  if (listen(f->f_socket, SOMAXCONN) < 0)
    return SOCKET_ERROR;

  if (su_wait_create(f->f_wait, f->f_socket, SU_WAIT_ACCEPT) < 0)
    return SOCKET_ERROR;

  if (su_root_register(f->f_pr->pr_root, f->f_wait,
		       forwarder_accept, f, 0) < 0)
    return SOCKET_ERROR;

  return 0;
}
示例#6
0
int tls_connect(su_root_magic_t *magic, su_wait_t *w, tport_t *self)
{
  tport_master_t *mr = self->tp_master;
  tport_tls_t *tlstp = (tport_tls_t *)self;
  tls_t *tls;
  int events = su_wait_events(w, self->tp_socket);
  int error;

  SU_DEBUG_7(("%s(%p): events%s%s%s%s\n", __func__, (void *)self,
              events & (SU_WAIT_CONNECT) ? " CONNECTING" : "",
              events & SU_WAIT_IN  ? " NEGOTIATING" : "",
              events & SU_WAIT_ERR ? " ERROR" : "",
              events & SU_WAIT_HUP ? " HANGUP" : ""));

#if HAVE_POLL
  assert(w->fd == self->tp_socket);
#endif

  if (events & SU_WAIT_ERR)
    tport_error_event(self);

  if (events & SU_WAIT_HUP && !self->tp_closed)
    tport_hup_event(self);

  if (self->tp_closed)
    return 0;

  error = su_soerror(self->tp_socket);
  if (error) {
    tport_error_report(self, error, NULL);
    return 0;
  }

  if ((tls = tlstp->tlstp_context) == NULL) {
    SU_DEBUG_3(("%s(%p): Error: no TLS context data for connected socket.\n",
                __func__, (void *)tlstp));
    tport_close(self);
    tport_set_secondary_timer(self);
    return 0;
  }

  if (self->tp_is_connected == 0) {
    int ret, status;

    ret = self->tp_accepted ? SSL_accept(tls->con) : SSL_connect(tls->con);
    status = SSL_get_error(tls->con, ret);

    switch (status) {
      case SSL_ERROR_WANT_READ:
        /* OpenSSL is waiting for the peer to send handshake data */
        self->tp_events = SU_WAIT_IN | SU_WAIT_ERR | SU_WAIT_HUP;
        su_root_eventmask(mr->mr_root, self->tp_index,
		          self->tp_socket, self->tp_events);
        return 0;

      case SSL_ERROR_WANT_WRITE:
        /* OpenSSL is waiting for the peer to receive handshake data */
        self->tp_events = SU_WAIT_IN | SU_WAIT_ERR | SU_WAIT_HUP | SU_WAIT_OUT;
        su_root_eventmask(mr->mr_root, self->tp_index,
                           self->tp_socket, self->tp_events);
        return 0;

      case SSL_ERROR_NONE:
        /* TLS Handshake complete */
	status = tls_post_connection_check(self, tls);
        if ( status == X509_V_OK ) {
          su_wait_t wait[1] = {SU_WAIT_INIT};
          tport_master_t *mr = self->tp_master;

          su_root_deregister(mr->mr_root, self->tp_index);
          self->tp_index = -1;
          self->tp_events = SU_WAIT_IN | SU_WAIT_ERR | SU_WAIT_HUP;

          if ((su_wait_create(wait, self->tp_socket, self->tp_events) == -1) ||
             ((self->tp_index = su_root_register(mr->mr_root, wait, tport_wakeup,
                                                           self, 0)) == -1)) {
            tport_close(self);
            tport_set_secondary_timer(self);
	    return 0;
          }

          tls->read_events = SU_WAIT_IN;
          tls->write_events = 0;
          self->tp_is_connected = 1;
	  self->tp_verified = tls->x509_verified;
	  self->tp_subjects = tls->subjects;

	  if (tport_has_queued(self))
            tport_send_event(self);
          else
            tport_set_secondary_timer(self);

          return 0;
	}
	break;

      default:
        {
	  char errbuf[64];
	  ERR_error_string_n(status, errbuf, 64);
          SU_DEBUG_3(("%s(%p): TLS setup failed (%s)\n",
					  __func__, (void *)self, errbuf));
        }
        break;
    }
  }

  /* TLS Handshake Failed or Peer Certificate did not Verify */
  tport_close(self);
  tport_set_secondary_timer(self);

  return 0;
}
示例#7
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);
}
示例#8
0
/** Add command line (standard input) to be waited. */
static int sofsip_init(cli_t *cli, int ac, char *av[])
{
  ssc_conf_t *conf = cli->cli_conf;
  int i;
  /* gboolean b = FALSE; */
  /* long, short, flags, arg, arg_data, desc, arg_desc */
  GOptionEntry options[] = {
    { "autoanswer", 'a', 0, G_OPTION_ARG_NONE, &conf->ssc_autoanswer, "Auto-answer to calls", NULL },
    { "register", 'R', 0, G_OPTION_ARG_NONE, &conf->ssc_register, "Register at startup", NULL },
    { "contact", 'c', 0, G_OPTION_ARG_STRING, &conf->ssc_contact, "SIP contact, local address to bind to (optional)", "SIP-URI" },
    { "media-addr", 'm', 0, G_OPTION_ARG_STRING, &conf->ssc_media_addr, "media address (optional)", "address"  },
    { "media-impl", 'i', 0, G_OPTION_ARG_STRING, &conf->ssc_media_impl, "media implementation to use", "dummy,gstreamer"  },
    { "registrar", 'r', 0, G_OPTION_ARG_STRING, &conf->ssc_registrar, "SIP registrar/server (optional)", "SIP-URI"  },
    { "proxy", 'p', 0, G_OPTION_ARG_STRING, &conf->ssc_proxy, "outbound proxy (optional)", "SIP-URI" },
    { "stun-server", 's', 0, G_OPTION_ARG_STRING, &conf->ssc_stun_server, "STUN server (optional)", "address"  },
    { NULL }
  };
  GOptionContext *context;
  GError *error = NULL;

  /* step: process environment variables */
  conf->ssc_aor = getenv("SOFSIP_ADDRESS");
  conf->ssc_proxy = getenv("SOFSIP_PROXY");
  conf->ssc_registrar = getenv("SOFSIP_REGISTRAR");
  conf->ssc_certdir = getenv("SOFSIP_CERTDIR");
  conf->ssc_stun_server = getenv("SOFSIP_STUN_SERVER");

  /* step: process command line arguments */
  context = g_option_context_new("- sofsip_cli usage");
  g_option_context_add_main_entries(context, options, "sofsip_cli");
#if HAVE_GST
  g_option_context_add_group (context, gst_init_get_option_group ());
#endif
  if (!g_option_context_parse(context, &ac, &av, &error)) {
      g_print ("option parsing failed: %s\n", error->message);
      exit (1);
  }
  g_option_context_free(context);

  for (i = 1; i < ac; i++) {
    if (av[i] && av[i][0] != '-') {
      cli->cli_conf->ssc_aor = av[i];
      break;
    }
  }
  // notice that in iOS we can't register STDIN; we get an error 'Invalid argument'
  // in su_root_register() below. Let's use a pipe instead for iOS core app <-> sofia sip communication
  su_wait_create(&cli->cli_input, cli->cli_input_fd, SU_WAIT_IN);
  if (su_root_register(cli->cli_root,
		       &cli->cli_input, 
		       sofsip_handle_input, 
		       NULL, 
		       0) == SOCKET_ERROR) {
    su_perror("su_root_register");
    return -1;
  }

  cli->cli_init = 1;

  return 0;
}
示例#9
0
int test_sendrecv(void)
{
  su_socket_t s, l, a;
  ssize_t n;
  su_sockaddr_t su, csu;
  socklen_t sulen = sizeof su.su_sin, csulen = sizeof csu.su_sin;
  char b1[8], b2[8], b3[8];
  su_iovec_t sv[3], rv[3];

  sv[0].siv_base = "one!one!", sv[0].siv_len = 8;
  sv[1].siv_base = "two!two!", sv[1].siv_len = 8;
  sv[2].siv_base = "third!", sv[2].siv_len = 6;

  rv[0].siv_base = b1, rv[0].siv_len = 8;
  rv[1].siv_base = b2, rv[1].siv_len = 8;
  rv[2].siv_base = b3, rv[2].siv_len = 8;

  BEGIN();

  s = su_socket(AF_INET, SOCK_DGRAM, 0); TEST_1(s != -1);
  su_setblocking(s, 1);

  memset(&su, 0, sulen);
  su.su_len = sulen;
  su.su_family = AF_INET;
  TEST(su_inet_pton(AF_INET, "127.0.0.1", &su.su_sin.sin_addr), 1);

  TEST(bind(s, &su.su_sa, sulen), 0);
  TEST(getsockname(s, &su.su_sa, &sulen), 0);

  n = su_vsend(s, sv, 3, 0, &su, sulen); TEST(n, 8 + 8 + 6);
  n = su_vrecv(s, rv, 3, 0, &su, &sulen); TEST(n, 8 + 8 + 6);

  TEST_M(rv[0].siv_base, sv[0].siv_base, sv[0].siv_len);
  TEST_M(rv[1].siv_base, sv[1].siv_base, sv[1].siv_len);
  TEST_M(rv[2].siv_base, sv[2].siv_base, sv[2].siv_len);

  su_close(s);

  l = su_socket(AF_INET, SOCK_STREAM, 0); TEST_1(l != -1);
  s = su_socket(AF_INET, SOCK_STREAM, 0); TEST_1(s != -1);

  memset(&su, 0, sulen);
  su.su_len = sulen;
  su.su_family = AF_INET;
  TEST(su_inet_pton(AF_INET, "127.0.0.1", &su.su_sin.sin_addr), 1);

  TEST(bind(l, &su.su_sa, sulen), 0);
  TEST(bind(s, &su.su_sa, sulen), 0);

  TEST(getsockname(l, &su.su_sa, &sulen), 0);
  TEST(listen(l, 5), 0);

  TEST(su_setblocking(s, 1), 0);

  TEST(connect(s, &su.su_sa, sulen), 0);
  a = accept(l, &csu.su_sa, &csulen); TEST_1(a != -1);

  TEST(su_setblocking(a, 1), 0);

  n = su_vsend(s, sv, 3, 0, NULL, 0); TEST(n, 8 + 8 + 6);
  n = su_vrecv(a, rv, 3, 0, NULL, NULL); TEST(n, 8 + 8 + 6);

  TEST_M(rv[0].siv_base, sv[0].siv_base, sv[0].siv_len);
  TEST_M(rv[1].siv_base, sv[1].siv_base, sv[1].siv_len);
  TEST_M(rv[2].siv_base, sv[2].siv_base, sv[2].siv_len);

  n = send(a, "", 0, 0); TEST(n, 0);
  n = su_vsend(a, sv, 3, 0, NULL, 0); TEST(n, 8 + 8 + 6);

  {
    su_wait_t w[1] = { SU_WAIT_INIT };

    TEST(su_wait_create(w, s, SU_WAIT_IN | SU_WAIT_HUP), 0);

    TEST(su_wait(w, 0, 500), SU_WAIT_TIMEOUT);

    TEST(su_wait(w, 1, 500), 0);
    TEST(su_wait_events(w, s), SU_WAIT_IN);

    TEST_SIZE(su_getmsgsize(s), 8 + 8 + 6);
    n = su_vrecv(s, rv, 3, 0, NULL, NULL); TEST(n, 8 + 8 + 6);

    TEST(su_wait(w, 1, 100), SU_WAIT_TIMEOUT);

    shutdown(a, 2);

    TEST(su_wait(w, 1, 100), 0);
#if SU_HAVE_WINSOCK
    TEST_1(su_wait_events(w, s) & SU_WAIT_HUP);
#else
    TEST_1(su_wait_events(w, s));
    n = su_vrecv(s, rv, 3, 0, NULL, NULL); TEST(n, 0);
#endif

    su_wait_destroy(w);
  }

  su_close(a);

  su_close(l);
  su_close(s);

  END();
}
static int register_test(root_test_t *rt)
{
  int i;
  int s;
  char msg[3] = "foo";

  BEGIN();

  TEST_1((s = su_socket(rt->rt_family, SOCK_DGRAM, 0)) != -1);

  for (i = 0; i < 5; i++) {
    rt->rt_ep[i]->registered =
      su_root_register(rt->rt_root, rt->rt_ep[i]->wait,
		       wakeups[i], rt->rt_ep[i], 0);
    TEST(rt->rt_ep[i]->registered, i + 1 + SU_HAVE_PTHREADS);
  }

  for (i = 0; i < 5; i++) {
    test_ep_t *ep = rt->rt_ep[i];
    TEST(su_sendto(s, msg, sizeof(msg), 0, ep->addr, ep->addrlen),
	 sizeof(msg));
    test_run(rt);
    TEST(rt->rt_received, i);
    TEST(rt->rt_wakeup, i);
  }

  for (i = 0; i < 5; i++) {
    TEST(su_root_unregister(rt->rt_root, rt->rt_ep[i]->wait,
			    wakeups[i], rt->rt_ep[i]),
	 rt->rt_ep[i]->registered);
  }


  for (i = 0; i < 5; i++) {
    rt->rt_ep[i]->registered =
      su_root_register(rt->rt_root, rt->rt_ep[i]->wait,
		       wakeups[i], rt->rt_ep[i], 1);
    TEST_1(rt->rt_ep[i]->registered > 0);
  }

  for (i = 0; i < 5; i++) {
    test_ep_t *ep = rt->rt_ep[i];
    TEST(su_sendto(s, msg, sizeof(msg), 0, ep->addr, ep->addrlen),
	 sizeof(msg));
    test_run(rt);
    TEST(rt->rt_received, i);
    TEST(rt->rt_wakeup, i);
  }

  for (i = 0; i < 5; i++) {
    TEST(su_root_deregister(rt->rt_root, rt->rt_ep[i]->registered),
	 rt->rt_ep[i]->registered);
  }

  for (i = 0; i < 5; i++) {
    test_ep_t *ep = rt->rt_ep[i];
    TEST_1(su_wait_create(ep->wait, ep->s, SU_WAIT_IN|SU_WAIT_ERR) != -1);
    ep->registered =
      su_root_register(rt->rt_root, ep->wait,
		       wakeups[i], ep, 1);
    TEST_1(ep->registered > 0);
  }

  for (i = 0; i < 5; i++) {
    test_ep_t *ep = rt->rt_ep[i];
    TEST(su_sendto(s, msg, sizeof(msg), 0, ep->addr, ep->addrlen),
	 sizeof(msg));
    test_run(rt);
    TEST(rt->rt_received, i);
    TEST(rt->rt_wakeup, i);
  }

  for (i = 0; i < 5; i++) {
    TEST(su_root_unregister(rt->rt_root, rt->rt_ep[i]->wait,
			    wakeups[i], rt->rt_ep[i]),
	 rt->rt_ep[i]->registered);
  }

  END();
}