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

📄 stun.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 5 页
字号:
    z = SSL_write(ssl, msg_req->enc_buf.data, msg_req->enc_buf.size);        if (z < 0) {      err = SSL_get_error(ssl, z);      if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)	return 0;      else {	STUN_ERROR(errno, SSL_write);	stun_free_buffer(&msg_req->enc_buf);	return -1;      }    }    sd->sd_state = stun_tls_reading;    break;  case stun_tls_reading:    events = SU_WAIT_ERR | SU_WAIT_OUT;    su_root_eventmask(self->sh_root, sd->sd_index,		      sd->sd_socket, events);    SU_DEBUG_5(("Shared Secret Request sent to server:\n"));    debug_print(&msg_req->enc_buf);    z = SSL_read(ssl, buf, sizeof(buf));    if (z <= 0) {      err = SSL_get_error(ssl, z);      if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)	return 0;      else {	stun_free_buffer(&msg_req->enc_buf);	return -1;      }    }    /* We end up here after there's something to read from the     * socket */    resp->enc_buf.size = z;    resp->enc_buf.data = malloc(z);    memcpy(resp->enc_buf.data, buf, z);    SU_DEBUG_5(("Shared Secret Response received from server:\n"));    debug_print(&resp->enc_buf);    /* closed TLS connection */    SSL_shutdown(ssl);    su_close(sd->sd_socket), sd->sd_socket = INVALID_SOCKET;    SSL_free(self->sh_ssl), ssl = NULL;    SSL_CTX_free(self->sh_ctx), ctx = NULL;    stun_free_buffer(&msg_req->enc_buf);      /* process response */    if (stun_parse_message(resp) < 0) {      perror("stun_parse_message");      stun_free_buffer(&resp->enc_buf);      return -1;    }    switch(resp->stun_hdr.msg_type) {    case SHARED_SECRET_RESPONSE:      username = stun_get_attr(resp->stun_attr, USERNAME);      password = stun_get_attr(resp->stun_attr, PASSWORD);      if (username != NULL && password != NULL) {	/* move result to se */	stun_copy_buffer(&self->sh_username, username->pattr);	stun_copy_buffer(&self->sh_passwd, password->pattr);      }      break;    case SHARED_SECRET_ERROR_RESPONSE:      if (stun_process_error_response(resp) < 0) {	SU_DEBUG_5(("Error in Shared Secret Error Response.\n"));       }      stun_free_buffer(&resp->enc_buf);      return -1;          break;    default:      break;    }        su_wait_destroy(w);    su_root_deregister(self->sh_root, sd->sd_index);    sd->sd_index = -1; /* mark index as deregistered */    self->sh_use_msgint = 1;    sd->sd_state = stun_tls_done;    if (sd->sd_callback)      sd->sd_callback(sd->sd_magic, self, sd, sd->sd_action, sd->sd_state);    break;  default:    return -1;  }  return 0;}#endif /* HAVE_OPENSSL */#if HAVE_OPENSSLstatic void stun_tls_connect_timer_cb(su_root_magic_t *magic, 				      su_timer_t *t,				      su_timer_arg_t *arg){  stun_discovery_t *sd = arg;  stun_handle_t *sh = sd->sd_handle;  enter;  su_timer_destroy(t);  if (t == sd->sd_timer) {    sd->sd_timer = NULL;  }  SU_DEBUG_7(("%s: timer destroyed.\n", __func__));  if (sd->sd_state != stun_tls_connecting)    return;  SU_DEBUG_7(("%s: connect() timeout.\n", __func__));  su_root_deregister(sh->sh_root, sd->sd_index);  sd->sd_index = -1; /* mark index as deregistered */    sd->sd_state = stun_tls_connection_timeout;  sd->sd_callback(sd->sd_magic, sh, sd, sd->sd_action, sd->sd_state);  return;}#endif /* HAVE_OPENSSL *//** Compose a STUN message of the format defined by stun_msg_t *  result encoded in enc_buf ready for sending as well. */int stun_make_sharedsecret_req(stun_msg_t *msg){  int i, len;   uint16_t tmp;  /* compose header */  msg->stun_hdr.msg_type = SHARED_SECRET_REQUEST;  msg->stun_hdr.msg_len = 0; /* actual len computed by				stun_send_message */  for (i = 0; i < STUN_TID_BYTES; i++) {    msg->stun_hdr.tran_id[i] = (1 + rand() % RAND_MAX_16);  }     /* no buffer assigned yet */  stun_init_buffer(&msg->enc_buf);    msg->enc_buf.data = malloc(20);  msg->enc_buf.size = 20;  tmp = htons(msg->stun_hdr.msg_type);  len = 0;    memcpy(msg->enc_buf.data, &tmp, sizeof(tmp));  len+=sizeof(tmp);  tmp = htons(msg->stun_hdr.msg_len);  memcpy(msg->enc_buf.data+len, &tmp, sizeof(tmp));  len+=sizeof(tmp);  memcpy(msg->enc_buf.data+len, msg->stun_hdr.tran_id, STUN_TID_BYTES);  len+=STUN_TID_BYTES;      return 0;}/* Return action of the request. If no request, return default value */su_inlinestun_action_t get_action(stun_request_t *req){  stun_discovery_t *sd = NULL;  /* XXX -- if no sr_handle something is leaking... */  if (!req || !req->sr_discovery || !req->sr_handle)    return stun_action_no_action;  sd = req->sr_discovery;  return sd->sd_action;}/* Find request from the request queue, based on TID */su_inlinestun_request_t *find_request(stun_handle_t *self, void *id){  void *match;  stun_request_t *req = NULL;  int len = STUN_TID_BYTES;  for (req = self->sh_requests; req; req = req->sr_next) {    match = req->sr_msg->stun_hdr.tran_id;    if (memcmp(match, id, len) == 0) {      return req;    }  }  return NULL;}/** Process socket event */static int stun_bind_callback(stun_magic_t *m, su_wait_t *w, su_wakeup_arg_t *arg){  stun_discovery_t *sd = arg;  stun_handle_t *self = sd->sd_handle;  int retval = -1, err = -1, dgram_len;  char addr[SU_ADDRSIZE];  stun_msg_t binding_response, *msg;  unsigned char dgram[512] = { 0 };  su_sockaddr_t recv;  socklen_t recv_len;  su_socket_t s = sd->sd_socket;  int events = su_wait_events(w, s);  enter;  SU_DEBUG_7(("%s(%p): events%s%s%s\n", __func__, (void *)self,	      events & SU_WAIT_IN ? " IN" : "",	      events & SU_WAIT_OUT ? " OUT" : "",	      events & SU_WAIT_ERR ? " ERR" : ""));  if (!(events & SU_WAIT_IN || events & SU_WAIT_OUT)) {    /* su_wait_destroy(w); */    /* su_root_deregister(self->sh_root, self->ss_root_index); */    /* self->sh_state = stun_bind_error; */    return 0;  }  /* receive response */  recv_len = sizeof(recv);  dgram_len = su_recvfrom(s, dgram, sizeof(dgram), 0, &recv, &recv_len);  err = errno;  if ((dgram_len < 0) && (err != EAGAIN)) {    /* su_wait_destroy(w); */    /* su_root_deregister(self->sh_root, self->ss_root_index); */    STUN_ERROR(err, recvfrom);    /* stun_free_message(binding_request); */    return err;  }  else if (dgram_len <= 0) {    STUN_ERROR(err, recvfrom);    /* No data available yet, wait for the event. */    return 0;  }  /* Message received. */  binding_response.enc_buf.data = (unsigned char *) malloc(dgram_len);  binding_response.enc_buf.size = dgram_len;  memcpy(binding_response.enc_buf.data, dgram, dgram_len);    SU_DEBUG_5(("%s: response from server %s:%u\n", __func__,	      su_inet_ntop(recv.su_family, SU_ADDR(&recv), addr, sizeof(addr)),	      ntohs(recv.su_port)));  debug_print(&binding_response.enc_buf);        /* Parse here the incoming message. */  if (stun_parse_message(&binding_response) < 0) {    stun_free_message(&binding_response);    SU_DEBUG_5(("%s: Error parsing response.\n", __func__));    return retval;  }  /* Based on the decoded payload, find the corresponding request   * (based on TID). */  do_action(self, &binding_response);  if (binding_response.enc_buf.size)    free(binding_response.enc_buf.data);  {    stun_attr_t **a, *b;    msg = &binding_response;    for (a = &msg->stun_attr; *a;) {            if ((*a)->pattr)	free((*a)->pattr);            if ((*a)->enc_buf.data)	free((*a)->enc_buf.data);            b = *a;      b = b->next;      free(*a);      *a = NULL;      *a = b;    }  }  return 0;}/** Choose the right state machine */static int do_action(stun_handle_t *sh, stun_msg_t *msg){  stun_request_t *req = NULL;  stun_action_t action = stun_action_no_action;  void *id;  enter;  if (!sh)    return errno = EFAULT, -1;  id = msg->stun_hdr.tran_id;  req = find_request(sh, id);  if (!req) {    SU_DEBUG_7(("warning: unable to find matching TID for response\n"));    return 0;  }  action = get_action(req);  /* Based on the action, use different state machines */  switch (action) {  case stun_action_binding_request:    action_bind(req, msg);    break;  case stun_action_test_nattype:    action_determine_nattype(req, msg);    break;  case stun_action_test_lifetime:    process_test_lifetime(req, msg);    break;  case stun_action_keepalive:    SU_DEBUG_3(("%s: Response to keepalive received.\n", __func__));    req->sr_state = stun_req_dispose_me;    break;  case stun_action_no_action:    SU_DEBUG_3(("%s: Unknown response. No matching request found.\n", __func__));    req->sr_state = stun_req_dispose_me;    break;  default:    SU_DEBUG_3(("%s: bad action.\n", __func__));    req->sr_state = stun_req_error;    req->sr_state = stun_req_dispose_me;    break;  }    return 0;}static int process_binding_request(stun_request_t *req, stun_msg_t *binding_response){  int retval = -1, clnt_addr_len;  stun_attr_t *mapped_addr, *chg_addr;  stun_handle_t *self = req->sr_handle;  su_localinfo_t *clnt_info = &req->sr_localinfo;  su_sockaddr_t *clnt_addr = clnt_info->li_addr;  stun_msg_t *binding_request;  stun_discovery_t *sd = req->sr_discovery;  enter;  binding_request = req->sr_msg;  switch (binding_response->stun_hdr.msg_type) {  case BINDING_RESPONSE:    if (stun_validate_message_integrity(binding_response, &self->sh_passwd) < 0) {      stun_free_message(binding_request);      stun_free_message(binding_response);      return retval;    }    memset(clnt_addr, 0, sizeof(su_sockaddr_t));    clnt_addr_len = sizeof(su_sockaddr_t);    mapped_addr = stun_get_attr(binding_response->stun_attr, MAPPED_ADDRESS);    if (mapped_addr != NULL) {      memcpy(clnt_addr, mapped_addr->pattr, clnt_addr_len);      retval = 0;    }    /* update alternative server address */    if (sd->sd_sec_addr->su_family == 0) {      /* alternative server address not present */      chg_addr = stun_get_attr(binding_response->stun_attr, CHANGED_ADDRESS);      if (chg_addr != NULL)	memcpy(sd->sd_sec_addr, chg_addr->pattr, sizeof(struct sockaddr_in));    }    break;      case BINDING_ERROR_RESPONSE:  default:    if (stun_process_error_response(binding_response) < 0) {      SU_DEBUG_3(("%s: Error in Binding Error Response.\n", __func__));    }    req->sr_state = stun_req_error;          break;  }  return retval;}static void stun_test_lifetime_timer_cb(su_root_magic_t *magic, 				       su_timer_t *t,				       su_timer_arg_t *arg){  stun_request_t *req = arg;  stun_discovery_t *sd = req->sr_discovery;  su_sockaddr_t *destination;  int err;  enter;  su_timer_destroy(t);  destination = (su_sockaddr_t *) sd->sd_pri_addr;  err = stun_send_binding_request(req, destination);  if (err < 0) {    stun_free_message(req->sr_msg);    return;  }  return;}static int process_test_lifetime(stun_request_t *req, stun_msg_t *binding_response){  stun_discovery_t *sd = req->sr_discovery;  stun_request_t *new;  stun_handle_t *sh = req->sr_handle;  su_localinfo_t *li;  su_sockaddr_t *sa;  su_timer_t *sockfdy_timer = NULL;  su_socket_t sockfdy = sd->sd_socket2;  int err;  stun_action_t action = get_action(req);  su_sockaddr_t *destination;  /* Even the first message could not be delivered */  if ((req->sr_state == stun_req_timeout) && (req->sr_from_y == -1)) {    SU_DEBUG_0(("%s: lifetime determination failed.\n", __func__));    sd->sd_state = stun_discovery_timeout;    req->sr_state = stun_req_dispose_me;    /* Use per discovery specific callback */    if (sd->sd_callback)      sd->sd_callback(sd->sd_magic, sh, sd, action, sd->sd_state);    return 0;  }  if (abs(sd->sd_lt_cur - sd->sd_lt) <= STUN_LIFETIME_CI) {    sd->sd_state = stun_discovery_done;    req->sr_state = stun_req_dispose_me;    /* Use per discovery specific callback */    if (sd->sd_callback)

⌨️ 快捷键说明

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