15a1c1c6998200697a708adcc23c62fb3e68abfc
[citadel.git] / webcit / tcp_sockets.c
1 /*
2  * $Id$
3  */
4
5 /*
6  * Uncomment this to log all communications with the Citadel server
7 #define SERV_TRACE 1
8  */
9
10
11 #include "webcit.h"
12 #include "webserver.h"
13
14 extern int DisableGzip;
15
16 /*
17  * register the timeout
18  */
19 RETSIGTYPE timeout(int signum)
20 {
21         lprintf(1, "Connection timed out; unable to reach citserver\n");
22         /* no exit here, since we need to server the connection unreachable thing. exit(3); */
23 }
24
25
26 /*
27  *  Connect a unix domain socket
28  *  sockpath where to open a unix domain socket
29  */
30 int uds_connectsock(char *sockpath)
31 {
32         struct sockaddr_un addr;
33         int s;
34
35         memset(&addr, 0, sizeof(addr));
36         addr.sun_family = AF_UNIX;
37         strncpy(addr.sun_path, sockpath, sizeof addr.sun_path);
38
39         s = socket(AF_UNIX, SOCK_STREAM, 0);
40         if (s < 0) {
41                 lprintf(1, "Can't create socket[%s]: %s\n",
42                         sockpath,
43                         strerror(errno));
44                 return(-1);
45         }
46
47         if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
48                 lprintf(1, "Can't connect [%s]: %s\n",
49                         sockpath,
50                         strerror(errno));
51                 close(s);
52                 return(-1);
53         }
54
55         return s;
56 }
57
58
59 /*
60  *  Connect a TCP/IP socket
61  *  host the host to connect to
62  *  service the service on the host to call
63  */
64 int tcp_connectsock(char *host, char *service)
65 {
66         int fdflags;
67         struct hostent *phe;
68         struct servent *pse;
69         struct protoent *ppe;
70         struct sockaddr_in sin;
71         int s;
72
73         memset(&sin, 0, sizeof(sin));
74         sin.sin_family = AF_INET;
75
76         pse = getservbyname(service, "tcp");
77         if (pse) {
78                 sin.sin_port = pse->s_port;
79         } else if ((sin.sin_port = htons((u_short) atoi(service))) == 0) {
80                 lprintf(1, "Can't get %s service entry\n", service);
81                 return (-1);
82         }
83         phe = gethostbyname(host);
84         if (phe) {
85                 memcpy(&sin.sin_addr, phe->h_addr, phe->h_length);
86         } else if ((sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE) {
87                 lprintf(1, "Can't get %s host entry: %s\n",
88                         host, strerror(errno));
89                 return (-1);
90         }
91         if ((ppe = getprotobyname("tcp")) == 0) {
92                 lprintf(1, "Can't get TCP protocol entry: %s\n",
93                         strerror(errno));
94                 return (-1);
95         }
96
97         s = socket(PF_INET, SOCK_STREAM, ppe->p_proto);
98         if (s < 0) {
99                 lprintf(1, "Can't create socket: %s\n", strerror(errno));
100                 return (-1);
101         }
102
103         fdflags = fcntl(s, F_GETFL);
104         if (fdflags < 0)
105                 lprintf(1, "unable to get socket flags!  %s.%s: %s \n",
106                         host, service, strerror(errno));
107         fdflags = fdflags | O_NONBLOCK;
108         if (fcntl(s, F_SETFD, fdflags) < 0)
109                 lprintf(1, "unable to set socket nonblocking flags!  %s.%s: %s \n",
110                         host, service, strerror(errno));
111
112         signal(SIGALRM, timeout);
113         alarm(30);
114
115         if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
116                 lprintf(1, "Can't connect to %s.%s: %s\n",
117                         host, service, strerror(errno));
118                 close(s);
119                 return (-1);
120         }
121         alarm(0);
122         signal(SIGALRM, SIG_IGN);
123
124         fdflags = fcntl(s, F_GETFL);
125         if (fdflags < 0)
126                 lprintf(1, "unable to get socket flags!  %s.%s: %s \n",
127                         host, service, strerror(errno));
128         fdflags = fdflags | O_NONBLOCK;
129         if (fcntl(s, F_SETFD, fdflags) < 0)
130                 lprintf(1, "unable to set socket nonblocking flags!  %s.%s: %s \n",
131                         host, service, strerror(errno));
132         return (s);
133 }
134
135
136
137 /*
138  *  input string from pipe
139  */
140 int serv_getln(char *strbuf, int bufsize)
141 {
142         wcsession *WCC = WC;
143         int len;
144
145         *strbuf = '\0';
146         StrBuf_ServGetln(WCC->MigrateReadLineBuf);
147         len = StrLength(WCC->MigrateReadLineBuf);
148         if (len > bufsize)
149                 len = bufsize - 1;
150         memcpy(strbuf, ChrPtr(WCC->MigrateReadLineBuf), len);
151         FlushStrBuf(WCC->MigrateReadLineBuf);
152         strbuf[len] = '\0';
153 #ifdef SERV_TRACE
154         lprintf(9, "%3d>%s\n", WC->serv_sock, strbuf);
155 #endif
156         return len;
157 }
158
159
160 int StrBuf_ServGetln(StrBuf *buf)
161 {
162         wcsession *WCC = WC;
163         const char *ErrStr = NULL;
164         int rc;
165
166         rc = StrBufTCP_read_buffered_line_fast(buf, 
167                                                WCC->ReadBuf, 
168                                                &WCC->ReadPos, 
169                                                &WCC->serv_sock, 
170                                                5, 1, 
171                                                &ErrStr);
172         if (rc < 0)
173         {
174                 lprintf(1, "Server connection broken: %s\n",
175                         ErrStr);
176                 wc_backtrace();
177                 WCC->serv_sock = (-1);
178                 WCC->connected = 0;
179                 WCC->logged_in = 0;
180         }
181         return rc;
182 }
183
184 int StrBuf_ServGetBLOBBuffered(StrBuf *buf, long BlobSize)
185 {
186         wcsession *WCC = WC;
187         const char *Err;
188         int rc;
189         
190         rc = StrBufReadBLOBBuffered(buf, 
191                                     WCC->ReadBuf, 
192                                     &WCC->ReadPos,
193                                     &WCC->serv_sock, 
194                                     1, 
195                                     BlobSize, 
196                                     NNN_TERM,
197                                     &Err);
198         if (rc < 0)
199         {
200                 lprintf(1, "Server connection broken: %s\n",
201                         Err);
202                 wc_backtrace();
203                 WCC->serv_sock = (-1);
204                 WCC->connected = 0;
205                 WCC->logged_in = 0;
206         }
207         return rc;
208 }
209
210 int StrBuf_ServGetBLOB(StrBuf *buf, long BlobSize)
211 {
212         wcsession *WCC = WC;
213         const char *Err;
214         int rc;
215         
216         WCC->ReadPos = NULL;
217         rc = StrBufReadBLOB(buf, &WCC->serv_sock, 1, BlobSize, &Err);
218         if (rc < 0)
219         {
220                 lprintf(1, "Server connection broken: %s\n",
221                         Err);
222                 wc_backtrace();
223                 WCC->serv_sock = (-1);
224                 WCC->connected = 0;
225                 WCC->logged_in = 0;
226         }
227         return rc;
228 }
229
230 /*
231  *  send binary to server
232  *  buf the buffer to write to citadel server
233  *  nbytes how many bytes to send to citadel server
234  */
235 void serv_write(const char *buf, int nbytes)
236 {
237         wcsession *WCC = WC;
238         int bytes_written = 0;
239         int retval;
240
241         FlushStrBuf(WCC->ReadBuf);
242         WCC->ReadPos = NULL;
243         while (bytes_written < nbytes) {
244                 retval = write(WCC->serv_sock, &buf[bytes_written],
245                                nbytes - bytes_written);
246                 if (retval < 1) {
247                         lprintf(1, "Server connection broken: %s\n",
248                                 strerror(errno));
249                         close(WCC->serv_sock);
250                         WCC->serv_sock = (-1);
251                         WCC->connected = 0;
252                         WCC->logged_in = 0;
253                         return;
254                 }
255                 bytes_written = bytes_written + retval;
256         }
257 }
258
259
260 /*
261  *  send line to server
262  *  string the line to send to the citadel server
263  */
264 void serv_puts(const char *string)
265 {
266         wcsession *WCC = WC;
267 #ifdef SERV_TRACE
268         lprintf(9, "%3d<%s\n", WC->serv_sock, string);
269 #endif
270         FlushStrBuf(WCC->ReadBuf);
271         WCC->ReadPos = NULL;
272
273         serv_write(string, strlen(string));
274         serv_write("\n", 1);
275 }
276
277 /*
278  *  send line to server
279  *  string the line to send to the citadel server
280  */
281 void serv_putbuf(const StrBuf *string)
282 {
283         wcsession *WCC = WC;
284 #ifdef SERV_TRACE
285         lprintf(9, "%3d<%s\n", WC->serv_sock, ChrPtr(string));
286 #endif
287         FlushStrBuf(WCC->ReadBuf);
288         WCC->ReadPos = NULL;
289
290         serv_write(ChrPtr(string), StrLength(string));
291         serv_write("\n", 1);
292 }
293
294
295 /*
296  *  convenience function to send stuff to the server
297  *  format the formatstring
298  *  ... the entities to insert into format 
299  */
300 void serv_printf(const char *format,...)
301 {
302         wcsession *WCC = WC;
303         va_list arg_ptr;
304         char buf[SIZ];
305         size_t len;
306
307         FlushStrBuf(WCC->ReadBuf);
308         WCC->ReadPos = NULL;
309
310         va_start(arg_ptr, format);
311         vsnprintf(buf, sizeof buf, format, arg_ptr);
312         va_end(arg_ptr);
313
314         len = strlen(buf);
315         buf[len++] = '\n';
316         buf[len] = '\0';
317         serv_write(buf, len);
318 #ifdef SERV_TRACE
319         lprintf(9, "<%s", buf);
320 #endif
321 }
322
323
324
325
326 int ClientGetLine(ParsedHttpHdrs *Hdr, StrBuf *Target)
327 {
328         const char *Error, *pch, *pchs;
329         int rlen, len, retval = 0;
330
331 #ifdef HAVE_OPENSSL
332         if (is_https) {
333                 int ntries = 0;
334                 if (StrLength(Hdr->ReadBuf) > 0) {
335                         pchs = ChrPtr(Hdr->ReadBuf);
336                         pch = strchr(pchs, '\n');
337                         if (pch != NULL) {
338                                 rlen = 0;
339                                 len = pch - pchs;
340                                 if (len > 0 && (*(pch - 1) == '\r') )
341                                         rlen ++;
342                                 StrBufSub(Target, Hdr->ReadBuf, 0, len - rlen);
343                                 StrBufCutLeft(Hdr->ReadBuf, len + 1);
344                                 return len - rlen;
345                         }
346                 }
347
348                 while (retval == 0) { 
349                                 pch = NULL;
350                                 pchs = ChrPtr(Hdr->ReadBuf);
351                                 if (*pchs != '\0')
352                                         pch = strchr(pchs, '\n');
353                                 if (pch == NULL) {
354                                         retval = client_read_sslbuffer(Hdr->ReadBuf, SLEEPING);
355                                         pchs = ChrPtr(Hdr->ReadBuf);
356                                         pch = strchr(pchs, '\n');
357                                 }
358                                 if (retval == 0) {
359                                         sleeeeeeeeeep(1);
360                                         ntries ++;
361                                 }
362                                 if (ntries > 10)
363                                         return 0;
364                 }
365                 if ((retval > 0) && (pch != NULL)) {
366                         rlen = 0;
367                         len = pch - pchs;
368                         if (len > 0 && (*(pch - 1) == '\r') )
369                                 rlen ++;
370                         StrBufSub(Target, Hdr->ReadBuf, 0, len - rlen);
371                         StrBufCutLeft(Hdr->ReadBuf, len + 1);
372                         return len - rlen;
373
374                 }
375                 else 
376                         return -1;
377         }
378         else 
379 #endif
380                 return StrBufTCP_read_buffered_line_fast(Target, 
381                                                          Hdr->ReadBuf,
382                                                          &Hdr->Pos,
383                                                          &Hdr->http_sock,
384                                                          5,
385                                                          1,
386                                                          &Error);
387 }
388
389 /* 
390  * This is a generic function to set up a master socket for listening on
391  * a TCP port.  The server shuts down if the bind fails.
392  *
393  * ip_addr      IP address to bind
394  * port_number  port number to bind
395  * queue_len    number of incoming connections to allow in the queue
396  */
397 int ig_tcp_server(char *ip_addr, int port_number, int queue_len)
398 {
399         struct protoent *p;
400         struct sockaddr_in sin;
401         int s, i;
402
403         memset(&sin, 0, sizeof(sin));
404         sin.sin_family = AF_INET;
405         if (ip_addr == NULL) {
406                 sin.sin_addr.s_addr = INADDR_ANY;
407         } else {
408                 sin.sin_addr.s_addr = inet_addr(ip_addr);
409         }
410
411         if (sin.sin_addr.s_addr == INADDR_NONE) {
412                 sin.sin_addr.s_addr = INADDR_ANY;
413         }
414
415         if (port_number == 0) {
416                 lprintf(1, "Cannot start: no port number specified.\n");
417                 exit(WC_EXIT_BIND);
418         }
419         sin.sin_port = htons((u_short) port_number);
420
421         p = getprotobyname("tcp");
422
423         s = socket(PF_INET, SOCK_STREAM, (p->p_proto));
424         if (s < 0) {
425                 lprintf(1, "Can't create a socket: %s\n", strerror(errno));
426                 exit(WC_EXIT_BIND);
427         }
428         /* Set some socket options that make sense. */
429         i = 1;
430         setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
431
432         #ifndef __APPLE__
433         fcntl(s, F_SETFL, O_NONBLOCK); /* maide: this statement is incorrect
434                                           there should be a preceding F_GETFL
435                                           and a bitwise OR with the previous
436                                           fd flags */
437         #endif
438         
439         if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
440                 lprintf(1, "Can't bind: %s\n", strerror(errno));
441                 exit(WC_EXIT_BIND);
442         }
443         if (listen(s, queue_len) < 0) {
444                 lprintf(1, "Can't listen: %s\n", strerror(errno));
445                 exit(WC_EXIT_BIND);
446         }
447         return (s);
448 }
449
450
451
452 /*
453  * Create a Unix domain socket and listen on it
454  * sockpath - file name of the unix domain socket
455  * queue_len - Number of incoming connections to allow in the queue
456  */
457 int ig_uds_server(char *sockpath, int queue_len)
458 {
459         struct sockaddr_un addr;
460         int s;
461         int i;
462         int actual_queue_len;
463
464         actual_queue_len = queue_len;
465         if (actual_queue_len < 5) actual_queue_len = 5;
466
467         i = unlink(sockpath);
468         if ((i != 0) && (errno != ENOENT)) {
469                 lprintf(1, "webcit: can't unlink %s: %s\n",
470                         sockpath, strerror(errno));
471                 exit(WC_EXIT_BIND);
472         }
473
474         memset(&addr, 0, sizeof(addr));
475         addr.sun_family = AF_UNIX;
476         safestrncpy(addr.sun_path, sockpath, sizeof addr.sun_path);
477
478         s = socket(AF_UNIX, SOCK_STREAM, 0);
479         if (s < 0) {
480                 lprintf(1, "webcit: Can't create a socket: %s\n",
481                         strerror(errno));
482                 exit(WC_EXIT_BIND);
483         }
484
485         if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
486                 lprintf(1, "webcit: Can't bind: %s\n",
487                         strerror(errno));
488                 exit(WC_EXIT_BIND);
489         }
490
491         if (listen(s, actual_queue_len) < 0) {
492                 lprintf(1, "webcit: Can't listen: %s\n",
493                         strerror(errno));
494                 exit(WC_EXIT_BIND);
495         }
496
497         chmod(sockpath, 0777);
498         return(s);
499 }
500
501
502
503
504 /*
505  * Read data from the client socket.
506  *
507  * sock         socket fd to read from
508  * buf          buffer to read into 
509  * bytes        number of bytes to read
510  * timeout      Number of seconds to wait before timing out
511  *
512  * Possible return values:
513  *      1       Requested number of bytes has been read.
514  *      0       Request timed out.
515  *      -1      Connection is broken, or other error.
516  */
517 int client_read_to(ParsedHttpHdrs *Hdr, StrBuf *Target, int bytes, int timeout)
518 {
519         const char *Error;
520         int retval = 0;
521
522 #ifdef HAVE_OPENSSL
523         if (is_https) {
524                 long bufremain;
525
526                 if (Hdr->Pos == NULL)
527                         Hdr->Pos = ChrPtr(Hdr->ReadBuf);
528                 bufremain = StrLength(Hdr->ReadBuf) - (Hdr->Pos - ChrPtr(Hdr->ReadBuf));
529
530                 if (bytes < bufremain)
531                         bufremain = bytes;
532                 StrBufAppendBufPlain(Target, Hdr->Pos, bufremain, 0);
533                 StrBufCutLeft(Hdr->ReadBuf, bufremain);
534
535                 if (bytes > bufremain) 
536                 {
537                         while ((StrLength(Hdr->ReadBuf) + StrLength(Target) < bytes) &&
538                                (retval >= 0))
539                                 retval = client_read_sslbuffer(Hdr->ReadBuf, timeout);
540                         if (retval >= 0) {
541                                 StrBufAppendBuf(Target, Hdr->ReadBuf, 0); /* todo: Buf > bytes? */
542 #ifdef HTTP_TRACING
543                                 write(2, "\033[32m", 5);
544                                 write(2, buf, bytes);
545                                 write(2, "\033[30m", 5);
546 #endif
547                                 return 1;
548                         }
549                         else {
550                                 lprintf(2, "client_read_ssl() failed\n");
551                                 return -1;
552                         }
553                 }
554                 else 
555                         return 1;
556         }
557 #endif
558
559         retval = StrBufReadBLOBBuffered(Target, 
560                                         Hdr->ReadBuf, 
561                                         &Hdr->Pos, 
562                                         &Hdr->http_sock, 
563                                         1, 
564                                         bytes,
565                                         O_TERM,
566                                         &Error);
567         if (retval < 0) {
568                 lprintf(2, "client_read() failed: %s\n",
569                         Error);
570                 return retval;
571         }
572
573 #ifdef HTTP_TRACING
574         write(2, "\033[32m", 5);
575         write(2, buf, bytes);
576         write(2, "\033[30m", 5);
577 #endif
578         return 1;
579 }
580
581
582 /*
583  * Begin buffering HTTP output so we can transmit it all in one write operation later.
584  */
585 void begin_burst(void)
586 {
587         if (WC->WBuf == NULL) {
588                 WC->WBuf = NewStrBufPlain(NULL, 32768);
589         }
590 }
591
592
593 /*
594  * Finish buffering HTTP output.  [Compress using zlib and] output with a Content-Length: header.
595  */
596 long end_burst(void)
597 {
598         wcsession *WCC = WC;
599         const char *ptr, *eptr;
600         long count;
601         ssize_t res = 0;
602         fd_set wset;
603         int fdflags;
604
605         if (!DisableGzip && (WCC->Hdr->HR.gzip_ok) && CompressBuffer(WCC->WBuf))
606         {
607                 hprintf("Content-encoding: gzip\r\n");
608         }
609
610         if (WCC->Hdr->HR.prohibit_caching)
611                 hprintf("Pragma: no-cache\r\nCache-Control: no-store\r\nExpires:-1\r\n");
612         hprintf("Content-length: %d\r\n\r\n", StrLength(WCC->WBuf));
613
614         ptr = ChrPtr(WCC->HBuf);
615         count = StrLength(WCC->HBuf);
616         eptr = ptr + count;
617
618 #ifdef HAVE_OPENSSL
619         if (is_https) {
620                 client_write_ssl(WCC->HBuf);
621                 client_write_ssl(WCC->WBuf);
622                 return (count);
623         }
624 #endif
625
626         
627 #ifdef HTTP_TRACING
628         
629         write(2, "\033[34m", 5);
630         write(2, ptr, StrLength(WCC->WBuf));
631         write(2, "\033[30m", 5);
632 #endif
633         if (WCC->Hdr->http_sock == -1)
634                 return -1;
635         fdflags = fcntl(WC->Hdr->http_sock, F_GETFL);
636
637         while ((ptr < eptr) && (WCC->Hdr->http_sock != -1)){
638                 if ((fdflags & O_NONBLOCK) == O_NONBLOCK) {
639                         FD_ZERO(&wset);
640                         FD_SET(WCC->Hdr->http_sock, &wset);
641                         if (select(WCC->Hdr->http_sock + 1, NULL, &wset, NULL, NULL) == -1) {
642                                 lprintf(2, "client_write: Socket select failed (%s)\n", strerror(errno));
643                                 return -1;
644                         }
645                 }
646
647                 if ((WCC->Hdr->http_sock == -1) || 
648                     (res = write(WCC->Hdr->http_sock, 
649                                  ptr,
650                                  count)) == -1) {
651                         lprintf(2, "client_write: Socket write failed (%s)\n", strerror(errno));
652                         wc_backtrace();
653                         return res;
654                 }
655                 count -= res;
656                 ptr += res;
657         }
658
659         ptr = ChrPtr(WCC->WBuf);
660         count = StrLength(WCC->WBuf);
661         eptr = ptr + count;
662
663 #ifdef HTTP_TRACING
664         
665         write(2, "\033[34m", 5);
666         write(2, ptr, StrLength(WCC->WBuf));
667         write(2, "\033[30m", 5);
668 #endif
669
670         while ((ptr < eptr) && (WCC->Hdr->http_sock != -1)) {
671                 if ((fdflags & O_NONBLOCK) == O_NONBLOCK) {
672                         FD_ZERO(&wset);
673                         FD_SET(WCC->Hdr->http_sock, &wset);
674                         if (select(WCC->Hdr->http_sock + 1, NULL, &wset, NULL, NULL) == -1) {
675                                 lprintf(2, "client_write: Socket select failed (%s)\n", strerror(errno));
676                                 return -1;
677                         }
678                 }
679
680                 if ((WCC->Hdr->http_sock == -1) || 
681                     (res = write(WCC->Hdr->http_sock, 
682                                  ptr,
683                                  count)) == -1) {
684                         lprintf(2, "client_write: Socket write failed (%s)\n", strerror(errno));
685                         wc_backtrace();
686                         return res;
687                 }
688                 count -= res;
689                 ptr += res;
690         }
691
692         return StrLength(WCC->WBuf);
693 }
694
695
696 /*
697  * lingering_close() a`la Apache. see
698  * http://www.apache.org/docs/misc/fin_wait_2.html for rationale
699  */
700 int lingering_close(int fd)
701 {
702         char buf[SIZ];
703         int i;
704         fd_set set;
705         struct timeval tv, start;
706
707         gettimeofday(&start, NULL);
708         if (fd == -1)
709                 return -1;
710         shutdown(fd, 1);
711         do {
712                 do {
713                         gettimeofday(&tv, NULL);
714                         tv.tv_sec = SLEEPING - (tv.tv_sec - start.tv_sec);
715                         tv.tv_usec = start.tv_usec - tv.tv_usec;
716                         if (tv.tv_usec < 0) {
717                                 tv.tv_sec--;
718                                 tv.tv_usec += 1000000;
719                         }
720                         FD_ZERO(&set);
721                         FD_SET(fd, &set);
722                         i = select(fd + 1, &set, NULL, NULL, &tv);
723                 } while (i == -1 && errno == EINTR);
724
725                 if (i <= 0)
726                         break;
727
728                 i = read(fd, buf, sizeof buf);
729         } while (i != 0 && (i != -1 || errno == EINTR));
730
731         return close(fd);
732 }
733
734 void
735 HttpNewModule_TCPSOCKETS
736 (ParsedHttpHdrs *httpreq)
737 {
738
739         httpreq->ReadBuf = NewStrBufPlain(NULL, SIZ * 4);
740 }
741
742 void
743 HttpDetachModule_TCPSOCKETS
744 (ParsedHttpHdrs *httpreq)
745 {
746
747         FlushStrBuf(httpreq->ReadBuf);
748         ReAdjustEmptyBuf(httpreq->ReadBuf, 4 * SIZ, SIZ);
749 }
750
751 void
752 HttpDestroyModule_TCPSOCKETS
753 (ParsedHttpHdrs *httpreq)
754 {
755
756         FreeStrBuf(&httpreq->ReadBuf);
757 }
758
759
760 void
761 SessionNewModule_TCPSOCKETS
762 (wcsession *sess)
763 {
764         sess->CLineBuf = NewStrBuf();
765         sess->MigrateReadLineBuf = NewStrBuf();
766 }
767
768 void 
769 SessionDestroyModule_TCPSOCKETS
770 (wcsession *sess)
771 {
772         FreeStrBuf(&sess->CLineBuf);
773         FreeStrBuf(&sess->ReadBuf);
774         FreeStrBuf(&sess->MigrateReadLineBuf);
775         if (sess->serv_sock > 0)
776                 close(sess->serv_sock);
777 }