1 /* -------------------------------------------------------------------------
2 * srvproto1.c - htun protocol 1 functions for the server side
3 * Copyright (C) 2002 Moshe Jacobson <moshe@runslinux.net>,
4 * Ola Nordström <ola@triblock.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * -------------------------------------------------------------------------
21 /* $Id: srvproto1.c,v 2.12 2002/08/16 01:49:47 jehsom Exp $ */
30 #include <arpa/inet.h>
36 #include "srvproto2.h"
40 int handle_f_p1( clidata_t
**clientp
) {
41 /* for now we just use f_p2 since they're identical */
42 return handle_f_p2(clientp
);
46 * Waits for one of the following conditions to become true before returning:
47 * 1. config->u.s.min_nack_delay time passes with no packets on sendq
48 * 2. sendq nonempty and config->u.s.packet_max_interval elapses since last packet queued
49 * 3. sendq contains at least config->u.s.packet_count_threshold packets.
50 * 4. config->u.s.max_response_delay has elapsed since the start of the function.
52 static inline size_t sendq_wait( queue_t
*q
) {
54 struct timeval t1
, t2
;
55 unsigned int nr_pkts
= 0;
56 unsigned long long ns
=0;
58 dprintf(log
, DEBUG
, "starting");
60 /* Get the start time */
61 gettimeofday(&t1
, NULL
);
63 /* Wait for at most config->u.s.min_nack_delay for data. Return if none */
64 ts
.tv_sec
= config
->u
.s
.min_nack_delay
/ 1000;
65 ts
.tv_nsec
= (config
->u
.s
.min_nack_delay
% 1000) * 1000000;
66 if( !q_timedwait(q
, &ts
) ) {
67 lprintf(log
, DEBUG
, "No data in queue after min nack delay (%lums)",
68 config
->u
.s
.min_nack_delay
);
73 /* If we have config->u.s.packet_count_threshold packets, return */
74 if( (nr_pkts
=q
->nr_nodes
) >= config
->u
.s
.packet_count_threshold
) {
76 "pkt count threshold of %d reached w/%d pkts.",
77 config
->u
.s
.packet_count_threshold
, nr_pkts
);
81 /* Put the current time in t2 */
82 gettimeofday(&t2
, NULL
);
84 /* Sleep till lastadd + config->u.s.packet_max_interval */
85 ns
= q
->lastadd
.tv_sec
* 1000000000
86 + q
->lastadd
.tv_usec
* 1000
87 + config
->u
.s
.packet_max_interval
* 1000000
88 - t2
.tv_sec
* 1000000000
91 if( ns
<= config
->u
.s
.packet_max_interval
* 1000000 ) {
92 ts
.tv_sec
= ns
/ 1000000000;
93 ts
.tv_nsec
= ns
% 1000000000;
96 "waiting %lu.%09lu sec for another pkt...",
97 ts
.tv_sec
, ts
.tv_nsec
);
101 /* If q->nr_nodes still hasn't changed, we can return */
102 if( nr_pkts
== q
->nr_nodes
) {
104 "no new packets since last check.");
110 gettimeofday(&t2
, NULL
);
113 "slept %lu.%06lu sec. %d pkts (%lu bytes) ready.",
114 t2
.tv_sec
- t1
.tv_sec
, t2
.tv_usec
- t1
.tv_usec
, q
->nr_nodes
,
119 static inline int send_queue( queue_t
*q
, int fd
, size_t amount
) {
125 dprintf(log
, DEBUG
, "no data to send to client");
126 fdprintf(fd
, RESPONSE_204
);
128 dprintf(log
, DEBUG
, "data to send.");
129 fdprintf(fd
, RESPONSE_200_NOBODY
, amount
);
131 while( sent
< amount
) {
132 if( (pkt
=q_remove(q
, 0, NULL
)) == NULL
) {
133 lprintf(log
, WARN
, "q_remove failed!");
136 if( (cnt
=write(fd
, pkt
, iplen(pkt
))) < 0 ) {
137 lprintf(log
, INFO
, "send failed: %s",
142 dprintf(log
, DEBUG
, "wrote %d bytes to client", cnt
);
147 lprintf(log
, INFO
, "Sent %d bytes in %d pkts.",
153 int handle_p_p1( clidata_t
*client
, char *hdrs
) {
155 queue_t
*sendq
= client
->sendq
;
156 int chan1
= client
->chan1
;
159 pkt
=getbody(chan1
, hdrs
, &tmp
);
162 send_queue(sendq
, chan1
, sendq
->totsize
);
164 dprintf(log
, DEBUG
, "returning");
169 int handle_s_p1( clidata_t
*client
, char *hdrs
) {
171 int expected
= get_content_length(hdrs
);
173 queue_t
*recvq
= client
->recvq
;
174 queue_t
*sendq
= client
->sendq
;
175 int chan1
= client
->chan1
;
179 "Client sent no Content-Length. Dropping.");
183 while( gotten
< expected
) {
184 if( (pkt
=get_packet(chan1
)) == NULL
) {
186 "get_packet() failed. Dropping client.");
187 fdprintf(chan1
, RESPONSE_500_ERR
);
191 gotten
+= iplen(pkt
);
192 dprintf(log
, DEBUG
, "got %d of %d bytes from client",
194 if( (q_add(recvq
, pkt
, Q_WAIT
, iplen(pkt
))) == -1 ) {
195 lprintf(log
, WARN
, "q_add() failed. Dropping client.");
196 fdprintf(chan1
, RESPONSE_500_ERR
);
201 lprintf(log
, INFO
, "Got %d bytes in %d pkts.",
204 send_queue(sendq
, chan1
, sendq_wait(client
->sendq
));
206 dprintf(log
, DEBUG
, "returning");