summaryrefslogtreecommitdiff
path: root/libmanda.h
blob: 70140a73318ae93e32fad8b9f5cc067384a3bc80 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
#ifndef _LIBMANDA_LIBMANDA_H
#define _LIBMANDA_LIBMANDA_H

#include "libmanda-config.h"

#include <glib.h>

#include <sys/socket.h>

/* idlist */
typedef struct manda_IDList manda_IDList;

typedef enum {
	MANDA_FD_READ = 1,
	MANDA_FD_WRITE = 2
} manda_async_events;

typedef struct manda_async_ctrl manda_async_ctrl;
typedef struct manda_fd_watcher manda_fd_watcher;
typedef struct manda_timeout manda_timeout;

typedef struct manda_server_callbacks manda_server_callbacks;
typedef struct manda_server_connection manda_server_connection;
typedef struct manda_server_backend_use manda_server_backend_use;
typedef struct manda_server_backend manda_server_backend;
typedef struct manda_server manda_server;

typedef struct manda_client_backend_callbacks manda_client_backend_callbacks;
typedef struct manda_client_backend manda_client_backend;
typedef struct manda_client manda_client;

typedef struct manda_connection manda_connection;

typedef void (*manda_fd_watcher_cb)(manda_fd_watcher *watcher);

typedef void (*manda_new_fd_watcher)(gpointer srv, manda_fd_watcher *watcher);
typedef void (*manda_update_fd_watcher)(gpointer srv, manda_fd_watcher *watcher);
typedef void (*manda_destroy_fd_watcher)(gpointer srv, manda_fd_watcher *watcher);

typedef void (*manda_timeout_cb)(manda_timeout *timeout);

typedef void (*manda_new_timeout)(gpointer srv, manda_timeout *timeout);
typedef void (*manda_start_timeout)(gpointer srv, manda_timeout *timeout);
typedef void (*manda_destroy_timeout)(gpointer srv, manda_timeout *timeout);

typedef double (*manda_get_time)(gpointer srv);

struct manda_async_ctrl {
	manda_new_fd_watcher new_fd_watcher;
	manda_update_fd_watcher update_fd_watcher;
	manda_destroy_fd_watcher destroy_fd_watcher;

	manda_new_timeout new_timeout;
	manda_start_timeout start_timeout; /* one shot */
	manda_destroy_timeout destroy_timeout;

	manda_get_time get_time;
};

struct manda_fd_watcher {
	gpointer data; /* application data */
	manda_fd_watcher_cb callback;
	int events; /* bitmask of manda_async_events; "update_fd_watcher" needs to check this */
	int fd;     /* filedescriptor; doesn't get changed after "new_fd_watcher" */

	/* private from here */

	gpointer priv;
};

struct manda_timeout {
	gpointer data; /* application data */
	manda_timeout_cb callback;
	double timeout; /* absolute timestamp; check in start_timeout */

	/* private from here */

	gpointer priv;
};

/* Server API */

typedef void (*manda_server_new_connection_cb)(gpointer srv, manda_server_connection *con);
typedef void (*manda_server_closed_connection_cb)(gpointer srv, manda_server_connection *con);

typedef void (*manda_server_bind_backend_cb)(gpointer srv, manda_server_connection *con, GString *name, guint16 reqid);
typedef void (*manda_server_update_backend_cb)(gpointer srv, manda_server_backend *backend, guint ndx);
typedef void (*manda_server_release_backend_cb)(gpointer srv, manda_server_backend *backend, guint old_ndx, manda_server_backend_use *old_use);

struct manda_server_callbacks {
	manda_server_new_connection_cb new_connection;
	manda_server_closed_connection_cb closed_connection;

	manda_server_bind_backend_cb bind_backend;
	manda_server_update_backend_cb update_backend;
	manda_server_release_backend_cb release_backend;
};

struct manda_server_connection {
	gpointer data; /* application data */
	manda_server *srv;

	/* private from here */
	gint refcount;

	manda_connection *con;

	GPtrArray *backends; /* manda_server_backend_use */
	manda_IDList *idlist;
};

struct manda_server_backend_use {
	manda_server_connection *con;
	guint32 backend_id;

	guint32 last_load, last_workers;

	/* private from here */
	manda_server_backend *backend;
	guint ndx;
};

struct manda_server_backend {
	gpointer data; /* application data */
	GPtrArray *usage; /* array of manda_server_backend_use */
	guint32 sum_last_load;

	GString *addr;

	/* private from here */
	gint refcount;
};

struct manda_server {
	gint refcount;
	gpointer data; /* application data */
	GPtrArray *connections;

	/* private from here */
	const manda_async_ctrl *ctrl;
	const manda_server_callbacks *callbacks;

	GPtrArray *sockets;
};

manda_server* manda_server_new(gpointer srv, const manda_async_ctrl *ctrl, const manda_server_callbacks *callbacks);
void manda_server_acquire(manda_server *s);
void manda_server_release(manda_server *s);

/* close everything */
void manda_server_close(manda_server *s);

void manda_server_add_socket(manda_server *s, int fd, gpointer data);

void manda_server_con_close(manda_server_connection *con);

manda_server_backend *manda_server_backend_new(gpointer data, GString *addr);
void manda_server_backend_acquire(manda_server_backend *backend);
void manda_server_backend_release(manda_server_backend *backend);

gboolean manda_server_return_backend(manda_server_connection *con, gint16 reqid, manda_server_backend *backend);
void manda_server_return_backend_fail(manda_server_connection *con, gint16 reqid, GString *errmsg);
void manda_server_drop_backend(manda_server_backend *backend); /* tell all users that the backend is gone */

/* Client API */

typedef void (*manda_client_return_backend)(gpointer srv, manda_client_backend *backend);
/* backend will be free()d after the callback, don't keep the pointer; reason is NULL if the connection was closed */
typedef void (*manda_client_lost_backend)(gpointer srv, manda_client_backend *backend, const GString *reason);

struct manda_client_backend_callbacks {
	manda_client_return_backend return_backend;
	manda_client_lost_backend lost_backend;
};

struct manda_client_backend {
	gpointer data; /* application data */
	manda_client *client;
	GString *addr;

	/* private from here */

	const manda_client_backend_callbacks *callbacks;
	guint32 id;
};

struct manda_client { /* private */
	gint refcount;
	gpointer data; /* application data */
	gboolean closed;

	const manda_async_ctrl *ctrl;

	struct sockaddr *addr;
	socklen_t addrlen;

	manda_connection *con;

	GPtrArray *backends; /* manda_client_backend* */

	/* establish connection */
	double last_connect_ts;
	int sock_fd;
	manda_fd_watcher sock_watcher;
};

manda_client* manda_client_new(gpointer srv, const manda_async_ctrl *ctrl, struct sockaddr *addr, socklen_t addrlen);
void manda_client_close(manda_client *c);
void manda_client_acquire(manda_client *c);
void manda_client_release(manda_client *c);

manda_client_backend* manda_client_bind_backend(manda_client *c, GString *name, gpointer data, const manda_client_backend_callbacks *callbacks);
void manda_client_release_backend(manda_client_backend *backend);
void manda_client_update_backend(manda_client_backend *backend, guint32 load, guint32 workers);

#endif