version 0.9.6
[rofl0r-htun.git] / src / srvproto1.c
blob4edc67bd4b4f7871cc5ea56eb0c3d0a9d728de66
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 $ */
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <time.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <sys/time.h>
30 #include <arpa/inet.h>
32 #include "common.h"
33 #include "log.h"
34 #include "http.h"
35 #include "util.h"
36 #include "srvproto2.h"
37 #include "tun.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 ) {
53 struct timespec ts;
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);
69 goto end;
72 while( 1 ) {
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 ) {
75 lprintf(log, DEBUG,
76 "pkt count threshold of %d reached w/%d pkts.",
77 config->u.s.packet_count_threshold, nr_pkts);
78 goto end;
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
89 - t2.tv_usec * 1000;
91 if( ns <= config->u.s.packet_max_interval * 1000000 ) {
92 ts.tv_sec = ns / 1000000000;
93 ts.tv_nsec = ns % 1000000000;
95 lprintf(log, DEBUG,
96 "waiting %lu.%09lu sec for another pkt...",
97 ts.tv_sec, ts.tv_nsec);
98 nanosleep(&ts, NULL);
101 /* If q->nr_nodes still hasn't changed, we can return */
102 if( nr_pkts == q->nr_nodes ) {
103 lprintf(log, DEBUG,
104 "no new packets since last check.");
105 goto end;
108 end:
110 gettimeofday(&t2, NULL);
112 lprintf(log, DEBUG,
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,
115 q->totsize);
116 return q->totsize;
119 static inline int send_queue( queue_t *q, int fd, size_t amount ) {
120 unsigned int sent=0;
121 int cnt, totcnt=0;
122 char *pkt;
124 if( amount == 0 ) {
125 dprintf(log, DEBUG, "no data to send to client");
126 fdprintf(fd, RESPONSE_204);
127 } else {
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!");
134 return -1;
136 if( (cnt=write(fd, pkt, iplen(pkt))) < 0 ) {
137 lprintf(log, INFO, "send failed: %s",
138 strerror(errno));
139 free(pkt);
140 return -1;
142 dprintf(log, DEBUG, "wrote %d bytes to client", cnt);
143 totcnt++;
144 sent += iplen(pkt);
145 free(pkt);
147 lprintf(log, INFO, "Sent %d bytes in %d pkts.",
148 sent, totcnt);
150 return 0;
153 int handle_p_p1( clidata_t *client, char *hdrs ) {
154 char *pkt;
155 queue_t *sendq = client->sendq;
156 int chan1 = client->chan1;
157 int tmp;
159 pkt=getbody(chan1, hdrs, &tmp);
160 free(pkt);
162 send_queue(sendq, chan1, sendq->totsize);
164 dprintf(log, DEBUG, "returning");
165 return 0;
169 int handle_s_p1( clidata_t *client, char *hdrs ) {
170 int gotten=0, cnt=0;
171 int expected = get_content_length(hdrs);
172 char *pkt;
173 queue_t *recvq = client->recvq;
174 queue_t *sendq = client->sendq;
175 int chan1 = client->chan1;
177 if( !expected ) {
178 lprintf(log, WARN,
179 "Client sent no Content-Length. Dropping.");
180 return -1;
183 while( gotten < expected ) {
184 if( (pkt=get_packet(chan1)) == NULL ) {
185 lprintf(log, WARN,
186 "get_packet() failed. Dropping client.");
187 fdprintf(chan1, RESPONSE_500_ERR);
188 return -1;
190 cnt++;
191 gotten += iplen(pkt);
192 dprintf(log, DEBUG, "got %d of %d bytes from client",
193 gotten, expected);
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);
197 free(pkt);
198 return -1;
201 lprintf(log, INFO, "Got %d bytes in %d pkts.",
202 gotten, cnt);
204 send_queue(sendq, chan1, sendq_wait(client->sendq));
206 dprintf(log, DEBUG, "returning");
208 return 0;