summaryrefslogtreecommitdiff
path: root/source4/winbind/wb_server.c
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2005-01-30 02:55:30 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:09:23 -0500
commit1447b9a8c135ddc8d369be9ab970a4cccf4ecf0e (patch)
treefea0e3bc04a63cb7d3eb0dfad86e0589b12a235d /source4/winbind/wb_server.c
parent597142ddd3575a50a491a89dd5ce5fb40945028f (diff)
downloadsamba-1447b9a8c135ddc8d369be9ab970a4cccf4ecf0e.tar.gz
samba-1447b9a8c135ddc8d369be9ab970a4cccf4ecf0e.tar.bz2
samba-1447b9a8c135ddc8d369be9ab970a4cccf4ecf0e.zip
r5104: - added support for task based servers. These are servers that within
themselves are run as a single process, but run as a child of the main process when smbd is run in the standard model, and run as part of the main process when in the single mode. - rewrote the winbind template code to use the new task services. Also fixed the packet queueing - got rid of event_context_merge() as it is no longer needed (This used to be commit 339964a596689278d2138cff05d7d444798a3504)
Diffstat (limited to 'source4/winbind/wb_server.c')
-rw-r--r--source4/winbind/wb_server.c253
1 files changed, 109 insertions, 144 deletions
diff --git a/source4/winbind/wb_server.c b/source4/winbind/wb_server.c
index b75cc897a8..fb30b76a0a 100644
--- a/source4/winbind/wb_server.c
+++ b/source4/winbind/wb_server.c
@@ -3,6 +3,7 @@
Main winbindd server routines
Copyright (C) Stefan Metzmacher 2005
+ Copyright (C) Andrew Tridgell 2005
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,8 +21,10 @@
*/
#include "includes.h"
+#include "dlinklist.h"
#include "events.h"
-#include "system/time.h"
+#include "smbd/service_task.h"
+#include "smbd/service_stream.h"
#define WINBINDD_DIR "/tmp/.winbindd/"
#define WINBINDD_ECHO_SOCKET WINBINDD_DIR"echo"
@@ -29,201 +32,163 @@
#define WINBINDD_ECHO_ADDR WINBINDD_ADDR_PREFIX"1"
#define WINBINDD_ECHO_PORT 55555
-static void winbind_accept(struct server_connection *conn)
-{
- DEBUG(10,("winbind_accept:\n"));
-}
+/*
+ state of an open winbind connection
+*/
+struct wbserver_connection {
+ DATA_BLOB blob;
+ struct send_queue {
+ struct send_queue *next, *prev;
+ DATA_BLOB blob;
+ } *queue;
+};
-static DATA_BLOB tmp_blob;
-static void winbind_recv(struct server_connection *conn, struct timeval t, uint16_t flags)
+/*
+ called when we get a new connection
+*/
+static void winbind_accept(struct stream_connection *conn)
{
+ struct wbserver_connection *wbconn;
+ wbconn = talloc_zero(conn, struct wbserver_connection);
+ wbconn->blob = data_blob_talloc(wbconn, NULL, 1024);
+
+ conn->private = wbconn;
+}
+/*
+ receive some data on a winbind connection
+*/
+static void winbind_recv(struct stream_connection *conn, struct timeval t, uint16_t flags)
+{
+ struct wbserver_connection *wbconn = talloc_get_type(conn->private, struct wbserver_connection);
NTSTATUS status;
size_t nread;
+ struct send_queue *q;
-if (!tmp_blob.data) {
- tmp_blob = data_blob_talloc(conn, NULL, 1024);
- if (tmp_blob.data == NULL) {
- return;
- }
-}
- tmp_blob.length = 1024;
- status = socket_recv(conn->socket, tmp_blob.data, tmp_blob.length, &nread, 0);
+ status = socket_recv(conn->socket, wbconn->blob.data, wbconn->blob.length, &nread, 0);
if (NT_STATUS_IS_ERR(status)) {
DEBUG(10,("socket_recv: %s\n",nt_errstr(status)));
- talloc_free(tmp_blob.data);
- server_terminate_connection(conn, "socket_recv: failed\n");
+ stream_terminate_connection(conn, "socket_recv: failed\n");
return;
}
- tmp_blob.length = nread;
-#if 0
-DEBUG(0,("winbind_recv:\n"));
-dump_data(0, tmp_blob.data, tmp_blob.length);
-#endif
- conn->event.fde->flags |= EVENT_FD_WRITE;
-}
-
-static void winbind_send(struct server_connection *conn, struct timeval t, uint16_t flags)
-{
- NTSTATUS status;
- size_t sendlen;
-
- if (tmp_blob.length > 1 && tmp_blob.data[0] == (uint8_t)'q') {
-
- }
- status = socket_send(conn->socket, &tmp_blob, &sendlen, 0);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10,("socket_send() %s\n",nt_errstr(status)));
- server_terminate_connection(conn, "socket_send: failed\n");
+ /* just reflect the data back down the socket */
+ q = talloc(wbconn, struct send_queue);
+ if (q == NULL) {
+ stream_terminate_connection(conn, "winbind_recv: out of memory\n");
return;
}
- if (tmp_blob.length > 1 && tmp_blob.data[0] == (uint8_t)'q') {
- server_terminate_connection(conn, "winbind_send: user quit\n");
+ q->blob = data_blob_talloc(q, wbconn->blob.data, nread);
+ if (q->blob.data == NULL) {
+ stream_terminate_connection(conn, "winbind_recv: out of memory\n");
return;
}
-#if 0
-DEBUG(0,("winbind_send:\n"));
-dump_data(0, tmp_blob.data, tmp_blob.length);
-#endif
- tmp_blob.length -= sendlen;
-
- if (tmp_blob.length == 0) {
- conn->event.fde->flags &= ~EVENT_FD_WRITE;
- }
-}
-static void winbind_idle(struct server_connection *conn, struct timeval t)
-{
- DEBUG(1,("winbind_idle: not implemented!\n"));
- return;
-}
+ DLIST_ADD_END(wbconn->queue, q, struct send_queue *);
-static void winbind_close(struct server_connection *conn, const char *reason)
-{
- DEBUG(10,("winbind_close: %s\n", reason));
-}
-
-
-
-static int winbind_task_server_contect_destructor(void *ptr)
-{
- struct server_context *server = ptr;
-
- server_service_shutdown(server, "exit");
-
- return 0;
+ conn->event.fde->flags |= EVENT_FD_WRITE;
}
-static void winbind_server_task_init(struct server_task *task)
+/*
+ called when we can write to a connection
+*/
+static void winbind_send(struct stream_connection *conn, struct timeval t, uint16_t flags)
{
- const char *wb_task_service[] = { "winbind_task", NULL };
- struct server_context *server;
-
- DEBUG(1,("winbindsrv_task_init\n"));
- server = server_service_startup("single", wb_task_service);
- if (!server) {
- DEBUG(0,("Starting Services (winbind_task) failed.\n"));
- return;
+ struct wbserver_connection *wbconn = talloc_get_type(conn->private, struct wbserver_connection);
+
+ while (wbconn->queue) {
+ struct send_queue *q = wbconn->queue;
+ NTSTATUS status;
+ size_t sendlen;
+
+ status = socket_send(conn->socket, &q->blob, &sendlen, 0);
+ if (NT_STATUS_IS_ERR(status)) {
+ DEBUG(10,("socket_send() %s\n",nt_errstr(status)));
+ stream_terminate_connection(conn, "socket_send: failed\n");
+ return;
+ }
+ if (!NT_STATUS_IS_OK(status)) {
+ return;
+ }
+
+ q->blob.length -= sendlen;
+ q->blob.data += sendlen;
+
+ if (q->blob.length == 0) {
+ DLIST_REMOVE(wbconn->queue, q);
+ talloc_free(q);
+ }
}
- task->task.private_data = talloc_steal(task, server);
-
- task->event.ctx = event_context_merge(task->event.ctx, server->event.ctx);
- server->event.ctx = talloc_reference(server, task->event.ctx);
-
- talloc_set_destructor(server, winbind_task_server_contect_destructor);
-
- /* wait for events */
- event_loop_wait(task->event.ctx);
+ conn->event.fde->flags &= ~EVENT_FD_WRITE;
}
-static const struct server_task_ops winbind_srver_task_ops = {
- .name = "winbind_server_task",
- .task_init = winbind_server_task_init
-};
-
-static const struct server_task_ops *winbind_srver_task_get_ops(void)
-{
- return &winbind_srver_task_ops;
-}
-
-static const struct server_stream_ops winbind_stream_ops = {
- .name = "winbind",
- .socket_init = NULL,
+static const struct stream_server_ops winbind_stream_ops = {
+ .name = "smb",
.accept_connection = winbind_accept,
.recv_handler = winbind_recv,
.send_handler = winbind_send,
- .idle_handler = winbind_idle,
- .close_connection = winbind_close
};
-static const struct server_stream_ops *winbind_get_stream_ops(void)
-{
- return &winbind_stream_ops;
-}
-
-static void winbind_task_init(struct server_service *service)
+/*
+ startup the winbind task
+*/
+static void winbind_task_init(struct task_server *task)
{
- struct server_stream_socket *stream_socket;
uint16_t port = 1;
+ const struct model_ops *model_ops;
+ NTSTATUS status;
- DEBUG(1,("winbind_task_init\n"));
+ /* within the winbind task we want to be a single process, so
+ ask for the single process model ops and pass these to the
+ stream_setup_socket() call. */
+ model_ops = process_model_byname("single");
+ if (!model_ops) {
+ task_terminate(task, "Can't find 'single' process model_ops");
+ return;
+ }
/* Make sure the directory for NCALRPC exists */
if (!directory_exist(WINBINDD_DIR, NULL)) {
mkdir(WINBINDD_DIR, 0755);
}
- stream_socket = service_setup_stream_socket(service, winbind_get_stream_ops(), "unix", WINBINDD_ECHO_SOCKET, &port);
- if (!stream_socket) {
- DEBUG(0,("service_setup_stream_socket(path=%s) failed\n",WINBINDD_ECHO_SOCKET));
+ status = stream_setup_socket(task->event_ctx, model_ops, &winbind_stream_ops,
+ "unix", WINBINDD_ECHO_SOCKET, &port, NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
+ WINBINDD_ECHO_SOCKET, nt_errstr(status)));
+ task_terminate(task, "winbind Failed to find to ECHO unix socket");
return;
}
port = WINBINDD_ECHO_PORT;
- stream_socket = service_setup_stream_socket(service, winbind_get_stream_ops(), "ipv4", WINBINDD_ECHO_ADDR, &port);
- if (!stream_socket) {
- DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed\n",WINBINDD_ECHO_ADDR, port));
+
+ status = stream_setup_socket(task->event_ctx, model_ops, &winbind_stream_ops,
+ "ipv4", WINBINDD_ECHO_ADDR, &port, NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n",
+ WINBINDD_ECHO_ADDR, port, nt_errstr(status)));
+ task_terminate(task, "winbind Failed to find to ECHO tcp socket");
return;
}
-
- return;
}
-static const struct server_service_ops winbind_task_ops = {
- .name = "winbind_task",
- .service_init = winbind_task_init,
-};
-
-const struct server_service_ops *winbind_task_get_ops(void)
+/*
+ initialise the winbind server
+ */
+static NTSTATUS winbind_init(struct event_context *event_ctx, const struct model_ops *model_ops)
{
- return &winbind_task_ops;
-}
-
-static void winbind_init(struct server_service *service)
-{
- DEBUG(1,("winbind_init\n"));
-
- server_run_task(service, winbind_srver_task_get_ops());
-
- return;
-}
-
-static const struct server_service_ops winbind_ops = {
- .name = "winbind",
- .service_init = winbind_init,
-};
-
-const struct server_service_ops *winbind_get_ops(void)
-{
- return &winbind_ops;
+ return task_server_startup(event_ctx, model_ops, winbind_task_init);
}
+/*
+ register ourselves as a available server
+*/
NTSTATUS server_service_winbind_init(void)
{
- return NT_STATUS_OK;
+ return register_server_service("winbind", winbind_init);
}