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

add websocket transport to sofia

上级 a70aa8f9
......@@ -234,6 +234,8 @@ struct nta_agent_s
unsigned sa_tport_tcp : 1; /**< Transports support TCP. */
unsigned sa_tport_sctp : 1; /**< Transports support SCTP. */
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_srv : 1; /**< Use SRV lookup */
......@@ -2045,22 +2047,24 @@ struct sipdns_tport {
char prefix[14]; /**< Prefix for SRV domains */
char service[10]; /**< NAPTR service */
}
#define SIPDNS_TRANSPORTS (4)
#define SIPDNS_TRANSPORTS (6)
const sipdns_tports[SIPDNS_TRANSPORTS] = {
{ "udp", "5060", "_sip._udp.", "SIP+D2U" },
{ "tcp", "5060", "_sip._tcp.", "SIP+D2T" },
{ "sctp", "5060", "_sip._sctp.", "SIP+D2S" },
{ "tls", "5061", "_sips._tcp.", "SIPS+D2T" },
{ "sctp", "5060", "_sip._sctp.", "SIP+D2S" },
{ "tls", "5061", "_sips._tcp.", "SIPS+D2T" },
{ "ws", "80", "_sips._ws.", "SIP+D2W" },
{ "wss", "443", "_sips._wss.", "SIPS+D2W" },
};
static char const * const tports_sip[] =
{
"udp", "tcp", "sctp", NULL
"udp", "tcp", "sctp", "ws", NULL
};
static char const * const tports_sips[] =
{
"tls", NULL
"tls", "ws", NULL
};
static tport_stack_class_t nta_agent_class[1] =
......@@ -2188,7 +2192,7 @@ int nta_agent_add_tport(nta_agent_t *self,
if (url->url_params) {
if (url_param(url->url_params, "transport", tp, sizeof(tp)) > 0) {
if (strchr(tp, ',')) {
int i; char *t, *tps[9];
int i; char *t, *tps[9] = {0};
/* Split tp into transports */
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)
self->sa_tport_tcp = 0;
self->sa_tport_sctp = 0;
self->sa_tport_tls = 0;
self->sa_tport_ws = 0;
self->sa_tport_wss = 0;
/* Set via fields for the tports */
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)
self->sa_tport_tcp = 1;
else if (su_casematch(tpn->tpn_proto, "sctp"))
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;
......@@ -2684,8 +2694,12 @@ nta_tpn_by_url(su_home_t *home,
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;
}
if (su_casematch(url->url_scheme, "sips"))
tpn->tpn_proto = "tls";
......
......@@ -44,7 +44,7 @@ if HAVE_STUN
USE_STUN_SRC = $(STUN_SRC)
endif
HTTP_SRC = tport_type_connect.c
HTTP_SRC = tport_type_connect.c tport_type_ws.c ws.c
if HAVE_NTH
USE_HTTP_SRC = $(HTTP_SRC)
endif
......
......@@ -202,7 +202,7 @@ int tport_is_registered(tport_t const *self)
/** Test if transport is stream. */
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. */
......@@ -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_tcp_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_udp_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_ws_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_threadpool_vtable;
......@@ -1359,6 +1361,8 @@ tport_vtable_t const *tport_vtables[TPORT_NUMBER_OF_TYPES + 1] =
{
#if HAVE_SOFIA_NTH
&tport_http_connect_vtable,
&tport_ws_client_vtable,
&tport_ws_vtable,
#endif
#if HAVE_TLS
&tport_tls_client_vtable,
......@@ -2426,6 +2430,13 @@ int getprotohints(su_addrinfo_t *hints,
proto = "tcp";
#endif
#if HAVE_SOFIA_NTH
if (su_casematch(proto, "ws"))
proto = "tcp";
if (su_casematch(proto, "wss"))
proto = "tcp";
#endif
#if HAVE_SCTP
if (su_casematch(proto, "sctp")) {
hints->ai_protocol = IPPROTO_SCTP;
......@@ -2869,7 +2880,7 @@ void tport_recv_event(tport_t *self)
}
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);
......
......@@ -161,6 +161,7 @@ struct tport_s {
unsigned tp_trunc:1;
unsigned tp_is_connected:1; /**< Connection is established */
unsigned tp_verified:1; /**< Certificate Chain was verified */
unsigned tp_pre_framed:1; /** Data is pre-framed **/
unsigned:0;
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);
int tport_next_keepalive(tport_t *self, su_time_t *, char const **);
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_client_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,
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, "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 */
/* 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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论