1 /* ircd/batch.c - batch management
2 * Copyright (c) 2016 Elizabeth Myers <elizabeth@interlinked.me>
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice is present in all copies.
8 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
9 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
11 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
12 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
13 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
14 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
15 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
16 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
17 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
18 * POSSIBILITY OF SUCH DAMAGE.
29 #include "rb_radixtree.h"
31 /* Multiple batches may be in progress for each slot. */
32 rb_dlink_list batches
[BATCH_LAST
];
35 generate_batch_id(char *ptr
, size_t len
)
38 const char batchchars
[65] =
39 "\0._0123456789" /* Zero-indexed */
40 "abcdefghijklmnopqrstuvwxyz"
41 "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
43 len
--; /* Room for \0 */
44 for(i
= 0; i
< len
; i
++)
50 r
= batchchars
[rand() & 0x7F]; /* random int between 0-64 */
52 if(r
== '\0' && i
> 3)
53 /* We have enough chars */
65 start_batch(batch_type batch
, void *data
, int parc
, ...)
67 struct Batch
*batch_p
= rb_malloc(sizeof(struct Batch
));
69 batch_p
->batch
= batch
;
70 generate_batch_id(batch_p
->id
, sizeof(batch_p
->id
));
75 /* Get the argument list */
78 batch_p
->parv
= rb_malloc(sizeof(char *) * parc
);
81 for(size_t i
= 0; i
< parc
; i
++)
82 batch_p
->parv
[i
] = va_arg(args
, char *);
86 /* Batch-type specific processing */
92 /* Build list of channels affected by the batch */
94 rb_radixtree_iteration_state iter
;
95 struct Channel
*chptr
;
97 batch_p
->pdata
= clist
= rb_malloc(sizeof(rb_dlink_list
));
99 /* Look for channels we need to send the batch to */
100 RB_RADIXTREE_FOREACH(chptr
, &iter
, channel_tree
)
104 if(rb_dlink_list_length(&chptr
->locmembers
) == 0)
105 /* They're all remotes, so don't send a batch */
108 /* Hunt for members in the channel from the target server
109 * If we find one, send the channel a BATCH message */
110 RB_DLINK_FOREACH(ptr
, chptr
->members
.head
)
112 struct Client
*client_p
= ptr
->data
;
114 if(client_p
->from
== data
)
116 rb_dlinkAddAlloc(rb_strdup(chptr
->chname
), clist
);
117 sendto_channel_local_with_capability(ALL_MEMBERS
, CLICAP_BATCH
, NOCAPS
,
118 chptr
, ":%s BATCH +%s %s %s",
120 batch
== BATCH_NETSPLIT
? "netsplit" : "netjoin",
121 batch_p
->parv
[0], batch_p
->parv
[1]);
133 rb_dlinkAdd(batch_p
, &batch_p
->node
, &batches
[batch
]);
139 finish_batch(struct Batch
*batch_p
)
144 /* Batch type-specific processing */
145 switch(batch_p
->batch
)
150 rb_dlink_list
*clist
= batch_p
->pdata
;
151 rb_dlink_node
*ptr
, *nptr
;
153 RB_DLINK_FOREACH_SAFE(ptr
, nptr
, clist
->head
)
155 struct Channel
*chptr
= find_channel(ptr
->data
);
157 if(chptr
!= NULL
) /* Shouldn't be but just in case... */
159 sendto_channel_local_with_capability(ALL_MEMBERS
, CLICAP_BATCH
, NOCAPS
,
160 chptr
, ":%s BATCH -%s %s %s",
162 batch_p
->batch
== BATCH_NETSPLIT
? "netsplit" : "netjoin",
163 batch_p
->parv
[0], batch_p
->parv
[1]);
167 rb_dlinkDestroy(ptr
, clist
);
178 /* Free all the strings */
179 for(size_t i
= 0; i
< (batch_p
->parc
- 1); i
++)
180 rb_free(batch_p
->parv
[i
]);
182 rb_free(batch_p
->parv
);
184 rb_dlinkDelete(&batch_p
->node
, &batches
[batch_p
->batch
]);
189 find_batch(batch_type batch
, void *data
)
193 RB_DLINK_FOREACH(ptr
, batches
[batch
].head
)
195 struct Batch
*batch_p
= ptr
->data
;
197 if(batch_p
->data
== data
)