1 /*
2 * Copyright (c) 1998,1999,2000
3 * Traakan, Inc., Los Altos, CA
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice unmodified, this list of conditions, and the following
11 * disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 /*
30 * Project: NDMJOB
31 * Ident: $Id: $
32 *
33 * Description:
34 *
35 */
36
37
38 #include "ndmagents.h"
39
40
41 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
42
ndma_client_session(struct ndm_session * sess,struct ndm_job_param * job,int swap_connect)43 int ndma_client_session(struct ndm_session* sess,
44 struct ndm_job_param* job,
45 int swap_connect)
46 {
47 int rc;
48
49 rc = ndma_job_audit(job, 0, 0);
50 if (rc) return -1;
51
52 /*
53 * Old behaviour enable all agents.
54 */
55 sess->control_agent_enabled = 1;
56 sess->data_agent_enabled = 1;
57 sess->tape_agent_enabled = 1;
58 sess->robot_agent_enabled = 1;
59
60 /*
61 * Old behaviour enable session snooping
62 */
63 sess->conn_snooping = 1;
64
65 /*
66 * Old behaviour enable media info dumping.
67 */
68 sess->dump_media_info = 1;
69
70 rc = ndma_session_initialize(sess);
71 if (rc) return rc;
72
73 memcpy(&sess->control_acb->job, job, sizeof(struct ndm_job_param));
74
75 sess->control_acb->job.index_log.nfc = sess->param->log.nfc;
76
77 sess->control_acb->swap_connect = swap_connect;
78
79 rc = ndma_session_commission(sess);
80 if (rc) return rc;
81
82 rc = ndmca_connect_control_agent(sess);
83 if (rc) return rc; /* already tattled */
84
85 sess->conn_open = 1;
86 sess->conn_authorized = 1;
87
88 rc = ndmca_control_agent(sess);
89
90 ndma_session_decommission(sess);
91 ndma_session_destroy(sess);
92
93 return rc;
94 }
95
96 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
97
98
99 #ifndef NDMOS_EFFECT_NO_SERVER_AGENTS
100
ndma_server_session(struct ndm_session * sess,int control_sock)101 int ndma_server_session(struct ndm_session* sess, int control_sock)
102 {
103 struct ndmconn* conn;
104 int rc;
105 struct sockaddr sa;
106 socklen_t len;
107
108 /*
109 * Old behaviour enable all agents.
110 */
111 sess->control_agent_enabled = 1;
112 sess->data_agent_enabled = 1;
113 sess->tape_agent_enabled = 1;
114 sess->robot_agent_enabled = 1;
115
116 /*
117 * Old behaviour enable session snooping
118 */
119 sess->conn_snooping = 1;
120
121 /*
122 * Old behaviour enable media info dumping.
123 */
124 sess->dump_media_info = 1;
125
126 rc = ndma_session_initialize(sess);
127 if (rc) return rc;
128
129 rc = ndma_session_commission(sess);
130 if (rc) return rc;
131
132 len = sizeof sa;
133 rc = getpeername(control_sock, &sa, &len);
134 if (rc < 0) {
135 perror("getpeername");
136 } else {
137 char ip_addr[100];
138 ndmalogf(sess, 0, 2, "Connection accepted from %s:%u",
139 inet_ntop(AF_INET, &(((struct sockaddr_in*)&sa)->sin_addr),
140 ip_addr, sizeof(ip_addr)));
141 }
142
143 len = sizeof sa;
144 rc = getsockname(control_sock, &sa, &len);
145 if (rc < 0) {
146 perror("getsockname");
147 } else {
148 char ip_addr[100];
149 ndmalogf(sess, 0, 2, "Connection accepted to %s",
150 inet_ntop(AF_INET, &((struct sockaddr_in*)&sa)->sin_addr, ip_addr,
151 sizeof(ip_addr)));
152 }
153
154 conn = ndmconn_initialize(0, "#C");
155 if (!conn) {
156 ndmalogf(sess, 0, 0, "can't init connection");
157 close(control_sock);
158 return -1;
159 }
160
161 ndmos_condition_control_socket(sess, control_sock);
162
163 if (sess->conn_snooping) {
164 ndmconn_set_snoop(conn, &sess->param->log, sess->param->log_level);
165 }
166 ndmconn_accept(conn, control_sock);
167
168 conn->call = ndma_call;
169 conn->context = sess;
170
171 sess->plumb.control = conn;
172
173 while (!conn->chan.eof) { ndma_session_quantum(sess, 1000); }
174
175 #if 1
176 {
177 char ip_addr[100];
178 ndmalogf(sess, 0, 2, "Connection close %s:%u",
179 inet_ntop(AF_INET, &(((struct sockaddr_in*)&sa)->sin_addr),
180 ip_addr, sizeof(ip_addr)),
181 ntohs(((struct sockaddr_in*)&sa)->sin_port));
182 }
183 #endif
184
185 ndmconn_destruct(conn);
186
187 ndma_session_decommission(sess);
188 ndma_session_destroy(sess);
189
190 return 0;
191 }
192
ndma_daemon_session(struct ndm_session * sess,int port)193 int ndma_daemon_session(struct ndm_session* sess, int port)
194 {
195 int listen_sock;
196 int conn_sock, rc;
197 socklen_t len;
198 struct sockaddr sa;
199
200 listen_sock = socket(AF_INET, SOCK_STREAM, 0);
201 if (listen_sock < 0) {
202 perror("socket");
203 return 1;
204 }
205
206 ndmos_condition_listen_socket(sess, listen_sock);
207
208 NDMOS_MACRO_SET_SOCKADDR(&sa, 0, port);
209
210 if (bind(listen_sock, &sa, sizeof sa) < 0) {
211 perror("bind");
212 close(listen_sock);
213 return 2;
214 }
215
216 if (listen(listen_sock, 1) < 0) {
217 perror("listen");
218 close(listen_sock);
219 return 3;
220 }
221
222 for (;;) {
223 len = sizeof sa;
224 conn_sock = accept(listen_sock, &sa, &len);
225 if (conn_sock < 0) {
226 perror("accept");
227 close(listen_sock);
228 return 4;
229 }
230
231 rc = fork();
232 if (rc < 0) {
233 perror("fork");
234 close(listen_sock);
235 close(conn_sock);
236 return 5;
237 }
238
239 if (rc == 0) {
240 close(listen_sock);
241 ndma_server_session(sess, conn_sock);
242 exit(0);
243 }
244 close(conn_sock);
245 }
246
247 return 0;
248 }
249
250 #endif /* !NDMOS_EFFECT_NO_SERVER_AGENTS */
251
252
ndma_session_distribute_quantum(struct ndm_session * sess)253 int ndma_session_distribute_quantum(struct ndm_session* sess)
254 {
255 int total_did_something = 0;
256 int did_something;
257
258 do {
259 did_something = 0;
260
261 if (sess->plumb.image_stream) did_something |= ndmis_quantum(sess);
262
263 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
264 if (sess->tape_acb &&
265 sess->tape_acb->mover_state.state != NDMP9_MOVER_STATE_IDLE)
266 did_something |= ndmta_quantum(sess);
267 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
268
269 #ifndef NDMOS_OPTION_NO_DATA_AGENT
270 if (sess->data_acb &&
271 sess->data_acb->data_state.state != NDMP9_DATA_STATE_IDLE)
272 did_something |= ndmda_quantum(sess);
273 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */
274
275 total_did_something |= did_something;
276
277 } while (did_something);
278
279 return total_did_something;
280 }
281
282
ndma_session_quantum(struct ndm_session * sess,int max_delay_secs)283 int ndma_session_quantum(struct ndm_session* sess, int max_delay_secs)
284 {
285 struct ndm_image_stream* is = sess->plumb.image_stream;
286 struct ndmconn* conn;
287 struct ndmconn* conntab[5];
288 int n_conntab;
289 struct ndmchan* chtab[16];
290 int n_chtab;
291 int i;
292 int max_delay_usec = max_delay_secs * 1000;
293
294 /*
295 * Gather distinct connections
296 */
297 n_conntab = 0;
298 if ((conn = sess->plumb.control)) conntab[n_conntab++] = conn;
299 if ((conn = sess->plumb.data) && conn != sess->plumb.control)
300 conntab[n_conntab++] = conn;
301 if ((conn = sess->plumb.tape) && conn != sess->plumb.data &&
302 conn != sess->plumb.control)
303 conntab[n_conntab++] = conn;
304 if ((conn = sess->plumb.robot) && conn != sess->plumb.tape &&
305 conn != sess->plumb.data && conn != sess->plumb.control)
306 conntab[n_conntab++] = conn;
307
308 /*
309 * Add connections to channel table
310 */
311 n_chtab = 0;
312 for (i = 0; i < n_conntab; i++) {
313 conn = conntab[i];
314 chtab[n_chtab++] = &conn->chan;
315 }
316
317 #ifndef NDMOS_OPTION_NO_DATA_AGENT
318 /*
319 * Add DATA AGENT channels to table if active (!IDLE)
320 */
321 if (sess->data_acb &&
322 sess->data_acb->data_state.state != NDMP9_DATA_STATE_IDLE) {
323 chtab[n_chtab++] = &sess->data_acb->formatter_image;
324 chtab[n_chtab++] = &sess->data_acb->formatter_error;
325 chtab[n_chtab++] = &sess->data_acb->formatter_wrap;
326 }
327 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */
328
329 /*
330 * Add image stream to channel table
331 */
332 if (is && is->remote.connect_status == NDMIS_CONN_LISTEN) {
333 chtab[n_chtab++] = &is->remote.listen_chan;
334 }
335
336 if (is) { chtab[n_chtab++] = &is->chan; }
337
338 /*
339 * Let TAPE and DATA AGENTS get a bit of work done.
340 * This fills channel buffers as much as possible prior to blocking.
341 */
342 if (ndma_session_distribute_quantum(sess)) max_delay_usec = 0;
343
344 /*
345 * Block awaiting ready I/O. Many channel buffers
346 * will have actual I/O (read/write) performed.
347 */
348 ndmchan_quantum(chtab, n_chtab, max_delay_usec);
349
350 /*
351 * Tattle for debug
352 */
353 if (sess->param->log_level > 7) {
354 for (i = 0; i < n_chtab; i++) {
355 struct ndmchan* ch = chtab[i];
356 char buf[80];
357
358 ndmchan_pp(ch, buf);
359 ndmalogf(sess, 0, 7, "ch %s", buf);
360 }
361 }
362
363 /*
364 * Let TAPE and DATA AGENTS get a bit more work done.
365 * This will mostly digest whatever data just arrived.
366 */
367 ndma_session_distribute_quantum(sess);
368
369 /*
370 * Dispatch any pending activity on the control connections
371 */
372 for (i = 0; i < n_conntab; i++) {
373 conn = conntab[i];
374 if (conn->chan.ready) {
375 conn->chan.ready = 0;
376 ndma_dispatch_conn(sess, conn);
377 }
378 }
379
380 return 0;
381 }
382
383
ndma_session_initialize(struct ndm_session * sess)384 int ndma_session_initialize(struct ndm_session* sess)
385 {
386 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
387 if (sess->control_agent_enabled && ndmca_initialize(sess)) return -1;
388 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
389
390 #ifndef NDMOS_OPTION_NO_DATA_AGENT
391 if (sess->data_agent_enabled && ndmda_initialize(sess)) return -1;
392 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */
393
394 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
395 if (sess->tape_agent_enabled && ndmta_initialize(sess)) return -1;
396 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
397
398 #ifndef NDMOS_OPTION_NO_ROBOT_AGENT
399 if (sess->robot_agent_enabled && ndmra_initialize(sess)) return -1;
400 #endif /* !NDMOS_OPTION_NO_ROBOT_AGENT */
401
402 return 0;
403 }
404
ndma_session_commission(struct ndm_session * sess)405 int ndma_session_commission(struct ndm_session* sess)
406 {
407 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
408 if (sess->control_agent_enabled && ndmca_commission(sess)) return -1;
409 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
410
411 #ifndef NDMOS_OPTION_NO_DATA_AGENT
412 if (sess->data_agent_enabled && ndmda_commission(sess)) return -1;
413 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */
414
415 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
416 if (sess->tape_agent_enabled && ndmta_commission(sess)) return -1;
417 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
418
419 #ifndef NDMOS_OPTION_NO_ROBOT_AGENT
420 if (sess->robot_agent_enabled && ndmra_commission(sess)) return -1;
421 #endif /* !NDMOS_OPTION_NO_ROBOT_AGENT */
422
423 return 0;
424 }
425
ndma_session_decommission(struct ndm_session * sess)426 int ndma_session_decommission(struct ndm_session* sess)
427 {
428 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
429 if (sess->control_agent_enabled && ndmca_decommission(sess)) return -1;
430 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
431
432 #ifndef NDMOS_OPTION_NO_DATA_AGENT
433 if (sess->data_agent_enabled && ndmda_decommission(sess)) return -1;
434 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */
435
436 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
437 if (sess->tape_agent_enabled && ndmta_decommission(sess)) return -1;
438 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
439
440 #ifndef NDMOS_OPTION_NO_ROBOT_AGENT
441 if (sess->robot_agent_enabled && ndmra_decommission(sess)) return -1;
442 #endif /* !NDMOS_OPTION_NO_ROBOT_AGENT */
443
444 return 0;
445 }
446
ndma_session_destroy(struct ndm_session * sess)447 int ndma_session_destroy(struct ndm_session* sess)
448 {
449 if (sess->config_info) {
450 NDMOS_API_FREE(sess->config_info);
451 sess->config_info = NULL;
452 }
453
454 ndmis_destroy(sess);
455
456 if (sess->plumb.control) {
457 ndmconn_destruct(sess->plumb.control);
458 sess->plumb.control = NULL;
459 }
460 if (sess->plumb.data) {
461 ndmconn_destruct(sess->plumb.data);
462 sess->plumb.data = NULL;
463 }
464 if (sess->plumb.tape) {
465 ndmconn_destruct(sess->plumb.tape);
466 sess->plumb.tape = NULL;
467 }
468 if (sess->plumb.robot) {
469 ndmconn_destruct(sess->plumb.robot);
470 sess->plumb.robot = NULL;
471 }
472
473 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
474 if (sess->control_agent_enabled && ndmca_destroy(sess)) return -1;
475 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
476
477 #ifndef NDMOS_OPTION_NO_DATA_AGENT
478 if (sess->data_agent_enabled && ndmda_destroy(sess)) return -1;
479 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */
480
481 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
482 if (sess->tape_agent_enabled && ndmta_destroy(sess)) return -1;
483 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
484
485 #ifndef NDMOS_OPTION_NO_ROBOT_AGENT
486 if (sess->robot_agent_enabled && ndmra_destroy(sess)) return -1;
487 #endif /* !NDMOS_OPTION_NO_ROBOT_AGENT */
488
489 return 0;
490 }
491