~drizzle-trunk/drizzle/development

1999.6.1 by kalebral at gmail
update Copyright strings to a more common format to help with creating the master debian copyright file
1
/* Copyright (C) 2008 PrimeBase Technologies GmbH, Germany
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
2
 *
3
 * PrimeBase Media Stream for MySQL
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
1802.10.2 by Monty Taylor
Update all of the copyright headers to include the correct address.
17
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
18
 *
19
 * Original author: Paul McCullagh
20
 * Continued development: Barry Leslie
21
 *
22
 * 2007-05-25
23
 *
24
 * H&G2JCtL
25
 *
26
 * Network interface.
27
 *
28
 */
29
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
30
#include "cslib/CSConfig.h"
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
31
#include <inttypes.h>
32
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
33
#include "defs_ms.h"
34
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
35
#include "cslib/CSGlobal.h"
36
#include "cslib/CSSocket.h"
37
#include "cslib/CSStrUtil.h"
38
#include "cslib/CSHTTPStream.h"
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
39
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
40
#include "connection_handler_ms.h"
41
#include "network_ms.h"
42
#include "open_table_ms.h"
43
#include "engine_ms.h"
44
#include "version_ms.h"
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
45
1548.2.10 by Barry.Leslie at PrimeBase
Merge from trunk.
46
//#include "mysql_ms.h"
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
47
48
u_long MSConnectionHandler::gMaxKeepAlive;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
49
50
MSConnectionHandler::MSConnectionHandler(CSThreadList *list):
51
	CSDaemon(list),
52
	amWaitingToListen(false),
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
53
	shuttingDown(false),
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
54
	lastUse(0),
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
55
	replyPending(false),
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
56
	iInputStream(NULL),
57
	iOutputStream(NULL),
58
	iTableURI(NULL)
59
{
60
}
61
62
void MSConnectionHandler::close()
63
{
64
	closeStream();
65
	freeRequestURI();
66
}
67
68
MSConnectionHandler *MSConnectionHandler::newHandler(CSThreadList *list)
69
{
70
	return new MSConnectionHandler(list);
71
}
72
73
/* Return false if not connection was openned, and the thread must quit. */
74
bool MSConnectionHandler::openStream()
75
{
76
	CSSocket		*sock;
77
	CSInputStream	*in;
78
	CSOutputStream	*out;
79
	
80
	enter_();
81
	if (!(sock = MSNetwork::openConnection(this)))
82
		return_(false);
83
	push_(sock);
84
	in = sock->getInputStream();
85
	in = CSBufferedInputStream::newStream(in);
86
	iInputStream = CSHTTPInputStream::newStream(in);
87
88
	out = sock->getOutputStream();
89
	out = CSBufferedOutputStream::newStream(out);
90
	iOutputStream = CSHTTPOutputStream::newStream(out);
91
	release_(sock);
92
	return_(true);
93
}
94
95
int MSConnectionHandler::getHTTPStatus(int err)
96
{
97
	int code;
98
99
	switch (err) {
100
		case MS_OK:						code = 200; break;
101
		case MS_ERR_ENGINE:				code = 500; break;
102
		case MS_ERR_UNKNOWN_TABLE:		code = 404; break;
103
		case MS_ERR_UNKNOWN_DB:			code = 404; break;
104
		case MS_ERR_DATABASE_DELETED:	code = 404; break;
105
		case MS_ERR_NOT_FOUND:			code = 404; break;
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
106
		case MS_ERR_REMOVING_REPO:		code = 404; break;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
107
		case MS_ERR_TABLE_LOCKED:		code = 412; break; // Precondition Failed
108
		case MS_ERR_INCORRECT_URL:		code = 404; break;
109
		case MS_ERR_AUTH_FAILED:		code = 403; break; // Forbidden
110
		default:						code = 500; break;
111
	}
112
	return code;
113
}
114
115
void MSConnectionHandler::writeException(const char *qualifier)
116
{
117
	int code;
118
119
	enter_();
120
	iOutputStream->clearHeaders();
121
	iOutputStream->clearBody();
122
	code = getHTTPStatus(myException.getErrorCode());
123
	iOutputStream->setStatus(code);
124
	iOutputStream->appendBody("<HTML><HEAD><TITLE>HTTP Error ");
125
	iOutputStream->appendBody(code);
126
	iOutputStream->appendBody(": ");
127
	iOutputStream->appendBody(CSHTTPOutputStream::getReasonPhrase(code));
128
	iOutputStream->appendBody("</TITLE></HEAD>");
129
	iOutputStream->appendBody("<BODY><H2>HTTP Error ");
130
	iOutputStream->appendBody(code);
131
	iOutputStream->appendBody(": ");
132
	iOutputStream->appendBody(CSHTTPOutputStream::getReasonPhrase(code));
133
	iOutputStream->appendBody("</H2>");
134
	if (qualifier)
135
		iOutputStream->appendBody(qualifier);
136
	iOutputStream->appendBody(EXCEPTION_REPLY_MESSAGE_PREFIX_TAG);
137
	iOutputStream->appendBody(myException.getMessage());
138
	iOutputStream->appendBody(EXCEPTION_REPLY_MESSAGE_SUFFIX_TAG);
139
	iOutputStream->appendBody(myException.getStackTrace());
140
	iOutputStream->appendBody(EXCEPTION_REPLY_STACK_TRACE_SUFFIX_TAG);
141
	iOutputStream->appendBody("MySQL ");
1548.2.24 by Barry.Leslie at PrimeBase
Reorganized code while fixing some minor problems.
142
	iOutputStream->appendBody(PBMSVersion::getCString());
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
143
	iOutputStream->appendBody(", PBMS ");
1548.2.24 by Barry.Leslie at PrimeBase
Reorganized code while fixing some minor problems.
144
	iOutputStream->appendBody(PBMSVersion::getCString());
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
145
	iOutputStream->appendBody("<br>Copyright &#169; 2009, PrimeBase Technologies GmbH</font></P></BODY></HTML>");
146
147
	replyPending = false;
148
	iOutputStream->writeHead();
149
	iOutputStream->writeBody();
150
	iOutputStream->flush();
151
	exit_();
152
}
153
154
void MSConnectionHandler::writeException()
155
{
156
	writeException(NULL);
157
}
158
159
void MSConnectionHandler::closeStream()
160
{
161
	enter_();
162
	if (iOutputStream) {
163
		if (replyPending) {
164
			try_(a) {
165
				writeException();
166
			}
167
			catch_(a) {
168
			}
169
			cont_(a);
170
		}
171
		iOutputStream->release();
172
		iOutputStream = NULL;
173
	}
174
	if (iInputStream) {
175
		iInputStream->release();
176
		iInputStream = NULL;
177
	}
178
	exit_();
179
}
180
181
void MSConnectionHandler::parseRequestURI()
182
{
183
	CSString	*uri = iInputStream->getRequestURI();
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
184
	uint32_t		pos = 0, end;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
185
	enter_();
186
	
187
	freeRequestURI();
188
	pos = uri->locate(0, "://");
189
	if (pos < uri->length())
190
		pos += 3;
191
	else
192
		pos = uri->skip(0, '/');
193
194
	// Table URI
195
	end = uri->locate(pos, '/');
196
	//end = uri->locate(uri->nextPos(end), '/'); I am not sure why this was done.
197
	//iTableURI = uri->substr(pos, end - pos);
198
	iTableURI = uri->substr(pos);
199
200
	exit_();
201
}
202
203
void MSConnectionHandler::freeRequestURI()
204
{
205
	if (iTableURI)
206
		iTableURI->release();
207
	iTableURI = NULL;
208
}
209
210
void MSConnectionHandler::writeFile(CSString *file_path)
211
{
212
	CSPath			*path;
213
	CSFile			*file;
214
215
	enter_();
216
	push_(file_path);
217
218
	path = CSPath::newPath(RETAIN(file_path));
219
	pop_(file_path);
220
	push_(path);
221
	if (path->exists()) {
222
		file = path->openFile(CSFile::READONLY);
223
		push_(file);
224
225
		iOutputStream->setContentLength((uint64_t) path->getSize());
226
		replyPending = false;
227
		iOutputStream->writeHead();
228
		
229
		CSStream::pipe(RETAIN(iOutputStream), file->getInputStream());
230
231
		release_(file);
232
	}
233
	else {
234
		myException.initFileError(CS_CONTEXT, path->getCString(), ENOENT);
235
		writeException();
236
	}
237
	release_(path);
238
239
	exit_();
240
}
241
242
/*
243
 * Request URI: /<blob URL>
244
* OR
245
 * Request URI: /<database>/<blob alias>
246
 */
1644.3.5 by Barry.Leslie at PrimeBase
Pulled out the pbms client lib. This has now been moved to its own project in launchpad lp:pbmslib.
247
void MSConnectionHandler::handleGet(bool info_only)
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
248
{
249
	const char	*bad_url_comment = "Incorrect URL: ";
250
	MSOpenTable	*otab;
251
	CSString	*info_request;
252
	CSString	*ping_request;
253
254
	enter_();
255
	self->myException.setErrorCode(0);
256
257
	iOutputStream->clearHeaders();
258
	iOutputStream->clearBody();
259
	//iOutputStream->setStatus(200); This is done in the send now.
260
	
261
	parseRequestURI();
262
263
	ping_request = iInputStream->getHeaderValue(MS_PING_REQUEST);
264
	if (ping_request) {
265
		MSDatabase *db;
266
		
267
		db = MSDatabase::getDatabase(ping_request, false);
268
		if (db) {
269
			push_(db);
270
			if (db->myBlobCloud->cl_getDefaultCloudRef()) {
271
				MSCloudInfo *info = db->myBlobCloud->cl_getCloudInfo();
272
				push_(info);
273
				iOutputStream->addHeader(MS_CLOUD_SERVER, info->getServer());
274
				release_(info);
275
			}
276
			release_(db);
277
		}
278
		
279
		iOutputStream->setStatus(200); 
280
		iOutputStream->writeHead();
281
		iOutputStream->flush();
282
		exit_();
283
284
	}
285
	
286
	info_request = iInputStream->getHeaderValue(MS_BLOB_INFO_REQUEST);
287
	if (info_request) {
288
		info_only = (info_request->compare("yes") == 0);
289
		info_request->release();
290
	}
291
	
292
  
293
	
294
	if (iTableURI->length() == 0)
295
		goto bad_url;
296
	
297
298
	MSBlobURLRec blob;
299
300
	if (iTableURI->equals("favicon.ico")) {
301
		iOutputStream->setStatus(200); 
302
		writeFile(iTableURI);
1548.2.24 by Barry.Leslie at PrimeBase
Reorganized code while fixing some minor problems.
303
	} else if (PBMSBlobURLTools::couldBeURL(iTableURI->getCString(), &blob)) {  
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
304
		uint64_t size, offset;
305
    
306
		if ((! info_only) && iInputStream->getRange(&size, &offset)) { 
307
			if (offset >= blob.bu_blob_size) {
308
				iOutputStream->setStatus(416); // Requested range not satisfiable.
309
				iOutputStream->writeHead();
310
				iOutputStream->flush();
311
				exit_();
312
			}
313
			
314
			if (size > (blob.bu_blob_size - offset))
315
				size = blob.bu_blob_size - offset;				
316
317
			iOutputStream->setRange(size, offset, blob.bu_blob_size);
318
		} else {
319
			size = blob.bu_blob_size;
320
			offset = 0;
321
		}
322
 
323
		if (blob.bu_type == MS_URL_TYPE_BLOB) {
324
			otab = MSTableList::getOpenTableByID(blob.bu_db_id, blob.bu_tab_id);
325
			frompool_(otab);
326
			otab->sendRepoBlob(blob.bu_blob_id, offset, size, blob.bu_auth_code, info_only, iOutputStream);
327
			backtopool_(otab);
328
		} else {
329
			MSRepoFile	*repo_file;
330
331
			if (!(otab = MSTableList::getOpenTableForDB(blob.bu_db_id))) {
332
				char buffer[CS_EXC_MESSAGE_SIZE];
333
				char id_str[12];
334
				
335
				snprintf(id_str, 12, "%"PRIu32"", blob.bu_db_id);
336
337
				cs_strcpy(CS_EXC_MESSAGE_SIZE, buffer, "Unknown database ID # ");
338
				cs_strcat(CS_EXC_MESSAGE_SIZE, buffer, id_str);
339
				CSException::throwException(CS_CONTEXT, MS_ERR_UNKNOWN_DB, buffer);
340
			}
341
			frompool_(otab);
342
			repo_file = otab->getDB()->getRepoFileFromPool(blob.bu_tab_id, false);
343
			frompool_(repo_file);
344
			repo_file->sendBlob(otab, blob.bu_blob_id, offset, size, blob.bu_auth_code, true, info_only, iOutputStream);
345
			backtopool_(repo_file);
346
			backtopool_(otab);
347
		}
348
	} 
349
	else { 
350
#ifdef HAVE_ALIAS_SUPPORT
351
352
		CSString	*db_name;
353
		CSString	*alias;
354
		MSDatabase * db;
355
		uint32_t repo_id;
356
		uint64_t blob_id;
357
		
358
		db_name = iTableURI->left("/");
359
		push_(db_name);
360
		alias = iTableURI->right("/");
361
		push_(alias);
362
363
		if (db_name->length() == 0 || alias->length() == 0 || alias->length() > BLOB_ALIAS_LENGTH) 
364
			goto bad_url;
365
		
366
		if (!(otab = MSTableList::getOpenTableForDB(MSDatabase::getDatabaseID(db_name->getCString(), true)))) {
367
			char buffer[CS_EXC_MESSAGE_SIZE];
368
369
			cs_strcpy(CS_EXC_MESSAGE_SIZE, buffer, "Unknown database: ");
370
			cs_strcat(CS_EXC_MESSAGE_SIZE, buffer, db_name->getCString());
371
			CSException::throwException(CS_CONTEXT, MS_ERR_UNKNOWN_DB, buffer);
372
		}
373
		frompool_(otab);
374
375
		db = otab->getDB();
376
		
377
		// lookup the blob alias in the database.
378
		if (!db->findBlobWithAlias(alias->getCString(), &repo_id, &blob_id)) {
379
			char buffer[CS_EXC_MESSAGE_SIZE];
380
381
			cs_strcpy(CS_EXC_MESSAGE_SIZE, buffer, "Unknown alias: ");
382
			cs_strcat(CS_EXC_MESSAGE_SIZE, buffer, alias->getCString());
383
			CSException::throwException(CS_CONTEXT, MS_ERR_NOT_FOUND, buffer);
384
		}
385
			
386
		MSRepoFile *repo_file = db->getRepoFileFromPool(repo_id, false);
387
		
388
		frompool_(repo_file);
389
		repo_file->sendBlob(otab, blob_id, 0, false, info_only, iOutputStream);
390
		backtopool_(repo_file);	
391
			
392
		backtopool_(otab);		
393
		
394
		release_(alias);
395
		release_(db_name);
396
397
#else
398
		char buffer[CS_EXC_MESSAGE_SIZE];
399
400
		cs_strcpy(CS_EXC_MESSAGE_SIZE, buffer, "Bad PBMS BLOB URL: ");
401
		cs_strcat(CS_EXC_MESSAGE_SIZE, buffer, iTableURI->getCString());
402
		CSException::throwException(CS_CONTEXT, MS_ERR_NOT_FOUND, buffer);
403
#endif
404
	}
405
	
406
407
	exit_();
408
409
	bad_url:
410
	char buffer[CS_EXC_MESSAGE_SIZE];
411
412
	cs_strcpy(CS_EXC_MESSAGE_SIZE, buffer, bad_url_comment);
413
	cs_strcat(CS_EXC_MESSAGE_SIZE, buffer, iInputStream->getRequestURI()->getCString());
414
	CSException::throwException(CS_CONTEXT, MS_ERR_INCORRECT_URL, buffer);
415
	exit_();
416
}
417
418
void MSConnectionHandler::handlePut()
419
{
1548.2.16 by Barry.Leslie at PrimeBase
Code cleanup.
420
	MSOpenTable *otab = NULL;
1548.2.17 by Barry.Leslie at PrimeBase
Possible solution to longjump clobber problem.
421
	uint32_t	db_id = 0, tab_id;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
422
423
	enter_();
424
	self->myException.setErrorCode(0);
425
426
	iOutputStream->clearHeaders();
427
	iOutputStream->clearBody();
428
	iOutputStream->setStatus(200);
429
	
430
	parseRequestURI();
431
	if (iTableURI->length() != 0)
432
		MSDatabase::convertTablePathToIDs(iTableURI->getCString(), &db_id, &tab_id, true);
433
1548.2.17 by Barry.Leslie at PrimeBase
Possible solution to longjump clobber problem.
434
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
435
	if ((!db_id) || !(otab = MSTableList::getOpenTableByID(db_id, tab_id))) {
436
		char buffer[CS_EXC_MESSAGE_SIZE];
437
438
		cs_strcpy(CS_EXC_MESSAGE_SIZE, buffer, "Incorrect URL: ");
439
		cs_strcat(CS_EXC_MESSAGE_SIZE, buffer, iInputStream->getRequestURI()->getCString());
440
		CSException::throwException(CS_CONTEXT, MS_ERR_INCORRECT_URL, buffer);
441
	}
1548.2.17 by Barry.Leslie at PrimeBase
Possible solution to longjump clobber problem.
442
	frompool_(otab);
443
	
444
	uint64_t			blob_len, cloud_blob_len = 0;
445
	PBMSBlobURLRec	bh;
446
	size_t			handle_len;
447
	uint16_t			metadata_size = 0; 
448
	CSStringBuffer	*metadata;
449
	
450
	new_(metadata, CSStringBuffer(80));
451
	push_(metadata);
452
	
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
453
	 if (! iInputStream->getContentLength(&blob_len)) {
1892.2.1 by Monty Taylor
Fixes most of the lintian warnings
454
		CSException::throwException(CS_CONTEXT, CS_ERR_MISSING_HTTP_HEADER, "Missing content length header");
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
455
	 }
456
	 
1548.2.17 by Barry.Leslie at PrimeBase
Possible solution to longjump clobber problem.
457
	
458
	// Collect the meta data.
459
	for (uint32_t i = 0; i < iInputStream->numHeaders(); i++) {
460
		CSHeader *header = iInputStream->getHeader(i);
461
		const char *name = header->getNameCString();
462
		
463
		push_(header);
464
		
465
		if (!strcmp(name, MS_BLOB_SIZE)) { // The actual BLOB data size if it is being stored in a cloud.
466
			sscanf(header->getValueCString(), "%"PRIu64"", &cloud_blob_len);
467
		}
468
			
469
		if (name && otab->getDB()->isValidHeaderField(name)) {
470
			uint16_t rec_size, name_size, value_size;
471
			const char *value = header->getValueCString();
472
			char *buf;
473
			if (!value)
474
				value = "";
475
				
476
			name_size = strlen(name);
477
			value_size = strlen(value);
478
			
479
			rec_size = name_size + value_size + 2;
480
			metadata->setLength(metadata_size + rec_size);
481
			
482
			buf = metadata->getBuffer(metadata_size);
483
			metadata_size += rec_size;
484
			
485
			memcpy(buf, name, name_size);
486
			buf += name_size;
487
			*buf = 0; buf++;
488
			
489
			memcpy(buf, value, value_size);
490
			buf += value_size;
491
			*buf = 0;
492
		}
493
		
494
		release_(header);
495
	}
496
	
497
	if (blob_len) {
498
		char hex_checksum[33];
499
		Md5Digest checksum;
500
		
501
		otab->createBlob(&bh, blob_len, metadata->getBuffer(0), metadata_size, RETAIN(iInputStream), NULL, &checksum);
502
503
		cs_bin_to_hex(33, hex_checksum, 16, checksum.val);
504
		iOutputStream->addHeader(MS_CHECKSUM_TAG, hex_checksum);
505
	} else { // If there is no BLOB data then the client will send it to the cloud server themselves.
506
		if (!cloud_blob_len)
507
			CSException::throwException(CS_CONTEXT, CS_ERR_MISSING_HTTP_HEADER, "Missing BLOB length header for cloud BLOB.");
508
		if (otab->getDB()->myBlobType == MS_CLOUD_STORAGE) {
509
			CloudKeyRec cloud_key;
510
			uint32_t signature_time;
511
			char time_str[20];
512
			CloudDB *cloud = otab->getDB()->myBlobCloud;
513
			MSCloudInfo *info;
514
			
515
			
516
			cloud->cl_getNewKey(&cloud_key);
517
			otab->createBlob(&bh, cloud_blob_len, metadata->getBuffer(0), metadata_size, NULL, &cloud_key);
518
			
519
			CSString *signature;
520
			signature = cloud->cl_getSignature(&cloud_key, iInputStream->getHeaderValue("Content-Type"), &signature_time);
521
			push_(signature);
522
			
523
			info = cloud->cl_getCloudInfo(cloud_key.cloud_ref);
524
			push_(info);
525
			iOutputStream->addHeader(MS_CLOUD_SERVER, info->getServer());
526
			iOutputStream->addHeader(MS_CLOUD_BUCKET, info->getBucket());
527
			iOutputStream->addHeader(MS_CLOUD_KEY, info->getPublicKey());
528
			iOutputStream->addHeader(MS_CLOUD_OBJECT_KEY, cloud->cl_getObjectKey(&cloud_key));
529
			iOutputStream->addHeader(MS_BLOB_SIGNATURE, signature->getCString());
530
			release_(info);
531
			
532
			release_(signature);
533
			snprintf(time_str, 20, "%"PRIu32"", signature_time);
534
			iOutputStream->addHeader(MS_BLOB_DATE, time_str);
535
			
536
		} else {
537
			// If the database is not using cloud storage then the client will
538
			// resend the BLOB data as a normal BLOB when it fails to get the
539
			// expected cloud server infor headers back.
540
			bh.bu_data[0] = 0;
541
		}
542
	}
543
	handle_len = strlen(bh.bu_data);
544
	iOutputStream->setContentLength(handle_len);
545
546
	replyPending = false;
547
	iOutputStream->writeHead();
548
	iOutputStream->write(bh.bu_data, handle_len);
549
	iOutputStream->flush();
550
551
	release_(metadata);
552
553
	backtopool_(otab);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
554
555
	exit_();
556
}
557
558
void MSConnectionHandler::serviceConnection()
559
{
560
	const char	*method;
561
	bool		threadStarted = false;
562
563
	for (;;) {
564
		iInputStream->readHead();
565
		if (iInputStream->expect100Continue()) {			
566
			iOutputStream->clearHeaders();
567
			iOutputStream->clearBody();
568
			iOutputStream->setStatus(100);
569
			iOutputStream->setContentLength(0);
570
			iOutputStream->writeHead();
571
			iOutputStream->flush();
572
		}
573
		
574
		if (!(method = iInputStream->getMethod()))
575
			break;
576
		if (!threadStarted /* && iInputStream->keepAlive() */) { // Ignore keepalive: Never trust the client!
577
			/* Start another service handler if no threads
578
			 * are waiting to listen!
579
			 */
580
			threadStarted = true;
581
			if (!MSNetwork::gWaitingToListen)
582
				MSNetwork::startConnectionHandler();
583
		}
584
		replyPending = true;
585
		if (strcmp(method, "GET") == 0)
1644.3.5 by Barry.Leslie at PrimeBase
Pulled out the pbms client lib. This has now been moved to its own project in launchpad lp:pbmslib.
586
			handleGet(false);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
587
		else if (strcmp(method, "PUT") == 0 ||
588
			strcmp(method, "POST") == 0)
589
			handlePut();
1644.3.5 by Barry.Leslie at PrimeBase
Pulled out the pbms client lib. This has now been moved to its own project in launchpad lp:pbmslib.
590
		else if (strcmp(method, "HEAD"))
591
			handleGet(true);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
592
		else
593
			CSException::throwCoreError(CS_CONTEXT, CS_ERR_UNKNOWN_METHOD, method);
594
	}
595
}
596
1548.2.11 by Barry.Leslie at PrimeBase
Removed libxml reqirement by using a home grown xml parser.
597
bool MSConnectionHandler::initializeWork()
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
598
{
599
	return true;
600
}
601
602
/*
603
 * Return false if no connection this thread should quit!
604
 */
605
bool MSConnectionHandler::doWork()
606
{
607
	enter_();
608
609
	/* Open a connection: */
610
	if (!openStream()) {
611
		myMustQuit = true;
612
		return_(false);
613
	}
614
615
	/* Do the work for the connection: */
616
	serviceConnection();
617
618
	/* Close the connection: */
619
	close();
620
621
	return_(false);
622
}
623
1548.2.11 by Barry.Leslie at PrimeBase
Removed libxml reqirement by using a home grown xml parser.
624
void *MSConnectionHandler::completeWork()
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
625
{
626
	shuttingDown = true;
627
	/* Close the stream, if it was openned. */
628
	close();
629
630
	return NULL;
631
}
632
633
bool MSConnectionHandler::handleException()
634
{
635
	if (!myMustQuit) {
636
		/* Start another handler if required: */
637
		if (!MSNetwork::gWaitingToListen)
638
			MSNetwork::startConnectionHandler();
639
	}
640
	close();
641
	if (!shuttingDown)
642
		CSDaemon::handleException();
643
	return false;
644
}
645
646