+ /* Apply QoS to the read data if necessary */
+ if (sock->qos) {
+ struct timeval curtime;
+ silc_gettimeofday(&curtime);
+
+ /* If we have passed the rate time limit, set our new time limit,
+ and zero the rate limit. */
+ if (!silc_compare_timeval(&curtime, &sock->qos->next_limit)) {
+ curtime.tv_sec++;
+ sock->qos->next_limit = curtime;
+ sock->qos->cur_rate = 0;
+ }
+ sock->qos->cur_rate++;
+
+ /* If we are not withing rate limit apply QoS for the read data */
+ if (sock->qos->cur_rate > sock->qos->read_rate) {
+ silc_socket_dup(sock);
+ silc_schedule_task_add(sock->qos->schedule, sock->sock,
+ silc_socket_read_qos, sock->qos,
+ sock->qos->limit_sec, sock->qos->limit_usec,
+ SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
+ silc_schedule_unset_listen_fd(sock->qos->schedule, sock->sock);
+
+ /* Check the byte limit as well, and do not return more than allowed */
+ if (sock->inbuf->len > sock->qos->read_limit_bytes) {
+ /* Hide the rest of the data from the buffer. */
+ sock->qos->data_len = sock->inbuf->len - sock->qos->read_limit_bytes;
+ silc_buffer_push_tail(sock->inbuf, sock->qos->data_len);
+ len = sock->inbuf->len;
+ } else {
+ /* Rate limit kicked in, do not return data yet */
+ return -2;
+ }
+ } else {
+ /* Check the byte limit, and do not return more than allowed */
+ if (sock->inbuf->len > sock->qos->read_limit_bytes) {
+ silc_socket_dup(sock);
+ silc_schedule_task_add(sock->qos->schedule, sock->sock,
+ silc_socket_read_qos, sock->qos,
+ sock->qos->limit_sec, sock->qos->limit_usec,
+ SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
+ silc_schedule_unset_listen_fd(sock->qos->schedule, sock->sock);
+
+ /* Hide the rest of the data from the buffer. */
+ sock->qos->data_len = sock->inbuf->len - sock->qos->read_limit_bytes;
+ silc_buffer_push_tail(sock->inbuf, sock->qos->data_len);
+ len = sock->inbuf->len;
+ }
+ }
+ }
+