2
* Copyright 2004 Apache Software Foundation
4
* Licensed under the Apache License, Version 2.0 (the "License"); you
5
* may not use this file except in compliance with the License. You
6
* may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13
* implied. See the License for the specific language governing
14
* permissions and limitations under the License.
16
* Originally developed by Gregory Trubetskoy.
21
* $Id: serverobject.c,v 1.22 2004/02/16 19:47:27 grisha Exp $
25
#include "mod_python.h"
29
** MpServer_FromServer
31
* This routine creates a Python serverobject given an Apache
36
PyObject * MpServer_FromServer(server_rec *s)
40
result = PyObject_New(serverobject, &MpServer_Type);
42
return PyErr_NoMemory();
44
result->dict = PyDict_New();
46
return PyErr_NoMemory();
51
return (PyObject *)result;
55
** server.get_config(server self)
57
* Returns the config directives set through Python* apache directives.
58
* unlike req.get_config, this one returns the per-server config
61
static PyObject * server_get_config(serverobject *self)
64
(py_config *) ap_get_module_config(self->server->module_config,
66
return MpTable_FromTable(conf->directives);
70
** server.register_cleanup(req, handler, data)
72
* same as request.register_cleanup, except the server pool is used.
73
* the server pool gets destroyed before the child dies or when the
74
* whole process dies in multithreaded situations.
77
static PyObject *server_register_cleanup(serverobject *self, PyObject *args)
81
PyObject *handler = NULL;
82
PyObject *data = NULL;
83
requestobject *req = NULL;
85
if (! PyArg_ParseTuple(args, "OO|O", &req, &handler, &data))
88
if (! MpRequest_Check(req)) {
89
PyErr_SetString(PyExc_ValueError,
90
"first argument must be a request object");
93
else if(!PyCallable_Check(handler)) {
94
PyErr_SetString(PyExc_ValueError,
95
"second argument must be a callable object");
99
ci = (cleanup_info *)malloc(sizeof(cleanup_info));
100
ci->request_rec = NULL;
101
ci->server_rec = self->server;
103
ci->handler = handler;
104
ci->interpreter = req->interpreter;
114
apr_pool_cleanup_register(child_init_pool, ci, python_cleanup,
115
apr_pool_cleanup_null);
121
static PyMethodDef server_methods[] = {
122
{"get_config", (PyCFunction) server_get_config, METH_NOARGS},
123
{"register_cleanup", (PyCFunction) server_register_cleanup, METH_VARARGS},
124
{ NULL, NULL } /* sentinel */
129
These are offsets into the Apache server_rec structure.
130
They are accessed via getset functions. Note that the types
131
specified here are irrelevant if a function other than
132
getreq_recmbr() is used. E.g. bytes_sent is a long long,
133
and is retrieved via getreq_recmbr_off() which ignores what's
137
#define OFF(x) offsetof(server_rec, x)
139
static struct PyMemberDef server_rec_mbrs[] = {
140
{"defn_name", T_STRING, OFF(defn_name)},
141
{"defn_line_number", T_INT, OFF(defn_line_number)},
142
{"server_admin", T_STRING, OFF(server_admin)},
143
{"server_hostname", T_STRING, OFF(server_hostname)},
144
{"port", T_SHORT, OFF(port)},
145
{"error_fname", T_STRING, OFF(error_fname)},
146
{"loglevel", T_INT, OFF(loglevel)},
147
{"is_virtual", T_INT, OFF(is_virtual)},
148
/* XXX implement module_config ? */
149
/* XXX implement lookup_defaults ? */
150
/* XXX implement server_addr_rec ? */
151
{"timeout", T_LONG, OFF(timeout)},
152
{"keep_alive_timeout", T_LONG, OFF(keep_alive_timeout)},
153
{"keep_alive_max", T_INT, OFF(keep_alive_max)},
154
{"keep_alive", T_INT, OFF(keep_alive)},
155
/* XXX send_buffer_size gone. where? document */
156
/*{"send_buffer_size", T_INT, OFF(send_buffer_size), RO},*/
157
{"path", T_STRING, OFF(path)},
158
{"pathlen", T_INT, OFF(pathlen)},
159
{"names", T_OBJECT, OFF(names)},
160
{"wild_names", T_OBJECT, OFF(wild_names)},
161
/* XXX server_uid and server_gid seem gone. Where? Document. */
162
/*{"server_uid", T_INT, OFF(server_uid), RO},*/
163
/*{"server_gid", T_INT, OFF(server_gid), RO},*/
164
/* XXX Document limit* below. Make RW? */
165
{"limit_req_line", T_INT, OFF(limit_req_line)},
166
{"limit_req_fieldsize", T_INT, OFF(limit_req_fieldsize)},
167
{"limit_req_fields", T_INT, OFF(limit_req_fields)},
168
{NULL} /* Sentinel */
174
* Retrieves server_rec structure members
177
static PyObject *getsrv_recmbr(serverobject *self, void *name)
179
return PyMember_GetOne((char*)self->server,
180
find_memberdef(server_rec_mbrs, name));
183
/* we don't need setsrv_recmbr for now */
186
** getsrv_recmbr_time
188
* Retrieves apr_time_t server_rec members
191
static PyObject *getsrv_recmbr_time(serverobject *self, void *name)
193
PyMemberDef *md = find_memberdef(server_rec_mbrs, name);
194
char *addr = (char *)self->server + md->offset;
195
apr_time_t time = *(apr_time_t*)addr;
196
return PyFloat_FromDouble(time*0.000001);
202
* For array headers that will get converted to tuple
205
static PyObject *getsrv_recmbr_ah(serverobject *self, void *name)
207
const PyMemberDef *md = find_memberdef(server_rec_mbrs, name);
208
apr_array_header_t *ah =
209
(apr_array_header_t *)((char *)self->server + md->offset);
211
return tuple_from_array_header(ah);
217
* A getter func that creates an object as needed.
220
static PyObject *getmakeobj(serverobject* self, void *objname)
222
char *name = (char *)objname;
223
PyObject *result = NULL;
225
if (strcmp(name, "next") == 0) {
226
if (!self->next && self->server->next)
227
self->next = MpServer_FromServer(self->server->next);
238
static PyObject *my_generation(serverobject *self, void *objname)
240
return PyInt_FromLong((long)ap_my_generation);
243
static PyObject *restart_time(serverobject *self, void *objname)
245
return PyFloat_FromDouble(ap_scoreboard_image->global->restart_time*0.000001);
248
static PyGetSetDef server_getsets[] = {
250
{"next", (getter)getmakeobj, NULL, "The next server in the list", "next"},
251
{"defn_name", (getter)getsrv_recmbr, NULL, "The name of the server", "defn_name"},
252
{"defn_line_number", (getter)getsrv_recmbr, NULL,
253
"The line of the config file that the server was defined on", "defn_line_number"},
254
{"server_admin", (getter)getsrv_recmbr, NULL, "The admin's contact information", "server_admin"},
255
{"server_hostname", (getter)getsrv_recmbr, NULL, "The server hostname", "server_hostname"},
256
{"port", (getter)getsrv_recmbr, NULL, " for redirects, etc.", "port"},
257
{"error_fname", (getter)getsrv_recmbr, NULL, "The name of the error log", "error_fname"},
258
/* XXX error_log apr_file_t */
259
{"loglevel", (getter)getsrv_recmbr, NULL, "The log level for this server", "loglevel"},
260
{"is_virtual", (getter)getsrv_recmbr, NULL, "true if this is the virtual server", "is_virtual"},
261
{"timeout", (getter)getsrv_recmbr_time, NULL, "Timeout, as interval, before we give up", "timeout"},
262
{"keep_alive_timeout", (getter)getsrv_recmbr_time, NULL, "The apr interval we will wait for another request", "keep_alive_timeout"},
263
{"keep_alive_max", (getter)getsrv_recmbr, NULL, "Maximum requests per connection", "keep_alive_max"},
264
{"keep_alive", (getter)getsrv_recmbr, NULL, "Use persistent connections?", "keep_alive"},
265
{"path", (getter)getsrv_recmbr, NULL, "Pathname for ServerPath", "path"},
266
{"pathlen", (getter)getsrv_recmbr, NULL, "Length of path", "pathlen"},
267
{"names", (getter)getsrv_recmbr_ah, NULL, "Normal names for ServerAlias servers", "names"},
268
{"wild_names", (getter)getsrv_recmbr_ah, NULL, "Wildcarded names for ServerAlias servers", "wild_names"},
269
{"limit_req_line", (getter)getsrv_recmbr, NULL, "limit on size of the HTTP request line", "limit_req_line"},
270
{"limit_req_fieldsize", (getter)getsrv_recmbr, NULL, "limit on size of any request header field", "limit_req_fieldsize"},
271
{"limit_req_fields", (getter)getsrv_recmbr, NULL, "limit on number of request header fields", "limit_req_fields"},
272
{"my_generation", (getter)my_generation, NULL, "Generation of this child", "my_generation"},
273
{"restart_time", (getter)restart_time, NULL, "Server restart time", "restart_time"},
274
{NULL} /* Sentinel */
284
static void server_dealloc(serverobject *self)
286
Py_XDECREF(self->dict);
287
Py_XDECREF(self->next);
291
static char server_doc[] =
292
"Apache server_rec structure\n";
294
PyTypeObject MpServer_Type = {
295
PyObject_HEAD_INIT(NULL)
298
sizeof(serverobject),
300
(destructor) server_dealloc, /*tp_dealloc*/
307
0, /*tp_as_sequence*/
312
PyObject_GenericGetAttr, /* tp_getattro */
313
PyObject_GenericSetAttr, /* tp_setattro */
314
0, /* tp_as_buffer */
316
Py_TPFLAGS_BASETYPE, /* tp_flags */
317
server_doc, /* tp_doc */
320
0, /* tp_richcompare */
321
0, /* tp_weaklistoffset */
324
server_methods, /* tp_methods */
326
server_getsets, /* tp_getset */
329
0, /* tp_descr_get */
330
0, /* tp_descr_set */
331
offsetof(serverobject, dict), /* tp_dictoffset */
335
(destructor)server_dealloc, /* tp_free */