Dillo v3.2.0-88-g47ab7c70
Loading...
Searching...
No Matches
dpi.c
Go to the documentation of this file.
1/*
2 * File: dpi.c
3 *
4 * Copyright (C) 2002-2007 Jorge Arellano Cid <jcid@dillo.org>
5 * Copyright (C) 2025 Rodrigo Arias Mallo <rodarima@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 */
12
22#include <unistd.h>
23#include <stdlib.h>
24#include <sys/types.h>
25#include <string.h>
26#include <stdio.h>
27#include <errno.h> /* for errno */
28#include <fcntl.h>
29#include <ctype.h> /* isxdigit */
30#include <stdint.h>
31
32#include <sys/socket.h>
33#include <sys/un.h>
34#include <netinet/in.h>
35#include <netinet/tcp.h>
36#include <arpa/inet.h>
37#include <netdb.h>
38
39#include "../msg.h"
40#include "../klist.h"
41#include "IO.h"
42#include "Url.h"
43#include "../../dpip/dpip.h"
44#include "dlib/dlib.h"
45
46/* This one is tricky, some sources state it should include the byte
47 * for the terminating NULL, and others say it shouldn't. */
48# define D_SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \
49 + strlen ((ptr)->sun_path))
50
51/* Solaris may not have this one... */
52#ifndef AF_LOCAL
53#define AF_LOCAL AF_UNIX
54#endif
55
56typedef struct {
57 int InTag;
58 int Send2EOF;
59
60 int DataTotalSize;
61 int DataRecvSize;
62
63 Dstr *Buf;
64
65 int BufIdx;
66 int TokIdx;
67 int TokSize;
68 int TokIsTag;
69
70 ChainLink *InfoRecv;
71 int Key;
72} dpi_conn_t;
73
74
75/*
76 * Local data
77 */
78static Klist_t *ValidConns = NULL; /* Active connections list. It holds
79 * pointers to dpi_conn_t structures. */
80static char SharedKey[32];
81
82/*
83 * Initialize local data
84 */
85void a_Dpi_init(void)
86{
87 /* empty */
88}
89
93static dpi_conn_t *Dpi_conn_new(ChainLink *Info)
94{
95 dpi_conn_t *conn = dNew0(dpi_conn_t, 1);
96
97 conn->Buf = dStr_sized_new(8*1024);
98 conn->InfoRecv = Info;
99 conn->Key = a_Klist_insert(&ValidConns, conn);
100
101 return conn;
102}
103
107static void Dpi_conn_free(dpi_conn_t *conn)
108{
109 a_Klist_remove(ValidConns, conn->Key);
110 dStr_free(conn->Buf, 1);
111 dFree(conn);
112}
113
118static int Dpi_conn_valid(int key)
119{
120 return (a_Klist_get_data(ValidConns, key)) ? 1 : 0;
121}
122
126static void Dpi_append_dbuf(dpi_conn_t *conn, DataBuf *dbuf)
127{
128 if (dbuf->Code == 0 && dbuf->Size > 0) {
129 dStr_append_l(conn->Buf, dbuf->Buf, dbuf->Size);
130 }
131}
132
143static int Dpi_get_token(dpi_conn_t *conn)
144{
145 int i, resp = -1;
146 char *buf = conn->Buf->str;
147
148 if (conn->BufIdx == conn->Buf->len) {
149 dStr_truncate(conn->Buf, 0);
150 conn->BufIdx = 0;
151 return resp;
152 }
153
154 if (conn->Send2EOF) {
155 conn->TokIdx = conn->BufIdx;
156 conn->TokSize = conn->Buf->len - conn->BufIdx;
157 conn->BufIdx = conn->Buf->len;
158 return 0;
159 }
160
161 _MSG("conn->BufIdx = %d; conn->Buf->len = %d\nbuf: [%s]\n",
162 conn->BufIdx,conn->Buf->len, conn->Buf->str + conn->BufIdx);
163
164 if (!conn->InTag) {
165 /* search for start of tag */
166 while (conn->BufIdx < conn->Buf->len && buf[conn->BufIdx] != '<')
167 ++conn->BufIdx;
168 if (conn->BufIdx < conn->Buf->len) {
169 /* found */
170 conn->InTag = 1;
171 conn->TokIdx = conn->BufIdx;
172 } else {
173 MSG_ERR("[Dpi_get_token] Can't find token start\n");
174 }
175 }
176
177 if (conn->InTag) {
178 /* search for end of tag (EOT=" '>") */
179 for (i = conn->BufIdx; i < conn->Buf->len; ++i)
180 if (buf[i] == '>' && i >= 2 && buf[i-1] == '\'' && buf[i-2] == ' ')
181 break;
182 conn->BufIdx = i;
183
184 if (conn->BufIdx < conn->Buf->len) {
185 /* found EOT */
186 conn->TokIsTag = 1;
187 conn->TokSize = conn->BufIdx - conn->TokIdx + 1;
188 ++conn->BufIdx;
189 conn->InTag = 0;
190 resp = 0;
191 }
192 }
193
194 return resp;
195}
196
200static void Dpi_parse_token(dpi_conn_t *conn)
201{
202 char *tag, *cmd, *msg, *urlstr;
203 DataBuf *dbuf;
204 char *Tok = conn->Buf->str + conn->TokIdx;
205
206 if (conn->Send2EOF) {
207 /* we're receiving data chunks from a HTML page */
208 dbuf = a_Chain_dbuf_new(Tok, conn->TokSize, 0);
209 a_Chain_fcb(OpSend, conn->InfoRecv, dbuf, "send_page_2eof");
210 dFree(dbuf);
211 return;
212 }
213
214 tag = dStrndup(Tok, (size_t)conn->TokSize);
215 _MSG("Dpi_parse_token: {%s}\n", tag);
216
217 cmd = a_Dpip_get_attr_l(Tok, conn->TokSize, "cmd");
218 if (strcmp(cmd, "send_status_message") == 0) {
219 msg = a_Dpip_get_attr_l(Tok, conn->TokSize, "msg");
220 a_Chain_fcb(OpSend, conn->InfoRecv, msg, cmd);
221 dFree(msg);
222
223 } else if (strcmp(cmd, "chat") == 0) {
224 msg = a_Dpip_get_attr_l(Tok, conn->TokSize, "msg");
225 a_Chain_fcb(OpSend, conn->InfoRecv, msg, cmd);
226 dFree(msg);
227
228 } else if (strcmp(cmd, "dialog") == 0) {
229 /* For now will send the dpip tag... */
230 a_Chain_fcb(OpSend, conn->InfoRecv, tag, cmd);
231
232 } else if (strcmp(cmd, "start_send_page") == 0) {
233 conn->Send2EOF = 1;
234 urlstr = a_Dpip_get_attr_l(Tok, conn->TokSize, "url");
235 a_Chain_fcb(OpSend, conn->InfoRecv, urlstr, cmd);
236 dFree(urlstr);
237 /* TODO: a_Dpip_get_attr_l(Tok, conn->TokSize, "send_mode") */
238
239 } else if (strcmp(cmd, "reload_request") == 0) {
240 urlstr = a_Dpip_get_attr_l(Tok, conn->TokSize, "url");
241 a_Chain_fcb(OpSend, conn->InfoRecv, urlstr, cmd);
242 dFree(urlstr);
243 }
244 dFree(cmd);
245
246 dFree(tag);
247}
248
249
250/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
251
257static int Dpi_blocking_write(int fd, const char *msg, int msg_len)
258{
259 int st, sent = 0;
260
261 while (sent < msg_len) {
262 st = write(fd, msg + sent, msg_len - sent);
263 if (st < 0) {
264 if (errno == EINTR) {
265 continue;
266 } else {
267 MSG_ERR("[Dpi_blocking_write] %s\n", dStrerror(errno));
268 break;
269 }
270 }
271 sent += st;
272 }
273
274 return (sent == msg_len) ? 1 : -1;
275}
276
284static char *Dpi_blocking_read(int fd)
285{
286 int st;
287 const int buf_sz = 8*1024;
288 char buf[buf_sz], *msg = NULL;
289 Dstr *dstr = dStr_sized_new(buf_sz);
290
291 do {
292 st = read(fd, buf, buf_sz);
293 if (st < 0) {
294 if (errno == EINTR) {
295 continue;
296 } else {
297 MSG_ERR("[Dpi_blocking_read] %s\n", dStrerror(errno));
298 break;
299 }
300 } else if (st > 0) {
301 dStr_append_l(dstr, buf, st);
302 }
303 } while (st == buf_sz);
304
305 msg = (dstr->len > 0) ? dstr->str : NULL;
306 dStr_free(dstr, (dstr->len > 0) ? FALSE : TRUE);
307 return msg;
308}
309
310/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
311
316static void Dpi_process_dbuf(int Op, void *Data1, dpi_conn_t *conn)
317{
318 DataBuf *dbuf = Data1;
319 int key = conn->Key;
320
321 /* Very useful for debugging: show the data stream as received. */
322 /* fwrite(dbuf->Buf, dbuf->Size, 1, stdout); */
323
324 if (Op == IORead) {
325 Dpi_append_dbuf(conn, dbuf);
326 /* 'conn' has to be validated because Dpi_parse_token() MAY call abort */
327 while (Dpi_conn_valid(key) && Dpi_get_token(conn) != -1) {
328 Dpi_parse_token(conn);
329 }
330
331 } else if (Op == IOClose) {
332 /* unused */
333 }
334}
335
340static int Dpi_start_dpid(void)
341{
342 pid_t pid;
343 int st_pipe[2], ret = 1;
344 char *answer;
345
346 /* create a pipe to track our child's status */
347 if (pipe(st_pipe))
348 return 1;
349
350 pid = fork();
351 if (pid == 0) {
352 /* This is the child process. Execute the command. */
353 char *path1 = dStrconcat(dGethomedir(), "/.dillo/dpid", NULL);
354 dClose(st_pipe[0]);
355 if (execl(path1, "dpid", (char*)NULL) == -1) {
356 dFree(path1);
357 path1 = dStrconcat(DILLO_BINDIR, "dpid", NULL);
358 if (execl(path1, "dpid", (char*)NULL) == -1) {
359 dFree(path1);
360 if (execlp("dpid", "dpid", (char*)NULL) == -1) {
361 MSG("Dpi_start_dpid (child): %s\n", dStrerror(errno));
362 if (Dpi_blocking_write(st_pipe[1], "ERROR", 5) == -1) {
363 MSG("Dpi_start_dpid (child): can't write to pipe.\n");
364 }
365 dClose(st_pipe[1]);
366 _exit (EXIT_FAILURE);
367 }
368 }
369 }
370 } else if (pid < 0) {
371 /* The fork failed. Report failure. */
372 MSG("Dpi_start_dpid: %s\n", dStrerror(errno));
373 /* close the unused pipe */
374 dClose(st_pipe[0]);
375 dClose(st_pipe[1]);
376 } else {
377 /* This is the parent process, check our child status... */
378 dClose(st_pipe[1]);
379 if ((answer = Dpi_blocking_read(st_pipe[0])) != NULL) {
380 MSG("Dpi_start_dpid: can't start dpid\n");
381 dFree(answer);
382 } else {
383 ret = 0;
384 }
385 dClose(st_pipe[0]);
386 }
387
388 return ret;
389}
390
395static int Dpi_read_comm_keys(int *port)
396{
397 FILE *In;
398 char *fname, *rcline = NULL, *tail;
399 int i, ret = -1;
400
401 fname = dStrconcat(dGethomedir(), "/.dillo/dpid_comm_keys", NULL);
402 if ((In = fopen(fname, "r")) == NULL) {
403 MSG_ERR("[Dpi_read_comm_keys] %s\n", dStrerror(errno));
404 } else if ((rcline = dGetline(In)) == NULL) {
405 MSG_ERR("[Dpi_read_comm_keys] empty file: %s\n", fname);
406 } else {
407 *port = strtol(rcline, &tail, 10);
408 for (i = 0; *tail && isxdigit(tail[i+1]); ++i)
409 SharedKey[i] = tail[i+1];
410 SharedKey[i] = 0;
411 ret = 1;
412 }
413 if (In)
414 fclose(In);
415 dFree(rcline);
416 dFree(fname);
417
418 return ret;
419}
420
424static int Dpi_make_socket_fd(void)
425{
426 int fd, one = 1, ret = -1;
427
428 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) != -1) {
429 /* avoid delays when sending small pieces of data */
430 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
431 ret = fd;
432 }
433 return ret;
434}
435
440static int Dpi_check_dpid_ids(void)
441{
442 struct sockaddr_in sin;
443 const socklen_t sin_sz = sizeof(sin);
444 int sock_fd, dpid_port, ret = -1;
445
446 /* socket connection test */
447 memset(&sin, 0, sizeof(sin));
448 sin.sin_family = AF_INET;
449 sin.sin_addr.s_addr = inet_addr("127.0.0.1");
450
451 if (Dpi_read_comm_keys(&dpid_port) != -1) {
452 sin.sin_port = htons(dpid_port);
453 if ((sock_fd = Dpi_make_socket_fd()) == -1) {
454 MSG("Dpi_check_dpid_ids: sock_fd=%d %s\n", sock_fd, dStrerror(errno));
455 } else if (connect(sock_fd, (struct sockaddr *)&sin, sin_sz) == -1) {
456 MSG("Dpi_check_dpid_ids: %s\n", dStrerror(errno));
457 } else {
458 dClose(sock_fd);
459 ret = 1;
460 }
461 }
462 return ret;
463}
464
469static int Dpi_check_dpid(int num_tries)
470{
471 static int starting = 0;
472 int check_st = 1, ret = 2;
473
474 check_st = Dpi_check_dpid_ids();
475 _MSG("Dpi_check_dpid: check_st=%d\n", check_st);
476
477 if (check_st == 1) {
478 /* connection test with dpi server passed */
479 starting = 0;
480 ret = 0;
481 } else {
482 if (!starting) {
483 /* start dpid */
484 if (Dpi_start_dpid() == 0) {
485 starting = 1;
486 ret = 1;
487 }
488 } else if (++starting < num_tries) {
489 /* starting */
490 ret = 1;
491 } else {
492 /* we waited too much, report an error... */
493 starting = 0;
494 }
495 }
496
497 _MSG("Dpi_check_dpid: %s\n",
498 (ret == 0) ? "OK" : (ret == 1 ? "EAGAIN" : "ERROR"));
499 return ret;
500}
501
507{
508 int cst, try = 0,
509 n_tries = 12; /* 3 seconds */
510
511 /* test the dpid, and wait a bit for it to start if necessary */
512 while ((cst = Dpi_check_dpid(n_tries)) == 1) {
513 MSG("Dpi_blocking_start_dpid: try %d\n", ++try);
514 dUsleep(250000UL);
515 }
516 return cst;
517}
518
527static int Dpi_get_server_port(const char *server_name)
528{
529 int sock_fd = -1, dpi_port = -1;
530 int dpid_port, ok = 0;
531 struct sockaddr_in sin;
532 char *cmd, *request, *rply = NULL, *port_str;
533 socklen_t sin_sz;
534
535 dReturn_val_if_fail (server_name != NULL, dpi_port);
536 _MSG("Dpi_get_server_port: server_name = [%s]\n", server_name);
537
538 /* Read dpid's port from saved file */
539 if (Dpi_read_comm_keys(&dpid_port) != -1) {
540 ok = 1;
541 }
542 if (ok) {
543 /* Connect a socket with dpid */
544 ok = 0;
545 sin_sz = sizeof(sin);
546 memset(&sin, 0, sizeof(sin));
547 sin.sin_family = AF_INET;
548 sin.sin_addr.s_addr = inet_addr("127.0.0.1");
549 sin.sin_port = htons(dpid_port);
550 if ((sock_fd = Dpi_make_socket_fd()) == -1 ||
551 connect(sock_fd, (struct sockaddr *)&sin, sin_sz) == -1) {
552 MSG("Dpi_get_server_port: %s\n", dStrerror(errno));
553 } else {
554 ok = 1;
555 }
556 }
557 if (ok) {
558 /* ask dpid to check the dpi and send its port number back */
559 ok = 0;
560 request = a_Dpip_build_cmd("cmd=%s msg=%s", "check_server", server_name);
561 _MSG("[%s]\n", request);
562
563 if (Dpi_blocking_write(sock_fd, request, strlen(request)) == -1) {
564 MSG("Dpi_get_server_port: %s\n", dStrerror(errno));
565 } else {
566 ok = 1;
567 }
568 dFree(request);
569 }
570 if (ok) {
571 /* Get the reply */
572 ok = 0;
573 if ((rply = Dpi_blocking_read(sock_fd)) == NULL) {
574 MSG("Dpi_get_server_port: can't read server port from dpid.\n");
575 } else {
576 ok = 1;
577 }
578 }
579 if (ok) {
580 /* Parse reply */
581 ok = 0;
582 cmd = a_Dpip_get_attr(rply, "cmd");
583 if (strcmp(cmd, "send_data") == 0) {
584 port_str = a_Dpip_get_attr(rply, "msg");
585 _MSG("Dpi_get_server_port: rply=%s\n", rply);
586 _MSG("Dpi_get_server_port: port_str=%s\n", port_str);
587 dpi_port = strtol(port_str, NULL, 10);
588 dFree(port_str);
589 ok = 1;
590 }
591 dFree(cmd);
592 }
593 dFree(rply);
594 dClose(sock_fd);
595
596 return ok ? dpi_port : -1;
597}
598
599
605static int Dpi_connect_socket(const char *server_name)
606{
607 struct sockaddr_in sin;
608 int sock_fd, dpi_port, ret = -1;
609 char *cmd = NULL;
610
611 /* Query dpid for the port number for this server */
612 if ((dpi_port = Dpi_get_server_port(server_name)) == -1) {
613 _MSG("Dpi_connect_socket: can't get port number for %s\n", server_name);
614 return -1;
615 }
616 _MSG("Dpi_connect_socket: server=%s port=%d\n", server_name, dpi_port);
617
618 /* connect with this server's socket */
619 memset(&sin, 0, sizeof(sin));
620 sin.sin_family = AF_INET;
621 sin.sin_addr.s_addr = inet_addr("127.0.0.1");
622 sin.sin_port = htons(dpi_port);
623
624 if ((sock_fd = Dpi_make_socket_fd()) == -1) {
625 MSG_ERR("[Dpi_connect_socket] %s\n", dStrerror(errno));
626 } else if (connect(sock_fd, (void*)&sin, sizeof(sin)) == -1) {
627 MSG_ERR("[Dpi_connect_socket] errno:%d %s\n", errno, dStrerror(errno));
628
629 /* send authentication Key (the server closes sock_fd on auth error) */
630 } else if (!(cmd = a_Dpip_build_cmd("cmd=%s msg=%s", "auth", SharedKey))) {
631 MSG_ERR("[Dpi_connect_socket] Can't make auth message.\n");
632 } else if (Dpi_blocking_write(sock_fd, cmd, strlen(cmd)) == -1) {
633 MSG_ERR("[Dpi_connect_socket] Can't send auth message.\n");
634 } else {
635 ret = sock_fd;
636 }
637 dFree(cmd);
638 if (sock_fd != -1 && ret == -1) /* can't send cmd? */
639 dClose(sock_fd);
640
641 return ret;
642}
643
647void a_Dpi_ccc(int Op, int Branch, int Dir, ChainLink *Info,
648 void *Data1, void *Data2)
649{
650 dpi_conn_t *conn;
651 int SockFD = -1, st;
652
653 dReturn_if_fail( a_Chain_check("a_Dpi_ccc", Op, Branch, Dir, Info) );
654
655 if (Branch == 1) {
656 if (Dir == BCK) {
657 /* Send commands to dpi-server */
658 switch (Op) {
659 case OpStart:
660 if ((st = Dpi_blocking_start_dpid()) == 0) {
661 if ((SockFD = Dpi_connect_socket(Data1)) != -1) {
662 int *fd = dNew(int, 1);
663 *fd = SockFD;
664 Info->LocalKey = fd;
665 a_Chain_link_new(Info, a_Dpi_ccc, BCK, a_IO_ccc, 1, 1);
666 a_Chain_bcb(OpStart, Info, NULL, NULL);
667 /* Let the FD known and tracked */
668 a_Chain_bcb(OpSend, Info, &SockFD, "FD");
669 a_Chain_fcb(OpSend, Info, &SockFD, "FD");
670 a_Chain_fcb(OpSend, Info, NULL, "DpidOK");
671 } else {
672 a_Dpi_ccc(OpAbort, 1, FWD, Info, NULL, NULL);
673 }
674 } else {
675 MSG_ERR("dpi.c: can't start dpi daemon\n");
676 a_Dpi_ccc(OpAbort, 1, FWD, Info, NULL, "DpidERROR");
677 }
678 break;
679 case OpSend:
680 a_Chain_bcb(OpSend, Info, Data1, NULL);
681 break;
682 case OpEnd:
683 a_Chain_bcb(OpEnd, Info, NULL, NULL);
684 dFree(Info->LocalKey);
685 dFree(Info);
686 break;
687 case OpAbort:
688 a_Chain_bcb(OpAbort, Info, NULL, NULL);
689 dFree(Info->LocalKey);
690 dFree(Info);
691 break;
692 default:
693 MSG_WARN("Unused CCC\n");
694 break;
695 }
696 } else { /* 1 FWD */
697 /* Send commands to dpi-server (status) */
698 switch (Op) {
699 case OpAbort:
700 a_Chain_fcb(OpAbort, Info, NULL, Data2);
701 dFree(Info);
702 break;
703 default:
704 MSG_WARN("Unused CCC\n");
705 break;
706 }
707 }
708
709 } else if (Branch == 2) {
710 if (Dir == FWD) {
711 /* Receiving from server */
712 switch (Op) {
713 case OpSend:
714 /* Data1 = dbuf */
715 Dpi_process_dbuf(IORead, Data1, Info->LocalKey);
716 break;
717 case OpAbort:
718 MSG_WARN("Dpi server aborted the connection\n");
719 /* fallthrough */
720 case OpEnd:
721 a_Chain_fcb(Op, Info, NULL, NULL);
722 Dpi_conn_free(Info->LocalKey);
723 dFree(Info);
724 break;
725 default:
726 MSG_WARN("Unused CCC\n");
727 break;
728 }
729 } else { /* 2 BCK */
730 switch (Op) {
731 case OpStart:
732 conn = Dpi_conn_new(Info);
733 Info->LocalKey = conn;
734
735 /* Hack: for receiving HTTP through the DPI framework */
736 if (strcmp(Data2, "http") == 0) {
737 conn->Send2EOF = 1;
738 }
739
740 a_Chain_link_new(Info, a_Dpi_ccc, BCK, a_IO_ccc, 2, 2);
741 a_Chain_bcb(OpStart, Info, NULL, NULL); /* IORead */
742 break;
743 case OpSend:
744 if (Data2 && !strcmp(Data2, "FD")) {
745 a_Chain_bcb(OpSend, Info, Data1, Data2);
746 }
747 break;
748 case OpAbort:
749 a_Chain_bcb(OpAbort, Info, NULL, NULL);
750 Dpi_conn_free(Info->LocalKey);
751 dFree(Info);
752 break;
753 default:
754 MSG_WARN("Unused CCC\n");
755 break;
756 }
757 }
758 }
759}
760
766{
767
768}
769
774char *a_Dpi_send_blocking_cmd(const char *server_name, const char *cmd)
775{
776 int cst, sock_fd;
777 char *ret = NULL;
778
779 /* test the dpid, and wait a bit for it to start if necessary */
780 if ((cst = Dpi_blocking_start_dpid()) != 0) {
781 return ret;
782 }
783
784 if ((sock_fd = Dpi_connect_socket(server_name)) == -1) {
785 MSG_ERR("[a_Dpi_send_blocking_cmd] Can't connect to server.\n");
786 } else if (Dpi_blocking_write(sock_fd, cmd, strlen(cmd)) == -1) {
787 MSG_ERR("[a_Dpi_send_blocking_cmd] Can't send message.\n");
788 } else if ((ret = Dpi_blocking_read(sock_fd)) == NULL) {
789 MSG_ERR("[a_Dpi_send_blocking_cmd] Can't read message.\n");
790 }
791 dClose(sock_fd);
792
793 return ret;
794}
795
void a_IO_ccc(int Op, int Branch, int Dir, ChainLink *Info, void *Data1, void *Data2)
CCC function for the IO module.
Definition IO.c:359
#define IORead
Definition IO.h:11
#define IOClose
Definition IO.h:13
#define _MSG(...)
Definition bookmarks.c:45
#define MSG(...)
Definition bookmarks.c:46
int a_Chain_bcb(int Op, ChainLink *Info, void *Data1, void *Data2)
Issue the backward callback of the 'Info' link.
Definition chain.c:126
DataBuf * a_Chain_dbuf_new(void *buf, int size, int code)
Allocate and initialize a new DataBuf structure.
Definition chain.c:171
ChainLink * a_Chain_link_new(ChainLink *AInfo, ChainFunction_t AFunc, int Direction, ChainFunction_t BFunc, int AtoB_branch, int BtoA_branch)
Create a new link from module A to module B.
Definition chain.c:55
int a_Chain_check(char *FuncStr, int Op, int Branch, int Dir, ChainLink *Info)
Check whether the CCC is operative.
Definition chain.c:186
int a_Chain_fcb(int Op, ChainLink *Info, void *Data1, void *Data2)
Issue the forward callback of the 'Info' link.
Definition chain.c:103
#define OpAbort
Definition chain.h:17
#define FWD
Definition chain.h:29
#define OpStart
Definition chain.h:13
#define BCK
Definition chain.h:30
#define OpSend
Definition chain.h:14
#define OpEnd
Definition chain.h:16
char * dGetline(FILE *stream)
Get a line from a FILE stream.
Definition dlib.c:956
char * dStrconcat(const char *s1,...)
Concatenate a NULL-terminated list of strings.
Definition dlib.c:102
void dFree(void *mem)
Definition dlib.c:68
Dstr * dStr_sized_new(int sz)
Create a new string with a given size.
Definition dlib.c:254
void dStr_free(Dstr *ds, int all)
Free a dillo string.
Definition dlib.c:337
int dClose(int fd)
Close a FD handling EINTR.
Definition dlib.c:979
void dStr_append_l(Dstr *ds, const char *s, int l)
Append a C string to a Dstr (providing length).
Definition dlib.c:308
int dUsleep(unsigned long usec)
Portable usleep() function.
Definition dlib.c:995
char * dStrndup(const char *s, size_t sz)
Definition dlib.c:88
void dStr_truncate(Dstr *ds, int len)
Truncate a Dstr to be 'len' bytes long.
Definition dlib.c:368
char * dGethomedir(void)
Return the home directory in a static string (don't free)
Definition dlib.c:934
#define dStrerror
Definition dlib.h:107
#define dReturn_if_fail(expr)
Definition dlib.h:84
#define dNew0(type, count)
Definition dlib.h:63
#define dReturn_val_if_fail(expr, val)
Definition dlib.h:88
#define TRUE
Definition dlib.h:35
#define FALSE
Definition dlib.h:31
#define dNew(type, count)
Definition dlib.h:61
#define MSG_ERR(...)
Definition dpid_common.h:23
char * a_Dpip_build_cmd(const char *format,...)
Printf like function for building dpip commands.
Definition dpip.c:83
char * a_Dpip_get_attr(const char *tag, const char *attrname)
Task: given a tag and an attribute name, return its value.
Definition dpip.c:192
char * a_Dpip_get_attr_l(const char *tag, size_t tagsize, const char *attrname)
Task: given a tag, its size and an attribute name, return the attribute value (stuffing of ' is remov...
Definition dpip.c:134
void a_Klist_remove(Klist_t *Klist, int Key)
Remove data by Key.
Definition klist.c:86
void * a_Klist_get_data(Klist_t *Klist, int Key)
Return the data pointer for a given Key (or NULL if not found)
Definition klist.c:43
int a_Klist_insert(Klist_t **Klist, void *Data)
Insert a data pointer and return a key for it.
Definition klist.c:56
#define MSG_WARN(...)
Definition msg.h:26
static int Dpi_check_dpid_ids(void)
Make a connection test for a IDS.
Definition dpi.c:440
static char SharedKey[32]
Definition dpi.c:80
static int Dpi_start_dpid(void)
Start dpid.
Definition dpi.c:340
static int Dpi_blocking_write(int fd, const char *msg, int msg_len)
Write data into a file descriptor taking care of EINTR and possible data splits.
Definition dpi.c:257
static dpi_conn_t * Dpi_conn_new(ChainLink *Info)
Create a new connection data structure.
Definition dpi.c:93
static void Dpi_parse_token(dpi_conn_t *conn)
Parse a dpi tag and take the appropriate actions.
Definition dpi.c:200
static int Dpi_conn_valid(int key)
Check whether a conn is still valid.
Definition dpi.c:118
static int Dpi_read_comm_keys(int *port)
Read dpid's communication keys from its saved file.
Definition dpi.c:395
static int Dpi_get_token(dpi_conn_t *conn)
Split the data stream into tokens.
Definition dpi.c:143
void a_Dpi_dillo_exit(void)
Let dpid know dillo is no longer running.
Definition dpi.c:765
void a_Dpi_ccc(int Op, int Branch, int Dir, ChainLink *Info, void *Data1, void *Data2)
CCC function for the Dpi module.
Definition dpi.c:647
static Klist_t * ValidConns
Definition dpi.c:78
static int Dpi_get_server_port(const char *server_name)
Return the dpi server's port number, or -1 on error.
Definition dpi.c:527
char * a_Dpi_send_blocking_cmd(const char *server_name, const char *cmd)
Send a command to a dpi server, and block until the answer is got.
Definition dpi.c:774
static int Dpi_blocking_start_dpid(void)
Confirm that the dpid is running.
Definition dpi.c:506
static void Dpi_process_dbuf(int Op, void *Data1, dpi_conn_t *conn)
Get a new data buffer (within a 'dbuf'), save it into local data, split in tokens and parse the conte...
Definition dpi.c:316
static char * Dpi_blocking_read(int fd)
Read all the available data from a filedescriptor.
Definition dpi.c:284
static int Dpi_make_socket_fd(void)
Return a socket file descriptor.
Definition dpi.c:424
static void Dpi_append_dbuf(dpi_conn_t *conn, DataBuf *dbuf)
Append the new buffer in 'dbuf' to Buf in 'conn'.
Definition dpi.c:126
static int Dpi_check_dpid(int num_tries)
Confirm that the dpid is running.
Definition dpi.c:469
static void Dpi_conn_free(dpi_conn_t *conn)
Free a connection data structure.
Definition dpi.c:107
void a_Dpi_init(void)
Definition dpi.c:85
static int Dpi_connect_socket(const char *server_name)
Connect a socket to a dpi server and return the socket's FD.
Definition dpi.c:605
A convenience data structure for passing data chunks between nodes.
Definition chain.h:52
char * Buf
Definition chain.h:53
int Code
Definition chain.h:55
int Size
Definition chain.h:54
Definition dlib.h:114
Dstr_char_t * str
Definition dlib.h:117
int len
Definition dlib.h:116