void server_mc_read_cb(struct bufferevent *bev, void *ctx) { struct server *s = (struct server *)ctx; struct evbuffer *in = bufferevent_get_input(bev); struct mc *mc = v_mc_find_if(s->peers, (void *)find_bev, bev); size_t len; char *line; /* Do nothing: this peer seems to exists, but we didn't approve it yet*/ if (mc == v_mc_end(s->peers)) return ; while ((line = evbuffer_readln(in, &len, EVBUFFER_EOL_CRLF)) != NULL) { struct vector_cptr *splited; char *cmd_name; log_debug("[META] [%s]", line); splited = split(line); cmd_name = v_cptr_at(splited, 0); if (strncmp(cmd_name, "udp_port", strlen(cmd_name)) == 0) { char *s_udp_port = v_cptr_at(splited, 1); unsigned short port = atoi(s_udp_port); struct endpoint udp_remote_endpoint; endpoint_init(&udp_remote_endpoint, mc->p.address, mc->p.len); endpoint_set_port(&udp_remote_endpoint, port); udp_register_new_peer(s->udp, &udp_remote_endpoint, DTLS_DISABLE); } v_cptr_delete(splited); free(line); } }
// Housekeeping for URLs url_t* url_init(url_t *target) { if (!mutable_string_init(&(target->url))) { return NULL; } if (!endpoint_init(&(target->endpoint))) { return NULL; } if (!uri_init(&(target->uri))) { return NULL; } if (!qs_init(&(target->query_string))) { return NULL; } target->proto_scheme = HTTP; return target; }
int server_init(struct server *s, struct event_base *evbase) { struct cfg_sockaddress *it_listen = NULL; struct cfg_sockaddress *ite_listen = NULL; struct cfg_sockaddress *it_client = NULL; struct cfg_sockaddress *ite_client = NULL; struct cfg_sockaddress *it_peer = NULL; struct cfg_sockaddress *ite_peer = NULL; size_t i = 0; s->peers = v_mc_new(); s->pending_peers = v_mc_new(); s->srv_list = v_evl_new(); s->frames_to_send = v_frame_new(); s->evbase = evbase; it_listen = v_sockaddr_begin(serv_opts.listen_addrs); ite_listen = v_sockaddr_end(serv_opts.listen_addrs); s->ev_sched = sched_new(evbase); /* Listen on all ListenAddress */ for (; it_listen != ite_listen; it_listen = v_sockaddr_next(it_listen), ++i) { struct evconnlistener *evl = NULL; char listenname[INET6_ADDRSTRLEN]; struct endpoint endp; evl = evconnlistener_new_bind(evbase, listen_callback, s, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, -1, (struct sockaddr *)&it_listen->sockaddr, it_listen->len); if (evl == NULL) { log_warnx("[INIT] failed to allocate the listener to listen to %s", address_presentation((struct sockaddr *)&it_listen->sockaddr, it_listen->len, listenname, sizeof listenname)); continue; } evconnlistener_set_error_cb(evl, NULL); evconnlistener_disable(evl); /* udp endpoint init */ /* * We listen on the same address for the udp socket */ endpoint_init(&endp, (struct sockaddr *)&it_listen->sockaddr, it_listen->len); s->udp = server_udp_new(s, &endp); if (s->udp == NULL) { log_warnx("[INIT] [UDP] failed to init the udp socket on %s", address_presentation((struct sockaddr *)&it_listen->sockaddr, it_listen->len, listenname, sizeof listenname)); continue; } v_evl_push(s->srv_list, evl); } // Listen enable for client in the ports registered it_client = v_sockaddr_begin(serv_opts.client_addrs); ite_client = v_sockaddr_end(serv_opts.client_addrs); #ifdef USE_TCLT /* Listen on all ClientAddress */ for (; it_client != ite_client; it_client = v_sockaddr_next(it_client), ++i) { char clientname[INET6_ADDRSTRLEN]; struct evconnlistener *evl = NULL; evl = evconnlistener_new_bind(evbase, listen_client_callback, s, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, -1, (struct sockaddr *)&it_client->sockaddr, it_client->len); if (evl == NULL) { log_warnx("[INIT] [TCP] failed to allocate the listener to listen to %s", address_presentation((struct sockaddr *) &it_client->sockaddr, it_client->len, clientname, sizeof clientname)); continue; } evconnlistener_set_error_cb(evl, NULL); evconnlistener_enable(evl); v_evl_push(s->srv_list, evl); } #endif /* If we don't have any PeerAddress it's finished */ if (v_sockaddr_size(serv_opts.peer_addrs) == 0) return 0; it_peer = v_sockaddr_begin(serv_opts.peer_addrs); ite_peer = v_sockaddr_end(serv_opts.peer_addrs); for (;it_peer != ite_peer; it_peer = v_sockaddr_next(it_peer)) { struct mc *mc_peer = NULL; #ifdef USE_TCLT peer p; char *cmd; /* TODO : Real information */ p.name = strdup(""); p.name = strdup(""); p.name = strdup(""); #endif mc_peer = mc_peer_connect(s, evbase, (struct sockaddr *)&it_peer->sockaddr, it_peer->len); #ifdef USE_TCLT if (mc_peer != NULL && s->mc_client.bev) { cmd = tclt_add_peer(&p); bufferevent_write(s->mc_client.bev, cmd, strlen(cmd)); free(cmd); } #endif } return 0; }
void server_mc_event_cb(struct bufferevent *bev, short events, void *ctx) { struct server *s = (struct server *)ctx; dump_flags(events); if (events & BEV_EVENT_CONNECTED) { struct mc *mc; /* * If we received the notification that the connection is established, * then we move the corresponding struct mc from s->pending_peers to * s->peers. */ mc = v_mc_find_if(s->pending_peers, (void *)find_bev, bev); if (mc != v_mc_end(s->pending_peers)) { struct mc tmp; struct endpoint e; endpoint_init(&e, mc->p.address, mc->p.len); /* Check for certificate */ if (mc->ssl_flags & TLS_ENABLE) { X509 *cert; SSL *ssl; EVP_PKEY *pubkey; char name[512]; ssl = bufferevent_openssl_get_ssl(mc->bev); cert = SSL_get_peer_certificate(ssl); if (cert == NULL) { log_info("[META] [TLS] %s doesn't share it's certificate.", mc_presentation(mc, name, sizeof name)); v_mc_erase(s->pending_peers, mc); mc_close(mc); return ; } pubkey = X509_get_pubkey(cert); //UNUSED ? } log_info("[META] [%s] connexion established with %s", mc->ssl_flags & TLS_ENABLE ? "TLS" : "TCP", endpoint_presentation(&e)); memcpy(&tmp, mc, sizeof(tmp)); v_mc_erase(s->pending_peers, mc); mc = v_mc_insert(s->peers, &tmp); mc_hello(mc, s->udp); mc_establish_tunnel(mc, s->udp); } } else if (events & BEV_EVENT_EOF) { /* Disconnected */ struct mc *mc; struct udp_peer *up; mc = v_mc_find_if(s->peers, (void *)find_bev, bev); if (mc != v_mc_end(s->peers)) { char name[INET6_ADDRSTRLEN]; struct sockaddr *sock = mc->p.address; up = v_udp_find_if(s->udp->udp_peers, find_udppeer, sock); if (up != v_udp_end(s->udp->udp_peers)) { v_udp_erase(s->udp->udp_peers, up); log_debug("[%s] stop peering with %s", (up->ssl_flags & DTLS_ENABLE) ? "DTLS" : "UDP", endpoint_presentation(&up->peer_addr)); } log_debug("[META] stop the meta-connexion with %s", mc_presentation(mc, name, sizeof(name))); mc_close(mc); v_mc_erase(s->peers, mc); } } else if (events & BEV_EVENT_ERROR) { struct mc *mc; int everr; int sslerr; everr = EVUTIL_SOCKET_ERROR(); if (everr != 0) { log_warnx("[META] unexpected shutdown of the meta-connexion: (%d) %s", everr, evutil_socket_error_to_string(everr)); } while ((sslerr = bufferevent_get_openssl_error(bev)) != 0) { log_warnx("[META] SSL error code (%d): %s in %s %s", sslerr, ERR_reason_error_string(sslerr), ERR_lib_error_string(sslerr), ERR_func_error_string(sslerr)); } /* * Find if the exception come from a pending peer or a * regular peer and close it. */ mc = v_mc_find_if(s->pending_peers, (void *)find_bev, bev); if (mc != v_mc_end(s->pending_peers)) { char name[128]; log_debug("[META] %s removed from the pending list", mc_presentation(mc, name, sizeof name)); mc_close(mc); v_mc_erase(s->pending_peers, mc); } else { mc = v_mc_find_if(s->peers, (void *)find_bev, bev); if (mc != v_mc_end(s->peers)) { mc_close(mc); v_mc_erase(s->peers, mc); log_debug("[META] socket removed from the peer list"); } } } }