]> err.no Git - sope/blob - sope-appserver/mod_ngobjweb/sns.c
INSTALL_ROOT_DIR patch
[sope] / sope-appserver / mod_ngobjweb / sns.c
1 /*
2   Copyright (C) 2000-2003 SKYRIX Software AG
3
4   This file is part of OGo
5
6   OGo is free software; you can redistribute it and/or modify it under
7   the terms of the GNU Lesser General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12   WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14   License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with OGo; see the file COPYING.  If not, write to the
18   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 */
21 // $Id$
22
23 #include "common.h"
24 #include "NGBufferedDescriptor.h"
25
26 extern int HEAVY_LOG;
27
28 //#define HTTP_DETAIL_LOG 1
29
30 #define SNS_HTTP_METHOD "POST"
31 #define SNS_LOOKUP_URL  "/snsd2/wa/lookupSession"
32 #define SNS_REQLINE     "reqline"
33 #define SNS_APPNAME     "appname"
34 #define SNS_COOKIES     "cookies"
35
36 static inline int _isPlistBreakChar(unsigned char c)
37 {
38     if (!apr_isalnum(c)) return 1;
39     
40     switch (c) {
41         case '_': case '@': case '#': case '$':
42         case '.': case '=': case ';': case ',':
43         case '{': case '}': case '(': case ')':
44         case '<': case '>': case '/': case '\\':
45         case '"':
46             return 1;
47             
48         default:
49             return 0;
50     }
51 }
52
53 static void _getSNSAddressForRequest(request_rec *_rq, struct sockaddr **_sns,
54                                      ngobjweb_dir_config *_cfg)
55 {
56   //extern struct sockaddr *sns;
57   struct sockaddr *result = NULL; //sns;
58   const char *socket;
59   
60   *_sns = NULL;
61   if (_rq == NULL) {
62     fprintf(stderr, "%s: missing request ...\n", __PRETTY_FUNCTION__);
63     return;
64   }
65   if (_cfg == NULL) {
66     ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, _rq->server,
67                  "SNS: missing directory config for request ..");
68     return;
69   }
70   
71     if ((socket = _cfg->snsPort)) {
72       long int port;
73       char     *end, *pos;
74       
75       if (_cfg->snsPortDomain == AF_UNIX) {
76         result = apr_palloc(_rq->pool, sizeof(struct sockaddr_un));
77         memset(result, 0, sizeof(struct sockaddr_un));
78         
79         ((struct sockaddr_un *)result)->sun_family = AF_UNIX;
80         strncpy(((struct sockaddr_un *)result)->sun_path,
81                 socket,
82                 sizeof(((struct sockaddr_un *)result)->sun_path) - 1);
83       }
84       else if (_cfg->snsPortDomain == AF_INET) {
85         /* the string contained a number - the port of an IP address */
86         struct sockaddr_in *snsi;
87         unsigned char *host;
88
89         /* try to convert port to number */
90         if ((pos = index(socket, ':'))) {
91           /* contains a ':' */
92           port = strtol((pos + 1), &end, 10);
93           
94           host = apr_palloc(_rq->pool, (pos - socket) + 3);
95           strncpy(host, socket, (pos - socket));
96           host[pos - socket] = '\0';
97         }
98         else {
99           host = "127.0.0.1";
100           port = strtol(socket, &end, 10);
101         }
102         
103         result = apr_palloc(_rq->pool, sizeof(struct sockaddr_in));
104         memset(result, 0, sizeof(struct sockaddr_in));
105         snsi = (struct sockaddr_in *)result;
106         
107         snsi->sin_addr.s_addr = apr_inet_addr(host);
108         
109         snsi->sin_family = AF_INET;
110         snsi->sin_port   = htons((short)(port & 0xFFFF));
111         
112         if (snsi->sin_addr.s_addr == -1) {
113           ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, _rq->server,
114                        "SNS: couldn't convert snsd IP address: %s", host);
115         }
116         if (HEAVY_LOG && 0) {
117           ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, _rq->server,
118                        "SNS: connect IP address: %s", host);
119         }
120       }
121       else {
122         ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, _rq->server,
123                      "SNS: unknown socket domain %i for SNS server "
124                      "(address=%s) !!!",
125                      _cfg->snsPortDomain, _cfg->snsPort);
126       }
127     }
128   
129   *_sns = result;
130 }
131
132 static void _logSNSConnect(request_rec *_rq, struct sockaddr *sns) {
133   if (sns == NULL) {
134     ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, _rq->server,
135                  "found no SNS socket address ...");
136     return;
137   }
138   if (sns->sa_family == AF_INET) {
139     struct sockaddr_in *snsi = (struct sockaddr_in *)sns;
140       
141     if (HEAVY_LOG) {
142       ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, _rq->server,
143                    "SNS: connecting INET socket (family=%d, ip=%s:%i) ...",
144                    sns->sa_family,
145                    inet_ntoa(snsi->sin_addr),
146                    ntohs(snsi->sin_port));
147     }
148   }
149   else if (sns->sa_family == AF_UNIX) {
150     if (HEAVY_LOG) {
151       ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, _rq->server,
152                    "SNS: connect UNIX socket (family=%d) ...",
153                    sns->sa_family);
154     }
155   }
156   else {
157     ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, _rq->server,
158                  "SNS: unknown socket address family: %d.",
159                  sns->sa_family);
160   }
161 }
162
163 void *_sendSNSQuery(request_rec *_rq, const char *_line,
164                     const char *_cookie,
165                     int *_domain, size_t *_len,
166                     const char *_appName,
167                     ngobjweb_dir_config *_cfg)
168 {
169   /*
170     Sends a query for the instance socket address to the session
171     name server.
172   */
173   NGBufferedDescriptor *toSNS = NULL;
174   int    fd;
175   struct sockaddr *sns;
176   int    failed = 0;
177   
178   _getSNSAddressForRequest(_rq, &sns, _cfg);
179   if (sns == NULL) {
180     return NULL;
181   }
182   
183   *_domain = 0;
184   *_len    = 0;
185   
186   if (_line   == NULL) _line   = "";
187   if (_cookie == NULL) _cookie = "";
188   
189   /* setup connection */
190   {
191     _logSNSConnect(_rq, sns);
192     
193     fd = socket(sns->sa_family, SOCK_STREAM, 0);
194     if (fd < 0) {
195       ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, _rq->server,
196                    "SNS: could not setup socket to SNS: %s.",
197                    strerror(errno));
198       return NULL;
199     }
200     
201     if (connect(fd, sns,
202                 (sns->sa_family == AF_INET)
203                 ? sizeof(struct sockaddr_in)
204                 : sizeof(struct sockaddr_un)) != 0) {
205       if (HEAVY_LOG) {
206         ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, _rq->server,
207                      "could not connect sns daemon %s: %s.",
208                      sns->sa_family == AF_UNIX
209                      ? ((struct sockaddr_un *)sns)->sun_path
210                      : "via ip",
211                      strerror(errno));
212       }
213       close(fd);
214       return NULL;
215     }
216     
217     toSNS = NGBufferedDescriptor_newWithOwnedDescriptorAndSize(fd, 1024);
218     if (toSNS == NULL) {
219       ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, _rq->server,
220                 "could not allocate buffered descriptor.");
221       close(fd);
222       return NULL;
223     }
224   }
225   
226   /* send request */
227   {
228     char c   = 50; // SNSLookupSession
229     int  len = strlen(_line);
230     
231     if (HEAVY_LOG) {
232       ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, _rq->server,
233                    "SNS: line %s cookie '%s'", _line, _cookie);
234     }
235     
236     /* send message code */
237     if (!NGBufferedDescriptor_safeWrite(toSNS, &c, 1)) {
238       failed = 1;
239       goto finish;
240     }
241     
242     /* send request line + space + appname */
243     len = strlen(_line) + 1 + strlen(_appName);
244     if (!NGBufferedDescriptor_safeWrite(toSNS, &len, sizeof(len))) {
245       failed = 2;
246       goto finish;
247     }
248     
249     if ((len = strlen(_line)) > 0) {
250       if (!NGBufferedDescriptor_safeWrite(toSNS, _line, len)) {
251         failed = 3;
252         goto finish;
253       }
254     }
255     if (!NGBufferedDescriptor_safeWrite(toSNS, " ", 1)) {
256       failed = 4;
257       goto finish;
258     }
259     if ((len = strlen(_appName)) > 0) {
260       if (!NGBufferedDescriptor_safeWrite(toSNS, _appName, len)) {
261         failed = 5;
262         goto finish;
263       }
264     }
265     
266     // send cookie
267     len = strlen(_cookie);
268     if (len > 2000) {
269       ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, _rq->server,
270                    "WARNING: cookie length > 2000 bytes (%i bytes): %s",
271                    len, _cookie);
272     }
273     if (!NGBufferedDescriptor_safeWrite(toSNS, &len, sizeof(len))) {
274       failed = 6;
275       goto finish;
276     }
277     if (len > 0) {
278       if (!NGBufferedDescriptor_safeWrite(toSNS, _cookie, len)) {
279         failed = 7;
280         goto finish;
281       }
282     }
283
284     if (!NGBufferedDescriptor_flush(toSNS)) {
285       failed = 8;
286       goto finish;
287     }
288     
289     if (HEAVY_LOG) {
290       ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, _rq->server,
291                    "SNS: reading response ..");
292     }
293     
294     // recv response
295     {
296       char *buffer;
297       int  domain;
298       int  size;
299
300       buffer = apr_palloc(_rq->pool, 1000);
301       memset(buffer, 0, 1000);
302       
303       if (!NGBufferedDescriptor_safeRead(toSNS, &domain, sizeof(domain))) {
304         failed = 9;
305         goto finish;
306       }
307       if (HEAVY_LOG) {
308         ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, _rq->server,
309                      "SNS:   domain: %i ..", domain);
310       }
311       
312       if (!NGBufferedDescriptor_safeRead(toSNS, &size, sizeof(size))) {
313         failed = 10;
314         goto finish;
315       }
316       if (HEAVY_LOG) {
317         ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, _rq->server,
318                      "SNS:   size: %i ..", size);
319       }
320       
321       if (size > 1024) {
322         ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, _rq->server,
323                      "SNS: size of returned address is too big (%i bytes) !",
324                      size);
325         goto finish;
326       }
327       
328       if (!NGBufferedDescriptor_safeRead(toSNS, buffer, size)) {
329         failed = 11;
330         goto finish;
331       }
332       
333       if (HEAVY_LOG) {
334         ap_log_error(__FILE__, __LINE__, APLOG_INFO, 0, _rq->server,
335                      "SNS: got address in domain %i, size is %i bytes !",
336                      domain, size);
337       }
338
339       *_domain = domain;
340       *_len    = size;
341       
342       if (toSNS) {
343         NGBufferedDescriptor_free(toSNS);
344         toSNS = NULL;
345       }
346       return buffer;
347     }
348   finish:
349     if (failed) {
350       ap_log_error(__FILE__, __LINE__, APLOG_ERR, 0, _rq->server,
351                    "SNS: lookup request failed (code=%i) !", failed);
352     }
353     if (toSNS) {
354       NGBufferedDescriptor_free(toSNS);
355       toSNS = NULL;
356     }
357   }
358   return NULL;
359 }