コード例 #1
0
ファイル: server.c プロジェクト: vikasga/sdk-dslink-c
static
void broker_server_client_ready(uv_poll_t *poll,
                                int status,
                                int events) {
    (void) status;
    Client *client = poll->data;
    Server *server = client->server;

    if (events & UV_READABLE) {
        server->data_ready(client, poll->loop->data);
        if (client->sock->socket_ctx.fd == -1) {
            // The callback closed the connection
            dslink_socket_free(client->sock);
            dslink_free(client);
            client = NULL;
            uv_close((uv_handle_t *) poll, broker_free_handle);
        }
    }

    if (client && (events & UV_WRITABLE)) {
        RemoteDSLink *link = client->sock_data;
        if (link) {
            link->ws->write_enabled = 1;
            wslay_event_send(link->ws);
        }
    }

}
コード例 #2
0
ファイル: websocket.c プロジェクト: ConfusedReality/h2o
void h2o_websocket_proceed(h2o_websocket_conn_t *conn)
{
    int handled;

    /* run the loop until getting to a point where no more progress can be achieved */
    do {
        handled = 0;
        if (!h2o_socket_is_writing(conn->sock) && wslay_event_want_write(conn->ws_ctx)) {
            if (wslay_event_send(conn->ws_ctx) != 0) {
                goto Close;
            }
            handled = 1;
        }
        if (conn->sock->input->size != 0 && wslay_event_want_read(conn->ws_ctx)) {
            if (wslay_event_recv(conn->ws_ctx) != 0) {
                goto Close;
            }
            handled = 1;
        }
    } while (handled);

    if (wslay_event_want_read(conn->ws_ctx)) {
        h2o_socket_read_start(conn->sock, on_recv);
    } else if (h2o_socket_is_writing(conn->sock) || wslay_event_want_write(conn->ws_ctx)) {
        h2o_socket_read_stop(conn->sock);
    } else {
        /* nothing is going on... close the socket */
        goto Close;
    }

    return;

Close:
    on_close(conn);
}
コード例 #3
0
ファイル: ws.c プロジェクト: kaendfinger/sdk-dslink-c
int dslink_ws_send(wslay_event_context_ptr ctx, const char *data) {
    struct wslay_event_msg msg;
    msg.msg = (const uint8_t *) data;
    msg.msg_length = strlen(data);
    msg.opcode = WSLAY_TEXT_FRAME;
    wslay_event_queue_msg(ctx, &msg);
    wslay_event_send(ctx);
    log_debug("Message sent: %s\n", data);
    return 0;
}
コード例 #4
0
ファイル: WebSocket.cpp プロジェクト: Andersbakken/plast
void WebSocket::write(const Message& msg)
{
    const String& data = msg.message();
    wslay_event_msg wmsg = {
        static_cast<uint8_t>(msg.opcode()),
        reinterpret_cast<const uint8_t*>(data.constData()),
        static_cast<size_t>(data.size())
    };
    wslay_event_queue_msg(mCtx, &wmsg);
    wslay_event_send(mCtx);
}
コード例 #5
0
ファイル: http_ws.c プロジェクト: cyrusimap/cyrus-imapd
HIDDEN void ws_output(struct transaction_t *txn)
{
    struct ws_context *ctx = (struct ws_context *) txn->ws_ctx;
    wslay_event_context_ptr ev = ctx->event;
    int want_write = wslay_event_want_write(ev);

    syslog(LOG_DEBUG, "ws_output()  eof: %d, want write: %d",
           txn->conn->pin->eof, want_write);

    if (want_write) {
        /* Send queued frame(s) */
        int r = wslay_event_send(ev);
        if (r) {
            syslog(LOG_ERR, "wslay_event_send: %s", wslay_strerror(r));
            txn->flags.conn = CONN_CLOSE;
        }
    }
}
コード例 #6
0
ファイル: mrb_wslay.c プロジェクト: Asmod4n/mruby-wslay
static mrb_value
mrb_wslay_event_send(mrb_state *mrb, mrb_value self)
{
  mrb_wslay_user_data *data = (mrb_wslay_user_data *) DATA_PTR(self);
  mrb_assert(data);

  int err = wslay_event_send(data->ctx);
  if (err == WSLAY_ERR_NOMEM) {
    mrb_sys_fail(mrb, "wslay_event_send");
  }
  else if (err == WSLAY_ERR_CALLBACK_FAILURE) {
    mrb_exc_raise(mrb, mrb_obj_value(mrb->exc));
  }
  else if (err != 0) {
    return MRB_WSLAY_ERROR(mrb_fixnum_value(err));
  }

  return self;
}
コード例 #7
0
ファイル: websocket.c プロジェクト: devnexen/h2o
void h2o_websocket_proceed(h2o_websocket_conn_t *conn)
{
    int handled;

    /* run the loop until getting to a point where no more progress can be achieved */
    do {
        handled = 0;
        if (!h2o_socket_is_writing(conn->sock) && wslay_event_want_write(conn->ws_ctx)) {
            if (wslay_event_send(conn->ws_ctx) != 0) {
                goto Close;
            }
            /* avoid infinite loop when user want send more bufers count than ours in on_msg_callback() */
            if (conn->_write_buf.cnt < sizeof(conn->_write_buf.bufs) / sizeof(conn->_write_buf.bufs[0])) {
                handled = 1;
            }
        }
        if (conn->sock->input->size != 0 && wslay_event_want_read(conn->ws_ctx)) {
            if (wslay_event_recv(conn->ws_ctx) != 0) {
                goto Close;
            }
            handled = 1;
        }
    } while (handled);

    if (!h2o_socket_is_writing(conn->sock) && conn->_write_buf.cnt > 0) {
        /* write */
        h2o_socket_write(conn->sock, conn->_write_buf.bufs, conn->_write_buf.cnt, on_write_complete);
    }

    if (wslay_event_want_read(conn->ws_ctx)) {
        h2o_socket_read_start(conn->sock, on_recv);
    } else if (h2o_socket_is_writing(conn->sock) || wslay_event_want_write(conn->ws_ctx)) {
        h2o_socket_read_stop(conn->sock);
    } else {
        /* nothing is going on... close the socket */
        goto Close;
    }

    return;

Close:
    on_close(conn);
}
コード例 #8
0
ファイル: ws.c プロジェクト: IOT-DSA/sdk-dslink-c
static
int dslink_ws_send_internal(wslay_event_context_ptr ctx, const char *data, uint8_t resend) {
    (void) resend;
    
    struct wslay_event_msg msg;
    msg.msg = (const uint8_t *) data;
    msg.msg_length = strlen(data);
    msg.opcode = WSLAY_TEXT_FRAME;
    if (wslay_event_queue_msg(ctx, &msg) != 0) {
        return 1;
    }
    
    if (wslay_event_send(ctx) != 0) {
        return 1;
    }
    
    log_debug("Message sent: %s\n", data);
    return 0;
}
コード例 #9
0
ファイル: websocket.c プロジェクト: drashti304/TizenRT
int websocket_handler(websocket_t *websocket)
{
	int r;
	int fd = websocket->fd;
	int timeout = 0;
	fd_set read_fds;
	fd_set write_fds;
	wslay_event_context_ptr ctx = (wslay_event_context_ptr) websocket->ctx;
	struct timeval tv;

	while (websocket->state != WEBSOCKET_STOP) {
		FD_ZERO(&read_fds);
		FD_ZERO(&write_fds);

		if (wslay_event_want_read(ctx)) {
			FD_SET(fd, &read_fds);
		}
		if (wslay_event_want_write(ctx)) {
			FD_SET(fd, &write_fds);
		}

		tv.tv_sec = (WEBSOCKET_HANDLER_TIMEOUT / 1000);
		tv.tv_usec = ((WEBSOCKET_HANDLER_TIMEOUT % 1000) * 1000);
		r = select(fd + 1, &read_fds, &write_fds, NULL, &tv);
		if (r < 0) {
			if (errno == EAGAIN || errno == EBUSY || errno == EINTR) {
				continue;
			}

			WEBSOCKET_DEBUG("select function returned errno == %d\n", errno);
			return WEBSOCKET_SOCKET_ERROR;
		} else if (r == 0) {
			if (WEBSOCKET_HANDLER_TIMEOUT != 0) {
				timeout++;
				if ((WEBSOCKET_HANDLER_TIMEOUT * timeout) >= (WEBSOCKET_PING_INTERVAL * 10)) {
					timeout = 0;
					if (websocket_ping_counter(websocket) != WEBSOCKET_SUCCESS) {
						return WEBSOCKET_SOCKET_ERROR;
					}
				}
			}

			continue;
		} else {
			timeout = 0;

			if (FD_ISSET(fd, &read_fds)) {
				r = wslay_event_recv(ctx);
				if (r != WEBSOCKET_SUCCESS) {
					WEBSOCKET_DEBUG("fail to process recv event, result : %d\n", r);
					websocket_update_state(websocket, WEBSOCKET_ERROR);
					return WEBSOCKET_SOCKET_ERROR;
				}
			}

			if (FD_ISSET(fd, &write_fds)) {
				r = wslay_event_send(ctx);
				if (r != WEBSOCKET_SUCCESS) {
					WEBSOCKET_DEBUG("fail to process send event, result : %d\n", r);
					websocket_update_state(websocket, WEBSOCKET_ERROR);
					return WEBSOCKET_SOCKET_ERROR;
				}
			}
		}
	}

	return WEBSOCKET_SUCCESS;
}
コード例 #10
0
ファイル: fork-echoserv.c プロジェクト: Andersbakken/wslay
/*
 * Communicate with the client. This function performs HTTP handshake
 * and WebSocket data transfer until close handshake is done or an
 * error occurs. *fd* is the file descriptor of the connection to the
 * client. This function returns 0 if it succeeds, or returns 0.
 */
int communicate(int fd)
{
  wslay_event_context_ptr ctx;
  struct wslay_event_callbacks callbacks = {
    recv_callback,
    send_callback,
    NULL,
    NULL,
    NULL,
    NULL,
    on_msg_recv_callback
  };
  struct Session session = { fd };
  int val = 1;
  struct pollfd event;
  int res = 0;

  if(http_handshake(fd) == -1) {
    return -1;
  }
  if(make_non_block(fd) == -1) {
    return -1;
  }
  if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, (socklen_t)sizeof(val))
     == -1) {
    perror("setsockopt: TCP_NODELAY");
    return -1;
  }
  memset(&event, 0, sizeof(struct pollfd));
  event.fd = fd;
  event.events = POLLIN;
  wslay_event_context_server_init(&ctx, &callbacks, &session);
  /*
   * Event loop: basically loop until both wslay_event_want_read(ctx)
   * and wslay_event_want_write(ctx) return 0.
   */
  while(wslay_event_want_read(ctx) || wslay_event_want_write(ctx)) {
    int r;
    while((r = poll(&event, 1, -1)) == -1 && errno == EINTR);
    if(r == -1) {
      perror("poll");
      res = -1;
      break;
    }
    if(((event.revents & POLLIN) && wslay_event_recv(ctx) != 0) ||
       ((event.revents & POLLOUT) && wslay_event_send(ctx) != 0) ||
       (event.revents & (POLLERR | POLLHUP | POLLNVAL))) {
      /*
       * If either wslay_event_recv() or wslay_event_send() return
       * non-zero value, it means serious error which prevents wslay
       * library from processing further data, so WebSocket connection
       * must be closed.
       */
      res = -1;
      break;
    }
    event.events = 0;
    if(wslay_event_want_read(ctx)) {
      event.events |= POLLIN;
    }
    if(wslay_event_want_write(ctx)) {
      event.events |= POLLOUT;
    }
  }
  return res;
}
コード例 #11
0
ファイル: wslay_event.c プロジェクト: drashti304/TizenRT
int wslay_event_recv(wslay_event_context_ptr ctx)
{
	struct wslay_frame_iocb iocb;
	ssize_t r;

	while (ctx->read_enabled) {
		memset(&iocb, 0, sizeof(iocb));
		r = wslay_frame_recv(ctx->frame_ctx, &iocb);
		if (r >= 0) {
			int new_frame = 0;
			/* RSV1 is not allowed on control and continuation frames */
			if ((!wslay_event_verify_rsv_bits(ctx, iocb.rsv)) || (wslay_get_rsv1(iocb.rsv) && (wslay_is_ctrl_frame(iocb.opcode) || iocb.opcode == WSLAY_CONTINUATION_FRAME)) || (ctx->server && !iocb.mask) || (!ctx->server && iocb.mask)) {
				if ((r = wslay_event_queue_close_wrapper(ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) {
					return r;
				}
				break;
			}
			if (ctx->imsg->opcode == 0xffu) {
				if (iocb.opcode == WSLAY_TEXT_FRAME || iocb.opcode == WSLAY_BINARY_FRAME || iocb.opcode == WSLAY_CONNECTION_CLOSE || iocb.opcode == WSLAY_PING || iocb.opcode == WSLAY_PONG) {
					wslay_event_imsg_set(ctx->imsg, iocb.fin, iocb.rsv, iocb.opcode);
					new_frame = 1;
				} else {
					if ((r = wslay_event_queue_close_wrapper(ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) {
						return r;
					}
					break;
				}
			} else if (ctx->ipayloadlen == 0 && ctx->ipayloadoff == 0) {
				if (iocb.opcode == WSLAY_CONTINUATION_FRAME) {
					ctx->imsg->fin = iocb.fin;
				} else if (iocb.opcode == WSLAY_CONNECTION_CLOSE || iocb.opcode == WSLAY_PING || iocb.opcode == WSLAY_PONG) {
					ctx->imsg = &ctx->imsgs[1];
					wslay_event_imsg_set(ctx->imsg, iocb.fin, iocb.rsv, iocb.opcode);
				} else {
					if ((r = wslay_event_queue_close_wrapper(ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) {
						return r;
					}
					break;
				}
				new_frame = 1;
			}
			if (new_frame) {
				if (ctx->imsg->msg_length + iocb.payload_length > ctx->max_recv_msg_length) {
					if ((r = wslay_event_queue_close_wrapper(ctx, WSLAY_CODE_MESSAGE_TOO_BIG, NULL, 0)) != 0) {
						return r;
					}
					break;
				}
				ctx->ipayloadlen = iocb.payload_length;
				wslay_event_call_on_frame_recv_start_callback(ctx, &iocb);
				if (!wslay_event_config_get_no_buffering(ctx) || wslay_is_ctrl_frame(iocb.opcode)) {
					if ((r = wslay_event_imsg_append_chunk(ctx->imsg, iocb.payload_length)) != 0) {
						ctx->read_enabled = 0;
						return r;
					}
				}
			}
			/* If RSV1 bit is set then it is too early for utf-8 validation */
			if ((!wslay_get_rsv1(iocb.rsv) && ctx->imsg->opcode == WSLAY_TEXT_FRAME)
				|| ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) {
				size_t i;
				if (ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) {
					i = 2;
				} else {
					i = 0;
				}
				for (; i < iocb.data_length; ++i) {
					uint32_t codep;
					if (decode(&ctx->imsg->utf8state, &codep, iocb.data[i]) == UTF8_REJECT) {
						if ((r = wslay_event_queue_close_wrapper(ctx, WSLAY_CODE_INVALID_FRAME_PAYLOAD_DATA, NULL, 0)) != 0) {
							return r;
						}
						break;
					}
				}
			}
			if (ctx->imsg->utf8state == UTF8_REJECT) {
				break;
			}
			wslay_event_call_on_frame_recv_chunk_callback(ctx, &iocb);
			if (iocb.data_length > 0) {
				if (!wslay_event_config_get_no_buffering(ctx) || wslay_is_ctrl_frame(iocb.opcode)) {
					struct wslay_event_byte_chunk *chunk;
					chunk = wslay_queue_tail(ctx->imsg->chunks);
					wslay_event_byte_chunk_copy(chunk, ctx->ipayloadoff, iocb.data, iocb.data_length);
				}
				ctx->ipayloadoff += iocb.data_length;
			}
			if (ctx->ipayloadoff == ctx->ipayloadlen) {
				if (ctx->imsg->fin && (ctx->imsg->opcode == WSLAY_TEXT_FRAME || ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) && ctx->imsg->utf8state != UTF8_ACCEPT) {
					if ((r = wslay_event_queue_close_wrapper(ctx, WSLAY_CODE_INVALID_FRAME_PAYLOAD_DATA, NULL, 0)) != 0) {
						return r;
					}
					break;
				}
				wslay_event_call_on_frame_recv_end_callback(ctx);
				if (ctx->imsg->fin) {
					if (ctx->callbacks.on_msg_recv_callback || ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE || ctx->imsg->opcode == WSLAY_PING || ctx->imsg->opcode == WSLAY_PONG) {
						struct wslay_event_on_msg_recv_arg arg;
						uint16_t status_code = 0;
						uint8_t *msg = NULL;
						size_t msg_length = 0;
						if (!wslay_event_config_get_no_buffering(ctx) || wslay_is_ctrl_frame(iocb.opcode)) {
							msg = wslay_event_flatten_queue(ctx->imsg->chunks, ctx->imsg->msg_length);
							if (ctx->imsg->msg_length && !msg) {
								ctx->read_enabled = 0;
								return WSLAY_ERR_NOMEM;
							}
							msg_length = ctx->imsg->msg_length;
						}
						if (ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) {
							const uint8_t *reason;
							size_t reason_length;
							if (ctx->imsg->msg_length >= 2) {
								memcpy(&status_code, msg, 2);
								status_code = ntohs(status_code);
								if (!wslay_event_is_valid_status_code(status_code)) {
									free(msg);
									if ((r = wslay_event_queue_close_wrapper(ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) {
										return r;
									}
									break;
								}
								reason = msg + 2;
								reason_length = ctx->imsg->msg_length - 2;
							} else {
								reason = NULL;
								reason_length = 0;
							}
							ctx->close_status |= WSLAY_CLOSE_RECEIVED;
							ctx->status_code_recv = status_code == 0 ? WSLAY_CODE_NO_STATUS_RCVD : status_code;
							if ((r = wslay_event_queue_close_wrapper(ctx, status_code, reason, reason_length)) != 0) {
								free(msg);
								return r;
							}
						} else if (ctx->imsg->opcode == WSLAY_PING) {
							struct wslay_event_msg pong_arg;
							pong_arg.opcode = WSLAY_PONG;
							pong_arg.msg = msg;
							pong_arg.msg_length = ctx->imsg->msg_length;
							if ((r = wslay_event_queue_msg(ctx, &pong_arg)) && r != WSLAY_ERR_NO_MORE_MSG) {
								ctx->read_enabled = 0;
								free(msg);
								return r;
							}
						} else if (ctx->imsg->opcode == WSLAY_PONG) {
							struct websocket_info_t *info = ctx->user_data;
							info->data->ping_cnt = 0;
						}
						if (ctx->callbacks.on_msg_recv_callback) {
							arg.rsv = ctx->imsg->rsv;
							arg.opcode = ctx->imsg->opcode;
							arg.msg = msg;
							arg.msg_length = msg_length;
							arg.status_code = status_code;
							ctx->error = 0;
							ctx->callbacks.on_msg_recv_callback(ctx, &arg, ctx->user_data);
							if (ctx->imsg->opcode != WSLAY_CONNECTION_CLOSE) {
								free(msg);
								wslay_event_imsg_reset(ctx->imsg);
								if (ctx->imsg == &ctx->imsgs[1]) {
									ctx->imsg = &ctx->imsgs[0];
								}
								ctx->ipayloadlen = ctx->ipayloadoff = 0;
								break;
							}
						}
						if (ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) {
							struct websocket_info_t *info = ctx->user_data;
							if (!wslay_queue_empty(ctx->send_ctrl_queue)) {
								wslay_event_send(ctx);
							}
							websocket_update_state(info->data, WEBSOCKET_STOP);
						}
						free(msg);
					}
					wslay_event_imsg_reset(ctx->imsg);
					if (ctx->imsg == &ctx->imsgs[1]) {
						ctx->imsg = &ctx->imsgs[0];
					}
				}
				ctx->ipayloadlen = ctx->ipayloadoff = 0;
			}
		} else {
			if (r != WSLAY_ERR_WANT_READ || (ctx->error != WSLAY_ERR_WOULDBLOCK && ctx->error != 0)) {
				if ((r = wslay_event_queue_close_wrapper(ctx, 0, NULL, 0)) != 0) {
					return r;
				}
				return WSLAY_ERR_CALLBACK_FAILURE;
			}
			break;
		}
	}
	return 0;
}
コード例 #12
0
ファイル: vs_websocket.c プロジェクト: zdenek-perutka/verse
/**
 * \brief The function with websocket infinite loop
 */
void *vs_websocket_loop(void *arg)
{
	/* The vContext is passed as *user_data* in callback functions. */
	struct vContext *C = (struct vContext*)arg;
	struct VS_CTX *vs_ctx = CTX_server_ctx(C);
	struct IO_CTX *io_ctx = CTX_io_ctx(C);
	struct VStreamConn *stream_conn = CTX_current_stream_conn(C);
	struct VSession *vsession = CTX_current_session(C);
	struct VMessage *r_message=NULL, *s_message=NULL;
	wslay_event_context_ptr wslay_ctx;
	fd_set read_set, write_set;
	struct timeval tv;
	int ret, flags;
	unsigned int int_size;

	struct wslay_event_callbacks callbacks = {
			vs_recv_ws_callback_data,
			vs_send_ws_callback_data,
			NULL,
			NULL,
			NULL,
			NULL,
			vs_ws_recv_msg_callback
	};

	/* Set socket blocking */
	flags = fcntl(io_ctx->sockfd, F_GETFL, 0);
	fcntl(io_ctx->sockfd, F_SETFL, flags & ~O_NONBLOCK);

	http_handshake(io_ctx->sockfd);

	/* Try to get size of TCP buffer */
	int_size = sizeof(int_size);
	getsockopt(io_ctx->sockfd, SOL_SOCKET, SO_RCVBUF,
			(void *)&stream_conn->socket_buffer_size, &int_size);

	r_message = (struct VMessage*)calloc(1, sizeof(struct VMessage));
	s_message = (struct VMessage*)calloc(1, sizeof(struct VMessage));
	CTX_r_message_set(C, r_message);
	CTX_s_message_set(C, s_message);

	stream_conn->host_state = TCP_SERVER_STATE_RESPOND_METHODS;

	if(is_log_level(VRS_PRINT_DEBUG_MSG)) {
		printf("%c[%d;%dm", 27, 1, 31);
		v_print_log(VRS_PRINT_DEBUG_MSG, "Server TCP state: RESPOND_methods\n");
		printf("%c[%dm", 27, 0);
	}

	/* Set non-blocking */
	flags = fcntl(io_ctx->sockfd, F_GETFL, 0);
	fcntl(io_ctx->sockfd, F_SETFL, flags | O_NONBLOCK);

	wslay_event_context_server_init(&wslay_ctx, &callbacks, C);

	/* "Never ending" loop */
	while(vsession->stream_conn->host_state != TCP_SERVER_STATE_CLOSED)
	{
		if(vs_ctx->state != SERVER_STATE_READY) {
			vsession->stream_conn->host_state = TCP_SERVER_STATE_CLOSING;
			/* Try to close connection with websocket client */
			wslay_event_queue_close(wslay_ctx,
					WSLAY_CODE_GOING_AWAY,
					(uint8_t*)"Server shutdown",	/* Close message */
					15);	/* The length of close message s*/
		}

		/* Initialize read set */
		FD_ZERO(&read_set);
		FD_SET(io_ctx->sockfd, &read_set);

		/* Initialize write set */
		FD_ZERO(&write_set);
		FD_SET(io_ctx->sockfd, &write_set);

		/* Set timeout for select() */
		if(stream_conn->host_state == TCP_SERVER_STATE_STREAM_OPEN) {
			/* Use negotiated FPS */
			tv.tv_sec = 0;
			tv.tv_usec = 1000000/vsession->fps_host;
		} else {
			/* User have to send something in 30 seconds */
			tv.tv_sec = VRS_TIMEOUT;
			tv.tv_usec = 0;
		}

		if( (ret = select(io_ctx->sockfd+1,
				&read_set,
				&write_set,
				NULL,			/* Exception*/
				&tv)) == -1) {
			if(is_log_level(VRS_PRINT_ERROR)) v_print_log(VRS_PRINT_ERROR, "%s:%s():%d select(): %s\n",
					__FILE__, __FUNCTION__,  __LINE__, strerror(errno));
			goto end;
			/* Was event on the listen socket */
		} else if(ret>0){
			if(FD_ISSET(io_ctx->sockfd, &read_set)) {
				if( wslay_event_recv(wslay_ctx) != 0 ) {
					goto end;
				}
			} else if (FD_ISSET(io_ctx->sockfd, &write_set)) {
				if( wslay_event_send(wslay_ctx) != 0 ) {
					goto end;
				}
			}
		}

		if(stream_conn->host_state == TCP_SERVER_STATE_STREAM_OPEN) {
			/* Check if there is any command in outgouing queue
			 * and eventually pack these commands to buffer */
			if((ret = v_STREAM_pack_message(C)) == 0 ) {
				goto end;
			}

			/* When at least one command was packed to buffer, then
			 * queue this buffer to WebSocket layer */
			if(ret == 1) {
				struct wslay_event_msg msgarg;
			    msgarg.opcode = WSLAY_BINARY_FRAME;
			    msgarg.msg = (uint8_t*)io_ctx->buf;
			    msgarg.msg_length = io_ctx->buf_size;
			    wslay_event_queue_msg(wslay_ctx, &msgarg);
			}
		}
	}

end:
	if(is_log_level(VRS_PRINT_DEBUG_MSG)) {
		printf("%c[%d;%dm", 27, 1, 31);
		v_print_log(VRS_PRINT_DEBUG_MSG, "Server TCP state: CLOSING\n");
		printf("%c[%dm", 27, 0);
	}

	/* Set up TCP CLOSING state (non-blocking) */
	vs_CLOSING(C);

	/* Receive and Send messages are not neccessary any more */
	if(r_message!=NULL) {
		free(r_message);
		r_message = NULL;
		CTX_r_message_set(C, NULL);
	}
	if(s_message!=NULL) {
		free(s_message);
		s_message = NULL;
		CTX_s_message_set(C, NULL);
	}

	/* TCP connection is considered as CLOSED, but it is not possible to use
	 * this connection for other client */
	stream_conn->host_state = TCP_SERVER_STATE_CLOSED;

	/* NULL pointer at stream connection */
	CTX_current_stream_conn_set(C, NULL);

	/* Set TCP connection to CLOSED */
	if(is_log_level(VRS_PRINT_DEBUG_MSG)) {
		printf("%c[%d;%dm", 27, 1, 31);
		v_print_log(VRS_PRINT_DEBUG_MSG, "Server TCP state: CLOSED\n");
		printf("%c[%dm", 27, 0);
	}


	pthread_mutex_lock(&vs_ctx->data.mutex);
	/* Unsubscribe this session (this avatar) from all nodes */
	vs_node_free_avatar_reference(vs_ctx, vsession);
	/* Try to destroy avatar node */
	vs_node_destroy_avatar_node(vs_ctx, vsession);
	pthread_mutex_unlock(&vs_ctx->data.mutex);

	/* This session could be used again for authentication */
	stream_conn->host_state=TCP_SERVER_STATE_LISTEN;

	/* Clear session flags */
	vsession->flags = 0;

	if(is_log_level(VRS_PRINT_DEBUG_MSG)) {
		printf("%c[%d;%dm", 27, 1, 31);
		v_print_log(VRS_PRINT_DEBUG_MSG, "Server TCP state: LISTEN\n");
		printf("%c[%dm", 27, 0);
	}

	free(C);
	C = NULL;

	pthread_exit(NULL);
	return NULL;
}
コード例 #13
0
void
rig_pb_stream_write(rig_pb_stream_t *stream,
                    rig_pb_stream_write_closure_t *closure)
{
    c_return_if_fail(stream->type != STREAM_TYPE_DISCONNECTED);

    switch (stream->type) {
    case STREAM_TYPE_BUFFER: {
        c_return_if_fail(stream->buffer.other_end != NULL);
        c_return_if_fail(stream->buffer.other_end->type == STREAM_TYPE_BUFFER);

        c_array_append_val(stream->buffer.other_end->buffer.incoming_write_closures, closure);

        queue_data_buffer_stream_read(stream->buffer.other_end);

        break;
    }

#ifdef USE_UV
    case STREAM_TYPE_FD:
    case STREAM_TYPE_TCP: {
        closure->write_req.data = closure;

        uv_write(&closure->write_req,
                 (uv_stream_t *)&stream->fd.uv_fd_pipe,
                 &closure->buf,
                 1, /* n buffers */
                 uv_write_done_cb);
        break;
    }
    case STREAM_TYPE_WEBSOCKET_SERVER: {
        struct wslay_event_fragmented_msg arg;

        memset(&arg, 0, sizeof(arg));
        arg.opcode = WSLAY_BINARY_FRAME;
        arg.source.data = closure;
        arg.read_callback = fragmented_wslay_read_cb;

        closure->current_offset = 0;

        wslay_event_queue_fragmented_msg(stream->websocket_server.ctx, &arg);
        wslay_event_send(stream->websocket_server.ctx);
        break;
    }
#endif

#ifdef __EMSCRIPTEN__
    case STREAM_TYPE_WORKER_IPC:
        if (stream->worker_ipc.in_worker)
            rig_emscripten_worker_post_to_main(closure->buf.base,
                                               closure->buf.len);
        else
            rig_emscripten_worker_post(stream->worker_ipc.worker,
                                       "rig_pb_stream_worker_onmessage",
                                       closure->buf.base,
                                       closure->buf.len);

        closure->done_callback(closure);
        break;

    case STREAM_TYPE_WEBSOCKET_CLIENT:
        c_debug("stream: websocket send() %d bytes", closure->buf.len);
        send(stream->websocket_client.socket,
             closure->buf.base,
             closure->buf.len,
             0 /* flags */);

        closure->done_callback(closure);
        break;
#endif

    case STREAM_TYPE_DISCONNECTED:
        c_warn_if_reached();
        break;
    }
}
コード例 #14
0
ファイル: test.c プロジェクト: GhostGumm/CarbonComet
 int on_write_event()
 {
   return wslay_event_send(ctx_);
 }