void* connection_worker(void *_w) { struct conn_worker_list *w = _w; struct conn_data *data = w->conn_data; struct connection *conn; void *ptr; do { /* * Remember: The locking here need to be synchronized with * the locking in disconnect_peer() to avoid nasty races * in case a connection is terminated when work is about to start. */ pthread_mutex_lock(&data->workers_lock); while (list_empty(&data->work_items) && !w->terminate) pthread_cond_wait(&data->workers_cond, &data->workers_lock); if (w->terminate) { pthread_mutex_unlock(&data->workers_lock); break; } conn = list_first_entry(&data->work_items, struct connection, work); list_del_init(&conn->work); /* * This needs to be in this order to avoid a race when * server_disconnect_cb() is running _now_. */ pthread_mutex_lock(&conn->worker_lock); pthread_mutex_unlock(&data->workers_lock); if (conn->terminate) { pthread_mutex_unlock(&conn->worker_lock); continue; } if (conn->worker) { pthread_mutex_unlock(&conn->worker_lock); log_printfn("connection", "Got new data too fast -- old worker is still busy"); continue; } conn->worker = 1; pthread_mutex_unlock(&conn->worker_lock); if (conn->rbuf[0] != '\0' && cli_run_cmd(&conn->pl->cli, conn->rbuf) < 0) conn_send(conn, "Unknown command or syntax error: \"%s\"\n", conn->rbuf); conn_send(conn, PROMPT); pthread_mutex_lock(&conn->worker_lock); conn->worker = 0; pthread_mutex_unlock(&conn->worker_lock); } while(1); return NULL; }
void kr_close(KrClient * client) { conn_send(client, KR_COMMAND_CLOSE, &client->db_id, sizeof(client->db_id)); conn_destroy(client); free(client->dev); free(client); }
void conn_error(struct connection *data, char *format, ...) { va_list ap; va_start(ap, format); conn_send(data, "Oops! An internal error occured: %s.\nYour current state is NOT saved and you are being forcibly disconnected.\nSorry!", format, ap); va_end(ap); server_disconnect_nicely(data); }
static void stream_continuation(uint_fast32_t id) { const char *h[][2] = { { ":status", "100" }, }; conn_send(vlc_h2_frame_headers(id, VLC_H2_DEFAULT_MAX_FRAME, false, 1, h)); }
int reqs_conn_send(struct reqs_t *reqs, void *data, int size) { if (reqs == NULL) { return 0; } return conn_send(reqs->conn, data, size); }
static void stream_reply(uint_fast32_t id, bool nodata) { struct vlc_http_msg *m = vlc_http_resp_create(200); assert(m != NULL); vlc_http_msg_add_agent(m, "VLC-h2-tester"); conn_send(vlc_http_msg_h2_frame(m, id, nodata)); vlc_http_msg_destroy(m); }
static void conn_respond(struct conn_t *c, struct request_t *req, int err) { struct request_t *resp; struct bproc_null_msg_t *msg; resp = bproc_new_resp(req, sizeof(*msg)); msg = bproc_msg(resp); msg->hdr.result = err; conn_send(c, resp); }
static rstatus_t core_send(struct context *ctx, struct conn *conn) { rstatus_t status; status = conn_send(ctx, conn); if (status != DN_OK) { log_info("send on %s %d failed: %s", conn_get_type_string(conn), conn->sd, strerror(errno)); } return status; }
static void conn_eof(struct conn_t *c) { struct request_t *req; struct bproc_null_msg_t *msg; c->state = CONN_CLOSING; req = bproc_new_req(BPROC_NODE_EOF, sizeof(*msg)); msg = bproc_msg(req); bpr_from_node(msg, node_number); bpr_to_node (msg, -1); conn_send(c, req); }
static void conn_send_version(struct conn_t *c) { struct request_t *req; struct bproc_version_msg_t *msg; req = bproc_new_req(BPROC_VERSION, sizeof(*msg)); msg = bproc_msg(req); bpr_from_node(msg, node_number); /* no reasonable value here... */ bpr_to_node(msg, -1); memcpy(&msg->vers, &version, sizeof(version)); msg->cookie = cookie; conn_send(c, req); }
static void send_char(wchar_t c) { char cbuf[STR_BOUNDS(1)]; size_t offs; int rc; offs = 0; chr_encode(c, cbuf, &offs, STR_BOUNDS(1)); rc = conn_send(cbuf, offs); if (rc != EOK) { printf("[Failed sending data]\n"); } }
int sip_transp_send(struct sip_connqent **qentp, struct sip *sip, void *sock, enum sip_transp tp, const struct sa *dst, struct mbuf *mb, sip_transp_h *transph, void *arg) { const struct sip_transport *transp; struct sip_conn *conn; bool secure = false; int err; if (!sip || !dst || !mb) return EINVAL; switch (tp) { case SIP_TRANSP_UDP: if (!sock) { transp = transp_find(sip, tp, sa_af(dst), dst); if (!transp) return EPROTONOSUPPORT; sock = transp->sock; } err = udp_send(sock, dst, mb); break; case SIP_TRANSP_TLS: secure = true; /*@fallthrough@*/ case SIP_TRANSP_TCP: conn = sock; if (conn && conn->tc) err = tcp_send(conn->tc, mb); else err = conn_send(qentp, sip, secure, dst, mb, transph, arg); break; default: err = EPROTONOSUPPORT; break; } return err; }
void kr_put(KrClient * client, size_t keysz, void* key, size_t valsz, void* val) { //build the message first //msg layout: 8byte key size followed by key data followed by 8byte val sz followed by val data size_t msglen = 8 + keysz + 8 + valsz + 1; void* msgbgn = malloc(msglen); *(uint8_t*)msgbgn = client->db_id; void* msgcurr = msgbgn + 1; memcpy(msgcurr, (char*)&keysz, 8); msgcurr += 8; memcpy(msgcurr, (char*)key, keysz); msgcurr += keysz; memcpy(msgcurr, (char*)&valsz, 8); msgcurr += 8; memcpy(msgcurr, (char*)val, valsz); conn_send(client, KR_COMMAND_PUT, msgbgn, msglen); }
KrClient * kr_open(const char * dev) { KrClient * client = (KrClient *)malloc(sizeof(KrClient)); KrMsg msg; size_t len = strlen(dev); client->dev = malloc(len + 1); strcpy(client->dev, dev); printf("Creating connection...\n"); conn_create(client); printf("Opening db \"%s\"...\n", client->dev); conn_send(client, KR_COMMAND_OPEN, client->dev, len + 1); conn_wait_reply(client, &msg); client->db_id = *(uint8_t*)msg.data; conn_msg_done(&msg); return client; }
void kr_get(KrClient* client, size_t keysz, void* key, size_t* valszout, void** valout) { size_t msglen = 8 + keysz + 1; void* msgbgn = malloc(msglen); *(uint8_t*)msgbgn = client->db_id; memcpy(msgbgn + 1, (char*)&keysz, 8); memcpy(msgbgn + 1 + 8, (char*)key, keysz); conn_send(client, KR_COMMAND_GET, msgbgn, msglen); KrMsg msg; conn_wait_reply(client, &msg); uint64_t len = *(uint64_t*)msg.data; *valszout = (size_t)len; *valout = malloc(len); memcpy(*valout, msg.data + 8, len); conn_msg_done(&msg); }
int conn_fulfixinit(struct connection *data) { log_printfn("connection", "initializing connection from peer %s", data->peer); data->pl = malloc(sizeof(*data->pl)); if (!data->pl) return -1; if (player_init(data->pl)) { free(data->pl); return -1; } data->pl->conn = data; player_go(data->pl, SECTOR, ptrlist_entry(&univ.sectors, 0)); conn_send(data, PROMPT); log_printfn("connection", "peer %s successfully logged in as %s", data->peer, data->pl->name); return 0; }
static void conn_create(void) { ssize_t val; int fds[2]; char hello[24]; if (socketpair(PF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC, 0, fds)) assert(!"socketpair"); struct vlc_tls *tls = vlc_tls_DummyCreate(NULL, fds[1]); assert(tls != NULL); external_fd = fds[0]; conn = vlc_h2_conn_create(tls); assert(conn != NULL); conn_send(vlc_h2_frame_settings()); val = recv(external_fd, hello, 24, MSG_WAITALL); assert(val == 24); assert(!memcmp(hello, "PRI * HTTP/2.0\r\n", 16)); conn_expect(SETTINGS); conn_expect(SETTINGS); }
static void stream_data(uint_fast32_t id, const char *str, bool eos) { conn_send(vlc_h2_frame_data(id, str, strlen(str), eos)); }
int main(void) { struct vlc_http_stream *s, *s2; struct vlc_http_msg *m; struct block_t *b; uint_fast32_t sid = -1; /* Second guessed stream IDs :-/ */ conn_create(); conn_destroy(); conn_create(); conn_send(vlc_h2_frame_ping(42)); conn_expect(PING); /* Test rejected stream */ sid += 2; s = stream_open(); assert(s != NULL); conn_expect(HEADERS); conn_send(vlc_h2_frame_rst_stream(sid, VLC_H2_REFUSED_STREAM)); m = vlc_http_stream_read_headers(s); assert(m == NULL); b = vlc_http_stream_read(s); assert(b == NULL); vlc_http_stream_close(s, false); conn_expect(RST_STREAM); /* Test accepted stream */ sid += 2; s = stream_open(); assert(s != NULL); stream_reply(sid, false); m = vlc_http_msg_get_initial(s); assert(m != NULL); vlc_http_msg_destroy(m); stream_data(3, "Hello ", false); /* late data */ stream_data(3, "world!", true); conn_expect(HEADERS); conn_expect(RST_STREAM); conn_expect(RST_STREAM); conn_expect(RST_STREAM); /* Test continuation then accepted stream */ sid += 2; s = stream_open(); assert(s != NULL); stream_continuation(sid); m = vlc_http_msg_get_initial(s); assert(m != NULL); assert(vlc_http_msg_get_status(m) == 100); stream_reply(sid, false); m = vlc_http_msg_iterate(m); assert(m != NULL); stream_data(sid, "Hello ", false); stream_data(sid, "world!", true); stream_data(sid, "Stray message", false); /* data after EOS */ b = vlc_http_msg_read(m); assert(b != NULL); block_Release(b); b = vlc_http_msg_read(m); assert(b != NULL); block_Release(b); b = vlc_http_msg_read(m); assert(b == NULL); vlc_http_msg_destroy(m); conn_expect(HEADERS); conn_expect(RST_STREAM); conn_expect(RST_STREAM); /* Test accepted stream after continuation */ sid += 2; s = stream_open(); assert(s != NULL); stream_continuation(sid); stream_reply(sid, true); sid += 2; s2 = stream_open(); /* second stream to enforce test timing/ordering */ assert(s2 != NULL); stream_reply(sid, true); m = vlc_http_msg_get_initial(s2); assert(m != NULL); vlc_http_msg_destroy(m); m = vlc_http_msg_get_initial(s); assert(m != NULL); assert(vlc_http_msg_get_status(m) == 200); b = vlc_http_msg_read(m); assert(b == NULL); vlc_http_msg_destroy(m); conn_expect(HEADERS); conn_expect(HEADERS); conn_expect(RST_STREAM); conn_expect(RST_STREAM); /* Test nonexistent stream reset */ conn_send(vlc_h2_frame_rst_stream(sid + 100, VLC_H2_REFUSED_STREAM)); /* Test multiple streams in non-LIFO order */ sid += 2; s = stream_open(); assert(s != NULL); sid += 2; s2 = stream_open(); assert(s2 != NULL); stream_reply(sid, false); stream_reply(sid - 2, true); stream_data(sid, "Discarded", false); /* not read data */ m = vlc_http_msg_get_initial(s); assert(m != NULL); vlc_http_msg_destroy(m); m = vlc_http_msg_get_initial(s2); assert(m != NULL); vlc_http_msg_destroy(m); conn_expect(HEADERS); conn_expect(HEADERS); conn_expect(RST_STREAM); conn_expect(RST_STREAM); /* might or might not seen one or two extra RST_STREAM now */ /* Test graceful connection termination */ sid += 2; s = stream_open(); assert(s != NULL); conn_send(vlc_h2_frame_goaway(sid - 2, VLC_H2_NO_ERROR)); m = vlc_http_stream_read_headers(s); assert(m == NULL); /* Test stream after connection shut down */ assert(stream_open() == NULL); /* Test releasing connection before stream */ conn_destroy(); vlc_http_stream_close(s, false); return 0; }
int main(void) { struct vlc_http_stream *s; struct vlc_http_msg *m; struct block_t *b; /* Dummy */ conn_create(); conn_destroy(); /* Test rejected connection */ conn_create(); conn_shutdown(SHUT_RD); s = stream_open(); assert(s == NULL); conn_destroy(); /* Test rejected stream */ conn_create(); s = stream_open(); assert(s != NULL); conn_shutdown(SHUT_WR); m = vlc_http_stream_read_headers(s); assert(m == NULL); b = vlc_http_stream_read(s); assert(b == NULL); m = vlc_http_stream_read_headers(s); assert(m == NULL); b = vlc_http_stream_read(s); assert(b == NULL); m = vlc_http_msg_get_initial(s); assert(m == NULL); s = stream_open(); assert(s == NULL); conn_destroy(); /* Test garbage */ conn_create(); s = stream_open(); assert(s != NULL); conn_send("Go away!\r\n\r\n"); conn_shutdown(SHUT_WR); m = vlc_http_stream_read_headers(s); assert(m == NULL); b = vlc_http_stream_read(s); assert(b == NULL); conn_destroy(); vlc_http_stream_close(s, false); /* Test HTTP/1.0 stream */ conn_create(); s = stream_open(); assert(s != NULL); conn_send("HTTP/1.0 200 OK\r\n\r\n"); m = vlc_http_msg_get_initial(s); assert(m != NULL); conn_send("Hello world!"); conn_shutdown(SHUT_WR); b = vlc_http_msg_read(m); assert(b != NULL); assert(b->i_buffer == 12); assert(!memcmp(b->p_buffer, "Hello world!", 12)); block_Release(b); b = vlc_http_msg_read(m); assert(b == NULL); vlc_http_msg_destroy(m); conn_destroy(); /* Test HTTP/1.1 with closed connection */ conn_create(); s = stream_open(); assert(s != NULL); conn_send("HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n"); m = vlc_http_msg_get_initial(s); assert(m != NULL); conn_send("Hello again!"); conn_shutdown(SHUT_WR); b = vlc_http_msg_read(m); assert(b != NULL); assert(b->i_buffer == 12); assert(!memcmp(b->p_buffer, "Hello again!", 12)); block_Release(b); b = vlc_http_msg_read(m); assert(b == NULL); vlc_http_msg_destroy(m); conn_destroy(); /* Test HTTP/1.1 with chunked transfer encoding */ conn_create(); s = stream_open(); assert(s != NULL); conn_send("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n" "Content-Length: 1000000\r\n\r\n"); /* length must be ignored */ m = vlc_http_msg_get_initial(s); assert(m != NULL); conn_send("C\r\nHello there!\r\n0\r\n\r\n"); b = vlc_http_msg_read(m); assert(b != NULL); assert(b->i_buffer == 12); assert(!memcmp(b->p_buffer, "Hello there!", 12)); block_Release(b); conn_destroy(); /* test connection release before closing stream */ b = vlc_http_msg_read(m); assert(b == NULL); vlc_http_msg_destroy(m); /* Test HTTP/1.1 with content length */ conn_create(); s = stream_open(); assert(s != NULL); conn_send("HTTP/1.1 200 OK\r\nContent-Length: 8\r\n\r\n"); m = vlc_http_msg_get_initial(s); assert(m != NULL); conn_send("Bye bye!"); b = vlc_http_msg_read(m); assert(b != NULL); assert(b->i_buffer == 8); assert(!memcmp(b->p_buffer, "Bye bye!", 8)); block_Release(b); b = vlc_http_msg_read(m); assert(b == NULL); vlc_http_msg_destroy(m); conn_destroy(); return 0; }