Skip to content

Commit

Permalink
fixes nanomsg#467 "utils/int.h" referenced by ws.h, but not installed
Browse files Browse the repository at this point in the history
fixes nanomsg#488 websocket test cases needed
  • Loading branch information
gdamore committed Oct 23, 2015
1 parent 7555f49 commit cd814f4
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 128 deletions.
9 changes: 8 additions & 1 deletion src/transports/ws/aws.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*
Copyright (c) 2012-2013 250bpm s.r.o. All rights reserved.
Copyright (c) 2014 Wirebird Labs LLC. All rights reserved.
Copyright 2015 Garrett D'Amore <garrett@damore.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"),
Expand All @@ -26,6 +27,7 @@
#include "../../utils/err.h"
#include "../../utils/cont.h"
#include "../../utils/attr.h"
#include "../../ws.h"

#define NN_AWS_STATE_IDLE 1
#define NN_AWS_STATE_ACCEPTING 2
Expand Down Expand Up @@ -144,6 +146,7 @@ static void nn_aws_handler (struct nn_fsm *self, int src, int type,
struct nn_aws *aws;
int val;
size_t sz;
uint8_t msg_type;

aws = nn_cont (self, struct nn_aws, fsm);

Expand Down Expand Up @@ -195,6 +198,10 @@ static void nn_aws_handler (struct nn_fsm *self, int src, int type,
nn_assert (sz == sizeof (val));
nn_usock_setsockopt (&aws->usock, SOL_SOCKET, SO_RCVBUF,
&val, sizeof (val));
sz = sizeof (val);
nn_epbase_getopt (aws->epbase, NN_WS, NN_WS_MSG_TYPE,
&val, &sz);
msg_type = (uint8_t)val;

/* Since the WebSocket handshake must poll, the receive
timeout is set to zero. Later, it will be set again
Expand All @@ -214,7 +221,7 @@ static void nn_aws_handler (struct nn_fsm *self, int src, int type,
/* Start the sws state machine. */
nn_usock_activate (&aws->usock);
nn_sws_start (&aws->sws, &aws->usock, NN_WS_SERVER,
NULL, NULL);
NULL, NULL, msg_type);
aws->state = NN_AWS_STATE_ACTIVE;

nn_epbase_stat_increment (aws->epbase,
Expand Down
11 changes: 10 additions & 1 deletion src/transports/ws/cws.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*
Copyright (c) 2012-2013 250bpm s.r.o. All rights reserved.
Copyright (c) 2014 Wirebird Labs LLC. All rights reserved.
Copyright 2015 Garrett D'Amore <garrett@damore.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"),
Expand Down Expand Up @@ -234,6 +235,7 @@ int nn_cws_create (void *hint, struct nn_epbase **epbase)
nn_epbase_getctx (&self->epbase));
self->state = NN_CWS_STATE_IDLE;
nn_usock_init (&self->usock, NN_CWS_SRC_USOCK, &self->fsm);

sz = sizeof (reconnect_ivl);
nn_epbase_getopt (&self->epbase, NN_SOL_SOCKET, NN_RECONNECT_IVL,
&reconnect_ivl, &sz);
Expand All @@ -246,6 +248,7 @@ int nn_cws_create (void *hint, struct nn_epbase **epbase)
reconnect_ivl_max = reconnect_ivl;
nn_backoff_init (&self->retry, NN_CWS_SRC_RECONNECT_TIMER,
reconnect_ivl, reconnect_ivl_max, &self->fsm);

nn_sws_init (&self->sws, NN_CWS_SRC_SWS, &self->epbase, &self->fsm);
nn_dns_init (&self->dns, NN_CWS_SRC_DNS, &self->fsm);

Expand Down Expand Up @@ -327,6 +330,8 @@ static void nn_cws_handler (struct nn_fsm *self, int src, int type,
NN_UNUSED void *srcptr)
{
struct nn_cws *cws;
int msg_type;
size_t sz;

cws = nn_cont (self, struct nn_cws, fsm);

Expand Down Expand Up @@ -409,9 +414,13 @@ static void nn_cws_handler (struct nn_fsm *self, int src, int type,
case NN_CWS_SRC_USOCK:
switch (type) {
case NN_USOCK_CONNECTED:
sz = sizeof (msg_type);
nn_epbase_getopt (&cws->epbase, NN_WS, NN_WS_MSG_TYPE,
&msg_type, &sz);
nn_assert(sz == sizeof (msg_type));
nn_sws_start (&cws->sws, &cws->usock, NN_WS_CLIENT,
nn_chunkref_data (&cws->resource),
nn_chunkref_data (&cws->remote_host));
nn_chunkref_data (&cws->remote_host), (uint8_t)msg_type);
cws->state = NN_CWS_STATE_ACTIVE;
cws->peer_gone = 0;
nn_epbase_stat_increment (&cws->epbase,
Expand Down
28 changes: 19 additions & 9 deletions src/transports/ws/sws.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*
Copyright (c) 2013 250bpm s.r.o. All rights reserved.
Copyright (c) 2014 Wirebird Labs LLC. All rights reserved.
Copyright 2015 Garrett D'Amore <garrett@damore.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"),
Expand Down Expand Up @@ -70,14 +71,17 @@
#define NN_WS_OPCODE_UNUSED5 0x05
#define NN_WS_OPCODE_UNUSED6 0x06
#define NN_WS_OPCODE_UNUSED7 0x07
#define NN_WS_OPCODE_CLOSE NN_WS_MSG_TYPE_CLOSE
#define NN_WS_OPCODE_PING NN_WS_MSG_TYPE_PING
#define NN_WS_OPCODE_PONG NN_WS_MSG_TYPE_PONG
#define NN_WS_OPCODE_CLOSE 0x08
#define NN_WS_OPCODE_PING 0x09
#define NN_WS_OPCODE_PONG 0x0A
#define NN_WS_OPCODE_UNUSEDB 0x0B
#define NN_WS_OPCODE_UNUSEDC 0x0C
#define NN_WS_OPCODE_UNUSEDD 0x0D
#define NN_WS_OPCODE_UNUSEDE 0x0E
#define NN_WS_OPCODE_UNUSEDF 0x0F
/* Private use for nanomsg - indicates failed connect. */
#define NN_WS_OPCODE_GONE 0x7F


/* WebSocket protocol header bit masks as per RFC 6455. */
#define NN_SWS_FRAME_BITMASK_MASKED 0x80
Expand Down Expand Up @@ -133,6 +137,7 @@ void nn_sws_init (struct nn_sws *self, int src,
nn_fsm_init (&self->fsm, nn_sws_handler, nn_sws_shutdown,
src, self, owner);
self->state = NN_SWS_STATE_IDLE;
self->epbase = epbase;
nn_ws_handshake_init (&self->handshaker,
NN_SWS_SRC_HANDSHAKE, &self->fsm);
self->usock = NULL;
Expand Down Expand Up @@ -176,7 +181,7 @@ int nn_sws_isidle (struct nn_sws *self)
}

void nn_sws_start (struct nn_sws *self, struct nn_usock *usock, int mode,
const char *resource, const char *host)
const char *resource, const char *host, uint8_t msg_type)
{
/* Take ownership of the underlying socket. */
nn_assert (self->usock == NULL && self->usock_owner.fsm == NULL);
Expand All @@ -188,6 +193,8 @@ void nn_sws_start (struct nn_sws *self, struct nn_usock *usock, int mode,
self->resource = resource;
self->remote_host = host;

self->msg_type = msg_type;

/* Launch the state machine. */
nn_fsm_start (&self->fsm);
}
Expand Down Expand Up @@ -391,17 +398,17 @@ static int nn_sws_send (struct nn_pipebase *self, struct nn_msg *msg)
msghdr.msg_control = nn_chunkref_data (&sws->outmsg.hdrs);
cmsg = NN_CMSG_FIRSTHDR (&msghdr);
while (cmsg) {
if (cmsg->cmsg_level == NN_WS && cmsg->cmsg_type == NN_WS_HDR_OPCODE)
if (cmsg->cmsg_level == NN_WS && cmsg->cmsg_type == NN_WS_MSG_TYPE)
break;
cmsg = NN_CMSG_NXTHDR (&msghdr, cmsg);
}
}

/* If the header does not specify an opcode, assume default. */
/* If the header does not specify an opcode, take default from option. */
if (cmsg)
sws->outhdr [0] = *(uint8_t *) NN_CMSG_DATA (cmsg);
else
sws->outhdr [0] = NN_WS_OPCODE_BINARY;
sws->outhdr [0] = sws->msg_type;

/* For now, enforce that outgoing messages are the final frame. */
sws->outhdr [0] |= NN_SWS_FRAME_BITMASK_FIN;
Expand Down Expand Up @@ -500,11 +507,14 @@ static int nn_sws_recv (struct nn_pipebase *self, struct nn_msg *msg)
/* Inform user this connection has been failed. */
nn_msg_init (msg, 0);

opcode_hdr = NN_WS_MSG_TYPE_GONE | NN_SWS_FRAME_BITMASK_FIN;
opcode_hdr = NN_WS_OPCODE_GONE | NN_SWS_FRAME_BITMASK_FIN;

iov [0].iov_base = sws->fail_msg;
iov [0].iov_len = sws->fail_msg_len;

/* TODO: Pretty sure we should not send anything at all on this
connection -- these failures are due to a protocol violations
by the peer, and we should just cut them off at the knees. */
/* TODO: Consider queueing and unconditionally sending close
handshake rather than skipping it. */
/* RFC 6455 7.1.7 - try to send helpful Closing Handshake only if
Expand Down Expand Up @@ -595,7 +605,7 @@ static int nn_sws_recv (struct nn_pipebase *self, struct nn_msg *msg)
nn_chunkref_init (&msg->hdrs, cmsgsz);
cmsg = nn_chunkref_data (&msg->hdrs);
cmsg->cmsg_level = NN_WS;
cmsg->cmsg_type = NN_WS_HDR_OPCODE;
cmsg->cmsg_type = NN_WS_MSG_TYPE;
cmsg->cmsg_len = cmsgsz;
memcpy (NN_CMSG_DATA (cmsg), &opcode_hdr, sizeof (opcode_hdr));

Expand Down
9 changes: 8 additions & 1 deletion src/transports/ws/sws.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*
Copyright (c) 2013 250bpm s.r.o. All rights reserved.
Copyright (c) 2014 Wirebird Labs LLC. All rights reserved.
Copyright 2015 Garrett D'Amore <garrett@damore.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"),
Expand Down Expand Up @@ -82,6 +83,12 @@ struct nn_sws {
struct nn_fsm fsm;
int state;

/* Endpoint base. */
struct nn_epbase *epbase;

/* Default message type set on outobund frames. */
uint8_t msg_type;

/* Controls Tx/Rx framing based on whether this peer is acting as
a Client or a Server. */
int mode;
Expand Down Expand Up @@ -191,7 +198,7 @@ void nn_sws_term (struct nn_sws *self);

int nn_sws_isidle (struct nn_sws *self);
void nn_sws_start (struct nn_sws *self, struct nn_usock *usock, int mode,
const char *resource, const char *host);
const char *resource, const char *host, uint8_t msg_type);
void nn_sws_stop (struct nn_sws *self);

#endif
Expand Down
104 changes: 18 additions & 86 deletions src/transports/ws/ws.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Copyright (c) 2012-2013 250bpm s.r.o. All rights reserved.
Copyright (c) 2013 GoPivotal, Inc. All rights reserved.
Copyright (c) 2014 Wirebird Labs LLC. All rights reserved.
Copyright 2015 Garrett D'Amore <garrett@damore.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"),
Expand Down Expand Up @@ -49,7 +50,7 @@
/* WebSocket-specific socket options. */
struct nn_ws_optset {
struct nn_optset base;
int placeholder;
int msg_type;
};

static void nn_ws_optset_destroy (struct nn_optset *self);
Expand Down Expand Up @@ -100,7 +101,7 @@ static struct nn_optset *nn_ws_optset ()
optset->base.vfptr = &nn_ws_optset_vfptr;

/* Default values for WebSocket options. */
optset->placeholder = 1000;
optset->msg_type = NN_WS_MSG_TYPE_BINARY;

return &optset->base;
}
Expand All @@ -117,15 +118,24 @@ static int nn_ws_optset_setopt (struct nn_optset *self, int option,
const void *optval, size_t optvallen)
{
struct nn_ws_optset *optset;
int val;

optset = nn_cont (self, struct nn_ws_optset, base);
if (optvallen != sizeof (int)) {
return -EINVAL;
}
val = *(int *)optval;

switch (option) {
case NN_WS_OPTION_PLACEHOLDER:
if (optvallen != sizeof (int))
case NN_WS_MSG_TYPE:
switch (val) {
case NN_WS_MSG_TYPE_TEXT:
case NN_WS_MSG_TYPE_BINARY:
optset->msg_type = val;
return 0;
default:
return -EINVAL;
optset->placeholder = *(int*) optval;
return 0;
}
default:
return -ENOPROTOOPT;
}
Expand All @@ -139,90 +149,12 @@ static int nn_ws_optset_getopt (struct nn_optset *self, int option,
optset = nn_cont (self, struct nn_ws_optset, base);

switch (option) {
case NN_WS_OPTION_PLACEHOLDER:
memcpy (optval, &optset->placeholder,
case NN_WS_MSG_TYPE:
memcpy (optval, &optset->msg_type,
*optvallen < sizeof (int) ? *optvallen : sizeof (int));
*optvallen = sizeof (int);
return 0;
default:
return -ENOPROTOOPT;
}
}

int nn_ws_send (int s, const void *msg, size_t len, uint8_t msg_type, int flags)
{
int rc;
struct nn_iovec iov;
struct nn_msghdr hdr;
struct nn_cmsghdr *cmsg;
size_t cmsgsz;

iov.iov_base = (void*) msg;
iov.iov_len = len;

cmsgsz = NN_CMSG_SPACE (sizeof (msg_type));
cmsg = nn_allocmsg (cmsgsz, 0);
if (cmsg == NULL)
return -1;

cmsg->cmsg_level = NN_WS;
cmsg->cmsg_type = NN_WS_HDR_OPCODE;
cmsg->cmsg_len = NN_CMSG_LEN (sizeof (msg_type));
memcpy (NN_CMSG_DATA (cmsg), &msg_type, sizeof (msg_type));

hdr.msg_iov = &iov;
hdr.msg_iovlen = 1;
hdr.msg_control = &cmsg;
hdr.msg_controllen = NN_MSG;

rc = nn_sendmsg (s, &hdr, flags);

return rc;
}

int nn_ws_recv (int s, void *msg, size_t len, uint8_t *msg_type, int flags)
{
struct nn_iovec iov;
struct nn_msghdr hdr;
struct nn_cmsghdr *cmsg;
void *cmsg_buf;
int rc;

iov.iov_base = msg;
iov.iov_len = len;

hdr.msg_iov = &iov;
hdr.msg_iovlen = 1;
hdr.msg_control = &cmsg_buf;
hdr.msg_controllen = NN_MSG;

rc = nn_recvmsg (s, &hdr, flags);
if (rc < 0)
return rc;

/* Find WebSocket opcode ancillary property. */
cmsg = NN_CMSG_FIRSTHDR (&hdr);
while (cmsg) {
if (cmsg->cmsg_level == NN_WS && cmsg->cmsg_type == NN_WS_HDR_OPCODE) {
*msg_type = *(uint8_t *) NN_CMSG_DATA (cmsg);
break;
}
cmsg = NN_CMSG_NXTHDR (&hdr, cmsg);
}

/* WebSocket transport should always report this header. */
nn_assert (cmsg);

/* WebSocket transport should always reassemble fragmented messages. */
nn_assert (*msg_type & NN_SWS_FRAME_BITMASK_FIN);

/* Return only the message type (opcode). */
if (*msg_type == (NN_WS_MSG_TYPE_GONE | NN_SWS_FRAME_BITMASK_FIN))
*msg_type = NN_WS_MSG_TYPE_GONE;
else
*msg_type &= NN_SWS_FRAME_BITMASK_OPCODE;

nn_freemsg (cmsg_buf);

return rc;
}
Loading

0 comments on commit cd814f4

Please sign in to comment.