int FlushBuffer(StreamSocket* sock) { // If GnuTLS has some data buffered, write it if (gbuffersize) return HandleWriteRet(sock, gnutls_record_uncork(this->sess, 0)); return 1; }
int cstp_uncork(worker_st *ws) { if (ws->session) { return gnutls_record_uncork(ws->session, GNUTLS_RECORD_WAIT); } else { int state = 0; #if defined(__linux__) setsockopt(ws->conn_fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state)); #elif defined(TCP_NOPUSH) setsockopt(ws->conn_fd, IPPROTO_TCP, TCP_NOPUSH, &state, sizeof(state)); #endif return 0; } }
static int gnutls_Shutdown(vlc_tls_t *tls, bool duplex) { gnutls_session_t session = tls->sys; ssize_t val; /* Flush any pending data */ val = gnutls_record_uncork(session, 0); if (val < 0) return gnutls_Error(tls, val); val = gnutls_bye(session, duplex ? GNUTLS_SHUT_RDWR : GNUTLS_SHUT_WR); if (val < 0) return gnutls_Error(tls, val); return 0; }
static ssize_t gnutls_Send (vlc_tls_t *tls, const struct iovec *iov, unsigned count) { gnutls_session_t session = tls->sys; ssize_t val; if (!gnutls_record_check_corked(session)) { gnutls_record_cork(session); while (count > 0) { val = gnutls_record_send(session, iov->iov_base, iov->iov_len); if (val < (ssize_t)iov->iov_len) break; iov++; count--; } } val = gnutls_record_uncork(session, 0); return (val < 0) ? gnutls_Error (tls, val) : val; }
static void do_gnutls_write(liGnuTLSFilter *f) { const ssize_t blocksize = 16*1024; /* 16k */ char *block_data; off_t block_len; ssize_t r; off_t write_max; #ifdef USE_CORK gboolean corked = FALSE; #endif liChunkQueue *cq = f->plain_drain.out; f_acquire(f); f->write_wants_read = FALSE; /* use space in (encrypted) outgoing buffer as amounts of bytes we try to write from (plain) output * don't care if we write a little bit more than the limit allowed */ write_max = li_chunkqueue_limit_available(f->crypt_source.out); LI_FORCE_ASSERT(write_max >= 0); /* we set a limit! */ if (0 == write_max) goto out; /* if we start writing, try to write at least blocksize bytes */ if (write_max < blocksize) write_max = blocksize; if (NULL != f->session && !f->initial_handshaked_finished && !do_gnutls_handshake(f, TRUE)) goto out; if (NULL == f->session) { f_abort_gnutls(f); goto out; } #ifdef USE_CORK if (0 != cq->length && cq->queue.length > 1) { corked = TRUE; gnutls_record_cork(f->session); } #endif do { GError *err = NULL; liChunkIter ci; if (0 == cq->length) break; ci = li_chunkqueue_iter(cq); switch (li_chunkiter_read(ci, 0, blocksize, &block_data, &block_len, &err)) { case LI_HANDLER_GO_ON: break; case LI_HANDLER_ERROR: if (NULL != err) { _ERROR(f->srv, f->wrk, f->log_context, "Couldn't read data from chunkqueue: %s", err->message); g_error_free(err); } /* fall through */ default: f_abort_gnutls(f); goto out; } r = gnutls_record_send(f->session, block_data, block_len); if (r <= 0) { do_handle_error(f, "gnutls_record_send", r, TRUE); goto out; } li_chunkqueue_skip(cq, r); write_max -= r; } while (r == block_len && write_max > 0); if (cq->is_closed && 0 == cq->length) { r = gnutls_bye(f->session, GNUTLS_SHUT_RDWR); switch (r) { case GNUTLS_E_SUCCESS: case GNUTLS_E_AGAIN: case GNUTLS_E_INTERRUPTED: f->plain_source.out->is_closed = TRUE; f->crypt_source.out->is_closed = TRUE; f->crypt_drain.out->is_closed = TRUE; li_stream_disconnect(&f->crypt_source); /* plain in -> crypt out */ f_close_gnutls(f); break; default: do_handle_error(f, "gnutls_bye", r, TRUE); f_abort_gnutls(f); break; } } else if (0 < cq->length && 0 != li_chunkqueue_limit_available(f->crypt_source.out)) { li_stream_again_later(&f->plain_drain); } out: #ifdef USE_CORK if (NULL != f->session && corked) { corked = TRUE; gnutls_record_uncork(f->session, 0); } #endif f_release(f); }
static void server(int fd) { int ret; char buffer[MAX_BUF + 1]; gnutls_session_t session; gnutls_anon_server_credentials_t anoncred; /* this must be called once in the program */ global_init(); if (debug) { gnutls_global_set_log_function(server_log_func); gnutls_global_set_log_level(4711); } gnutls_anon_allocate_server_credentials(&anoncred); gnutls_init(&session, GNUTLS_SERVER | GNUTLS_DATAGRAM); gnutls_dtls_set_mtu(session, 1500); /* avoid calling all the priority functions, since the defaults * are adequate. */ gnutls_priority_set_direct(session, "NONE:+VERS-DTLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-ECDH:+CURVE-ALL", NULL); gnutls_credentials_set(session, GNUTLS_CRD_ANON, anoncred); gnutls_transport_set_int(session, fd); do { ret = gnutls_handshake(session); } while (ret < 0 && gnutls_error_is_fatal(ret) == 0); if (ret < 0) { close(fd); gnutls_deinit(session); terminate(); fail("server: Handshake has failed (%s)\n\n", gnutls_strerror(ret)); } if (debug) success("server: Handshake was completed\n"); if (debug) success("server: TLS version is: %s\n", gnutls_protocol_get_name (gnutls_protocol_get_version(session))); /* see the Getting peer's information example */ /* print_info(session); */ /* avoid uninitialized warnings */ memset(buffer, 1, sizeof(buffer)); ret = gnutls_record_send(session, buffer, gnutls_dtls_get_data_mtu(session) + 12); if (ret != GNUTLS_E_LARGE_PACKET) { terminate(); fail("send[%d]: %s\n", __LINE__, gnutls_strerror(ret)); } ret = gnutls_record_send(session, buffer, gnutls_dtls_get_data_mtu(session) + 5048); if (ret != GNUTLS_E_LARGE_PACKET) { terminate(); fail("send[%d]: %s\n", __LINE__, gnutls_strerror(ret)); } ret = gnutls_record_send(session, buffer, gnutls_dtls_get_data_mtu(session)); if (ret < 0) { terminate(); fail("send[%d]: %s\n", __LINE__, gnutls_strerror(ret)); } gnutls_dtls_set_mtu(session, MAX_MTU); ret = gnutls_record_send(session, buffer, gnutls_dtls_get_data_mtu(session) + 12); if (ret != GNUTLS_E_LARGE_PACKET) { terminate(); fail("send[%d]: %s\n", __LINE__, gnutls_strerror(ret)); } ret = gnutls_record_send(session, buffer, gnutls_dtls_get_data_mtu(session) + 5048); if (ret != GNUTLS_E_LARGE_PACKET) { terminate(); fail("send[%d]: %s\n", __LINE__, gnutls_strerror(ret)); } ret = gnutls_record_send(session, buffer, gnutls_dtls_get_data_mtu(session)); if (ret > 16384 || ret < 0) { terminate(); fail("send[%d]: %s\n", __LINE__, gnutls_strerror(ret)); } /* test cork and uncork */ gnutls_record_cork(session); ret = gnutls_record_send(session, buffer, gnutls_dtls_get_data_mtu(session)); if (ret < 0) { terminate(); fail("send[%d]: %s\n", __LINE__, gnutls_strerror(ret)); } ret = gnutls_record_uncork(session, 0); if (ret < 0) { terminate(); fail("send[%d]: %s\n", __LINE__, gnutls_strerror(ret)); } gnutls_record_cork(session); ret = gnutls_record_send(session, buffer, gnutls_dtls_get_data_mtu(session) - 16); if (ret < 0) { terminate(); fail("send[%d]: %s\n", __LINE__, gnutls_strerror(ret)); } ret = gnutls_record_send(session, buffer, gnutls_dtls_get_data_mtu(session)); if (ret != GNUTLS_E_LARGE_PACKET) { terminate(); fail("send[%d]: %s\n", __LINE__, gnutls_strerror(ret)); } ret = gnutls_record_uncork(session, GNUTLS_RECORD_WAIT); if (ret < 0) { terminate(); fail("send[%d]: %s\n", __LINE__, gnutls_strerror(ret)); } /* do not wait for the peer to close the connection. */ gnutls_bye(session, GNUTLS_SHUT_WR); close(fd); gnutls_deinit(session); gnutls_anon_free_server_credentials(anoncred); gnutls_global_deinit(); if (debug) success("server: finished\n"); }