提交 62e62e1e authored 作者: Anthony Minessale's avatar Anthony Minessale

add websocket transport to sofia

上级 a70aa8f9
...@@ -234,6 +234,8 @@ struct nta_agent_s ...@@ -234,6 +234,8 @@ struct nta_agent_s
unsigned sa_tport_tcp : 1; /**< Transports support TCP. */ unsigned sa_tport_tcp : 1; /**< Transports support TCP. */
unsigned sa_tport_sctp : 1; /**< Transports support SCTP. */ unsigned sa_tport_sctp : 1; /**< Transports support SCTP. */
unsigned sa_tport_tls : 1; /**< Transports support TLS. */ unsigned sa_tport_tls : 1; /**< Transports support TLS. */
unsigned sa_tport_ws : 1; /**< Transports support WS. */
unsigned sa_tport_wss : 1; /**< Transports support WSS. */
unsigned sa_use_naptr : 1; /**< Use NAPTR lookup */ unsigned sa_use_naptr : 1; /**< Use NAPTR lookup */
unsigned sa_use_srv : 1; /**< Use SRV lookup */ unsigned sa_use_srv : 1; /**< Use SRV lookup */
...@@ -2045,22 +2047,24 @@ struct sipdns_tport { ...@@ -2045,22 +2047,24 @@ struct sipdns_tport {
char prefix[14]; /**< Prefix for SRV domains */ char prefix[14]; /**< Prefix for SRV domains */
char service[10]; /**< NAPTR service */ char service[10]; /**< NAPTR service */
} }
#define SIPDNS_TRANSPORTS (4) #define SIPDNS_TRANSPORTS (6)
const sipdns_tports[SIPDNS_TRANSPORTS] = { const sipdns_tports[SIPDNS_TRANSPORTS] = {
{ "udp", "5060", "_sip._udp.", "SIP+D2U" }, { "udp", "5060", "_sip._udp.", "SIP+D2U" },
{ "tcp", "5060", "_sip._tcp.", "SIP+D2T" }, { "tcp", "5060", "_sip._tcp.", "SIP+D2T" },
{ "sctp", "5060", "_sip._sctp.", "SIP+D2S" }, { "sctp", "5060", "_sip._sctp.", "SIP+D2S" },
{ "tls", "5061", "_sips._tcp.", "SIPS+D2T" }, { "tls", "5061", "_sips._tcp.", "SIPS+D2T" },
{ "ws", "80", "_sips._ws.", "SIP+D2W" },
{ "wss", "443", "_sips._wss.", "SIPS+D2W" },
}; };
static char const * const tports_sip[] = static char const * const tports_sip[] =
{ {
"udp", "tcp", "sctp", NULL "udp", "tcp", "sctp", "ws", NULL
}; };
static char const * const tports_sips[] = static char const * const tports_sips[] =
{ {
"tls", NULL "tls", "ws", NULL
}; };
static tport_stack_class_t nta_agent_class[1] = static tport_stack_class_t nta_agent_class[1] =
...@@ -2188,7 +2192,7 @@ int nta_agent_add_tport(nta_agent_t *self, ...@@ -2188,7 +2192,7 @@ int nta_agent_add_tport(nta_agent_t *self,
if (url->url_params) { if (url->url_params) {
if (url_param(url->url_params, "transport", tp, sizeof(tp)) > 0) { if (url_param(url->url_params, "transport", tp, sizeof(tp)) > 0) {
if (strchr(tp, ',')) { if (strchr(tp, ',')) {
int i; char *t, *tps[9]; int i; char *t, *tps[9] = {0};
/* Split tp into transports */ /* Split tp into transports */
for (i = 0, t = tp; t && i < 8; i++) { for (i = 0, t = tp; t && i < 8; i++) {
...@@ -2311,6 +2315,8 @@ int agent_init_via(nta_agent_t *self, tport_t *primaries, int use_maddr) ...@@ -2311,6 +2315,8 @@ int agent_init_via(nta_agent_t *self, tport_t *primaries, int use_maddr)
self->sa_tport_tcp = 0; self->sa_tport_tcp = 0;
self->sa_tport_sctp = 0; self->sa_tport_sctp = 0;
self->sa_tport_tls = 0; self->sa_tport_tls = 0;
self->sa_tport_ws = 0;
self->sa_tport_wss = 0;
/* Set via fields for the tports */ /* Set via fields for the tports */
for (tp = primaries; tp; tp = tport_next(tp)) { for (tp = primaries; tp; tp = tport_next(tp)) {
...@@ -2343,6 +2349,10 @@ int agent_init_via(nta_agent_t *self, tport_t *primaries, int use_maddr) ...@@ -2343,6 +2349,10 @@ int agent_init_via(nta_agent_t *self, tport_t *primaries, int use_maddr)
self->sa_tport_tcp = 1; self->sa_tport_tcp = 1;
else if (su_casematch(tpn->tpn_proto, "sctp")) else if (su_casematch(tpn->tpn_proto, "sctp"))
self->sa_tport_sctp = 1; self->sa_tport_sctp = 1;
else if (su_casematch(tpn->tpn_proto, "ws"))
self->sa_tport_ws = 1;
else if (su_casematch(tpn->tpn_proto, "wss"))
self->sa_tport_wss = 1;
if (tport_has_tls(tp)) self->sa_tport_tls = 1; if (tport_has_tls(tp)) self->sa_tport_tls = 1;
...@@ -2684,8 +2694,12 @@ nta_tpn_by_url(su_home_t *home, ...@@ -2684,8 +2694,12 @@ nta_tpn_by_url(su_home_t *home,
tpn->tpn_ident = NULL; tpn->tpn_ident = NULL;
if (tpn->tpn_proto) if (tpn->tpn_proto) {
if (su_casematch(url->url_scheme, "sips") && su_casematch(tpn->tpn_proto, "ws")) {
tpn->tpn_proto = "wss";
}
return 1; return 1;
}
if (su_casematch(url->url_scheme, "sips")) if (su_casematch(url->url_scheme, "sips"))
tpn->tpn_proto = "tls"; tpn->tpn_proto = "tls";
......
...@@ -44,7 +44,7 @@ if HAVE_STUN ...@@ -44,7 +44,7 @@ if HAVE_STUN
USE_STUN_SRC = $(STUN_SRC) USE_STUN_SRC = $(STUN_SRC)
endif endif
HTTP_SRC = tport_type_connect.c HTTP_SRC = tport_type_connect.c tport_type_ws.c ws.c
if HAVE_NTH if HAVE_NTH
USE_HTTP_SRC = $(HTTP_SRC) USE_HTTP_SRC = $(HTTP_SRC)
endif endif
......
...@@ -202,7 +202,7 @@ int tport_is_registered(tport_t const *self) ...@@ -202,7 +202,7 @@ int tport_is_registered(tport_t const *self)
/** Test if transport is stream. */ /** Test if transport is stream. */
int tport_is_stream(tport_t const *self) int tport_is_stream(tport_t const *self)
{ {
return self && self->tp_addrinfo->ai_socktype == SOCK_STREAM; return self && !self->tp_pre_framed && self->tp_addrinfo->ai_socktype == SOCK_STREAM;
} }
/** Test if transport is dgram. */ /** Test if transport is dgram. */
...@@ -1345,10 +1345,12 @@ int tport_set_params(tport_t *self, ...@@ -1345,10 +1345,12 @@ int tport_set_params(tport_t *self,
extern tport_vtable_t const tport_udp_vtable; extern tport_vtable_t const tport_udp_vtable;
extern tport_vtable_t const tport_tcp_vtable; extern tport_vtable_t const tport_tcp_vtable;
extern tport_vtable_t const tport_tls_vtable; extern tport_vtable_t const tport_tls_vtable;
extern tport_vtable_t const tport_ws_vtable;
extern tport_vtable_t const tport_sctp_vtable; extern tport_vtable_t const tport_sctp_vtable;
extern tport_vtable_t const tport_udp_client_vtable; extern tport_vtable_t const tport_udp_client_vtable;
extern tport_vtable_t const tport_tcp_client_vtable; extern tport_vtable_t const tport_tcp_client_vtable;
extern tport_vtable_t const tport_sctp_client_vtable; extern tport_vtable_t const tport_sctp_client_vtable;
extern tport_vtable_t const tport_ws_client_vtable;
extern tport_vtable_t const tport_tls_client_vtable; extern tport_vtable_t const tport_tls_client_vtable;
extern tport_vtable_t const tport_http_connect_vtable; extern tport_vtable_t const tport_http_connect_vtable;
extern tport_vtable_t const tport_threadpool_vtable; extern tport_vtable_t const tport_threadpool_vtable;
...@@ -1359,6 +1361,8 @@ tport_vtable_t const *tport_vtables[TPORT_NUMBER_OF_TYPES + 1] = ...@@ -1359,6 +1361,8 @@ tport_vtable_t const *tport_vtables[TPORT_NUMBER_OF_TYPES + 1] =
{ {
#if HAVE_SOFIA_NTH #if HAVE_SOFIA_NTH
&tport_http_connect_vtable, &tport_http_connect_vtable,
&tport_ws_client_vtable,
&tport_ws_vtable,
#endif #endif
#if HAVE_TLS #if HAVE_TLS
&tport_tls_client_vtable, &tport_tls_client_vtable,
...@@ -2426,6 +2430,13 @@ int getprotohints(su_addrinfo_t *hints, ...@@ -2426,6 +2430,13 @@ int getprotohints(su_addrinfo_t *hints,
proto = "tcp"; proto = "tcp";
#endif #endif
#if HAVE_SOFIA_NTH
if (su_casematch(proto, "ws"))
proto = "tcp";
if (su_casematch(proto, "wss"))
proto = "tcp";
#endif
#if HAVE_SCTP #if HAVE_SCTP
if (su_casematch(proto, "sctp")) { if (su_casematch(proto, "sctp")) {
hints->ai_protocol = IPPROTO_SCTP; hints->ai_protocol = IPPROTO_SCTP;
...@@ -2869,7 +2880,7 @@ void tport_recv_event(tport_t *self) ...@@ -2869,7 +2880,7 @@ void tport_recv_event(tport_t *self)
} }
if (again >= 0) if (again >= 0)
tport_parse(self, !again, self->tp_rtime); tport_parse(self, self->tp_pre_framed ? 1 : !again, self->tp_rtime);
} }
while (again > 1); while (again > 1);
......
...@@ -161,6 +161,7 @@ struct tport_s { ...@@ -161,6 +161,7 @@ struct tport_s {
unsigned tp_trunc:1; unsigned tp_trunc:1;
unsigned tp_is_connected:1; /**< Connection is established */ unsigned tp_is_connected:1; /**< Connection is established */
unsigned tp_verified:1; /**< Certificate Chain was verified */ unsigned tp_verified:1; /**< Certificate Chain was verified */
unsigned tp_pre_framed:1; /** Data is pre-framed **/
unsigned:0; unsigned:0;
tport_t *tp_left, *tp_right, *tp_dad; /**< Links in tport tree */ tport_t *tp_left, *tp_right, *tp_dad; /**< Links in tport tree */
...@@ -527,6 +528,10 @@ void tport_recv_timeout_timer(tport_t *self, su_time_t now); ...@@ -527,6 +528,10 @@ void tport_recv_timeout_timer(tport_t *self, su_time_t now);
int tport_next_keepalive(tport_t *self, su_time_t *, char const **); int tport_next_keepalive(tport_t *self, su_time_t *, char const **);
void tport_keepalive_timer(tport_t *self, su_time_t now); void tport_keepalive_timer(tport_t *self, su_time_t now);
extern tport_vtable_t const tport_ws_vtable;
extern tport_vtable_t const tport_ws_client_vtable;
extern tport_vtable_t const tport_wss_vtable;
extern tport_vtable_t const tport_wss_client_vtable;
extern tport_vtable_t const tport_sctp_vtable; extern tport_vtable_t const tport_sctp_vtable;
extern tport_vtable_t const tport_sctp_client_vtable; extern tport_vtable_t const tport_sctp_client_vtable;
extern tport_vtable_t const tport_tls_vtable; extern tport_vtable_t const tport_tls_vtable;
......
...@@ -382,6 +382,8 @@ void tport_capt_msg(tport_t const *self, msg_t *msg, size_t n, ...@@ -382,6 +382,8 @@ void tport_capt_msg(tport_t const *self, msg_t *msg, size_t n,
if(strcmp(self->tp_name->tpn_proto, "tcp") == 0) hep_header.hp_p = IPPROTO_TCP; if(strcmp(self->tp_name->tpn_proto, "tcp") == 0) hep_header.hp_p = IPPROTO_TCP;
else if(strcmp(self->tp_name->tpn_proto, "tls") == 0) hep_header.hp_p = IPPROTO_IDP; /* FAKE*/ else if(strcmp(self->tp_name->tpn_proto, "tls") == 0) hep_header.hp_p = IPPROTO_IDP; /* FAKE*/
else if(strcmp(self->tp_name->tpn_proto, "sctp") == 0) hep_header.hp_p = IPPROTO_SCTP; else if(strcmp(self->tp_name->tpn_proto, "sctp") == 0) hep_header.hp_p = IPPROTO_SCTP;
else if(strcmp(self->tp_name->tpn_proto, "ws") == 0) hep_header.hp_p = IPPROTO_TCP;
else if(strcmp(self->tp_name->tpn_proto, "wss") == 0) hep_header.hp_p = IPPROTO_TCP;
else hep_header.hp_p = IPPROTO_UDP; /* DEFAULT UDP */ else hep_header.hp_p = IPPROTO_UDP; /* DEFAULT UDP */
/* Check destination */ /* Check destination */
......
/*
* This file is part of the Sofia-SIP package
*
* Copyright (C) 2005 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
*
*/
#ifndef TPORT_WS_H
/** Defined when <tport_ws.h> has been included. */
#define TPORT_WS_H
/**@internal
* @file tport_ws.h
* @brief Internal WS interface
*
* @author Mike Jerris <mike@jerris.com>
*
* Copyright 2013 Michael Jerris. All rights reserved.
*
*/
#ifndef SU_TYPES_H
#include <sofia-sip/su_types.h>
#endif
#include "tport_internal.h"
#include "ws.h"
SOFIA_BEGIN_DECLS
typedef enum {
TPORT_WS_OPCODE_CONTINUATION = 0x0,
TPORT_WS_OPCODE_TEXT = 0x1,
TPORT_WS_OPCODE_BINARY = 0x2,
TPORT_WS_OPCODE_CLOSE = 0x8,
TPORT_WS_OPCODE_PING = 0x9,
TPORT_WS_OPCODE_PONG = 0xA
} tport_ws_opcode_t;
typedef struct tport_ws_s {
tport_t wstp_tp[1];
wsh_t ws[1];
char *wstp_buffer;
unsigned ws_initialized:1;
unsigned ws_secure:1;
unsigned:0;
} tport_ws_t;
int tport_recv_stream_ws(tport_t *self);
ssize_t tport_send_stream_ws(tport_t const *self, msg_t *msg,
msg_iovec_t iov[], size_t iovused);
int tport_ws_ping(tport_t *self, su_time_t now);
int tport_ws_pong(tport_t *self);
int tport_ws_init_primary(tport_primary_t *,
tp_name_t tpn[1],
su_addrinfo_t *, tagi_t const *,
char const **return_culprit);
int tport_ws_init_client(tport_primary_t *,
tp_name_t tpn[1],
su_addrinfo_t *, tagi_t const *,
char const **return_culprit);
int tport_ws_init_secondary(tport_t *self, int socket, int accepted,
char const **return_reason);
int tport_ws_next_timer(tport_t *self, su_time_t *, char const **);
void tport_ws_timer(tport_t *self, su_time_t);
SOFIA_END_DECLS
#endif
差异被折叠。
#ifndef _WS_H
#define _WS_H
#define MAXLEN 0x10000
#define WEBSOCKET_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
#define B64BUFFLEN 1024
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <string.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <assert.h>
#include <errno.h>
//#include "sha1.h"
#include <openssl/ssl.h>
struct globals_s {
const SSL_METHOD *ssl_method;
SSL_CTX *ssl_ctx;
char cert[512];
char key[512];
};
extern struct globals_s globals;
typedef int ws_socket_t;
#define ws_sock_invalid -1
typedef enum {
WS_NONE = 0,
WS_NORMAL = 1000,
WS_PROTO_ERR = 1002,
WS_DATA_TOO_BIG = 1009
} ws_cause_t;
typedef enum {
WSOC_CONTINUATION = 0x0,
WSOC_TEXT = 0x1,
WSOC_BINARY = 0x2,
WSOC_CLOSE = 0x8,
WSOC_PING = 0x9,
WSOC_PONG = 0xA
} ws_opcode_t;
typedef struct wsh_s {
ws_socket_t sock;
char *buffer;
size_t buflen;
ssize_t datalen;
char *payload;
ssize_t plen;
ssize_t rplen;
SSL *ssl;
int handshake;
uint8_t down;
int secure;
} wsh_t;
ssize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes);
ssize_t ws_raw_write(wsh_t *wsh, void *data, size_t bytes);
ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data);
ssize_t ws_write_frame(wsh_t *wsh, ws_opcode_t oc, void *data, size_t bytes);
int ws_init(wsh_t *wsh, ws_socket_t sock, size_t buflen, int secure);
ssize_t ws_close(wsh_t *wsh, int16_t reason);
void init_ssl(void);
void deinit_ssl(void);
static inline uint64_t get_unaligned_uint64(const void *p)
{
const struct { uint64_t d; } __attribute__((packed)) *pp = p;
return pp->d;
}
#endif
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论