2016-11-09 13:18:16 +00:00
|
|
|
|
|
|
|
/*
|
2016-11-10 10:30:03 +00:00
|
|
|
* soprano.
|
2016-11-09 13:18:16 +00:00
|
|
|
*
|
|
|
|
* Protocol-level PostgreSQL client library.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
#include <so_macro.h>
|
|
|
|
#include <so_stream.h>
|
|
|
|
#include <so_header.h>
|
2016-11-16 12:02:33 +00:00
|
|
|
#include <so_key.h>
|
2016-11-09 13:18:16 +00:00
|
|
|
#include <so_beread.h>
|
|
|
|
|
2016-11-29 12:28:33 +00:00
|
|
|
void so_bestartup_init(so_bestartup_t *su)
|
2016-11-10 12:12:44 +00:00
|
|
|
{
|
|
|
|
su->is_cancel = 0;
|
2016-11-11 11:28:09 +00:00
|
|
|
su->database = NULL;
|
|
|
|
su->database_len = 0;
|
|
|
|
su->user = NULL;
|
|
|
|
su->user_len = 0;
|
2016-11-16 12:19:12 +00:00
|
|
|
so_keyinit(&su->key);
|
2016-11-10 12:12:44 +00:00
|
|
|
}
|
|
|
|
|
2016-11-29 12:28:33 +00:00
|
|
|
void so_bestartup_free(so_bestartup_t *su)
|
2016-11-10 12:12:44 +00:00
|
|
|
{
|
2016-11-11 11:28:09 +00:00
|
|
|
if (su->database)
|
|
|
|
free(su->database);
|
|
|
|
if (su->user)
|
|
|
|
free(su->user);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int
|
2016-11-29 12:28:33 +00:00
|
|
|
so_beread_options(so_bestartup_t *su, uint8_t *pos, uint32_t pos_size)
|
2016-11-11 11:28:09 +00:00
|
|
|
{
|
|
|
|
struct {
|
|
|
|
char *key;
|
|
|
|
int key_size;
|
|
|
|
char *value;
|
|
|
|
int value_size;
|
|
|
|
} argv[32];
|
|
|
|
int argc = 0;
|
|
|
|
|
|
|
|
int rc;
|
|
|
|
for (;;) {
|
|
|
|
if (so_unlikely(argc == 32))
|
|
|
|
return -1;
|
|
|
|
int size;
|
|
|
|
uint8_t *start;
|
|
|
|
uint8_t *end;
|
|
|
|
/* key */
|
|
|
|
start = pos;
|
|
|
|
rc = so_stream_readsz(&pos, &pos_size);
|
|
|
|
if (so_unlikely(rc == -1))
|
|
|
|
return -1;
|
|
|
|
end = pos;
|
|
|
|
size = end - start;
|
|
|
|
if (size == 1)
|
|
|
|
break;
|
|
|
|
argv[argc].key = (char*)start;
|
|
|
|
argv[argc].key_size = size;
|
|
|
|
/* value */
|
|
|
|
start = pos;
|
|
|
|
rc = so_stream_readsz(&pos, &pos_size);
|
|
|
|
if (so_unlikely(rc == -1))
|
|
|
|
return -1;
|
|
|
|
end = pos;
|
|
|
|
size = end - start;
|
|
|
|
argv[argc].value = (char*)start;
|
|
|
|
argv[argc].value_size = size;
|
|
|
|
argc++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* match common options */
|
|
|
|
int i = 0;
|
|
|
|
for (; i < argc; i++) {
|
|
|
|
if (argv[i].key_size == 5 && memcmp(argv[i].key, "user", 5) == 0) {
|
|
|
|
su->user = argv[i].value;
|
|
|
|
su->user_len = argv[i].value_size;
|
|
|
|
} else
|
|
|
|
if (argv[i].key_size == 9 && memcmp(argv[i].key, "database", 9) == 0) {
|
|
|
|
su->database = argv[i].value;
|
|
|
|
su->database_len = argv[i].value_size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* user is mandatory */
|
|
|
|
if (su->user == NULL)
|
|
|
|
return -1;
|
|
|
|
su->user = strdup(su->user);
|
|
|
|
if (su->user == NULL)
|
|
|
|
return -1;
|
|
|
|
if (su->database)
|
|
|
|
su->database = strdup(su->database);
|
|
|
|
else
|
|
|
|
su->database = strdup(su->user);
|
|
|
|
if (su->database == NULL) {
|
|
|
|
free(su->user);
|
|
|
|
su->user = NULL;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
2016-11-10 12:12:44 +00:00
|
|
|
}
|
|
|
|
|
2016-11-29 12:28:33 +00:00
|
|
|
int so_beread_startup(so_bestartup_t *su, uint8_t *data, uint32_t size)
|
2016-11-09 13:18:16 +00:00
|
|
|
{
|
|
|
|
uint32_t pos_size = size;
|
|
|
|
uint8_t *pos = data;
|
|
|
|
int rc;
|
2016-11-10 11:51:45 +00:00
|
|
|
uint32_t len;
|
|
|
|
rc = so_stream_read32(&len, &pos, &pos_size);
|
|
|
|
if (so_unlikely(rc == -1))
|
|
|
|
return -1;
|
2016-11-09 13:18:16 +00:00
|
|
|
uint32_t version;
|
|
|
|
rc = so_stream_read32(&version, &pos, &pos_size);
|
|
|
|
if (so_unlikely(rc == -1))
|
|
|
|
return -1;
|
|
|
|
switch (version) {
|
|
|
|
/* StartupMessage */
|
|
|
|
case 196608:
|
|
|
|
su->is_cancel = 0;
|
2016-11-11 11:28:09 +00:00
|
|
|
rc = so_beread_options(su, pos, pos_size);
|
|
|
|
if (so_unlikely(rc == -1))
|
|
|
|
return -1;
|
2016-11-09 13:18:16 +00:00
|
|
|
break;
|
|
|
|
/* CancelRequest */
|
|
|
|
case 80877102: {
|
|
|
|
su->is_cancel = 1;
|
2016-11-16 12:02:33 +00:00
|
|
|
rc = so_stream_read32(&su->key.key_pid, &pos, &pos_size);
|
2016-11-09 13:18:16 +00:00
|
|
|
if (so_unlikely(rc == -1))
|
2016-11-16 13:19:30 +00:00
|
|
|
return -1;
|
2016-11-16 12:02:33 +00:00
|
|
|
rc = so_stream_read32(&su->key.key, &pos, &pos_size);
|
2016-11-09 13:18:16 +00:00
|
|
|
if (so_unlikely(rc == -1))
|
|
|
|
return -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|