Exemplo n.º 1
0
void* serviceConnection(void* psa)
{
	int success;
	connection conn;
	http_server srv;
	http_request request;
	http_response response;
	meta_error e = meta_error_new();

	conn = (connection)psa;
	srv =  connection_arg2(conn);
	request = http_server_get_request(srv);
	response = http_server_get_response(srv);

	success = serviceConnection2(srv, conn, request, response, e);
	if(!success && is_tcpip_error(e)) {
		connection_discard(conn);
	}
	else {
		connection_close(conn);
	}

	http_server_recycle_request(srv, request);
	http_server_recycle_response(srv, response);

	meta_error_free(e);
	return (void*)success;
}
Exemplo n.º 2
0
/* delete a state object */
void
delete_state(struct state *st)
{
    struct connection *const c = st->st_connection;
    struct state *old_cur_state = cur_state == st? NULL : cur_state;

    openswan_log("deleting state #%lu (%s)",
                 st->st_serialno,
                 enum_show(&state_names, st->st_state));

    /*
     * for most IKEv2 things, we may have further things to do after marking the state deleted,
     * so we do not actually free it here at all, but back in the main loop when all the work is done.
     */
    if(st->st_ikev2) {
        /* child sa*/
        if(st->st_clonedfrom != 0) {
            DBG(DBG_CONTROL, DBG_log("received request to delete child state"));
            if(st->st_state == STATE_CHILDSA_DEL) {
		DBG(DBG_CONTROL, DBG_log("now deleting the child state"));

            } else {
                /* Only send request if child sa is established
		 * otherwise continue with deletion
		 */
		if(IS_CHILD_SA_ESTABLISHED(st)) {
                    DBG(DBG_CONTROL, DBG_log("sending Child SA delete equest"));
                    send_delete(st);
                    change_state(st, STATE_CHILDSA_DEL);

                    /* actual deletion when we receive peer response*/
                    return;
		}
            }

        } else {
            DBG(DBG_CONTROL, DBG_log("considering request to delete IKE parent state"));
            /* parent sa */
            if(st->st_state == STATE_IKESA_DEL) {
                DBG(DBG_CONTROL, DBG_log("now deleting the IKE (or parent) state"));

            } else {
		/* Another check to verify if a secured
		 * INFORMATIONAL exchange can be sent or not
		 */
		if(st->st_skey_ei.ptr && st->st_skey_ai.ptr
                   && st->st_skey_er.ptr && st->st_skey_ar.ptr) {
                    DBG(DBG_CONTROL, DBG_log("sending IKE SA delete request"));
                    send_delete(st);
                    change_state(st, STATE_IKESA_DEL);

                    /* actual deletion when we receive peer response*/
                    return;
		}
            }
        }
    }

    /* If DPD is enabled on this state object, clear any pending events */
    if(st->st_dpd_event != NULL)
            delete_dpd_event(st);

    /* if there is a suspended state transition, disconnect us */
    if (st->st_suspended_md != NULL)
    {
	passert(st->st_suspended_md->st == st);
	DBG(DBG_CONTROL, DBG_log("disconnecting state #%lu from md",
	    st->st_serialno));
	st->st_suspended_md->st = NULL;
    }

    /* tell the other side of any IPSEC SAs that are going down */
    if (IS_IPSEC_SA_ESTABLISHED(st->st_state)
    || IS_ISAKMP_SA_ESTABLISHED(st->st_state))
	send_delete(st);

    delete_event(st);	/* delete any pending timer event */

    /* Ditch anything pending on ISAKMP SA being established.
     * Note: this must be done before the unhash_state to prevent
     * flush_pending_by_state inadvertently and prematurely
     * deleting our connection.
     */
    flush_pending_by_state(st);

    /* if there is anything in the cryptographic queue, then remove this
     * state from it.
     */
    delete_cryptographic_continuation(st);

    /* effectively, this deletes any ISAKMP SA that this state represents */
    unhash_state(st);

    /* tell kernel to delete any IPSEC SA
     * ??? we ought to tell peer to delete IPSEC SAs
     */
    if (IS_IPSEC_SA_ESTABLISHED(st->st_state)
	|| IS_CHILD_SA_ESTABLISHED(st))
	delete_ipsec_sa(st, FALSE);
    else if (IS_ONLY_INBOUND_IPSEC_SA_ESTABLISHED(st->st_state))
	delete_ipsec_sa(st, TRUE);

    if (c->newest_ipsec_sa == st->st_serialno)
	c->newest_ipsec_sa = SOS_NOBODY;

    if (c->newest_isakmp_sa == st->st_serialno)
	c->newest_isakmp_sa = SOS_NOBODY;

    /*
     * fake a state change here while we are still associated with a
     * connection.  Without this the state logging (when enabled) cannot
     * work out what happened.
     */
    fake_state(st, STATE_UNDEFINED);

    st->st_connection = NULL;	/* we might be about to free it */
    cur_state = old_cur_state;	/* without st_connection, st isn't complete */
    connection_discard(c);

    change_state(st, STATE_UNDEFINED);

    release_whack(st);

    change_state(st, STATE_CHILDSA_DEL);
}
Exemplo n.º 3
0
int server(unsigned short port, int demarcaciones, int taxPorDemarcacion, int iters, int timeout_millis, int txdelay_millis, bool debug) {
	connection_t conn;
	packet_t outgoing;
	packet_t * incoming;

	if (!connection_server(&conn, port)) {
		fprintf(stderr, "Unable to spawn server on port %u: ", port);
		connection_error(&conn, stderr);
		fprintf(stderr, "\n");
		return 1;
	}

	if (debug) {
		connection_debug(&conn, stderr);
	}

	gestion_taxi_t * taxis = calloc(demarcaciones * taxPorDemarcacion, sizeof(gestion_taxi_t));
	if (taxis == NULL) {
		fprintf(stderr, "Failed to allocate memory for taxi stats structure: %s\n", strerror(errno));
		return 1;
	}

	fprintf(stderr, "Waiting for clientes at port: [%d]\n", port);
	int connected = 0;
	int pendingAccAck = demarcaciones * taxPorDemarcacion;
	while (pendingAccAck > 0) {
		if (!connection_receive(&conn, &incoming, NULL)) { /* TODO: check how to safely implement a timeout here */
			fprintf(stderr, "Error receiving login packet: ");
			connection_error(&conn, stderr);
			fprintf(stderr, "\n");

			if (connection_dead(&conn)) {
				connection_close(&conn);
				free(taxis);
				return 1;
			}

			continue;
		}

		bool duplicate = false;
		int pos;
		switch (incoming->type) {
			case PACKET_TYPE_LOGIN:
				if (incoming->login.version != PACKET_VERSION) {
					fprintf(stderr, "Got LOGIN with version %08X but server version is %08X\n", incoming->login.version, PACKET_VERSION);
					connection_discard(&conn);
					continue;
				}
				connection_accept(&conn);

				for (pos = 0; pos < connected; pos++) {
					if (connection_cmp(&taxis[pos].conexionConTaxi, &conn)) {
						duplicate = true;
						fprintf(stderr, "Got duplicated login packet from taxi %d-%d. Re-sending acknowledgement\n", pos / taxPorDemarcacion, pos % taxPorDemarcacion);
						break;
					}
				}

				if (!duplicate) {
					if (connected == taxPorDemarcacion * demarcaciones) {
						fprintf(stderr, "Received new LOGIN but all taxis have been already registered\n");
						continue;
					}

					fprintf(stderr, "Registered new taxi %d-%d\n", connected / taxPorDemarcacion, connected % taxPorDemarcacion);
					memcpy(&taxis[connected].conexionConTaxi, &conn, sizeof(conn));
					connected++;
				}

				outgoing.type = PACKET_TYPE_ACCEPT;
				outgoing.accept.zone = pos / taxPorDemarcacion;
				outgoing.accept.id = pos % taxPorDemarcacion;
				outgoing.accept.neighbors = taxPorDemarcacion - 1;
				outgoing.accept.ticks = iters;
				outgoing.accept.timeout = timeout_millis;
				outgoing.accept.txdelay = txdelay_millis;
				if (!connection_send(&conn, &outgoing)) {
					fprintf(stderr, "Error replying to login packet: ");
					connection_error(&conn, stderr);
					fprintf(stderr, "\n");
					connection_close(&conn);
					free(taxis);
					return 1;
				}

				break;

			case PACKET_TYPE_ACCACK:
				if (incoming->accack.zone >= demarcaciones || incoming->accack.id >= taxPorDemarcacion) {
					fprintf(stderr, "Received illegal accept acknowledgement from taxi %u-%u\n", incoming->accack.zone, incoming->accack.id);
					connection_discard(&conn);
					continue;
				}
				connection_accept(&conn);

				gestion_taxi_t * taxi = &taxis[incoming->accack.zone * taxPorDemarcacion + incoming->accack.id];
				if (!taxi->hasAckdAccept) {
					taxi->hasAckdAccept = true;
					pendingAccAck--;
				}
				break;

			default:
				connection_discard(&conn);
				fprintf(stderr, "Unexpected packet %s during login phase. Discarding.\n", packet_name(incoming));
				continue;
		}
	}

	outgoing.type = PACKET_TYPE_START;
	for (int pos = 0; pos < demarcaciones * taxPorDemarcacion; pos++) {
		if (!connection_send(&taxis[pos].conexionConTaxi, &outgoing)) {
			fprintf(stderr, "Error sending start packet: ");
			connection_error(&conn, stderr);
			fprintf(stderr, "\n");
			connection_close(&conn);
			free(taxis);
			return 1;
		}
	}

	int statsRcv = 0;
	struct timeval defaulttimeout = { (timeout_millis * 2) / 1000, ((timeout_millis * 2) % 1000) * 1000 };
	struct timeval timeout = defaulttimeout;
	while (statsRcv < demarcaciones * taxPorDemarcacion) {
		if (!connection_receive(&conn, &incoming, NULL)) {
			fprintf(stderr, "Error receiving packet in main loop: ");
			connection_error(&conn, stderr);
			fprintf(stderr, "\n");

			if (conn.err == CONNERR_TIMEOUT) {
				break;
			}

			if (connection_dead(&conn)) {
				connection_close(&conn);
				free(taxis);
				return 1;
			}

			continue;
		}

		gestion_taxi_t * taxi;
		switch (incoming->type) {
			case PACKET_TYPE_ACCACK:
				outgoing.type = PACKET_TYPE_START;
				if (!connection_send(&conn, &outgoing)) {
					fprintf(stderr, "Failed to send start packet in main loop: ");
					connection_error(&conn, stderr);
					fprintf(stderr, "\n");
					connection_close(&conn);
					return 1;
				}
				timeout = defaulttimeout;
				break;

			case PACKET_TYPE_POSITION:
				if (incoming->position.zone > demarcaciones || incoming->position.id > taxPorDemarcacion) {
					fprintf(stderr, "Received position from illegal taxi %u-%u\n", outgoing.position.zone, outgoing.position.id);
					connection_discard(&conn);
					continue;
				}

				for (int neighbor = 0; neighbor < taxPorDemarcacion; neighbor++) {
					if (neighbor == incoming->position.id) {
						continue;
					}

					if (!connection_send(&taxis[incoming->position.zone * taxPorDemarcacion + neighbor].conexionConTaxi, incoming)) {
						fprintf(stderr, "Error forwarding position packet: ");
						connection_error(&taxis[incoming->position.zone * taxPorDemarcacion + neighbor].conexionConTaxi, stderr);
						fprintf(stderr, "\n");
						connection_close(&conn);
						free(taxis);
						return 1;
					}
				}
				timeout = defaulttimeout;
				connection_accept(&conn);
				break;

			case PACKET_TYPE_POSACK:
				if (incoming->posack.zone > demarcaciones || incoming->posack.id > taxPorDemarcacion) {
					fprintf(stderr, "Received acknowledgement from illegal taxi %u-%u\n", incoming->posack.zone, incoming->posack.id);
					break;
				}

				if (incoming->posack.neighbor > taxPorDemarcacion) {
					fprintf(stderr, "Received acknowledgement from %u-%u targeting out-of-bounds taxi %u-%u\n", incoming->posack.zone, incoming->posack.id, incoming->posack.zone, incoming->posack.neighbor);
					break;
				}

				taxi = &taxis[incoming->posack.zone * taxPorDemarcacion + incoming->posack.neighbor];
				if (!connection_send(&taxi->conexionConTaxi, incoming)) {
					fprintf(stderr, "Error forwarding acknowledgement packet: ");
					connection_error(&taxi->conexionConTaxi, stderr);
					fprintf(stderr, "\n");
					connection_close(&conn);
					free(taxis);
					return 1;
				}
				timeout = defaulttimeout;
				connection_accept(&conn);
				break;

			case PACKET_TYPE_STATS:
				taxi = &taxis[incoming->stats.zone * taxPorDemarcacion + incoming->stats.id];
				if (!taxi->hasSentStats) {
					printf("%u, %u, %u, %u, %u, %u, %u, %u\n",
						incoming->stats.zone,
						incoming->stats.id,
						incoming->stats.ticks,
						incoming->stats.posrcv,
						incoming->stats.ackrcv,
						incoming->stats.itmin,
						incoming->stats.itavg,
						incoming->stats.itmax
					);
					taxi->hasSentStats = true;
					statsRcv++;
				}

				outgoing.type = PACKET_TYPE_STATACK;
				if (!connection_send(&taxi->conexionConTaxi, &outgoing)) {
					fprintf(stderr, "Error sending stats acknowledgement packet: ");
					connection_error(&taxi->conexionConTaxi, stderr);
					fprintf(stderr, "\n");
					connection_close(&conn);
					free(taxis);
					return 1;
				}

				timeout = defaulttimeout;
				connection_accept(&conn);
				break;

			default:
				fprintf(stderr, "Unexpected packet %s during main loop\n", packet_name(incoming));
				connection_discard(&conn);
				continue;
		}
	}

	// TODO: Interpretar estadísticas
	return 0;
}