*/
static void wrepl_socket_dead(struct wrepl_socket *wrepl_socket, NTSTATUS status)
{
+ talloc_set_destructor(wrepl_socket, NULL);
wrepl_socket->dead = True;
if (wrepl_socket->fde) {
return;
}
- DLIST_REMOVE(wrepl_socket->send_queue, req);
- DLIST_ADD_END(wrepl_socket->recv_queue, req, struct wrepl_request *);
- req->state = WREPL_REQUEST_RECV;
+ if (req->disconnect_after_send) {
+ DLIST_REMOVE(wrepl_socket->send_queue, req);
+ req->status = NT_STATUS_OK;
+ req->state = WREPL_REQUEST_DONE;
+ wrepl_socket_dead(wrepl_socket, NT_STATUS_LOCAL_DISCONNECT);
+ if (req->async.fn) {
+ req->async.fn(req);
+ }
+ return;
+ }
+
+ if (req->send_only) {
+ DLIST_REMOVE(wrepl_socket->send_queue, req);
+ req->status = NT_STATUS_OK;
+ req->state = WREPL_REQUEST_DONE;
+ if (req->async.fn) {
+ EVENT_FD_READABLE(wrepl_socket->fde);
+ req->async.fn(req);
+ return;
+ }
+ } else {
+ DLIST_REMOVE(wrepl_socket->send_queue, req);
+ DLIST_ADD_END(wrepl_socket->recv_queue, req, struct wrepl_request *);
+ req->state = WREPL_REQUEST_RECV;
+ }
EVENT_FD_READABLE(wrepl_socket->fde);
}
static int wrepl_socket_destructor(void *ptr)
{
struct wrepl_socket *sock = talloc_get_type(ptr, struct wrepl_socket);
- wrepl_socket_dead(sock, NT_STATUS_CONNECTION_DISCONNECTED);
+ wrepl_socket_dead(sock, NT_STATUS_LOCAL_DISCONNECT);
return 0;
}
connect a wrepl_socket to a WINS server
*/
struct wrepl_request *wrepl_connect_send(struct wrepl_socket *wrepl_socket,
- const char *address)
+ const char *our_ip, const char *peer_ip)
{
struct wrepl_request *req;
NTSTATUS status;
DLIST_ADD(wrepl_socket->recv_queue, req);
talloc_set_destructor(req, wrepl_request_destructor);
-
- status = socket_connect(wrepl_socket->sock, iface_best_ip(address), 0, address,
+
+ if (!our_ip) {
+ our_ip = iface_best_ip(peer_ip);
+ }
+
+ status = socket_connect(wrepl_socket->sock, our_ip, 0, peer_ip,
WINS_REPLICATION_PORT, 0);
if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) goto failed;
/*
connect a wrepl_socket to a WINS server - sync API
*/
-NTSTATUS wrepl_connect(struct wrepl_socket *wrepl_socket, const char *address)
+NTSTATUS wrepl_connect(struct wrepl_socket *wrepl_socket, const char *our_ip, const char *peer_ip)
{
- struct wrepl_request *req = wrepl_connect_send(wrepl_socket, address);
+ struct wrepl_request *req = wrepl_connect_send(wrepl_socket, our_ip, peer_ip);
return wrepl_connect_recv(req);
}
}
+/*
+ stop an association - send
+*/
+struct wrepl_request *wrepl_associate_stop_send(struct wrepl_socket *wrepl_socket,
+ struct wrepl_associate_stop *io)
+{
+ struct wrepl_packet *packet;
+ struct wrepl_request *req;
+
+ packet = talloc_zero(wrepl_socket, struct wrepl_packet);
+ if (packet == NULL) return NULL;
+
+ packet->opcode = WREPL_OPCODE_BITS;
+ packet->assoc_ctx = io->in.assoc_ctx;
+ packet->mess_type = WREPL_STOP_ASSOCIATION;
+ packet->message.stop.reason = io->in.reason;
+
+ req = wrepl_request_send(wrepl_socket, packet);
+
+ if (req && io->in.reason == 0) {
+ req->send_only = True;
+ req->disconnect_after_send = True;
+ }
+
+ talloc_free(packet);
+
+ return req;
+}
+
+/*
+ stop an association - recv
+*/
+NTSTATUS wrepl_associate_stop_recv(struct wrepl_request *req,
+ struct wrepl_associate_stop *io)
+{
+ struct wrepl_packet *packet=NULL;
+ NTSTATUS status;
+ status = wrepl_request_recv(req, req->wrepl_socket, &packet);
+ NT_STATUS_NOT_OK_RETURN(status);
+ talloc_free(packet);
+ return status;
+}
+
+/*
+ setup an association - sync api
+*/
+NTSTATUS wrepl_associate_stop(struct wrepl_socket *wrepl_socket,
+ struct wrepl_associate_stop *io)
+{
+ struct wrepl_request *req = wrepl_associate_stop_send(wrepl_socket, io);
+ return wrepl_associate_stop_recv(req, io);
+}
+
/*
fetch the partner tables - send
*/
io->out.num_names = packet->message.replication.info.reply.num_names;
- status = NT_STATUS_NO_MEMORY;
-
io->out.names = talloc_array(packet, struct wrepl_name, io->out.num_names);
if (io->out.names == NULL) goto nomem;
struct wrepl_socket *wrepl_socket2;
struct wrepl_associate associate2;
struct wrepl_pull_table pull_table;
+ struct wrepl_packet *rep_packet;
+ struct wrepl_associate_stop assoc_stop;
NTSTATUS status;
printf("Test if assoc_ctx is only valid on the conection it was created on\n");
wrepl_socket1 = wrepl_socket_init(mem_ctx, NULL);
wrepl_socket2 = wrepl_socket_init(mem_ctx, NULL);
-
+
printf("Setup 2 wrepl connections\n");
- status = wrepl_connect(wrepl_socket1, address);
+ status = wrepl_connect(wrepl_socket1, NULL, address);
CHECK_STATUS(status, NT_STATUS_OK);
- status = wrepl_connect(wrepl_socket2, address);
+ status = wrepl_connect(wrepl_socket2, NULL, address);
CHECK_STATUS(status, NT_STATUS_OK);
printf("Send a start association request (conn1)\n");
printf("association context (conn2): 0x%x\n", associate2.out.assoc_ctx);
- printf("Send a replication table query, with assoc 1 (conn2), should be ignored\n");
+ printf("Send a replication table query, with assoc 1 (conn2), the anwser should be on conn1\n");
pull_table.in.assoc_ctx = associate1.out.assoc_ctx;
req = wrepl_pull_table_send(wrepl_socket2, &pull_table);
- talloc_free(req);
+ req->send_only = True;
+ status = wrepl_request_recv(req, mem_ctx, &rep_packet);
+ CHECK_STATUS(status, NT_STATUS_OK);
printf("Send a association request (conn2), to make sure the last request was ignored\n");
status = wrepl_associate(wrepl_socket2, &associate2);
CHECK_STATUS(status, NT_STATUS_OK);
+ printf("Send a replication table query, with invalid assoc (conn1), receive answer from conn2\n");
+ pull_table.in.assoc_ctx = 0;
+ req = wrepl_pull_table_send(wrepl_socket1, &pull_table);
+ status = wrepl_request_recv(req, mem_ctx, &rep_packet);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ printf("Send a association request (conn1), to make sure the last request was handled correct\n");
+ status = wrepl_associate(wrepl_socket1, &associate2);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ assoc_stop.in.assoc_ctx = associate1.out.assoc_ctx;
+ assoc_stop.in.reason = 4;
+ printf("Send a association stop request (conn1), reson: %u\n", assoc_stop.in.reason);
+ status = wrepl_associate_stop(wrepl_socket1, &assoc_stop);
+ CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
+
+ assoc_stop.in.assoc_ctx = associate2.out.assoc_ctx;
+ assoc_stop.in.reason = 0;
+ printf("Send a association stop request (conn2), reson: %u\n", assoc_stop.in.reason);
+ status = wrepl_associate_stop(wrepl_socket2, &assoc_stop);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
done:
printf("Close 2 wrepl connections\n");
talloc_free(wrepl_socket1);
wrepl_socket = wrepl_socket_init(mem_ctx, NULL);
printf("Setup wrepl connections\n");
- status = wrepl_connect(wrepl_socket, address);
+ status = wrepl_connect(wrepl_socket, NULL, address);
CHECK_STATUS(status, NT_STATUS_OK);
wrepl_socket = wrepl_socket_init(mem_ctx, NULL);
printf("Setup wrepl connections\n");
- status = wrepl_connect(wrepl_socket, address);
+ status = wrepl_connect(wrepl_socket, NULL, address);
CHECK_STATUS(status, NT_STATUS_OK);
printf("Send a start association request\n");