/* performs an HTTP post to the given URL, with callback */ int netio_http_post_host(char *host, char *path, char *urlstr, char *content_type, char *data, int data_len, void (*func) (char *url, int respcode, char *data, int data_len, void *pkg), void *pkg) { addr_t addr; int ret = -1; struct sockaddr *sa = NULL; socklen_t sa_len; netio_http_conn_t *http_conn = NULL; ASSERT_ZERO(ident_addr_str_to_addr_lookup(host, &addr), err); addr.type = IPPROTO_TCP; if (addr.port < 1) addr.port = 80; ASSERT_ZERO(ident_addr_addr_to_sa(&addr, &sa, &sa_len), err); /* new managed api: */ if ((http_conn = netio_http_wait_new(&addr, urlstr, host, path, content_type, data, data_len, func, pkg))) { ship_lock(conns); http_conn->socket = netio_man_connto(sa, sa_len, http_conn, __netio_http_cb_conn, __netio_http_cb_data); if (http_conn->socket != -1) { netio_http_track_conn(http_conn, http_conn->socket); ret = 0; ship_unlock(http_conn); } ship_unlock(conns); } err: freez(sa); return ret; }
/* inits the */ int addrbook_init(processor_config_t *config) { ASSERT_ZERO(processor_config_get_string(config, P2PSHIP_CONF_CONTACTS_FILE, &contacts_file), err); ASSERT_TRUE(addrbook_lock = ship_list_new(), err); #ifdef CONFIG_LIBEBOOK_ENABLED ASSERT_ZERO(addrbook_libebook_init(), err); #endif return 0; err: return -1; }
int ac_init(processor_config_t *config) { processor_config_set_dynamic_update(config, P2PSHIP_CONF_AC_MAX_PATH, ac_cb_config_update); processor_config_set_dynamic_update(config, P2PSHIP_CONF_AC_HTTP, ac_cb_config_update); processor_config_set_dynamic_update(config, P2PSHIP_CONF_PDD_LOG, ac_cb_config_update); processor_config_set_dynamic_update(config, P2PSHIP_CONF_PDD_RESET_MODE, ac_cb_config_update); ASSERT_TRUE(filters = ship_obj_list_new(), err); #ifdef DO_STATS ac_packetfilter_add(ac_packetfilter_stats, NULL, 1); #endif ac_packetfilter_add(ac_packetfilter_debug, NULL, 1); ac_packetfilter_add(ac_packetfilter_simple, NULL, 0); ac_packetfilter_add(ac_packetfilter_blacklist, NULL, 0); ac_packetfilter_add(ac_packetfilter_whitelist, NULL, 0); ac_packetfilter_add(ac_packetfilter_trust, NULL, 0); #ifdef AC_HTTP_PF ac_packetfilter_add(ac_packetfilter_http, NULL, 0); #endif #ifdef CONFIG_OP_ENABLED ac_packetfilter_add(ac_packetfilter_op, NULL, 0); #endif ac_cb_config_update(config, NULL, NULL); #ifdef CONFIG_OP_ENABLED processor_config_set_dynamic_update(config, P2PSHIP_CONF_IDENT_FILTERING, ac_cb_config_update); #endif #ifdef DO_STATS ASSERT_TRUE(stats = ship_ht_new(), err); ASSERT_TRUE(done_stats = ship_list_new(), err); ASSERT_TRUE(done_stats_ht = ship_ht_new(), err); #endif /* whites / blacks */ ASSERT_TRUE(white_list = ship_ht_new(), err); ASSERT_TRUE(black_list = ship_ht_new(), err); ASSERT_ZERO(processor_config_get_string(config, P2PSHIP_CONF_WHITELIST_FILE, &wl_file), err); ASSERT_ZERO(processor_config_get_string(config, P2PSHIP_CONF_BLACKLIST_FILE, &bl_file), err); ASSERT_ZERO(ac_lists_load(white_list, wl_file), err); ASSERT_ZERO(ac_lists_load(black_list, bl_file), err); ident_register_default_service(SERVICE_TYPE_STATS, &ac_stats_service); return 0; err: return -1; }
static netio_http_conn_t * netio_http_conn_new(int socket) { netio_http_conn_t *ret = 0; if (socket != -1) while ((ret = netio_http_get_conn_by_socket(socket, 1))) { ret->owns_socket = 0; ship_unlock(ret); } ASSERT_TRUE(ret = mallocz(sizeof(netio_http_conn_t)), err); ret->socket = socket; ret->forward_socket = -1; ASSERT_ZERO(ship_lock_new(&ret->lock), err); netio_http_track_conn(ret, socket); ASSERT_TRUE(ret->params = ship_ht_new(), err); ASSERT_TRUE(ret->headers = ship_ht_new(), err); /* this last! */ ret->owns_socket = 1; return ret; err: netio_http_conn_close(ret); return 0; }
/* callback for new connections */ static void __netio_http_conn_cb(int s, struct sockaddr *sa, socklen_t addrlen, int ss) { netio_http_conn_t *conn = 0; LOG_DEBUG("Got connection on netio_http, socket %d (ss: %d)\n", s, ss); netio_http_conn_close_all(s); ASSERT_TRUE(conn = netio_http_conn_new(s), err); ASSERT_ZERO(ident_addr_sa_to_addr(sa, addrlen, &(conn->addr)), err); conn->ss = ss; ship_unlock(conn); ASSERT_ZERO(netio_read(s, __netio_http_conn_read_cb), err); return; err: netio_http_conn_close(conn); }
/* modifies the port / host the server is listening to */ static int __netio_http_server_listen(char *new_address) { struct sockaddr *sa = 0; socklen_t salen; int ret = -1; char buf[1024]; ASSERT_ZERO(ident_addr_str_to_sa(new_address, &sa, &salen), err); ASSERT_ZERO(ident_addr_sa_to_str(sa, salen, buf), err); LOG_INFO("Using %s for HTTP server\n", buf); ASSERT_TRUE((ret = netio_new_listener(sa, salen, __netio_http_conn_cb)) != -1, err); freez(sa); err: freez(sa); return ret; }
/* loads / saves a white / black list */ static int ac_lists_load(ship_ht_t *list, char *filename) { int ret = -1; ASSERT_ZERO(ship_read_file(filename, list, _ac_lists_load_cb, NULL), err); ret = 0; err: return ret; }
/* Creates a new media proxy callid, local_aor, remote_aor should be clear mediatype is the mediatype (currently not used..) bindaddr is the address on which we should bind the listener targetaddr is where the media should be sent sendby indicates whether direct / through tunnel */ sipp_media_proxy_t * sipp_mp_create_new(char *callid, char *local_aor, char *remote_aor, char *mediatype, addr_t *bindaddr, addr_t *targetaddr, int sendby) { sipp_media_proxy_t *ret; struct sockaddr *sa = NULL; socklen_t size; ASSERT_TRUE(ret = (sipp_media_proxy_t *)mallocz(sizeof(sipp_media_proxy_t)), err); ASSERT_TRUE(ret->callid = strdup(callid), err); ASSERT_TRUE(ret->mediatype = strdup(mediatype), err); ret->sendby = sendby; time(&ret->last); memcpy(&(ret->local_addr), bindaddr, sizeof(addr_t)); ASSERT_TRUE(ret->sip_aor = strdup(local_aor), err); ASSERT_TRUE(ret->remote_aor = strdup(remote_aor), err); if (targetaddr) { memcpy(&(ret->remote_addr), targetaddr, sizeof(addr_t)); } else { bzero(&(ret->remote_addr), sizeof(addr_t)); } /* todo: this doesn't work for tcp or anything else */ ASSERT_TRUE(ret->local_addr.type == IPPROTO_UDP, err); ASSERT_ZERO(ident_addr_addr_to_sa(&(ret->local_addr), &sa, &size), err); ret->socket = netio_new_packet_socket(sa, size); if (ret->socket == -1) goto err; ASSERT_ZERO(getsockname(ret->socket, sa, &size), err); ASSERT_ZERO(ident_addr_sa_to_addr(sa, size, &(ret->local_addr)), err); ret->local_addr.type = IPPROTO_UDP; ship_list_add(sipp_mps, ret); freez(sa); return ret; err: freez(sa); sipp_mp_close(ret); return 0; }
/* retrieve a list of contacts from the address book */ static int addrbook_libebook_retrieve(ship_list_t *list) { int ret = -1; contact_t *ct = 0; GError *error = 0; GList *contacts = 0, *loop; EBookQuery *query = 0; ship_lock(addrbook_lock); ASSERT_TRUE(query = e_book_query_any_field_contains(""), err); ASSERT_TRUE(e_book_get_contacts(book, query, &contacts, &error), err); ASSERT_ZERO(error, err); for (loop = contacts; loop; loop = g_list_next(loop)) { EContact *c = loop->data; char *name = 0; name = e_contact_get(c, E_CONTACT_OSSO_CONTACT_STATE); if (!name || strcmp(name, "DELETED")) { char **arrs = 0; ASSERT_TRUE(ct = ident_contact_new(), cerr); ASSERT_TRUE(ct->name = e_contact_get(c, E_CONTACT_FULL_NAME), cerr); ASSERT_TRUE(arrs = e_contact_get(c, E_CONTACT_SIP), cerr); ASSERT_TRUE(ct->sip_aor = addrbook_normalize_aor(arrs[0]), cerr); /* apparently arrs doesn't need to be free'd afterwards */ g_list_foreach((GList*)arrs, (GFunc)g_free, NULL); ship_list_add(list, ct); ct = 0; cerr: ident_contact_free(ct); } if (name) g_free(name); } ret = 0; err: if (contacts) { g_list_free(contacts); } if (query) { e_book_query_unref(query); } if (error) { LOG_ERROR("Error getting contacts: %s\n", error->message); g_error_free(error); } ship_unlock(addrbook_lock); return ret; }
netio_http_conn_t* netio_http_parse_data(char *data, int datalen) { netio_http_conn_t *ret = 0; ASSERT_TRUE(ret = netio_http_conn_new(-1), err); ASSERT_ZERO(__netio_http_parse_data(ret, data, datalen), err); return ret; err: netio_http_conn_close(ret); return 0; }
static int pdd_record_pdd(pdd_stat_t *stat) { char *tmp = 0, *filename = 0; int ret = -1; FILE *f = NULL; int total = stat->end - stat->start, lookup = stat->lookup_done - stat->lookup_start, connect = stat->connect_done - stat->connect_start, auth = (stat->connect_done? stat->sip_sent - stat->connect_done : 0), remote = stat->remote_done - stat->remote_start; /* create the file name .. */ ASSERT_ZERO(ship_get_homedir_file(PDD_LOG_FILE, &filename), err); ASSERT_ZERO(ship_ensure_file(filename, "From, To, Message type, Dot, Total, Lookup, Connect, Auth, Remote, Misc\n"), err); ASSERT_TRUE(tmp = mallocz(strlen(stat->from) + strlen(stat->to) + strlen(stat->msg_type) + 128), err); sprintf(tmp, "%s, %s, %s, %d, %u, %u, %u, %u, %u, %u\n", stat->from, stat->to, stat->msg_type, (int)stat->created, total, lookup, connect, auth, remote, (int)(total - lookup - connect - auth - remote)); if ((f = fopen(filename, "a"))) { fwrite(tmp, sizeof(char), strlen(tmp), f); fclose(f); } LOG_INFO("recorded PDD into csv file %s..\n", filename); ret = 0; err: if (ret) { LOG_ERROR("could not record PDD: %d\n", ret); } freez(tmp); freez(filename); return ret; }
static ac_sip_t* ac_sip_new(sipp_request_t *req, ac_packetfilter_cb func) { ac_sip_t* ret = 0; ASSERT_TRUE(ret = mallocz(sizeof(ac_sip_t)), err); ASSERT_TRUE(ret->req = req, err); ASSERT_TRUE(ret->cb_func = func, err); ASSERT_TRUE(ret->filters = ship_obj_list_new(), err); ASSERT_ZERO(sipp_get_sip_aors(req->evt->sip, &ret->from, &ret->to, 0), err); ret->verdict = AC_VERDICT_NONE; return ret; err: ac_sip_free(ret); return 0; }
static void ac_cb_config_update(processor_config_t *config, char *k, char *v) { #ifdef DO_STATS processor_config_get_bool(config, P2PSHIP_CONF_PDD_RESET_MODE, &pdd_reset_mode); processor_config_get_bool(config, P2PSHIP_CONF_PDD_LOG, &pdd_log); #endif #ifdef CONFIG_OP_ENABLED processor_config_get_enum(config, P2PSHIP_CONF_IDENT_FILTERING, &op_filtering); #endif ASSERT_ZERO(processor_config_get_int(config, P2PSHIP_CONF_AC_MAX_PATH, &max_path), err); #ifdef AC_HTTP_PF freez(http_ac); ASSERT_TRUE((http_ac = strdup(processor_config_string(config, P2PSHIP_CONF_AC_HTTP))), err); #endif return; err: PANIC(); }
int test1() { int child = fork(); int i; data_t* smem; pid_t mypid; int cooloffs = 5; sched_param_t params = {1, 50, cooloffs}; int status; int counter = 0; if (child != 0) { smem = (data_t*)make_shared(sizeof(data_t), 1); smem->curr = 0; mypid = getpid(); ASSERT_POSITIVE(mypid); nice(1); // be nicer than child ASSERT_ZERO(sched_setscheduler(mypid, SCHED_SHORT, ¶ms)); ASSERT_EQUALS(sched_setscheduler(mypid, SCHED_SHORT, ¶ms), -1); ASSERT_EQUALS(errno, EPERM); ASSERT_EQUALS(is_SHORT(mypid), 1); smem->arr[smem->curr] = FATHER+0; // init value ASSERT_ZERO(sched_setscheduler(child, SCHED_SHORT, ¶ms)); // now we lost control until child will be overdue // child got into overdue. we gained control again. we should still be short here. smem->arr[++smem->curr] = FATHER+1; while (is_SHORT(mypid)) ; smem->arr[++smem->curr] = FATHER+(1*10)+OVERDUE_PERIOD; // got into first overdue period ASSERT_EQUALS(remaining_cooloffs(mypid), cooloffs-1); for (i = 1; i <= cooloffs; ++i) { while (!is_SHORT(mypid)) ; smem->arr[++smem->curr] = FATHER+(i*10); // got out of overdue period ASSERT_EQUALS(remaining_cooloffs(mypid), cooloffs-i); while (is_SHORT(mypid)) ; smem->arr[++smem->curr] = FATHER+((i+1)*10)+OVERDUE_PERIOD; // got into overdue period ASSERT_EQUALS(remaining_cooloffs(mypid), max(cooloffs-(i+1), 0)); } // now should be overdue forever ASSERT_ZERO(remaining_cooloffs(mypid)); waitpid(child, &status, 0); // use `gcc -DVERBOSE ...` in order to print the array state if (IS_VERBOSE()) { for (i = 0; i <= 24; i++) { printf("%d:\t%d\n", i, smem->arr[i]); } } // check array ASSERT_EQUALS(smem->arr[0], FATHER+0); ASSERT_EQUALS(smem->arr[1], SON+0); ASSERT_EQUALS(smem->arr[2], FATHER+1); ASSERT_EQUALS(smem->arr[3], SON+10+OVERDUE_PERIOD); ASSERT_EQUALS(smem->arr[4], SON+10); ASSERT_EQUALS(smem->arr[5], FATHER+10+OVERDUE_PERIOD); ASSERT_EQUALS(smem->arr[6], FATHER+10); ASSERT_EQUALS(smem->arr[7], SON+20+OVERDUE_PERIOD); ASSERT_EQUALS(smem->arr[8], SON+20); ASSERT_EQUALS(smem->arr[9], FATHER+20+OVERDUE_PERIOD); ASSERT_EQUALS(smem->arr[10], FATHER+20); ASSERT_EQUALS(smem->arr[11], SON+30+OVERDUE_PERIOD); ASSERT_EQUALS(smem->arr[12], SON+30); ASSERT_EQUALS(smem->arr[13], FATHER+30+OVERDUE_PERIOD); ASSERT_EQUALS(smem->arr[14], FATHER+30); ASSERT_EQUALS(smem->arr[15], SON+40+OVERDUE_PERIOD); ASSERT_EQUALS(smem->arr[16], SON+40); ASSERT_EQUALS(smem->arr[17], FATHER+40+OVERDUE_PERIOD); ASSERT_EQUALS(smem->arr[18], FATHER+40); ASSERT_EQUALS(smem->arr[19], SON+50+OVERDUE_PERIOD); ASSERT_EQUALS(smem->arr[20], SON+50); ASSERT_EQUALS(smem->arr[21], FATHER+50+OVERDUE_PERIOD); ASSERT_EQUALS(smem->arr[22], FATHER+50); ASSERT_EQUALS(smem->arr[23], SON+60+OVERDUE_PERIOD); // son finished ASSERT_EQUALS(smem->arr[24], FATHER+60+OVERDUE_PERIOD); return 1; } else { pid_t mypid = getpid(); ASSERT_POSITIVE(mypid); while (is_SHORT(mypid) != 1) ; data_t* smem = (data_t*)make_shared(sizeof(data_t), 0); smem->arr[++smem->curr] = SON+0; // this is the first SHORT time slice while (is_SHORT(mypid)) ; smem->arr[++smem->curr] = SON+(1*10)+OVERDUE_PERIOD; // got into first overdue period ASSERT_EQUALS(remaining_cooloffs(mypid), cooloffs-1); for (i = 1; i <= cooloffs; ++i) { while (!is_SHORT(mypid)) ; smem->arr[++smem->curr] = SON+(i*10); // got out of overdue period ASSERT_EQUALS(remaining_cooloffs(mypid), cooloffs-i); while (is_SHORT(mypid)) ; smem->arr[++smem->curr] = SON+((i+1)*10)+OVERDUE_PERIOD; // got into overdue period ASSERT_EQUALS(remaining_cooloffs(mypid), max(cooloffs-(i+1), 0)); } // now should be overdue forever ASSERT_ZERO(remaining_cooloffs(mypid)); exit(0); } return 0; }
/* callback when data is got */ static void __netio_http_conn_read_cb(int s, char *data, ssize_t datalen) { netio_http_conn_t *conn = 0; int ret = -1; char *newbuf = NULL; ASSERT_TRUE(conn = netio_http_get_conn_by_socket(s, 1), err); if (datalen < 1) { goto err; } // todo: some sort of half- ready handling #connect // forward-tunnel also!! if (conn->forward_socket != -1) { if (datalen > 0) { netio_send(conn->forward_socket, data, datalen); ret = 1; } } else if (conn->service_forward_service) { int l2; /* add tracking id to buffer */ l2 = datalen + strlen(conn->tracking_id) + 1; ASSERT_TRUE(newbuf = mallocz(l2+1), err); strcpy(newbuf, conn->tracking_id); strcat(newbuf, "\n"); memcpy(newbuf+strlen(newbuf), data, datalen); ASSERT_ZERO(conn_send_slow(conn->service_forward_to, conn->service_forward_from, conn->service_forward_service, newbuf, l2, NULL, NULL), err); ret = 1; } else if (datalen > 0) { ret = __netio_http_parse_data(conn, data, datalen); } /* process.. */ while (!ret) { netio_http_conn_t *new_conn = 0; ret = __netio_http_process_req(conn); // should ret be checked?? if (!strcmp(conn->method, "CONNECT")) break; if (!strcmp(conn->http_version, "HTTP/1.0")) { ret = -1; goto err; } /* we create a new conn for this socket as there might be another request coming. This instead of clearing the one as .. the http proxy will close the http_conn if after responding to just one request. */ netio_http_cut_overrun(conn, &data, &datalen); ship_unlock(conn); ASSERT_TRUE(new_conn = netio_http_conn_new(s), err); memcpy(&(new_conn->addr), &(conn->addr), sizeof(addr_t)); new_conn->ss = conn->ss; conn->owns_socket = 0; /* ..parse the data at this point, it IS pointing at the buffer in the old conn! */ if (datalen > 0) ret = __netio_http_parse_data(new_conn, data, datalen); else ret = 1; ship_unlock(new_conn); netio_http_conn_lock(conn); if (ret < 1) { netio_http_conn_close(conn); } else { ship_unlock(conn); } netio_http_conn_lock(new_conn); conn = new_conn; } err: if (ret < 1) { netio_http_conn_close(conn); } else if (conn) { ship_unlock(conn); } }
/* dumps the current status of all mediaproxies as a json blob */ int sipp_mp_dump_json(char **msg) { int buflen = 0, datalen = 0; char *buf = 0; void *ptr = 0, *ptr2 = 0; sipp_media_proxy_t *mp = NULL; char *tmpaddr1 = 0, *tmpaddr2 = 0, *tmp = 0; ship_list_t *callids = 0; char *str = 0; int ret = -1; ship_lock(sipp_mps); /* collect callids */ ASSERT_TRUE(callids = ship_list_new(), err); while ((mp = ship_list_next(sipp_mps, &ptr))) { int found = 0; while (!found && (str = ship_list_next(callids, &ptr2))) { if (!strcmp(str, mp->callid)) found = 1; } if (!found) { ship_list_add(callids, mp->callid); } } /* for each call id .. */ ASSERT_TRUE(buf = append_str("var p2pship_mps = {\n", buf, &buflen, &datalen), err); ptr2 = 0; while ((str = ship_list_next(callids, &ptr2))) { ASSERT_TRUE(buf = append_str(" \"", buf, &buflen, &datalen), err); ASSERT_TRUE(buf = append_str(str, buf, &buflen, &datalen), err); ASSERT_TRUE(buf = append_str("\" : [\n", buf, &buflen, &datalen), err); ptr = 0; while ((mp = ship_list_next(sipp_mps, &ptr))) { int len = 0; if (!strcmp(mp->callid, str)) { ASSERT_ZERO(ident_addr_addr_to_str(&(mp->local_addr), &tmpaddr1), err); ASSERT_ZERO(ident_addr_addr_to_str(&(mp->remote_addr), &tmpaddr2), err); len = zstrlen(mp->sip_aor) + zstrlen(tmpaddr1) + zstrlen(mp->remote_aor) + zstrlen(tmpaddr2) + zstrlen(mp->callid) + zstrlen(mp->mediatype) + 512; ASSERT_TRUE(tmp = mallocz(len), err); sprintf(tmp, " [ \"%s\", \"%s\", \"%s\", \"%s\", \"%s\",\n \"%s\", \"%s\", \"%d\", \"%d\", \"%d\", \"%d\" ],\n", mp->sip_aor, tmpaddr1, mp->remote_aor, tmpaddr2, sipp_mp_sendby_str(mp->sendby), mp->callid, mp->mediatype, mp->started, (int)mp->start_time, (int)mp->last, mp->counter); ASSERT_TRUE(buf = append_str(tmp, buf, &buflen, &datalen), err); freez(tmp); freez(tmpaddr1); freez(tmpaddr2); } } ASSERT_TRUE(replace_end(buf, &buflen, &datalen, ",\n", "\n"), err); ASSERT_TRUE(buf = append_str(" ],\n", buf, &buflen, &datalen), err); } ASSERT_TRUE(replace_end(buf, &buflen, &datalen, ",\n", "\n"), err); ASSERT_TRUE(buf = append_str("};\n", buf, &buflen, &datalen), err); *msg = buf; buf = 0; ret = 0; err: ship_unlock(sipp_mps); ship_list_free(callids); freez(buf); freez(tmpaddr1); freez(tmpaddr2); freez(tmp); return ret; }
/* starts the media proxy */ int sipp_mp_start(sipp_media_proxy_t *mp, int remotely_got) { sipp_media_proxy_t *mp2; void *ptr = NULL, *lastptr = NULL; sipp_mp_autoclean(); /* remove possible loops */ ship_lock(sipp_mps); while ((mp2 = ship_list_next(sipp_mps, &ptr))) { if (!ident_addr_cmp(&mp->local_addr, &mp2->remote_addr)) { LOG_WARN("mediaproxy loop detected! local will be changed!\n"); memcpy(&mp->local_addr, &mp2->local_addr, sizeof(addr_t)); } else if (!ident_addr_cmp(&mp->remote_addr, &mp2->local_addr)) { LOG_WARN("mediaproxy loop detected! remote will be changed!\n"); memcpy(&mp->remote_addr, &mp2->remote_addr, sizeof(addr_t)); } else mp2 = NULL; if (mp2) { ship_list_remove(sipp_mps, mp2); sipp_mp_close(mp2); ptr = lastptr; } lastptr = ptr; } ship_unlock(sipp_mps); LOG_INFO("starting mp (type %d) for %s (%s:%d -> %s:%d)..\n", mp->sendby, mp->sip_aor, mp->local_addr.addr, mp->local_addr.port, mp->remote_addr.addr, mp->remote_addr.port); if (remotely_got && sipp_mp_supports_fragmentation(mp->remote_aor, &(mp->remote_addr))) { mp->frag_support = 1; LOG_DEBUG("detected fragmentation-aware endpoint at %s:%d!\n", mp->remote_addr.addr, mp->remote_addr.port); } /* start reading packets */ switch (mp->sendby) { case SIPP_MP_SENDBY_DIRECT: #ifdef USE_FF_DIRECT ASSERT_ZERO(netio_ff_add(mp->socket, &(mp->remote_addr), &(mp->counter), mp->frag_support), err); break; #endif default: ASSERT_ZERO(netio_packet_read(mp->socket, sipp_mp_cb_data_got), err); } mp->started = 1; time(&mp->start_time); if (!remotely_got) { LOG_DEBUG("sending fragmentation-support flag for the proxy at %s:%d\n", mp->local_addr.addr, mp->local_addr.port); sipp_mp_notify_fragmentation_support(mp); } return 0; err: return -1; }
/* returns 0 = done, ok. 1 = not done yet, -1 = error */ static int __netio_http_parse_data(netio_http_conn_t* conn, char *data, int datalen) { /* collect data. */ if (!conn->buf || (conn->buf_len - conn->data_len < datalen)) { int ns = conn->buf_len + datalen + 1024; char *tmp = 0; ASSERT_TRUE(tmp = mallocz(ns+1), err); if (conn->buf) memcpy(tmp, conn->buf, conn->data_len); freez(conn->buf); conn->buf = tmp; conn->buf_len = ns; } if (datalen > 0) { memcpy(conn->buf + conn->data_len, data, datalen); conn->data_len += datalen; } /* check if we have the header, parse url & datalen (if present) */ if (!conn->header_got && strstr(conn->buf, "\r\n\r\n")) { char *line = conn->buf, *le; conn->header_got = 1; conn->header_len = strstr(conn->buf, "\r\n\r\n") - conn->buf + 4; do { le = strstr(line, "\r\n"); if (le == line) break; if (str_startswith(line, "POST") || str_startswith(line, "GET") || str_startswith(line, "OPTIONS") || str_startswith(line, "HEAD") || str_startswith(line, "PUT") || str_startswith(line, "DELETE") || str_startswith(line, "TRACE") || str_startswith(line, "CONNECT")) { /* requests! */ char *tmple; /* store method */ if ((tmple = strchr(line, ' '))) { char *t2; tmple++; freez(conn->url); freez(conn->http_version); if (le) { t2 = le; while ((t2 > tmple) && *t2 != ' ') t2--; } else t2 = strrchr(tmple, ' '); if (t2) { conn->url = strndup(tmple, t2-tmple); conn->http_version = trim(strndup(t2, le-t2)); } else { conn->url = strndup(tmple, le-tmple); } freez(conn->method); conn->method = strndup(line, tmple-line); trim(conn->method); trim(conn->url); } } else if (str_startswith(line, "HTTP")) { /* for responses! */ freez(conn->resp_code_line); conn->resp_code_line = trim(strndup(line, le-line)); if (strchr(line, ' ')) conn->resp_code = atoi(strchr(line, ' ')+1); } else { /* generic parameter */ char *tmple = strchr(line, ':'); if (str_startswith(line, "Content-Length: ")) { conn->content_len = atoi(strchr(line, ' ') + 1); } if (tmple) { char *val = strndup(tmple+1, le-tmple+1); char *key = strndup(line, tmple-line); netio_http_set_header(conn, key, val); freez(val); freez(key); } } if (le) line = le+2; } while (le); } /* process data.. */ if (conn->header_got && ((conn->content_len == -1 && datalen < 1) || (conn->content_len != -1 && (conn->content_len <= (conn->data_len - conn->header_len))))) { if (conn->content_len == -1) { conn->content_len = conn->data_len - conn->header_len; } if (conn->method) { LOG_DEBUG("Got total %d bytes, %d bytes data for %s on http\n", conn->data_len, conn->content_len, conn->url); /* treat multipart & 'normal' posts differently */ if (!strcmp(conn->method, "POST") && str_startswith(netio_http_get_header(conn, "Content-Type"), "multipart")) { char *bound, *ps, *pe; bound = strstr_after(netio_http_get_header(conn, "Content-Type"), "boundary="); /* go through parts one-by-one, parsing name & data */ if (bound) { ps = memmem_after(&conn->buf[conn->header_len], conn->data_len - conn->header_len, bound, strlen(bound)); while (ps) { char *tmp, *name, *tmp2 = 0; pe = (char*)memmem(ps, conn->data_len - (ps-conn->buf), bound, strlen(bound)); if (!pe) { pe = conn->buf + conn->data_len; tmp = 0; } else tmp = pe + strlen(bound); if ((name = strstr(ps, "Content-Disposition: "))) tmp2 = strstr(name, "\r\n"); ps = strstr_after(ps, "\r\n\r\n"); if (ps && name && tmp2) { tmp2[0] = 0; if ((name = strstr_after(name, "name=\"")) && (tmp2 = strchr(name, '"'))) { int datalen = pe-ps-4; ASSERT_ZERO(netio_http_conn_set_param(conn, name, tmp2-name, ps, datalen), err); } } ps = tmp; } } } else { int parsedata = conn->header_len; char *ns; ns = &(conn->buf[parsedata]); /* if get, set parsedata to the url's first ?-char */ if (!strcmp(conn->method, "GET")) { char *params = strchr(conn->url, '?'); if (params) { params[0] = 0; ns = params+1; conn->url_extras = strdup(ns); } } while (ns) { char *tmp = 0, *pe = 0; char *ps = strchr(ns, '='); if (ps) { pe = strchr(ps, '&'); if (!pe) { pe = ps + strlen(ps); tmp = 0; } else tmp = pe+1; } if (ps) { char *k = strndup(ns, ps-ns); char *v = strndup(ps+1, pe-ps-1); if (k && v) { ship_urldecode(k); ship_urldecode(v); ASSERT_ZERO(netio_http_conn_set_param(conn, k, strlen(k), v, strlen(v)), err); } freez(k); freez(v); } ns = tmp; } } } /* ..and we're done! */ if (conn->url) { conn->original_url = conn->url; conn->url = strdup(conn->original_url); ship_urldecode(conn->url); } return 0; } else if (datalen < 1) goto err; return 1; err: return -1; }
/* point-of-entry */ int main(int argc, char **argv) { int ret = -1, c, index, action = ACTION_NONE, tmp; char *action_param = NULL; processor_config_t *config = 0, *config2 = 0; char *conf_file = 0; int load_autoreg = 0; int flag_quiet = 0; int log_to_file = 0; int console_only = 0; int do_test = 0; // do whatever the test of the day is xmlInitParser(); xmlInitThreads(); //initGenericErrorDefaultFunc((xmlGenericErrorFunc *)xml_error_func); /* the getopt values */ static struct option long_options[] = { {"verbose", no_argument, 0, 0}, {"iface", required_argument, 0, 0}, {"threads", required_argument, 0, 0}, {"help", no_argument, 0, 0}, {"version", no_argument, 0, 0}, {"console", no_argument, 0, 0}, #ifdef CONFIG_PYTHON_ENABLED {"shell", no_argument, 0, 0}, {"run", required_argument, 0, 0}, {"no-scripts", no_argument, 0, 0}, #endif #ifdef CONFIG_SIP_ENABLED {"proxy-iface", required_argument, 0, 0}, {"no-mp", no_argument, 0, 0}, {"tunnel-mp", no_argument, 0, 0}, {"force-mp", no_argument, 0, 0}, {"allow-unknown", no_argument, 0, 0}, {"allow-untrusted", no_argument, 0, 0}, #endif {"list-ca", no_argument, 0, 0}, {"import-ca", required_argument, 0, 0}, {"remove-ca", required_argument, 0, 0}, {"list", no_argument, 0, 0}, {"import", required_argument, 0, 0}, {"remove", required_argument, 0, 0}, {"idents", required_argument, 0, 0}, {"log", required_argument, 0, 0}, #ifdef CONFIG_BROADCAST_ENABLED {"bc-addr", required_argument, 0, 0}, #endif #ifdef CONFIG_WEBCONF_ENABLED {"webconf", required_argument, 0, 0}, #endif #ifdef CONFIG_OPENDHT_ENABLED {"opendht", required_argument, 0, 0}, #endif #ifdef CONFIG_HIP_ENABLED {"list-hits", no_argument, 0, 0}, {"rvs", required_argument, 0, 0}, {"provide-rvs", no_argument, 0, 0}, #endif {0, 0, 0, 0} }; #ifdef LOCK_DEBUG debug2_init(); #endif #ifdef REF_DEBUG2 ship_debug_initref(); #endif if (!(config = processor_config_new()) || !(config2 = processor_config_new())) { USER_ERROR("Error loading application\n"); goto err; } if (processor_config_load_defaults(config2)) { USER_ERROR("Error loading default configurations\n"); goto err; } processor_config_get_string(config2, P2PSHIP_CONF_CONF_FILE, &conf_file); opterr = 0; while ((c = getopt_long(argc, argv, "LqvhDVs:c:p:i:Rr:kKt", long_options, &index)) != -1) { if (!c) { if (!strcmp(long_options[index].name, "threads")) { processor_config_set_int(config, P2PSHIP_CONF_WORKER_THREADS, atoi(optarg)); } else if (!strcmp(long_options[index].name, "help")) { c = '?'; } else if (!strcmp(long_options[index].name, "version")) { c = 'V'; } else if (!strcmp(long_options[index].name, "verbose")) { c = 'v'; } else if (!strcmp(long_options[index].name, "iface")) { c = 'i'; } else if (!strcmp(long_options[index].name, "console")) { console_only = 1; #ifdef CONFIG_PYTHON_ENABLED } else if (!strcmp(long_options[index].name, "shell")) { processor_config_set_true(config, P2PSHIP_CONF_START_SHELL); } else if (!strcmp(long_options[index].name, "run")) { processor_config_set_string(config, P2PSHIP_CONF_RUN_SCRIPT, optarg); } else if (!strcmp(long_options[index].name, "no-scripts")) { processor_config_set_false(config, P2PSHIP_CONF_STARTUP_SCRIPTS); #endif #ifdef CONFIG_SIP_ENABLED } else if (!strcmp(long_options[index].name, "proxy-iface")) { processor_config_set_string(config, P2PSHIP_CONF_SIPP_PROXY_IFACES, optarg); } else if (!strcmp(long_options[index].name, "no-mp")) { processor_config_set_string(config, P2PSHIP_CONF_SIPP_MEDIA_PROXY, "no"); } else if (!strcmp(long_options[index].name, "tunnel-mp")) { processor_config_set_string(config, P2PSHIP_CONF_SIPP_TUNNEL_PROXY, "yes"); } else if (!strcmp(long_options[index].name, "force-mp")) { processor_config_set_string(config, P2PSHIP_CONF_SIPP_FORCE_PROXY, "yes"); } else if (!strcmp(long_options[index].name, "allow-unknown")) { processor_config_set_string(config, P2PSHIP_CONF_IDENT_ALLOW_UNKNOWN_REGISTRATIONS, "yes"); } else if (!strcmp(long_options[index].name, "allow-untrusted")) { processor_config_set_string(config, P2PSHIP_CONF_IDENT_ALLOW_UNTRUSTED, "yes"); #endif } else if (!action && !strcmp(long_options[index].name, "list-ca")) { action = ACTION_LIST_CA; } else if (!action && !strcmp(long_options[index].name, "remove-ca")) { action = ACTION_REMOVE_CA; if (!action_param) action_param = strdup(optarg); } else if (!action && !strcmp(long_options[index].name, "import-ca")) { action = ACTION_IMPORT_CA; if (!action_param) action_param = strdup(optarg); } else if (!action && !strcmp(long_options[index].name, "list")) { action = ACTION_LIST; } else if (!action && !strcmp(long_options[index].name, "remove")) { action = ACTION_REMOVE; if (!action_param) action_param = strdup(optarg); } else if (!action && !strcmp(long_options[index].name, "import")) { action = ACTION_IMPORT; if (!action_param) action_param = strdup(optarg); } else if (!strcmp(long_options[index].name, "idents")) { processor_config_set_string(config, P2PSHIP_CONF_IDENTS_FILE, optarg); } else if (!strcmp(long_options[index].name, "log")) { processor_config_set_string(config, P2PSHIP_CONF_LOG_FILE, optarg); #ifdef CONFIG_BROADCAST_ENABLED } else if (!strcmp(long_options[index].name, "bc-addr")) { processor_config_set_string(config, P2PSHIP_CONF_BC_ADDR, optarg); #endif #ifdef CONFIG_OPENDHT_ENABLED } else if (!strcmp(long_options[index].name, "opendht")) { processor_config_set_string(config, P2PSHIP_CONF_OPENDHT_PROXY, optarg); #endif #ifdef CONFIG_HIP_ENABLED } else if (!strcmp(long_options[index].name, "list-hits")) { action = ACTION_LIST_HITS; } else if (!strcmp(long_options[index].name, "rvs")) { processor_config_set_string(config, P2PSHIP_CONF_RVS, optarg); } else if (!strcmp(long_options[index].name, "provide-rvs")) { processor_config_set_string(config, P2PSHIP_CONF_PROVIDE_RVS, "yes"); #endif #ifdef CONFIG_WEBCONF_ENABLED } else if (!strcmp(long_options[index].name, "webconf")) { processor_config_set_string(config, P2PSHIP_CONF_WEBCONF_SS, optarg); #endif } else { c = '?'; } } switch (c) { case 0: /* already processed */ break; case 'v': if (p2pship_log_level > -1) p2pship_log_level++; break; case 'q': flag_quiet = 1; p2pship_log_level = -1; break; case 'D': log_to_file = 1; processor_config_set_string(config, P2PSHIP_CONF_DAEMON, "yes"); break; case 'c': conf_file = optarg; processor_config_set_string(config, P2PSHIP_CONF_CONF_FILE, conf_file); break; case 'i': processor_config_set_string(config, P2PSHIP_CONF_IFACES, optarg); break; #ifdef CONFIG_SIP_ENABLED case 'p': if (sscanf(optarg, "%u", &tmp) != 1) { USER_ERROR("Invalid port %s\n", optarg); return 1; } else { processor_config_set_int(config, P2PSHIP_CONF_SIPP_PROXY_PORT, tmp); } break; #endif case 's': if (sscanf(optarg, "%u", &tmp) != 1) { USER_ERROR("Invalid port %s\n", optarg); return 1; } else { processor_config_set_int(config, P2PSHIP_CONF_SHIP_PORT, tmp); } break; case 'V': print_version(); return 0; case 'R': load_autoreg = 1; break; case 'r': processor_config_set_string(config, P2PSHIP_CONF_AUTOREG_FILE, optarg); break; case 'L': log_to_file = 1; break; case 'k': processor_kill_existing_pid(); break; case 'K': processor_kill_all_existing(); break; case 't': do_test = 1; break; case 'h': case '?': default: print_version(); print_usage(); return 1; } } if (!flag_quiet) print_version(); /* 1. load the defaults (done already), 2. load the conf file, 3. put on the manual overrides */ /* ensure that we have a config file! */ if (ship_ensure_file(conf_file, "# Autocreated\n\n") || processor_config_load(config2, conf_file)) { USER_ERROR("Error processing config file %s\n", conf_file); goto err; } if (processor_config_transfer(config2, config)) { USER_ERROR("Error processing configs\n"); goto err; } /* transfer */ processor_config_free(config); config = config2; config2 = NULL; /* ok, ready to rock! */ processor_config_ensure_configs(config); if (log_to_file) { p2pship_log_file = processor_config_string(config, P2PSHIP_CONF_LOG_FILE); } #ifdef CONFIG_START_GLIB_MAIN_LOOP if (!g_thread_supported()) g_thread_init(NULL); #endif #ifdef CONFIG_START_GTK gdk_threads_init(); gdk_threads_enter(); gtk_init(&argc, &argv); #endif #ifdef CALL_DEBUG calldebug_init(); #endif /* mark starttime for uptime calcs */ time(&p2pship_start); /* register each modules */ ASSERT_ZERO(processor_init(config), err); #ifdef CONFIG_HIP_ENABLED hipapi_register(); #endif #ifdef CONFIG_SIP_ENABLED sipp_register(); #endif ident_addr_register(); ident_register(); #ifdef CONFIG_WEBCONF_ENABLED webconf_register(); #endif #ifdef CONFIG_EXTAPI_ENABLED extapi_register(); #endif #ifdef CONFIG_WEBCACHE_ENABLED webcache_register(); #endif resourceman_register(); olclient_register(); conn_register(); netio_register(); netio_events_register(); netio_ff_register(); netio_man_register(); netio_http_register(); ui_register(); ui_stdin_register(); processor_init_module("ui_stdin", config); #ifdef CONFIG_DBUS_ENABLED dbus_register(); #endif if (!console_only) { #ifdef CONFIG_GTKUI_ENABLED ui_gtk_register(); processor_init_module("ui_gtk", config); #endif } addrbook_register(); #ifdef CONFIG_PYTHON_ENABLED pymod_register(); #endif #ifdef CONFIG_MEDIA_ENABLED media_register(); #endif /* check what we actually should do */ switch (action) { case ACTION_LIST_CA: { /* list ca */ if (processor_init_module("ident", config)) { USER_ERROR("Error initializing system\n"); } else { ident_data_print_cas(ident_get_cas()); } break; } case ACTION_REMOVE_CA: { /* remove ca */ if (processor_init_module("ident", config)) { USER_ERROR("Error initializing system\n"); } else { ident_remove_ca(action_param); } break; } case ACTION_LIST: { /* list */ if (processor_init_module("ident", config)) { USER_ERROR("Error initializing system\n"); } else { ident_data_print_idents(ident_get_identities()); } break; } case ACTION_REMOVE: { /* remove */ if (processor_init_module("ident", config)) { USER_ERROR("Error initializing system\n"); } else { ident_remove_ident(action_param); } break; } case ACTION_IMPORT: /* import */ case ACTION_IMPORT_CA: { /* import ca */ if (processor_init_module("ident", config)) { USER_ERROR("Error initializing system\n"); } else { if (ident_import_file(action_param, 1)) { USER_ERROR("Error loading processing file %s\n", action_param); } } break; } #ifdef CONFIG_HIP_ENABLED case ACTION_LIST_HITS: { if (processor_init_module("hipapi", config)) { USER_ERROR("Error initializing system\n"); } else { hipapi_list_hits(); } break; } #endif case ACTION_NONE: default: { struct rlimit rl; int result; #ifdef CONFIG_PYTHON_ENABLED if (processor_config_is_true(config, P2PSHIP_CONF_START_SHELL)) processor_config_set_false(config, P2PSHIP_CONF_DAEMON); #endif /* go daemon (..whee!) */ if (processor_config_is_true(config, P2PSHIP_CONF_DAEMON)) { if (fork()) goto err; } /* check the stack size */ if (!(result = getrlimit(RLIMIT_STACK, &rl))) { const rlim_t stacksize = 32L * 1024L * 1024L; if (rl.rlim_cur < stacksize) { LOG_INFO("increasing stack size to %d\n", stacksize); rl.rlim_cur = stacksize; if (setrlimit(RLIMIT_STACK, &rl)) { LOG_ERROR("could not set new stack size!\n"); } } } else { LOG_ERROR("error checking stack size\n"); } if (processor_init_modules(config) || (load_autoreg && ident_autoreg_load())) { USER_ERROR("Error initializing system\n"); } else { #ifdef REMOTE_DEBUG ship_remote_debug_init(config); #endif /* start the main loop, blocks */ #ifdef REF_DEBUG2 // processor_tasks_add_periodic(ship_debug_reportref, 10000); #endif if (do_test) { LOG_DEBUG("Run tests..\n"); } processor_run(); } } } ret = 0; err: #ifdef REF_DEBUG2 ship_debug_reportref(); #endif processor_close(); freez(action_param); processor_config_free(config); processor_config_free(config2); #ifdef LOCK_DEBUG debug2_close(); #endif #ifdef REF_DEBUG2 ship_debug_closeref(); #endif xmlCleanupThreads(); if (!ret && !flag_quiet) USER_ERROR("ending ok\n"); processor_cleanup_pid(); return ret; }
/* imports contacts */ int addrbook_import_contacts(ship_list_t *newco, int *concount, int query) { ship_list_t *imps = 0; int ret = -1; void *ptr = 0; contact_t *c = 0; *concount = 0; #ifdef OLD_LOGIC void *last = 0; ship_list_t *done = 0; ship_list_t *imported = 0; /* this is the 'old' way - check whether we already have imported an entry, skip if so. */ /* copy over to an array for filtering */ ASSERT_TRUE(imps = ship_list_new(), err); while (c = ship_list_next(newco, &ptr)) ship_list_add(imps, c); /* load up what we've imported already */ ASSERT_TRUE(imported = ship_list_new(), err); ASSERT_TRUE(done = ship_list_new(), err); ASSERT_ZERO(addrbook_load_imported(imported), err); ptr = 0; while (c = ship_list_next(imported, &ptr)) ship_list_add(done, c); /* filter out those we already have based on the sip aor */ ptr = 0; while (c = ship_list_next(imps, &ptr)) { void *ptr2 = 0; contact_t *c2 = 0; int found = 0; while (!found && (c2 = ship_list_next(imported, &ptr2))) { if (!strcmp(c2->sip_aor, c->sip_aor)) { found = 1; /* should we query whether to update the field if something has changed? */ } } /* here we just skip those we already have imported */ if (found) { ptr = last; ship_list_remove(imps, c); } last = ptr; } /* todo: check for ones with same sip aor? */ /* todo: check for ones with same name? */ #else /* this is another way - check if we *have* the entry, skip if so */ ASSERT_TRUE(imps = ship_list_new(), err); while ((c = ship_list_next(newco, &ptr))) { if (!addrbook_has_contact(NULL, c->sip_aor)) ship_list_add(imps, c); } #endif #ifdef CONFIG_LIBEBOOK_ENABLED ret = addrbook_libebook_import(imps, concount, query); #else *concount = ship_list_length(imps); /* print out */ while ((c = ship_list_next(newco, &ptr))) { LOG_WARN("Ignoring import of contact %s, sip: %s\n", c->name, c->sip_aor); } ret = 0; #endif err: #ifdef OLD_LOGIC if (!ret) addrbook_save_imported(done); if (imported) { while (c = ship_list_pop(imported)) ident_contact_free(c); ship_list_free(imported); } ship_list_free(imps); ship_list_free(done); #endif return ret; }
static int ui_gtk_query_ident_operation(ident_t *ident, const char *operation, const char* true_op, const char *false_op) { const char *templ = "<big>%s identity?</big>\n\nYour confirmation is required for %sing the identity <b>%s</b> %s:\n Name: <i>%s</i>\n Certified name: <i>%s</i>\n Issued by: <i>%s</i>\n Valid from: <i>%s</i>\n Until: <i>%s</i>\n"; char *str = 0; time_t start, end; GtkDialog *diag = 0; char startb[64], endb[64], *issuer = 0, *cname = 0, *op2 = 0, *tmp, *aor = 0, *uname = 0; int ret = 0; gdk_threads_enter(); /* cert data */ if (!(issuer = ident_data_x509_get_cn(X509_get_issuer_name(ident->cert)))) { ASSERT_TRUE(issuer = strdup("UNKNOWN ISSUER"), err); } if (!(cname = ident_data_x509_get_cn(X509_get_subject_name(ident->cert)))) { ASSERT_TRUE(cname = strdup("UNKNOWN SUBJECT"), err); } /* validity */ ASSERT_ZERO(ident_data_x509_get_validity(ident->cert, &start, &end), err); ship_format_time_human(start, startb, sizeof(startb)); ship_format_time_human(end, endb, sizeof(endb)); ASSERT_TRUE(op2 = strdup(operation), err); ASSERT_TRUE(aor = ship_pangoify(ident->sip_aor), err); ASSERT_TRUE(uname = ship_pangoify(ident->username), err); ASSERT_TRUE(tmp = ship_pangoify(cname), err); freez(cname); cname = tmp; ASSERT_TRUE(tmp = ship_pangoify(issuer), err); freez(issuer); issuer = tmp; str = malloc(strlen(templ) + strlen(startb) + strlen(endb) + strlen(issuer) + strlen(cname) + strlen(aor) + strlen(uname) + 1024); op2[0] = toupper(op2[0]); if (!strcmp(operation, "replace")) { sprintf(str, templ, "Replace", "replace", aor, "New identity", uname, cname, issuer, startb, endb); } else { sprintf(str, templ, op2, operation, aor, "Details", uname, cname, issuer, startb, endb); } ASSERT_TRUE(diag = (GtkDialog*)gtk_message_dialog_new_with_markup(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, str, NULL), err); gtk_dialog_add_buttons(diag, op2, 1, "Cancel", 0, NULL); ret = gtk_dialog_run(diag); gtk_widget_destroy((GtkWidget*)diag); err: gdk_threads_leave(); freez(op2); freez(str); freez(issuer); freez(cname); freez(uname); freez(aor); return ret; }
int main(int argc, char **argv) { init_config(argc, argv); open_authorizations("r"); init_webfinger(); /** OPEN MAGIC DATABASE **/ magic_cookie = magic_open(MAGIC_MIME); if(magic_load(magic_cookie, RS_MAGIC_DATABASE) != 0) { log_error("Failed to load magic database: %s", magic_error(magic_cookie)); exit(EXIT_FAILURE); } log_info("starting process: main"); if(prctl(PR_SET_NAME, "rs-serve [main]", 0, 0, 0) != 0) { log_error("Failed to set process name: %s", strerror(errno)); } /** SETUP EVENT BASE **/ rs_event_base = event_base_new(); ASSERT_NOT_NULL(rs_event_base, "event_base_new()"); log_debug("libevent method: %s", event_base_get_method(rs_event_base)); event_set_log_callback(log_event_base_message); // TODO: add error cb to base /** SETUP AUTH TOKENS HASH TABLE **/ auth_sessions = sm_new(1024); // FIXME: this a hardcoded value. /** SETUP MAIN LISTENER **/ struct sockaddr_in sin; memset(&sin, 0, sizeof(struct sockaddr_in)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(0); sin.sin_port = htons(RS_PORT); evhtp_t *server = evhtp_new(rs_event_base, NULL); if(RS_USE_SSL) { evhtp_ssl_cfg_t ssl_config = { .pemfile = RS_SSL_CERT_PATH, .privfile = RS_SSL_KEY_PATH, .cafile = RS_SSL_CA_PATH, // what's this??? .capath = NULL, .ciphers = "RC4+RSA:HIGH:+MEDIUM:+LOW", .ssl_opts = SSL_OP_NO_SSLv2, .ssl_ctx_timeout = 60*60*48, .verify_peer = SSL_VERIFY_PEER, .verify_depth = 42, .x509_verify_cb = dummy_ssl_verify_callback, .x509_chk_issued_cb = dummy_check_issued_cb, .scache_type = evhtp_ssl_scache_type_internal, .scache_size = 1024, .scache_timeout = 1024, .scache_init = NULL, .scache_add = NULL, .scache_get = NULL, .scache_del = NULL }; if(evhtp_ssl_init(server, &ssl_config) != 0) { log_error("evhtp_ssl_init() failed"); exit(EXIT_FAILURE); } } /* WEBFINGER */ evhtp_callback_cb webfinger_cb = (RS_WEBFINGER_ENABLED ? handle_webfinger : reject_webfinger); evhtp_set_cb(server, "/.well-known/webfinger", webfinger_cb, NULL); // support legacy webfinger clients (we don't support XRD though): evhtp_set_cb(server, "/.well-known/host-meta", webfinger_cb, NULL); evhtp_set_cb(server, "/.well-known/host-meta.json", webfinger_cb, NULL); /* REMOTESTORAGE */ evhtp_callback_t *storage_cb = evhtp_set_regex_cb(server, "^/storage/([^/]+)/.*$", handle_storage, NULL); evhtp_set_hook(&storage_cb->hooks, evhtp_hook_on_request_fini, finish_request, NULL); if(evhtp_bind_sockaddr(server, (struct sockaddr*)&sin, sizeof(sin), 1024) != 0) { log_error("evhtp_bind_sockaddr() failed: %s", strerror(errno)); exit(EXIT_FAILURE); } /** SETUP AUTH LISTENER **/ memset(&sin, 0, sizeof(struct sockaddr_in)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(0); sin.sin_port = htons(RS_AUTH_PORT); evhtp_t *server_auth = evhtp_new(rs_event_base, NULL); if(RS_USE_SSL) { evhtp_ssl_cfg_t ssl_config = { .pemfile = RS_SSL_CERT_PATH, .privfile = RS_SSL_KEY_PATH, .cafile = RS_SSL_CA_PATH, // what's this??? .capath = NULL, .ciphers = "RC4+RSA:HIGH:+MEDIUM:+LOW", .ssl_opts = SSL_OP_NO_SSLv2, .ssl_ctx_timeout = 60*60*48, .verify_peer = SSL_VERIFY_PEER, .verify_depth = 42, .x509_verify_cb = dummy_ssl_verify_callback, .x509_chk_issued_cb = dummy_check_issued_cb, .scache_type = evhtp_ssl_scache_type_internal, .scache_size = 1024, .scache_timeout = 1024, .scache_init = NULL, .scache_add = NULL, .scache_get = NULL, .scache_del = NULL }; if(evhtp_ssl_init(server_auth, &ssl_config) != 0) { log_error("evhtp_ssl_init() failed"); exit(EXIT_FAILURE); } } /* AUTH */ evhtp_set_cb(server_auth, "/authenticate", handle_authenticate, NULL); evhtp_set_cb(server_auth, "/authorizations", handle_authorizations, NULL); evhtp_set_hook(&storage_cb->hooks, evhtp_hook_on_request_fini, finish_request, NULL); if(evhtp_bind_sockaddr(server_auth, (struct sockaddr*)&sin, sizeof(sin), 1024) != 0) { log_error("evhtp_bind_sockaddr() failed: %s", strerror(errno)); exit(EXIT_FAILURE); } /** SETUP SIGNALS **/ sigset_t sigmask; sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGTERM); sigaddset(&sigmask, SIGCHLD); ASSERT_ZERO(sigprocmask(SIG_BLOCK, &sigmask, NULL), "sigprocmask()"); int sfd = signalfd(-1, &sigmask, SFD_NONBLOCK); ASSERT_NOT_EQ(sfd, -1, "signalfd()"); struct event *signal_event = event_new(rs_event_base, sfd, EV_READ | EV_PERSIST, handle_signal, NULL); event_add(signal_event, NULL); /** RUN EVENT LOOP **/ if(RS_DETACH) { int pid = fork(); if(pid == 0) { event_reinit(rs_event_base); if(RS_LOG_FILE == stdout) { log_warn("No --log-file option given. Future output will be lost."); freopen("/dev/null", "r", stdout); freopen("/dev/null", "r", stderr); } return event_base_dispatch(rs_event_base); } else { printf("rs-serve detached with pid %d\n", pid); if(RS_PID_FILE) { fprintf(RS_PID_FILE, "%d", pid); fflush(RS_PID_FILE); } _exit(EXIT_SUCCESS); } } else { if(RS_PID_FILE) { fprintf(RS_PID_FILE, "%d", getpid()); fflush(RS_PID_FILE); } return event_base_dispatch(rs_event_base); } }