diff options
author | Stefan Metzmacher <metze@samba.org> | 2005-12-12 21:31:42 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:47:17 -0500 |
commit | 36acd6e79c8cb881b9c333313402d993a6d0f511 (patch) | |
tree | 29738d21349a159c3cd28d4577779c6c7e8f209e /source4/wrepl_server/wrepl_in_connection.c | |
parent | b052ab8ad4ea31a45d61d5c6d8e34b6879848045 (diff) | |
download | samba-36acd6e79c8cb881b9c333313402d993a6d0f511.tar.gz samba-36acd6e79c8cb881b9c333313402d993a6d0f511.tar.xz samba-36acd6e79c8cb881b9c333313402d993a6d0f511.zip |
r12200: - move the the winsreplication client and server code to the packet_context
system
- this needs to be in one big patch, because of the merging code,
that changes client in server connections and the other way around
- use socket_connect_send/_recv() in the client code
metze
(This used to be commit f0105b7fcdc3032d22444a1973927fff2dd9a06f)
Diffstat (limited to 'source4/wrepl_server/wrepl_in_connection.c')
-rw-r--r-- | source4/wrepl_server/wrepl_in_connection.c | 271 |
1 files changed, 110 insertions, 161 deletions
diff --git a/source4/wrepl_server/wrepl_in_connection.c b/source4/wrepl_server/wrepl_in_connection.c index e06e69103e2..a6abf99e411 100644 --- a/source4/wrepl_server/wrepl_in_connection.c +++ b/source4/wrepl_server/wrepl_in_connection.c @@ -24,6 +24,7 @@ #include "dlinklist.h" #include "lib/events/events.h" #include "lib/socket/socket.h" +#include "lib/stream/packet.h" #include "smbd/service_task.h" #include "smbd/service_stream.h" #include "lib/messaging/irpc.h" @@ -37,226 +38,156 @@ void wreplsrv_terminate_in_connection(struct wreplsrv_in_connection *wreplconn, stream_terminate_connection(wreplconn->conn, reason); } -/* - called when we get a new connection -*/ -static void wreplsrv_accept(struct stream_connection *conn) +static int terminate_after_send_destructor(void *ptr) { - struct wreplsrv_service *service = talloc_get_type(conn->private, struct wreplsrv_service); - struct wreplsrv_in_connection *wreplconn; - const char *peer_ip; - - wreplconn = talloc_zero(conn, struct wreplsrv_in_connection); - if (!wreplconn) { - stream_terminate_connection(conn, "wreplsrv_accept: out of memory"); - return; - } - - wreplconn->conn = conn; - wreplconn->service = service; - wreplconn->our_ip = socket_get_my_addr(conn->socket, wreplconn); - if (!wreplconn->our_ip) { - wreplsrv_terminate_in_connection(wreplconn, "wreplsrv_accept: out of memory"); - return; - } - - peer_ip = socket_get_peer_addr(conn->socket, wreplconn); - if (!peer_ip) { - wreplsrv_terminate_in_connection(wreplconn, "wreplsrv_accept: out of memory"); - return; - } - - wreplconn->partner = wreplsrv_find_partner(service, peer_ip); - - conn->private = wreplconn; - - irpc_add_name(conn->msg_ctx, "wreplsrv_connection"); + struct wreplsrv_in_connection **tas = talloc_get_type(ptr, struct wreplsrv_in_connection *); + wreplsrv_terminate_in_connection(*tas, "wreplsrv_in_connection: terminate_after_send"); + return 0; } /* receive some data on a WREPL connection */ -static void wreplsrv_recv(struct stream_connection *conn, uint16_t flags) +static NTSTATUS wreplsrv_recv_request(void *private, DATA_BLOB blob) { - struct wreplsrv_in_connection *wreplconn = talloc_get_type(conn->private, struct wreplsrv_in_connection); + struct wreplsrv_in_connection *wreplconn = talloc_get_type(private, struct wreplsrv_in_connection); struct wreplsrv_in_call *call; DATA_BLOB packet_in_blob; DATA_BLOB packet_out_blob; struct wrepl_wrap packet_out_wrap; - struct data_blob_list_item *rep; - NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - size_t nread; - - /* avoid recursion, because of half async code */ - if (wreplconn->processing) { - EVENT_FD_NOT_READABLE(conn->event.fde); - return; - } - - if (wreplconn->partial.length == 0) { - wreplconn->partial = data_blob_talloc(wreplconn, NULL, 4); - if (wreplconn->partial.data == NULL) { - status = NT_STATUS_NO_MEMORY; - goto failed; - } - wreplconn->partial_read = 0; - } - - /* read in the packet length */ - if (wreplconn->partial_read < 4) { - uint32_t packet_length; - - status = socket_recv(conn->socket, - wreplconn->partial.data + wreplconn->partial_read, - 4 - wreplconn->partial_read, - &nread, 0); - if (NT_STATUS_IS_ERR(status)) goto failed; - if (!NT_STATUS_IS_OK(status)) return; - - wreplconn->partial_read += nread; - if (wreplconn->partial_read != 4) return; - - packet_length = RIVAL(wreplconn->partial.data, 0) + 4; - - wreplconn->partial.data = talloc_realloc(wreplconn, wreplconn->partial.data, - uint8_t, packet_length); - if (wreplconn->partial.data == NULL) { - status = NT_STATUS_NO_MEMORY; - goto failed; - } - wreplconn->partial.length = packet_length; - } - - /* read in the body */ - status = socket_recv(conn->socket, - wreplconn->partial.data + wreplconn->partial_read, - wreplconn->partial.length - wreplconn->partial_read, - &nread, 0); - if (NT_STATUS_IS_ERR(status)) goto failed; - if (!NT_STATUS_IS_OK(status)) return; - - wreplconn->partial_read += nread; - if (wreplconn->partial_read != wreplconn->partial.length) return; - - packet_in_blob.data = wreplconn->partial.data + 4; - packet_in_blob.length = wreplconn->partial.length - 4; + NTSTATUS status; call = talloc_zero(wreplconn, struct wreplsrv_in_call); - if (!call) { - status = NT_STATUS_NO_MEMORY; - goto failed; - } + NT_STATUS_HAVE_NO_MEMORY(call); call->wreplconn = wreplconn; + talloc_steal(call, blob.data); - /* we have a full request - parse it */ - status = ndr_pull_struct_blob(&packet_in_blob, - call, &call->req_packet, - (ndr_pull_flags_fn_t)ndr_pull_wrepl_packet); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(2,("Failed to parse incoming WINS-Replication packet - %s\n", - nt_errstr(status))); - DEBUG(10,("packet length %lu\n", (long)wreplconn->partial.length)); - NDR_PRINT_DEBUG(wrepl_packet, &call->req_packet); - goto failed; - } + packet_in_blob.data = blob.data + 4; + packet_in_blob.length = blob.length - 4; - /* - * we have parsed the request, so we can reset the wreplconn->partial_read, - * maybe we could also free wreplconn->partial, but for now we keep it, - * and overwrite it the next time - */ - wreplconn->partial_read = 0; + status = ndr_pull_struct_blob(&packet_in_blob, call, &call->req_packet, + (ndr_pull_flags_fn_t)ndr_pull_wrepl_packet); + NT_STATUS_NOT_OK_RETURN(status); if (DEBUGLVL(10)) { - DEBUG(10,("Received WINS-Replication packet of length %lu\n", (long)wreplconn->partial.length)); + DEBUG(10,("Received WINS-Replication packet of length %u\n", packet_in_blob.length + 4)); NDR_PRINT_DEBUG(wrepl_packet, &call->req_packet); } - /* actually process the request */ - wreplconn->processing = True; status = wreplsrv_in_call(call); - wreplconn->processing = False; - if (NT_STATUS_IS_ERR(status)) goto failed; + NT_STATUS_IS_ERR_RETURN(status); if (!NT_STATUS_IS_OK(status)) { /* w2k just ignores invalid packets, so we do */ DEBUG(10,("Received WINS-Replication packet was invalid, we just ignore it\n")); talloc_free(call); - return; + return NT_STATUS_OK; } /* and now encode the reply */ packet_out_wrap.packet = call->rep_packet; status = ndr_push_struct_blob(&packet_out_blob, call, &packet_out_wrap, (ndr_push_flags_fn_t)ndr_push_wrepl_wrap); - if (!NT_STATUS_IS_OK(status)) goto failed; + NT_STATUS_NOT_OK_RETURN(status); if (DEBUGLVL(10)) { DEBUG(10,("Sending WINS-Replication packet of length %d\n", (int)packet_out_blob.length)); NDR_PRINT_DEBUG(wrepl_packet, &call->rep_packet); } - rep = talloc(wreplconn, struct data_blob_list_item); - if (!rep) { - status = NT_STATUS_NO_MEMORY; - goto failed; + if (call->terminate_after_send) { + struct wreplsrv_in_connection **tas; + tas = talloc(packet_out_blob.data, struct wreplsrv_in_connection *); + NT_STATUS_HAVE_NO_MEMORY(tas); + *tas = wreplconn; + talloc_set_destructor(tas, terminate_after_send_destructor); } - rep->blob = packet_out_blob; - talloc_steal(rep, packet_out_blob.data); - /* we don't need the call anymore */ - talloc_free(call); + status = packet_send(wreplconn->packet, packet_out_blob); + NT_STATUS_NOT_OK_RETURN(status); - if (!wreplconn->send_queue) { - EVENT_FD_WRITEABLE(conn->event.fde); - } - DLIST_ADD_END(wreplconn->send_queue, rep, struct data_blob_list_item *); + talloc_free(call); + return NT_STATUS_OK; +} - if (wreplconn->terminate) { - EVENT_FD_NOT_READABLE(conn->event.fde); - } else { - EVENT_FD_READABLE(conn->event.fde); - } - return; +/* + called when the socket becomes readable +*/ +static void wreplsrv_recv(struct stream_connection *conn, uint16_t flags) +{ + struct wreplsrv_in_connection *wreplconn = talloc_get_type(conn->private, + struct wreplsrv_in_connection); -failed: - wreplsrv_terminate_in_connection(wreplconn, nt_errstr(status)); + packet_recv(wreplconn->packet); } /* - called when we can write to a connection + called when the socket becomes writable */ static void wreplsrv_send(struct stream_connection *conn, uint16_t flags) { - struct wreplsrv_in_connection *wreplconn = talloc_get_type(conn->private, struct wreplsrv_in_connection); - NTSTATUS status; + struct wreplsrv_in_connection *wreplconn = talloc_get_type(conn->private, + struct wreplsrv_in_connection); + packet_queue_run(wreplconn->packet); +} - while (wreplconn->send_queue) { - struct data_blob_list_item *rep = wreplconn->send_queue; - size_t sendlen; +/* + handle socket recv errors +*/ +static void wreplsrv_recv_error(void *private, NTSTATUS status) +{ + struct wreplsrv_in_connection *wreplconn = talloc_get_type(private, + struct wreplsrv_in_connection); + wreplsrv_terminate_in_connection(wreplconn, nt_errstr(status)); +} - status = socket_send(conn->socket, &rep->blob, &sendlen, 0); - if (NT_STATUS_IS_ERR(status)) goto failed; - if (!NT_STATUS_IS_OK(status)) return; +/* + called when we get a new connection +*/ +static void wreplsrv_accept(struct stream_connection *conn) +{ + struct wreplsrv_service *service = talloc_get_type(conn->private, struct wreplsrv_service); + struct wreplsrv_in_connection *wreplconn; + const char *peer_ip; - rep->blob.length -= sendlen; - rep->blob.data += sendlen; + wreplconn = talloc_zero(conn, struct wreplsrv_in_connection); + if (!wreplconn) { + stream_terminate_connection(conn, "wreplsrv_accept: out of memory"); + return; + } - if (rep->blob.length == 0) { - DLIST_REMOVE(wreplconn->send_queue, rep); - talloc_free(rep); - } + wreplconn->packet = packet_init(wreplconn); + if (!wreplconn->packet) { + wreplsrv_terminate_in_connection(wreplconn, "wreplsrv_accept: out of memory"); + return; } + packet_set_private(wreplconn->packet, wreplconn); + packet_set_socket(wreplconn->packet, conn->socket); + packet_set_callback(wreplconn->packet, wreplsrv_recv_request); + packet_set_full_request(wreplconn->packet, packet_full_request_u32); + packet_set_error_handler(wreplconn->packet, wreplsrv_recv_error); + packet_set_event_context(wreplconn->packet, conn->event.ctx); + packet_set_fde(wreplconn->packet, conn->event.fde); + packet_set_serialise(wreplconn->packet); - if (wreplconn->terminate) { - wreplsrv_terminate_in_connection(wreplconn, "connection terminated after all pending packets are send"); + wreplconn->conn = conn; + wreplconn->service = service; + wreplconn->our_ip = socket_get_my_addr(conn->socket, wreplconn); + if (!wreplconn->our_ip) { + wreplsrv_terminate_in_connection(wreplconn, "wreplsrv_accept: out of memory"); return; } - EVENT_FD_NOT_WRITEABLE(conn->event.fde); - return; + peer_ip = socket_get_peer_addr(conn->socket, wreplconn); + if (!peer_ip) { + wreplsrv_terminate_in_connection(wreplconn, "wreplsrv_accept: out of memory"); + return; + } -failed: - wreplsrv_terminate_in_connection(wreplconn, nt_errstr(status)); + wreplconn->partner = wreplsrv_find_partner(service, peer_ip); + + conn->private = wreplconn; + + irpc_add_name(conn->msg_ctx, "wreplsrv_connection"); } static const struct stream_server_ops wreplsrv_stream_ops = { @@ -271,6 +202,7 @@ static const struct stream_server_ops wreplsrv_stream_ops = { */ NTSTATUS wreplsrv_in_connection_merge(struct wreplsrv_partner *partner, struct socket_context *sock, + struct packet_context *packet, struct wreplsrv_in_connection **_wrepl_in) { struct wreplsrv_service *service = partner->service; @@ -301,9 +233,26 @@ NTSTATUS wreplsrv_in_connection_merge(struct wreplsrv_partner *partner, wrepl_in, &conn); NT_STATUS_NOT_OK_RETURN(status); + /* + * make the wreplsrv_in_connection structure a child of the + * stream_connection, to match the hierachie of wreplsrv_accept + */ wrepl_in->conn = conn; talloc_steal(conn, wrepl_in); + /* + * now update the packet handling callback,... + */ + wrepl_in->packet = talloc_steal(wrepl_in, packet); + packet_set_private(wrepl_in->packet, wrepl_in); + packet_set_socket(wrepl_in->packet, conn->socket); + packet_set_callback(wrepl_in->packet, wreplsrv_recv_request); + packet_set_full_request(wrepl_in->packet, packet_full_request_u32); + packet_set_error_handler(wrepl_in->packet, wreplsrv_recv_error); + packet_set_event_context(wrepl_in->packet, conn->event.ctx); + packet_set_fde(wrepl_in->packet, conn->event.fde); + packet_set_serialise(wrepl_in->packet); + *_wrepl_in = wrepl_in; return NT_STATUS_OK; } |