~ubuntu-branches/ubuntu/edgy/sope/edgy

« back to all changes in this revision

Viewing changes to sope-appserver/mod_ngobjweb/sns.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Ley
  • Date: 2005-08-19 16:53:31 UTC
  • Revision ID: james.westby@ubuntu.com-20050819165331-hs683wz1osm708pw
Tags: upstream-4.4rc.2
ImportĀ upstreamĀ versionĀ 4.4rc.2

Show diffs side-by-side

added added

removed removed

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