📄 dpi.c
字号:
{ FILE *in; gchar *saved_name_filename; /* :) */ gchar dpid_uds_dir[256], *p; saved_name_filename = g_strconcat(g_get_home_dir(), "/", ".dillo/dpi_socket_dir", NULL); in = fopen(saved_name_filename, "r"); g_free(saved_name_filename); if (in != NULL) { fgets(dpid_uds_dir, 256, in); fclose(in); if ((p = strchr(dpid_uds_dir, '\n'))) *p = 0; if (access(dpid_uds_dir, F_OK) == 0) p = g_strdup(dpid_uds_dir); _MSG("Dpi_get_dpid_uds_dir:: %s\n", p); return p; } _MSG("Dpi_get_dpid_uds_dir: %s \n", g_strerror(errno)); return NULL;}/* * Return the dpid's UDS name, NULL on failure. */gchar *Dpi_get_dpid_uds_name(void){ gchar *dpid_uds_dir, *dpid_uds_name = NULL; if ((dpid_uds_dir = Dpi_get_dpid_uds_dir()) != NULL) dpid_uds_name= g_strconcat(dpid_uds_dir, "/", "dpid.srs", NULL); g_free(dpid_uds_dir); return dpid_uds_name;}/* * Confirm that the dpid is running. If not, start it. * Return: 0 running OK, 1 starting (EAGAIN), 2 Error. */gint Dpi_check_dpid(){ static gint starting = 0; gchar *dpid_uds_name; gint check_st = 1, ret = 2; if ((dpid_uds_name = Dpi_get_dpid_uds_name())) check_st = Dpi_check_uds(dpid_uds_name); _MSG("Dpi_check_dpid: dpid_uds_name=%s, check_st=%d\n", dpid_uds_name, check_st); if (check_st == 0) { /* connection test with dpi server passed */ starting = 0; ret = 0; } else if (!dpid_uds_name || check_st) { if (!starting) { /* start dpid */ if (Dpi_start_dpid() == 0) { starting = 1; ret = 1; } } else if (++starting < 25) { ret = 1; } else { /* we waited too much, report an error... */ starting = 0; } } g_free(dpid_uds_name); DEBUG_MSG(2, "Dpi_check_dpid:: %s\n", (ret == 0) ? "OK" : (ret == 1 ? "EAGAIN" : "ERROR")); return ret;}/* * Return the UDS name of a dpi server. * (A query is sent to dpid and then its answer parsed) * note: as the available servers and/or the dpi socket directory can * change at any time, we'll ask each time. If someday we find * that connecting each time significantly degrades performance, * an optimized approach can be tried. */gchar *Dpi_get_server_uds_name(gchar *server_name){ gchar *dpid_uds_dir, *dpid_uds_name = NULL, *server_uds_name = NULL; g_return_val_if_fail (server_name != NULL, NULL); DEBUG_MSG(2, "Dpi_get_server_uds_name:: server_name = [%s]\n", server_name); dpid_uds_dir = Dpi_get_dpid_uds_dir(); if (dpid_uds_dir) { struct sockaddr_un dpid; gint sock, req_sz, rdlen, buflen; gchar buf[128], *cmd, *request, *rply; /* Get the server's uds name from dpid */ sock = socket(AF_LOCAL, SOCK_STREAM, 0); dpid.sun_family = AF_LOCAL; dpid_uds_name = g_strconcat(dpid_uds_dir, "/", "dpid.srs", NULL); _MSG("dpid_uds_name = [%s]\n", dpid_uds_name); strncpy(dpid.sun_path, dpid_uds_name, sizeof(dpid.sun_path)); if (connect(sock, (struct sockaddr *) &dpid, sizeof(dpid)) == -1) perror("connect"); /* ask dpid to check the server plugin and send its UDS name back */ request = g_strdup_printf("<dpi cmd='check_server' msg='%s'>", server_name); DEBUG_MSG(2, "[%s]\n", request); if (write(sock, request, strlen(request)) == -1) perror("writing request"); g_free(request); shutdown(sock, 1); /* signals no more writes to dpid */ /* Get the reply */ rply = NULL; buf[0] = '\0'; buflen = sizeof(buf)/sizeof(buf[0]); for (req_sz = 0; (rdlen = read(sock, buf, buflen)) != 0 && rdlen != -1; req_sz += rdlen) { rply = g_realloc(rply, req_sz + rdlen + 1); if (req_sz == 0) rply[0] = '\0'; strncat(rply, buf, rdlen); } close(sock); DEBUG_MSG(2, "rply = [%s]\n", rply); /* Parse reply */ if (rply) { cmd = Get_attr_value(rply, strlen(rply), "cmd"); if (strcmp(cmd, "send_data") == 0) server_uds_name = Get_attr_value(rply, strlen(rply), "msg"); g_free(cmd); g_free(rply); } } g_free(dpid_uds_dir); g_free(dpid_uds_name); DEBUG_MSG(2, "Dpi_get_server_uds_name:: %s\n", server_uds_name); return server_uds_name;}/* * Connect a socket to a dpi server and return the socket's FD. * We have to ask 'dpid' (dpi daemon) for the UDS of the target dpi server. * Once we have it, then the proper file descriptor is returned (-1 on error). */static gint Dpi_connect_socket(gchar *server_name, gint retry){ char *server_uds_name; struct sockaddr_un pun; gint SockFD, err; /* Query dpid for the UDS name for this server */ server_uds_name = Dpi_get_server_uds_name(server_name); DEBUG_MSG(2, "server_uds_name = [%s]\n", server_uds_name); if (access(server_uds_name, F_OK) != 0) { MSG("server socket was NOT found\n"); return -1; } /* connect with this server's socket */ memset(&pun, 0, sizeof(struct sockaddr_un)); pun.sun_family = AF_LOCAL; strncpy(pun.sun_path, server_uds_name, sizeof (pun.sun_path)); g_free(server_uds_name); if ((SockFD = socket(AF_LOCAL, SOCK_STREAM, 0)) == -1) perror("[dpi::socket]"); else if (connect(SockFD, (void*)&pun, D_SUN_LEN(&pun)) == -1) { err = errno; SockFD = -1; MSG("[dpi::connect] errno:%d %s\n", errno, g_strerror(errno)); if (retry) { switch (err) { case ECONNREFUSED: case EBADF: case ENOTSOCK: case EADDRNOTAVAIL: /* the server may crash and its socket name survive */ unlink(pun.sun_path); SockFD = Dpi_connect_socket(server_name, FALSE); break; } } } return SockFD;}/* * CCC function for the Dpi module */void a_Dpi_ccc(int Op, int Branch, int Dir, ChainLink *Info, void *Data1, void *Data2){ GSList *list; gint SockFD = -1, st; a_Chain_debug_msg("a_Dpi_ccc", Op, Branch, Dir); if (Branch == 1) { if (Dir == BCK) { /* Cache request, return the FD. */ /* (Data1 = Url; Data2 = Web) */ switch (Op) { case OpStart: /* We'll know the FD later, enqueue this connection. * (The Url is used as an identifier for the connection) */ Info->LocalKey = a_Url_dup(Data1); PendingNodes = g_slist_append(PendingNodes, (gpointer)Info); break; } } else { /* FWD */ switch (Op) { case OpEnd: /* End this requesting branch */ a_Url_free(Info->LocalKey); a_Chain_fcb(OpEnd, Info, NULL, NULL); break; case OpAbort: list = g_slist_find_custom( PendingNodes, Info->LocalKey, Dpi_node_cmp); if (list) { /* The connection is not pending anymore */ PendingNodes = g_slist_remove(PendingNodes, list->data); } a_Url_free(Info->LocalKey); a_Chain_fcb(OpAbort, Info, NULL, NULL); break; } } } else if (Branch == 2) { if (Dir == BCK) { /* Send commands to dpi-server */ switch (Op) { case OpStart: if ((st = Dpi_check_dpid()) == 0) { SockFD = Dpi_connect_socket(Data1, TRUE); if (SockFD != -1) { gint *fd = g_new(gint, 1); *fd = SockFD; Info->LocalKey = fd; a_Chain_link_new(Info, a_Dpi_ccc, BCK, a_IO_ccc, 3, 2); a_Chain_bcb(OpStart, Info, Info->LocalKey, NULL); /* tell the capi to start the receiving branch */ a_Chain_fcb(OpSend, Info, Info->LocalKey, "SockFD"); } } if (st == 0 && SockFD != -1) a_Chain_fcb(OpSend, Info, NULL, (void*)"DpidOK"); else if (st == 1) a_Chain_fcb(OpSend, Info, NULL, (void*)"DpidEAGAIN"); else { DEBUG_MSG(4, "dpi.c: ERROR, can't start dpi daemon\n"); a_Dpi_ccc(OpAbort, 2, FWD, Info, "ERR_dpid", NULL); } break; case OpSend: a_Chain_bcb(OpSend, Info, Data1, NULL); break; case OpEnd: a_Chain_bcb(OpEnd, Info, NULL, NULL); g_free(Info->LocalKey); g_free(Info); break; case OpAbort: MSG("a_Dpi_ccc: OpAbort[2B], Not implemented\n"); g_free(Info->LocalKey); g_free(Info); break; } } else { /* FWD */ /* Send commands to dpi-server (status) */ switch (Op) { case OpEnd: a_Chain_del_link(Info, BCK); g_free(Info); break; case OpSend: case OpAbort: a_Chain_fcb(OpAbort, Info, Data1, NULL); g_free(Info); break; } } } else if (Branch == 3) { if (Dir == FWD) { /* Receiving from server */ switch (Op) { case OpSend: Dpi_process_io(IORead, Data1, Info->LocalKey); break; case OpEnd: a_Chain_del_link(Info, BCK); Dpi_process_io(IOClose, Data1, Info->LocalKey); Dpi_conn_data_free(Info->LocalKey); a_Chain_fcb(OpEnd, Info, NULL, NULL); break; case OpAbort: MSG(" Not implemented\n"); break; } } else { /* BCK */ switch (Op) { case OpStart: { IOData_t *io2; Info->LocalKey = Dpi_conn_data_new(Info); io2 = a_IO_new(IORead, *(int*)Data1); /* SockFD */ a_IO_set_buf(io2, NULL, IOBufLen); a_Chain_link_new(Info, a_Dpi_ccc, BCK, a_IO_ccc, 2, 3); a_Chain_bcb(OpStart, Info, io2, NULL); break; } case OpSend: /* now that we have the FD, resume the connection. * (Data1 = FD, Data2 = Url) */ list = g_slist_find_custom(PendingNodes, Data2, Dpi_node_cmp); if (list) { ChainLink *P_Info = list->data; /* Tell the cache to start the receiving CCC */ a_Chain_fcb(OpSend, P_Info, Data1, NULL); /* The connection is not pending anymore */ PendingNodes = g_slist_remove(PendingNodes, list->data); /* End this requesting CCC */ a_Dpi_ccc(OpEnd, 1, FWD, P_Info, NULL, NULL); } break; case OpStop: /* Stop transfer, abort the pending node. * (Data1 = Url, Data2 = NULL) */ list = g_slist_find_custom(PendingNodes, Data1, Dpi_node_cmp); if (list) { ChainLink *P_Info = list->data; /* Abort this requesting CCC */ a_Dpi_ccc(OpAbort, 1, FWD, P_Info, Data1, NULL); } break; case OpAbort: MSG(" Not implemented\n"); break; } } } else if (Branch == 4) { /* Unused */ g_assert_not_reached(); }}/*! Send DpiBye to dpid * Note: currently disabled. Maybe it'd be better to have a * dpid_idle_timeout variable in the config file. */void a_Dpi_bye_dpid(){ char *DpiBye_cmd = "<dpi cmd='DpiBye'>"; struct sockaddr_un sa; size_t sun_path_len, addr_len; char *srs_name; int new_socket; srs_name = Dpi_get_dpid_uds_name(); sun_path_len = sizeof(sa.sun_path); addr_len = sizeof(sa); sa.sun_family = AF_LOCAL; if ((new_socket = socket(AF_LOCAL, SOCK_STREAM, 0)) == -1) { DEBUG_MSG(4, "a_Dpi_bye_dpid: %s\n", g_strerror(errno)); } strncpy(sa.sun_path, srs_name, sizeof (sa.sun_path)); if (connect(new_socket, (struct sockaddr *) &sa, addr_len) == -1) { DEBUG_MSG(4, "a_Dpi_bye_dpid: %s\n", g_strerror(errno)); fprintf(stderr, "%s\n", sa.sun_path); } (void) write(new_socket, DpiBye_cmd, strlen(DpiBye_cmd)); close(new_socket);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -