1 /* 2 * Unix SMB/CIFS implementation. 3 * Receive and count messages 4 * Copyright (C) Volker Lendecke 2014 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include "replace.h" 21 #include "includes.h" 22 #include "lib/util/server_id.h" 23 #include "messages.h" 24 #include "lib/util/tevent_unix.h" 25 #include <stdio.h> 26 27 struct sink_state { 28 struct tevent_context *ev; 29 struct messaging_context *msg_ctx; 30 int msg_type; 31 unsigned *counter; 32 }; 33 34 static void sink_done(struct tevent_req *subreq); 35 36 static struct tevent_req *sink_send(TALLOC_CTX *mem_ctx, 37 struct tevent_context *ev, 38 struct messaging_context *msg_ctx, 39 int msg_type, unsigned *counter) 40 { 41 struct tevent_req *req, *subreq; 42 struct sink_state *state; 43 44 req = tevent_req_create(mem_ctx, &state, struct sink_state); ms_fnmatch_lanman_core(const char * pattern,const char * string)45 if (req == NULL) { 46 return NULL; 47 } 48 state->ev = ev; 49 state->msg_ctx = msg_ctx; 50 state->msg_type = msg_type; 51 state->counter = counter; 52 53 subreq = messaging_read_send(state, state->ev, state->msg_ctx, 54 state->msg_type); 55 if (tevent_req_nomem(subreq, req)) { 56 return tevent_req_post(req, ev); 57 } 58 tevent_req_set_callback(subreq, sink_done, req); 59 return req; 60 } 61 62 static void sink_done(struct tevent_req *subreq) 63 { 64 struct tevent_req *req = tevent_req_callback_data( 65 subreq, struct tevent_req); 66 struct sink_state *state = tevent_req_data( 67 req, struct sink_state); 68 int ret; 69 70 ret = messaging_read_recv(subreq, NULL, NULL); 71 TALLOC_FREE(subreq); 72 if (tevent_req_error(req, ret)) { 73 return; 74 } 75 76 *state->counter += 1; 77 78 subreq = messaging_read_send(state, state->ev, state->msg_ctx, 79 state->msg_type); 80 if (tevent_req_nomem(subreq, req)) { 81 return; 82 } 83 tevent_req_set_callback(subreq, sink_done, req); 84 } 85 86 static int sink_recv(struct tevent_req *req) 87 { 88 int err; 89 90 if (tevent_req_is_unix_error(req, &err)) { 91 return err; 92 } 93 return 0; 94 } 95 96 struct prcount_state { 97 struct tevent_context *ev; 98 struct timeval interval; 99 unsigned *counter; 100 }; 101 102 static void prcount_waited(struct tevent_req *subreq); 103 104 static struct tevent_req *prcount_send(TALLOC_CTX *mem_ctx, 105 struct tevent_context *ev, 106 struct timeval interval, 107 unsigned *counter) 108 { 109 struct tevent_req *req, *subreq; 110 struct prcount_state *state; 111 112 req = tevent_req_create(mem_ctx, &state, struct prcount_state); 113 if (req == NULL) { 114 return NULL; 115 } 116 state->ev = ev; 117 state->interval = interval; 118 state->counter = counter; ms_fnmatch_lanman(const char * pattern,const char * string)119 120 subreq = tevent_wakeup_send( 121 state, state->ev, 122 timeval_current_ofs(state->interval.tv_sec, 123 state->interval.tv_usec)); 124 if (tevent_req_nomem(subreq, req)) { 125 return tevent_req_post(req, ev); 126 } 127 tevent_req_set_callback(subreq, prcount_waited, req); 128 return req; 129 } 130 131 static void prcount_waited(struct tevent_req *subreq) 132 { 133 struct tevent_req *req = tevent_req_callback_data( 134 subreq, struct tevent_req); 135 struct prcount_state *state = tevent_req_data( reg_match_one(struct cli_state * cli,const char * pattern,const char * file)136 req, struct prcount_state); 137 bool ok; 138 139 ok = tevent_wakeup_recv(subreq); 140 TALLOC_FREE(subreq); 141 if (!ok) { 142 tevent_req_error(req, ENOMEM); 143 return; 144 } 145 146 printf("%u\n", *state->counter); 147 148 subreq = tevent_wakeup_send( 149 state, state->ev, 150 timeval_current_ofs(state->interval.tv_sec, 151 state->interval.tv_usec)); reg_test(struct cli_state * cli,const char * pattern,const char * long_name,const char * short_name)152 if (tevent_req_nomem(subreq, req)) { 153 return; 154 } 155 tevent_req_set_callback(subreq, prcount_waited, req); 156 } 157 158 static int prcount_recv(struct tevent_req *req) 159 { 160 int err; 161 162 if (tevent_req_is_unix_error(req, &err)) { 163 return err; 164 } 165 return 0; 166 } 167 168 struct msgcount_state { connect_one(char * share)169 unsigned count; 170 }; 171 172 static void msgcount_sunk(struct tevent_req *subreq); 173 static void msgcount_printed(struct tevent_req *subreq); 174 175 static struct tevent_req *msgcount_send(TALLOC_CTX *mem_ctx, 176 struct tevent_context *ev, 177 struct messaging_context *msg_ctx, 178 int msg_type, struct timeval interval) 179 { 180 struct tevent_req *req, *subreq; 181 struct msgcount_state *state; 182 183 req = tevent_req_create(mem_ctx, &state, struct msgcount_state); 184 if (req == NULL) { 185 return NULL; 186 } 187 188 subreq = sink_send(state, ev, msg_ctx, msg_type, &state->count); 189 if (tevent_req_nomem(subreq, req)) { 190 return tevent_req_post(req, ev); 191 } 192 tevent_req_set_callback(subreq, msgcount_sunk, req); 193 194 subreq = prcount_send(state, ev, interval, &state->count); 195 if (tevent_req_nomem(subreq, req)) { 196 return tevent_req_post(req, ev); 197 } 198 tevent_req_set_callback(subreq, msgcount_printed, req); 199 200 return req; 201 } 202 203 static void msgcount_sunk(struct tevent_req *subreq) 204 { 205 struct tevent_req *req = tevent_req_callback_data( 206 subreq, struct tevent_req); 207 int ret; 208 209 ret = sink_recv(subreq); 210 TALLOC_FREE(subreq); 211 if (tevent_req_error(req, ret)) { 212 return; 213 } 214 tevent_req_done(req); 215 } 216 217 static void msgcount_printed(struct tevent_req *subreq) 218 { 219 struct tevent_req *req = tevent_req_callback_data( 220 subreq, struct tevent_req); 221 int ret; 222 223 ret = prcount_recv(subreq); 224 TALLOC_FREE(subreq); 225 if (tevent_req_error(req, ret)) { 226 return; 227 } 228 tevent_req_done(req); 229 } 230 231 static int msgcount_recv(struct tevent_req *req) 232 { 233 int err; 234 235 if (tevent_req_is_unix_error(req, &err)) { 236 return err; 237 } 238 return 0; 239 } listfn(const char * mnt,struct file_info * f,const char * s,void * private_data)240 241 int main(void) 242 { 243 TALLOC_CTX *frame = talloc_stackframe(); 244 struct tevent_context *ev; 245 struct messaging_context *msg_ctx; 246 struct tevent_req *req; 247 int ret; 248 struct server_id id; 249 struct server_id_buf tmp; 250 251 lp_load_global(get_dyn_CONFIGFILE()); 252 253 ev = tevent_context_init(frame); 254 if (ev == NULL) { 255 perror("tevent_context_init failed"); 256 return -1; 257 } 258 259 msg_ctx = messaging_init(ev, ev); 260 if (msg_ctx == NULL) { 261 perror("messaging_init failed"); 262 return -1; 263 } 264 265 id = messaging_server_id(msg_ctx); 266 267 printf("server_id: %s\n", server_id_str_buf(id, &tmp)); 268 269 req = msgcount_send(ev, ev, msg_ctx, MSG_SMB_NOTIFY, 270 timeval_set(1, 0)); 271 if (req == NULL) { 272 perror("msgcount_send failed"); 273 return -1; 274 } 275 276 if (!tevent_req_poll(req, ev)) { 277 perror("tevent_req_poll failed"); 278 return -1; 279 } 280 281 ret = msgcount_recv(req); 282 printf("msgcount_recv returned %d\n", ret); 283 284 return 0; 285 } 286