Cleaned up some of the comments ... removed vestiges of last year's doxygen experiment
[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 /*
15  *  register the timeout
16  *  signum signalhandler number
17  * \return signals
18  */
19 RETSIGTYPE timeout(int signum)
20 {
21         lprintf(1, "Connection timed out.\n");
22         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\n",
42                         strerror(errno));
43                 return(-1);
44         }
45
46         if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
47                 lprintf(1, "Can't connect: %s\n",
48                         strerror(errno));
49                 close(s);
50                 return(-1);
51         }
52
53         return s;
54 }
55
56
57 /*
58  *  Connect a TCP/IP socket
59  *  host the host to connect to
60  *  service the service on the host to call
61  */
62 int tcp_connectsock(char *host, char *service)
63 {
64         struct hostent *phe;
65         struct servent *pse;
66         struct protoent *ppe;
67         struct sockaddr_in sin;
68         int s;
69
70         memset(&sin, 0, sizeof(sin));
71         sin.sin_family = AF_INET;
72
73         pse = getservbyname(service, "tcp");
74         if (pse) {
75                 sin.sin_port = pse->s_port;
76         } else if ((sin.sin_port = htons((u_short) atoi(service))) == 0) {
77                 lprintf(1, "Can't get %s service entry\n", service);
78                 return (-1);
79         }
80         phe = gethostbyname(host);
81         if (phe) {
82                 memcpy(&sin.sin_addr, phe->h_addr, phe->h_length);
83         } else if ((sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE) {
84                 lprintf(1, "Can't get %s host entry: %s\n",
85                         host, strerror(errno));
86                 return (-1);
87         }
88         if ((ppe = getprotobyname("tcp")) == 0) {
89                 lprintf(1, "Can't get TCP protocol entry: %s\n",
90                         strerror(errno));
91                 return (-1);
92         }
93
94         s = socket(PF_INET, SOCK_STREAM, ppe->p_proto);
95         if (s < 0) {
96                 lprintf(1, "Can't create socket: %s\n", strerror(errno));
97                 return (-1);
98         }
99         signal(SIGALRM, timeout);
100         alarm(30);
101
102         if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
103                 lprintf(1, "Can't connect to %s.%s: %s\n",
104                         host, service, strerror(errno));
105                 close(s);
106                 return (-1);
107         }
108         alarm(0);
109         signal(SIGALRM, SIG_IGN);
110
111         return (s);
112 }
113
114
115
116
117 /*
118  *  Input binary data from socket
119  *  buf the buffer to get the input to
120  *  bytes the maximal number of bytes to read
121  */
122 inline void _serv_read(char *buf, int bytes, struct wcsession *WCC)
123 {
124         int len, rlen;
125
126         len = 0;
127         while (len < bytes) {
128                 rlen = read(WCC->serv_sock, &buf[len], bytes - len);
129                 if (rlen < 1) {
130                         lprintf(1, "Server connection broken: %s\n",
131                                 strerror(errno));
132                         wc_backtrace();
133                         close(WCC->serv_sock);
134                         WCC->serv_sock = (-1);
135                         WCC->connected = 0;
136                         WCC->logged_in = 0;
137                         memset(buf, 0, bytes);
138                         return;
139                 }
140                 len = len + rlen;
141         }
142 }
143
144 void serv_read(char *buf, int bytes)
145 {
146         struct wcsession *WCC = WC;
147         _serv_read(buf, bytes, WCC);
148 }
149
150 /*
151  *  input string from pipe
152  */
153 int serv_getln(char *strbuf, int bufsize)
154 {
155         struct wcsession *WCC = WC;
156         int ch, len;
157         char buf[2];
158
159         len = 0;
160         strbuf[0] = 0;
161         do {
162                 _serv_read(&buf[0], 1, WCC);
163                 ch = buf[0];
164                 if ((ch != 13) && (ch != 10)) {
165                         strbuf[len++] = ch;
166                 }
167         } while ((ch != 10) && (ch != 0) && (len < (bufsize-1)));
168         strbuf[len] = 0;
169 #ifdef SERV_TRACE
170         lprintf(9, "%3d>%s\n", WC->serv_sock, strbuf);
171 #endif
172         return len;
173 }
174
175 int StrBuf_ServGetln(StrBuf *buf)
176 {
177         const char *ErrStr;
178         int rc;
179
180         rc = StrBufTCP_read_line(buf, &WC->serv_sock, 0, &ErrStr);
181         if (rc < 0)
182         {
183                 lprintf(1, "Server connection broken: %s\n",
184                         ErrStr);
185                 wc_backtrace();
186                 WC->serv_sock = (-1);
187                 WC->connected = 0;
188                 WC->logged_in = 0;
189         }
190         return rc;
191 }
192
193 int StrBuf_ServGetBLOB(StrBuf *buf, long BlobSize)
194 {
195         const char *Err;
196         int rc;
197         
198         rc = StrBufReadBLOB(buf, &WC->serv_sock, 1, BlobSize, &Err);
199         if (rc < 0)
200         {
201                 lprintf(1, "Server connection broken: %s\n",
202                         Err);
203                 wc_backtrace();
204                 WC->serv_sock = (-1);
205                 WC->connected = 0;
206                 WC->logged_in = 0;
207         }
208         return rc;
209 }
210
211 /*
212  *  send binary to server
213  *  buf the buffer to write to citadel server
214  *  nbytes how many bytes to send to citadel server
215  */
216 void serv_write(const char *buf, int nbytes)
217 {
218         int bytes_written = 0;
219         int retval;
220         while (bytes_written < nbytes) {
221                 retval = write(WC->serv_sock, &buf[bytes_written],
222                                nbytes - bytes_written);
223                 if (retval < 1) {
224                         lprintf(1, "Server connection broken: %s\n",
225                                 strerror(errno));
226                         close(WC->serv_sock);
227                         WC->serv_sock = (-1);
228                         WC->connected = 0;
229                         WC->logged_in = 0;
230                         return;
231                 }
232                 bytes_written = bytes_written + retval;
233         }
234 }
235
236
237 /*
238  *  send line to server
239  *  string the line to send to the citadel server
240  */
241 void serv_puts(const char *string)
242 {
243 #ifdef SERV_TRACE
244         lprintf(9, "%3d<%s\n", WC->serv_sock, string);
245 #endif
246         serv_write(string, strlen(string));
247         serv_write("\n", 1);
248 }
249
250 /*
251  *  send line to server
252  *  string the line to send to the citadel server
253  */
254 void serv_putbuf(const StrBuf *string)
255 {
256 #ifdef SERV_TRACE
257         lprintf(9, "%3d<%s\n", WC->serv_sock, ChrPtr(string));
258 #endif
259         serv_write(ChrPtr(string), StrLength(string));
260         serv_write("\n", 1);
261 }
262
263
264 /*
265  *  convenience function to send stuff to the server
266  *  format the formatstring
267  *  ... the entities to insert into format 
268  */
269 void serv_printf(const char *format,...)
270 {
271         va_list arg_ptr;
272         char buf[SIZ];
273         size_t len;
274
275         va_start(arg_ptr, format);
276         vsnprintf(buf, sizeof buf, format, arg_ptr);
277         va_end(arg_ptr);
278
279         len = strlen(buf);
280         buf[len++] = '\n';
281         buf[len] = '\0';
282         serv_write(buf, len);
283 #ifdef SERV_TRACE
284         lprintf(9, "<%s", buf);
285 #endif
286 }
287