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

📄 tport_stub_stun.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
字号:
/* * This file is part of the Sofia-SIP package * * Copyright (C) 2006 Nokia Corporation. * * Contact: Pekka Pessi <pekka.pessi@nokia.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * *//**@CFILE tport_stub_stun.c Stub interface for STUN * * @author Pekka Pessi <Pekka.Pessi@nokia.com> * * @date Created: Fri Mar 31 12:31:36 EEST 2006 */#include "config.h"#include <sofia-sip/stun.h>#include <sofia-sip/su_tagarg.h>#define TPORT_STUN_SERVER_T stun_mini_t#include "tport_internal.h"#include "sofia-sip/msg_buffer.h"#include "sofia-sip/msg_addr.h"#include <assert.h>#include <string.h>/* ---------------------------------------------------------------------- *//* Plugin pointer */tport_stun_server_vtable_t const *tport_stun_server_vtable = NULL;statictport_stun_server_t *vst_create(su_root_t *root, tagi_t const *tags){  return stun_mini_create();}statictport_stun_server_vtable_t const stun_mini_vtable =   {    sizeof stun_mini_vtable,    vst_create,     stun_mini_destroy,    stun_mini_add_socket,     stun_mini_remove_socket,     stun_mini_request  };/** Initialize stun server */int tport_init_stun_server(tport_master_t *mr, tagi_t const *tags){  tport_stun_server_vtable_t const *vst = tport_stun_server_vtable;  if (vst == NULL)    /* Nobody has plugged better server in, use miniserver */    tport_stun_server_vtable = vst = &stun_mini_vtable;  if (!vst)    return 0;  if (mr->mr_params->tpp_stun_server)    mr->mr_stun_server = vst->vst_create(mr->mr_root, tags);  mr->mr_master->tp_has_stun_server = mr->mr_stun_server != NULL;  return 0;}/** Deinit stun server */void tport_deinit_stun_server(tport_master_t *mr){  tport_stun_server_vtable_t const *vst = tport_stun_server_vtable;  if (mr->mr_stun_server) {    assert(vst);    vst->vst_destroy(mr->mr_stun_server), mr->mr_stun_server = NULL;  }}int tport_stun_server_add_socket(tport_t *tp){  tport_stun_server_t *stun_server = tp->tp_master->mr_stun_server;  if (tport_stun_server_vtable &&       stun_server &&      tp->tp_params->tpp_stun_server) {    if (tport_stun_server_vtable->vst_add_socket(stun_server, 						 tp->tp_socket) == 0)      tp->tp_has_stun_server = 1;  }  return 0;}int tport_stun_server_remove_socket(tport_t *tp){  tport_stun_server_t *stun_server = tp->tp_master->mr_stun_server;  if (tport_stun_server_vtable &&      stun_server &&      tp->tp_has_stun_server) {    tport_stun_server_vtable->vst_remove_socket(stun_server, tp->tp_socket);    tp->tp_has_stun_server = 0;  }  return 0;}/**Process stun messagee. * * @retval -1 error * @retval 3  stun message received, ignore   */int tport_recv_stun_dgram(tport_t const *self,			  msg_t **in_out_msg,			  su_sockaddr_t *from,			  socklen_t fromlen){  int retval = -1;  msg_t *msg;  uint8_t *request;  size_t n;  assert(in_out_msg); assert(*in_out_msg);  msg = *in_out_msg;  request = msg_buf_committed_data(msg);  n = msg_buf_committed(msg);  if (n < 20 || request == NULL) {    su_seterrno(EBADMSG);    retval = -1;  }  else if (request[0] == 1) {    /* This is a response. */    if (self->tp_pri->pri_vtable->vtp_stun_response) {      if (self->tp_pri->pri_vtable->vtp_stun_response(self, request, n, 						      from, fromlen) < 0)	retval = -1;    }    else      SU_DEBUG_7(("tport(%p): recv_stun_dgram(): "		  "ignoring request with "MOD_ZU" bytes\n", (void *)self, n));  }  else if (request[0] == 0 && self->tp_master->mr_stun_server) {    tport_stun_server_vtable_t const *vst = tport_stun_server_vtable;    vst->vst_request(self->tp_master->mr_stun_server,		     self->tp_socket, request, n, 		     (void *)from, fromlen);  }  else if (request[0] == 0) {    /* Respond to stun request with a simple error message. */    int const status = 600;    char const *error = "Not Implemented";    size_t unpadded = strlen(error);    uint16_t elen;    uint8_t dgram[128];    if (unpadded > sizeof(dgram) - 28)      unpadded = sizeof(dgram) - 28;    elen = (uint16_t)unpadded;    elen = (elen + 3) & -4;	/* Round up to 4 */    SU_DEBUG_7(("tport(%p): recv_stun_dgram(): "		"responding %u %s\n", (void *)self, status, error));  /*     0                   1                   2                   3     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+    |      STUN Message Type        |         Message Length        |    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+    |    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                             Transaction ID    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                                                                    |    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+    */#define set16(b, offset, value)			\  (((b)[(offset) + 0] = ((value) >> 8) & 255),	\   ((b)[(offset) + 1] = (value) & 255))    /* Respond to request */    dgram[0] = 1; /* Mark as response */    dgram[1] = request[1] | 0x10; /* Mark as error response */    set16(dgram, 2, elen + 4 + 4);    /* TransactionID is there at bytes 4..19 */    memcpy(dgram + 4, request + 4, 16);    /*    TLV At 20:     0                   1                   2                   3     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+    |         Type                  |            Length             |    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+    */    set16(dgram, 20, 0x0009); /* ERROR-CODE */    set16(dgram, 22, elen + 4);    /*    ERROR-CODE at 24:     0                   1                   2                   3     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+    |                   0                     |Class|     Number    |    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+    |      Reason Phrase (variable)                                ..    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+     */    dgram[24] = 0, dgram[25] = 0;    dgram[26] = status / 100, dgram[27] = status % 100;    memcpy(dgram + 28, error, unpadded);    memset(dgram + 28 + unpadded, 0, elen - unpadded);    sendto(self->tp_socket, (void *)dgram, 28 + elen, 0,	   (void *)from, fromlen);#undef set16  }  else {    SU_DEBUG_0(("tport(%p): recv_stun_dgram(): internal error\n", (void *)self));    su_seterrno(EBADMSG);    retval = -1;  }  *in_out_msg = NULL, msg_destroy(msg);  return retval;}/** Activate (STUN) keepalive for transport */int tport_keepalive(tport_t *tp, su_addrinfo_t const *ai,		    tag_type_t tag, tag_value_t value, ...){  if (tp && tp->tp_pri && tp->tp_pri->pri_vtable->vtp_keepalive) {    int retval;    ta_list ta;    ta_start(ta, tag, value);    retval = tp->tp_pri->pri_vtable->vtp_keepalive(tp, ai, ta_args(ta));    ta_end(ta);    return retval;  }  return -1;}/* ---------------------------------------------------------------------- *//* Plugin interface *//** Plug in stun server. * * @note This function @b must be called before any transport is initialized. */int tport_plug_in_stun_server(tport_stun_server_vtable_t const *vtable){  if (!vtable)    return 0;  if (vtable->vst_size <= (int)sizeof *vtable)    return su_seterrno(EINVAL);  if (!vtable->vst_create ||       !vtable->vst_destroy ||      !vtable->vst_add_socket ||      !vtable->vst_remove_socket ||      !vtable->vst_request)    return su_seterrno(EFAULT);  if (tport_stun_server_vtable)    return su_seterrno(EEXIST);  tport_stun_server_vtable = vtable;  return 0;}

⌨️ 快捷键说明

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