/* Distributed Checksum Clearinghouse * * connect to a DCC server for an administrative program * * --C-LICENSE-- * $Revision: 1.56 $ */ #include "dcc_clnt.h" #include "dcc_heap_debug.h" static DCC_CLNT_CTXT *ctxt_free; static int ctxts_active; /* current DCC server host name * This can give the wrong answer if another thread sneaks in and * switches servers */ const char * dcc_srvr_nm(u_char grey) { const DCC_SRVR_CLASS *class; SRVR_INX srvr_inx; const DCC_SRVR_ADDR *cur_addr; NAM_INX nam_inx; if (!dcc_clnt_info) return "???"; class = grey ? &dcc_clnt_info->dcc : &dcc_clnt_info->grey; srvr_inx = class->srvr_inx; if (VALID_SRVR(class, srvr_inx)) { cur_addr = &class->addrs[srvr_inx]; nam_inx = cur_addr->nam_inx; if (VALID_NAM(nam_inx)) return class->nms[nam_inx].hostname; } return grey ? "greylist server" : "DCC server"; } /* Create a DCC client context * The contexts must be locked */ DCC_CLNT_CTXT * /* 0=failed */ dcc_alloc_ctxt(void) { DCC_CLNT_CTXT *ctxt; assert_ctxts_locked(); ctxt = ctxt_free; if (ctxt) { ctxt_free = ctxt->fwd; } else { ctxt = dcc_malloc(sizeof(*ctxt)); } memset(ctxt, 0, sizeof(*ctxt)); ctxt->soc[0].s = INVALID_SOCKET; ctxt->soc[1].s = INVALID_SOCKET; ++ctxts_active; return ctxt; } /* the contexts must be locked */ void dcc_rel_ctxt(DCC_CLNT_CTXT *ctxt) { assert_ctxts_locked(); dcc_clnt_socs_close(ctxt); ctxt->fwd = ctxt_free; ctxt_free = ctxt; if (--ctxts_active < 0) abort(); } /* create a temporary an anonymous map file * The contexts must be locked. * On failure, everything is undone. * On success, the file is initialized and mapped. */ u_char /* 0=failed; 1=mapped & locked */ dcc_map_tmp_info(DCC_EMSG *emsg, /* cleared of stale messages */ const DCC_SRVR_NM *nm, const DCC_IP *src4, const DCC_IP *src6, DCC_INFO_FGS info_fgs) /* DCC_INFO_FG_* */ { DCC_PATH tmp_info_nm; int fd; assert_ctxts_locked(); fd = dcc_mkstemp(emsg, &tmp_info_nm, 0, 0, 0, 0, "map", 1, 0); if (fd < 0) return 0; if (!dcc_create_map(emsg, tmp_info_nm.c, &fd, nm, 1, nm, 1, src4, src6, info_fgs | DCC_INFO_FG_TMP)) return 0; return dcc_map_info(emsg, tmp_info_nm.c, fd); } /* start to get ready for an operation * on entry, nothing is locked, * on success, the contexts and info are locked * on failure, nothing is locked */ DCC_CLNT_CTXT * /* 0=failed */ dcc_clnt_start(DCC_EMSG *emsg, DCC_CLNT_CTXT *ctxt, const char *new_info_map_nm, DCC_CLNT_FGS clnt_fgs) { dcc_ctxts_lock(); if (!ctxt) ctxt = dcc_alloc_ctxt(); if (emsg) emsg->c[0] = '\0'; if (!dcc_map_info(emsg, new_info_map_nm, -1)) { dcc_rel_ctxt(ctxt); dcc_ctxts_unlock(); return 0; } if (!dcc_clnt_rdy(emsg, ctxt, clnt_fgs)) { if (!(clnt_fgs & DCC_CLNT_FG_BAD_SRVR_OK)) { dcc_unmap_close_info(0); dcc_rel_ctxt(ctxt); dcc_ctxts_unlock(); return 0; } if (emsg && dcc_clnt_debug) dcc_trace_msg("%s", emsg->c); /* try to lock the shared information since we are not * admitting that dcc_clnt_rdy() failed */ if (!dcc_info_lock(emsg)) { dcc_rel_ctxt(ctxt); dcc_ctxts_unlock(); return 0; } } return ctxt; } /* release both locks */ DCC_CLNT_CTXT * /* 0=failed */ dcc_clnt_start_fin(DCC_EMSG *emsg, /* cleared of stale messages */ DCC_CLNT_CTXT *ctxt) { if (!dcc_info_unlock(emsg)) { dcc_unmap_close_info(0); dcc_rel_ctxt(ctxt); dcc_ctxts_unlock(); return 0; } dcc_ctxts_unlock(); return ctxt; } /* on entry, nothing is locked * on success the info file is mapped, but nothing is locked * on failure, nothing is mapped or locked */ DCC_CLNT_CTXT * /* 0=failed */ dcc_clnt_init(DCC_EMSG *emsg, DCC_CLNT_CTXT *ctxt, const char *new_info_map_nm, DCC_CLNT_FGS clnt_fgs) { ctxt = dcc_clnt_start(emsg, ctxt, new_info_map_nm, clnt_fgs); if (ctxt) ctxt = dcc_clnt_start_fin(emsg, ctxt); return ctxt; } /* start talking to a DCC server using an temporary parameter file * on entry nothing is locked * on success the info file is mapped, but nothing is locked * on failure, nothing is mapped or locked */ DCC_CLNT_CTXT * /* 0=failed, 1=ready */ dcc_tmp_clnt_init(DCC_EMSG *emsg, DCC_CLNT_CTXT *ctxt, const DCC_SRVR_NM *new_srvr, const DCC_IP *src4, const DCC_IP *src6, DCC_CLNT_FGS clnt_fgs, DCC_INFO_FGS info_fgs) /* DCC_INFO_FG_* */ { if (emsg) emsg->c[0] = '\0'; dcc_ctxts_lock(); if (!dcc_map_tmp_info(emsg, new_srvr, src4, src6, info_fgs)) { if (ctxt) dcc_rel_ctxt(ctxt); dcc_ctxts_unlock(); return 0; } dcc_ctxts_unlock(); ctxt = dcc_clnt_init(emsg, ctxt, 0, clnt_fgs | DCC_CLNT_FG_NO_FAIL); if (!ctxt) { dcc_ctxts_lock(); dcc_unmap_close_info(0); dcc_ctxts_unlock(); } return ctxt; }