/** SEND user call */ tcp_error_t tcp_uc_send(tcp_conn_t *conn, void *data, size_t size, xflags_t flags) { size_t buf_free; size_t xfer_size; log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_uc_send()", conn->name); tcp_conn_lock(conn); if (conn->cstate == st_closed) { tcp_conn_unlock(conn); return TCP_ENOTEXIST; } if (conn->cstate == st_listen) { /* Change connection to active */ tcp_conn_sync(conn); } if (conn->snd_buf_fin) { tcp_conn_unlock(conn); return TCP_ECLOSING; } while (size > 0) { buf_free = conn->snd_buf_size - conn->snd_buf_used; while (buf_free == 0 && !conn->reset) { log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: buf_free == 0, waiting.", conn->name); fibril_condvar_wait(&conn->snd_buf_cv, &conn->lock); buf_free = conn->snd_buf_size - conn->snd_buf_used; } if (conn->reset) { tcp_conn_unlock(conn); return TCP_ERESET; } xfer_size = min(size, buf_free); /* Copy data to buffer */ memcpy(conn->snd_buf + conn->snd_buf_used, data, xfer_size); data += xfer_size; conn->snd_buf_used += xfer_size; size -= xfer_size; tcp_tqueue_new_data(conn); } tcp_tqueue_new_data(conn); tcp_conn_unlock(conn); return TCP_EOK; }
/** CLOSE user call */ tcp_error_t tcp_uc_close(tcp_conn_t *conn) { log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_uc_close(%p)", conn->name, conn); tcp_conn_lock(conn); if (conn->cstate == st_closed) { log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_uc_close - ENOTEXIST"); tcp_conn_unlock(conn); return TCP_ENOTEXIST; } if (conn->cstate == st_listen || conn->cstate == st_syn_sent) { log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_uc_close - listen/syn_sent"); tcp_conn_reset(conn); tcp_conn_unlock(conn); return TCP_EOK; } if (conn->snd_buf_fin) { log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_uc_close - ECLOSING"); tcp_conn_unlock(conn); return TCP_ECLOSING; } log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_uc_close - set snd_buf_fin"); conn->snd_buf_fin = true; tcp_tqueue_new_data(conn); tcp_conn_unlock(conn); return TCP_EOK; }
/** CLOSE user call */ tcp_error_t tcp_uc_close(tcp_conn_t *conn) { log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_uc_close()", conn->name); fibril_mutex_lock(&conn->lock); if (conn->cstate == st_closed) { fibril_mutex_unlock(&conn->lock); return TCP_ENOTEXIST; } if (conn->snd_buf_fin) { fibril_mutex_unlock(&conn->lock); return TCP_ECLOSING; } conn->snd_buf_fin = true; tcp_tqueue_new_data(conn); fibril_mutex_unlock(&conn->lock); return TCP_EOK; }