48
client = hash_lookup(master_requests, POINTER_CAST(reply->tag));
49
client = hash_table_lookup(master_requests, POINTER_CAST(reply->tag));
49
50
if (client == NULL)
50
51
i_fatal("Master sent reply with unknown tag %u", reply->tag);
52
hash_remove(master_requests, POINTER_CAST(reply->tag));
53
hash_table_remove(master_requests, POINTER_CAST(reply->tag));
53
54
if (client != &destroyed_client) {
54
client_call_master_callback(client, reply->status);
55
client_call_master_callback(client, reply);
55
56
/* NOTE: client may be destroyed now */
59
60
void master_request_login(struct client *client, master_callback_t *callback,
60
61
unsigned int auth_pid, unsigned int auth_id)
62
struct master_login_request req;
64
struct master_login_request *req;
66
const unsigned char *data;
69
unsigned int cmd_tag_size;
65
71
i_assert(auth_pid != 0);
67
73
if (master_fd == -1) {
74
struct master_login_reply reply;
68
76
i_assert(closing_down);
69
callback(client, MASTER_LOGIN_STATUS_INTERNAL_ERROR);
77
memset(&reply, 0, sizeof(reply));
78
reply.status = MASTER_LOGIN_STATUS_INTERNAL_ERROR;
79
callback(client, &reply);
73
memset(&req, 0, sizeof(req));
74
req.version = MASTER_LOGIN_PROTOCOL_VERSION;
75
req.tag = ++master_tag_counter;
77
req.tag = ++master_tag_counter;
78
req.auth_pid = auth_pid;
79
req.auth_id = auth_id;
80
req.local_ip = client->local_ip;
81
req.remote_ip = client->ip;
83
data = i_stream_get_data(client->input, &size);
84
cmd_tag_size = client->auth_command_tag == NULL ? 0 :
85
strlen(client->auth_command_tag);
87
buf = buffer_create_dynamic(pool_datastack_create(),
88
sizeof(*req) + size + cmd_tag_size);
89
buffer_write(buf, sizeof(*req), client->auth_command_tag, cmd_tag_size);
90
buffer_write(buf, sizeof(*req) + cmd_tag_size, data, size);
91
req = buffer_get_space_unsafe(buf, 0, sizeof(*req));
92
req->version = MASTER_LOGIN_PROTOCOL_VERSION;
93
req->tag = ++master_tag_counter;
95
req->tag = ++master_tag_counter;
96
req->auth_pid = auth_pid;
97
req->auth_id = auth_id;
98
req->local_ip = client->local_ip;
99
req->remote_ip = client->ip;
100
req->cmd_tag_size = cmd_tag_size;
101
req->data_size = req->cmd_tag_size + size;
102
#if (LOGIN_MAX_INBUF_SIZE*2) != MASTER_LOGIN_MAX_DATA_SIZE
103
# error buffer max sizes unsynced
105
i_assert(req->data_size <= LOGIN_MAX_INBUF_SIZE);
83
107
if (fstat(client->fd, &st) < 0)
84
108
i_fatal("fstat(client) failed: %m");
109
req->ino = st.st_ino;
87
if (fd_send(master_fd, client->fd, &req, sizeof(req)) != sizeof(req))
111
ret = fd_send(master_fd, client->fd, buf->data, buf->used);
88
113
i_fatal("fd_send(%d) failed: %m", client->fd);
114
if ((size_t)ret != buf->used) {
115
i_fatal("fd_send() sent only %d of %d bytes",
116
(int)ret, (int)buf->used);
90
client->master_tag = req.tag;
119
client->master_tag = req->tag;
91
120
client->master_callback = callback;
93
hash_insert(master_requests, POINTER_CAST(req.tag), client);
122
hash_table_insert(master_requests, POINTER_CAST(req->tag), client);
96
125
void master_request_abort(struct client *client)
127
struct master_login_reply reply;
98
129
/* we're still going to get the reply from the master, so just
99
130
remember that we want to ignore it */
100
hash_update(master_requests, POINTER_CAST(client->master_tag),
131
hash_table_update(master_requests, POINTER_CAST(client->master_tag),
103
client_call_master_callback(client, MASTER_LOGIN_STATUS_INTERNAL_ERROR);
134
memset(&reply, 0, sizeof(reply));
135
reply.status = MASTER_LOGIN_STATUS_INTERNAL_ERROR;
136
client_call_master_callback(client, &reply);
106
139
void master_notify_state_change(enum master_login_state state)