mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-12 19:18:20 +00:00
make client able to connect ws server with ws://
This commit is contained in:
parent
4ae0833701
commit
b64a0ef4c6
|
@ -1501,10 +1501,15 @@ int net_udp_send(NETSOCKET sock, const NETADDR *addr, const void *data, int size
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONF_WEBSOCKETS)
|
#if defined(CONF_WEBSOCKETS)
|
||||||
if(addr->type&NETTYPE_WEBSOCKET_IPV4)
|
if(addr->type & NETTYPE_WEBSOCKET_IPV4)
|
||||||
{
|
{
|
||||||
if(sock.web_ipv4sock >= 0)
|
if(sock.web_ipv4sock >= 0)
|
||||||
d = websocket_send(sock.web_ipv4sock, (const unsigned char*)data, size, addr->port);
|
{
|
||||||
|
char addr_str[NETADDR_MAXSTRSIZE];
|
||||||
|
str_format(addr_str, sizeof(addr_str), "%d.%d.%d.%d", addr->ip[0], addr->ip[1], addr->ip[2], addr->ip[3]);
|
||||||
|
d = websocket_send(sock.web_ipv4sock, (const unsigned char *)data, size, addr_str, addr->port);
|
||||||
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
dbg_msg("net", "can't send websocket_ipv4 traffic to this socket");
|
dbg_msg("net", "can't send websocket_ipv4 traffic to this socket");
|
||||||
}
|
}
|
||||||
|
|
|
@ -708,6 +708,12 @@ void CClient::Connect(const char *pAddress, const char *pPassword)
|
||||||
|
|
||||||
str_format(aBuf, sizeof(aBuf), "connecting to '%s'", m_aServerAddressStr);
|
str_format(aBuf, sizeof(aBuf), "connecting to '%s'", m_aServerAddressStr);
|
||||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf);
|
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf);
|
||||||
|
bool is_websocket = false;
|
||||||
|
if(strncmp(m_aServerAddressStr, "ws://", 5) == 0)
|
||||||
|
{
|
||||||
|
is_websocket = true;
|
||||||
|
str_copy(m_aServerAddressStr, pAddress + 5, sizeof(m_aServerAddressStr));
|
||||||
|
}
|
||||||
|
|
||||||
ServerInfoRequest();
|
ServerInfoRequest();
|
||||||
if(net_host_lookup(m_aServerAddressStr, &m_ServerAddress, m_NetClient[CLIENT_MAIN].NetType()) != 0)
|
if(net_host_lookup(m_aServerAddressStr, &m_ServerAddress, m_NetClient[CLIENT_MAIN].NetType()) != 0)
|
||||||
|
@ -735,6 +741,10 @@ void CClient::Connect(const char *pAddress, const char *pPassword)
|
||||||
m_pConsole->DeregisterTempAll();
|
m_pConsole->DeregisterTempAll();
|
||||||
if(m_ServerAddress.port == 0)
|
if(m_ServerAddress.port == 0)
|
||||||
m_ServerAddress.port = Port;
|
m_ServerAddress.port = Port;
|
||||||
|
if(is_websocket)
|
||||||
|
{
|
||||||
|
m_ServerAddress.type = NETTYPE_WEBSOCKET_IPV4;
|
||||||
|
}
|
||||||
m_NetClient[CLIENT_MAIN].Connect(&m_ServerAddress);
|
m_NetClient[CLIENT_MAIN].Connect(&m_ServerAddress);
|
||||||
SetState(IClient::STATE_CONNECTING);
|
SetState(IClient::STATE_CONNECTING);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#if defined(CONF_WEBSOCKETS)
|
#if defined(CONF_WEBSOCKETS)
|
||||||
|
|
||||||
|
#include <map>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string>
|
||||||
|
|
||||||
#include "base/system.h"
|
#include "base/system.h"
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
|
@ -36,7 +37,7 @@ typedef struct
|
||||||
struct per_session_data
|
struct per_session_data
|
||||||
{
|
{
|
||||||
struct lws *wsi;
|
struct lws *wsi;
|
||||||
int port;
|
std::string addr_str;
|
||||||
sockaddr_in addr;
|
sockaddr_in addr;
|
||||||
TSendBuffer send_buffer;
|
TSendBuffer send_buffer;
|
||||||
};
|
};
|
||||||
|
@ -44,9 +45,8 @@ struct per_session_data
|
||||||
struct context_data
|
struct context_data
|
||||||
{
|
{
|
||||||
lws_context *context;
|
lws_context *context;
|
||||||
per_session_data *port_map[WS_CLIENTS];
|
std::map<std::string, per_session_data *> port_map;
|
||||||
TRecvBuffer recv_buffer;
|
TRecvBuffer recv_buffer;
|
||||||
int last_used_port;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int receive_chunk(context_data *ctx_data, struct per_session_data *pss,
|
static int receive_chunk(context_data *ctx_data, struct per_session_data *pss,
|
||||||
|
@ -69,58 +69,49 @@ static int websocket_callback(struct lws *wsi, enum lws_callback_reasons reason,
|
||||||
struct per_session_data *pss = (struct per_session_data *)user;
|
struct per_session_data *pss = (struct per_session_data *)user;
|
||||||
lws_context *context = lws_get_context(wsi);
|
lws_context *context = lws_get_context(wsi);
|
||||||
context_data *ctx_data = (context_data *)lws_context_user(context);
|
context_data *ctx_data = (context_data *)lws_context_user(context);
|
||||||
|
|
||||||
switch(reason)
|
switch(reason)
|
||||||
{
|
{
|
||||||
|
case LWS_CALLBACK_WSI_CREATE:
|
||||||
|
if(pss == NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* FALLTHRU */
|
||||||
case LWS_CALLBACK_ESTABLISHED:
|
case LWS_CALLBACK_ESTABLISHED:
|
||||||
{
|
{
|
||||||
int port = -1;
|
|
||||||
for(int i = 0; i < WS_CLIENTS; i++)
|
|
||||||
{
|
|
||||||
int j = (ctx_data->last_used_port + i + 1) % WS_CLIENTS;
|
|
||||||
if(ctx_data->port_map[j] == NULL)
|
|
||||||
{
|
|
||||||
port = j;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(port == -1)
|
|
||||||
{
|
|
||||||
dbg_msg("websockets", "no free ports, dropping");
|
|
||||||
pss->port = -1;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ctx_data->last_used_port = port;
|
|
||||||
pss->wsi = wsi;
|
pss->wsi = wsi;
|
||||||
int fd = lws_get_socket_fd(wsi);
|
int fd = lws_get_socket_fd(wsi);
|
||||||
socklen_t addr_size = sizeof(pss->addr);
|
socklen_t addr_size = sizeof(pss->addr);
|
||||||
getpeername(fd, (struct sockaddr *)&pss->addr, &addr_size);
|
getpeername(fd, (struct sockaddr *)&pss->addr, &addr_size);
|
||||||
int orig_port = ntohs(pss->addr.sin_port);
|
int orig_port = ntohs(pss->addr.sin_port);
|
||||||
pss->addr.sin_port = htons(port);
|
|
||||||
pss->send_buffer.Init();
|
pss->send_buffer.Init();
|
||||||
pss->port = port;
|
|
||||||
ctx_data->port_map[port] = pss;
|
|
||||||
char addr_str[NETADDR_MAXSTRSIZE];
|
char addr_str[NETADDR_MAXSTRSIZE];
|
||||||
inet_ntop(AF_INET, &pss->addr.sin_addr, addr_str, sizeof(addr_str));
|
inet_ntop(AF_INET, &pss->addr.sin_addr, addr_str, sizeof(addr_str));
|
||||||
dbg_msg("websockets",
|
dbg_msg("websockets",
|
||||||
"connection established with %s:%d , assigned fake port %d",
|
"connection established with %s:%d",
|
||||||
addr_str, orig_port, port);
|
addr_str, orig_port);
|
||||||
|
char buf[100];
|
||||||
|
snprintf(buf, sizeof(buf), "%s:%d", addr_str, orig_port);
|
||||||
|
pss->addr_str = std::string(buf);
|
||||||
|
ctx_data->port_map[pss->addr_str] = pss;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LWS_CALLBACK_CLOSED:
|
case LWS_CALLBACK_CLOSED:
|
||||||
{
|
{
|
||||||
dbg_msg("websockets", "connection with fake port %d closed", pss->port);
|
dbg_msg("websockets", "connection with addr string %s closed", pss->addr_str.c_str());
|
||||||
if(pss->port > -1)
|
if(!pss->addr_str.empty())
|
||||||
{
|
{
|
||||||
unsigned char close_packet[] = {0x10, 0x0e, 0x00, 0x04};
|
unsigned char close_packet[] = {0x10, 0x0e, 0x00, 0x04};
|
||||||
receive_chunk(ctx_data, pss, &close_packet, sizeof(close_packet));
|
receive_chunk(ctx_data, pss, &close_packet, sizeof(close_packet));
|
||||||
pss->wsi = 0;
|
pss->wsi = 0;
|
||||||
ctx_data->port_map[pss->port] = NULL;
|
ctx_data->port_map.erase(pss->addr_str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case LWS_CALLBACK_CLIENT_WRITEABLE:
|
||||||
|
/* FALLTHRU */
|
||||||
case LWS_CALLBACK_SERVER_WRITEABLE:
|
case LWS_CALLBACK_SERVER_WRITEABLE:
|
||||||
{
|
{
|
||||||
websocket_chunk *chunk = (websocket_chunk *)pss->send_buffer.First();
|
websocket_chunk *chunk = (websocket_chunk *)pss->send_buffer.First();
|
||||||
|
@ -143,8 +134,10 @@ static int websocket_callback(struct lws *wsi, enum lws_callback_reasons reason,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case LWS_CALLBACK_CLIENT_RECEIVE:
|
||||||
|
/* FALLTHRU */
|
||||||
case LWS_CALLBACK_RECEIVE:
|
case LWS_CALLBACK_RECEIVE:
|
||||||
if(pss->port == -1)
|
if(pss->addr_str.empty())
|
||||||
return -1;
|
return -1;
|
||||||
if(receive_chunk(ctx_data, pss, in, len))
|
if(receive_chunk(ctx_data, pss, in, len))
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -200,9 +193,7 @@ int websocket_create(const char *addr, int port)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memset(ctx_data->port_map, 0, sizeof(ctx_data->port_map));
|
|
||||||
ctx_data->recv_buffer.Init();
|
ctx_data->recv_buffer.Init();
|
||||||
ctx_data->last_used_port = 0;
|
|
||||||
return first_free;
|
return first_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,15 +238,37 @@ int websocket_recv(int socket, unsigned char *data, size_t maxsize,
|
||||||
}
|
}
|
||||||
|
|
||||||
int websocket_send(int socket, const unsigned char *data, size_t size,
|
int websocket_send(int socket, const unsigned char *data, size_t size,
|
||||||
int port)
|
const char *addr_str, int port)
|
||||||
{
|
{
|
||||||
lws_context *context = contexts[socket].context;
|
lws_context *context = contexts[socket].context;
|
||||||
if(context == NULL)
|
if(context == NULL)
|
||||||
|
{
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
context_data *ctx_data = (context_data *)lws_context_user(context);
|
context_data *ctx_data = (context_data *)lws_context_user(context);
|
||||||
struct per_session_data *pss = ctx_data->port_map[port];
|
char buf[100];
|
||||||
|
snprintf(buf, sizeof(buf), "%s:%d", addr_str, port);
|
||||||
|
std::string addr_str_with_port = std::string(buf);
|
||||||
|
struct per_session_data *pss = ctx_data->port_map[addr_str_with_port];
|
||||||
if(pss == NULL)
|
if(pss == NULL)
|
||||||
return -1;
|
{
|
||||||
|
struct lws_client_connect_info ccinfo = {0};
|
||||||
|
ccinfo.context = context;
|
||||||
|
ccinfo.address = addr_str;
|
||||||
|
ccinfo.port = port;
|
||||||
|
ccinfo.protocol = protocols[0].name;
|
||||||
|
lws *wsi = lws_client_connect_via_info(&ccinfo);
|
||||||
|
if(wsi == NULL)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
lws_service(context, -1);
|
||||||
|
pss = ctx_data->port_map[addr_str_with_port];
|
||||||
|
if(pss == NULL)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
websocket_chunk *chunk = (websocket_chunk *)pss->send_buffer.Allocate(
|
websocket_chunk *chunk = (websocket_chunk *)pss->send_buffer.Allocate(
|
||||||
size + sizeof(websocket_chunk) + LWS_SEND_BUFFER_PRE_PADDING +
|
size + sizeof(websocket_chunk) + LWS_SEND_BUFFER_PRE_PADDING +
|
||||||
LWS_SEND_BUFFER_POST_PADDING);
|
LWS_SEND_BUFFER_POST_PADDING);
|
||||||
|
@ -266,6 +279,7 @@ int websocket_send(int socket, const unsigned char *data, size_t size,
|
||||||
memcpy(&chunk->addr, &pss->addr, sizeof(sockaddr_in));
|
memcpy(&chunk->addr, &pss->addr, sizeof(sockaddr_in));
|
||||||
memcpy(&chunk->data[LWS_SEND_BUFFER_PRE_PADDING], data, size);
|
memcpy(&chunk->data[LWS_SEND_BUFFER_PRE_PADDING], data, size);
|
||||||
lws_callback_on_writable(pss->wsi);
|
lws_callback_on_writable(pss->wsi);
|
||||||
|
lws_service(context, -1);
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,12 +290,11 @@ int websocket_fd_set(int socket, fd_set *set)
|
||||||
return -1;
|
return -1;
|
||||||
context_data *ctx_data = (context_data *)lws_context_user(context);
|
context_data *ctx_data = (context_data *)lws_context_user(context);
|
||||||
int max = 0;
|
int max = 0;
|
||||||
for(int i = 0; i < WS_CLIENTS; i++)
|
for(auto const &x : ctx_data->port_map)
|
||||||
{
|
{
|
||||||
per_session_data *pss = ctx_data->port_map[i];
|
if(x.second == NULL)
|
||||||
if(pss == NULL)
|
|
||||||
continue;
|
continue;
|
||||||
int fd = lws_get_socket_fd(pss->wsi);
|
int fd = lws_get_socket_fd(x.second->wsi);
|
||||||
if(fd > max)
|
if(fd > max)
|
||||||
max = fd;
|
max = fd;
|
||||||
FD_SET(fd, set);
|
FD_SET(fd, set);
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define ENGINE_SHARED_WEBSOCKETS_H
|
#define ENGINE_SHARED_WEBSOCKETS_H
|
||||||
|
|
||||||
#if !defined(CONF_FAMILY_UNIX)
|
#if !defined(CONF_FAMILY_UNIX)
|
||||||
#error websockets only work on unix, sorry
|
#error websockets only work on unix, sorry
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
@ -10,7 +10,8 @@
|
||||||
int websocket_create(const char *addr, int port);
|
int websocket_create(const char *addr, int port);
|
||||||
int websocket_destroy(int socket);
|
int websocket_destroy(int socket);
|
||||||
int websocket_recv(int socket, unsigned char *data, size_t maxsize, struct sockaddr_in *sockaddrbuf, size_t fromLen);
|
int websocket_recv(int socket, unsigned char *data, size_t maxsize, struct sockaddr_in *sockaddrbuf, size_t fromLen);
|
||||||
int websocket_send(int socket, const unsigned char *data, size_t size, int port);
|
int websocket_send(int socket, const unsigned char *data, size_t size,
|
||||||
|
const char *addr_str, int port);
|
||||||
int websocket_fd_set(int socket, fd_set *set);
|
int websocket_fd_set(int socket, fd_set *set);
|
||||||
|
|
||||||
#endif // ENGINE_SHARED_WEBSOCKETS_H
|
#endif // ENGINE_SHARED_WEBSOCKETS_H
|
||||||
|
|
Loading…
Reference in a new issue