Exemple #1
0
vsf_err_t vsfip_dhcpd_start(struct vsfip_netif_t *netif,
                            struct vsfip_dhcpd_t *dhcpd)
{
    if ((NULL == netif) || (NULL == dhcpd))
    {
        return VSFERR_FAIL;
    }

    dhcpd->alloc_idx = 1;
    netif->dhcp.dhcpd = dhcpd;
    dhcpd->netif = netif;
    memset(&dhcpd->assoc, 0, sizeof(dhcpd->assoc));

    dhcpd->sockaddr.sin_port = DHCP_CLIENT_PORT;
    dhcpd->sockaddr.sin_addr.size = 4;

    dhcpd->so = vsfip_socket(AF_INET, IPPROTO_UDP);
    if (NULL == dhcpd->so)
    {
        goto cleanup;
    }
    vsfip_socket_cb(dhcpd->so, dhcpd, vsfip_dhcpd_input, NULL);
    if (vsfip_bind(dhcpd->so, DHCP_SERVER_PORT))
    {
        goto cleanup;
    }
    return vsfip_listen(dhcpd->so, 0);
cleanup:
    if (dhcpd->so != NULL)
    {
        vsfip_close(dhcpd->so);
        dhcpd->so = NULL;
    }
    return VSFERR_FAIL;
}
Exemple #2
0
static vsf_err_t
vsfip_telnetd_session_tx_thread(struct vsfsm_pt_t *pt, vsfsm_evt_t evt)
{
	struct vsfip_telnetd_session_t *session =
								(struct vsfip_telnetd_session_t *)pt->user_data;
	uint32_t len;
	vsf_err_t err;

	vsfsm_pt_begin(pt);

	session->caller_txpt.sm = pt->sm;
	while (!session->disconnect)
	{
		len = stream_get_data_size(session->stream_tx);
		if (!len && vsfsm_sem_pend(&session->stream_tx_sem, pt->sm))
		{
			vsfsm_pt_wfe(pt, VSFIP_TELNETD_EVT_STREAM_IN);
			if (session->disconnect)
				break;
			continue;
		}

	retry_alloc_buf:
		session->outbuf = VSFIP_TCPBUF_GET(len);
		if (NULL == session->outbuf)
		{
			vsfsm_pt_delay(pt, 5);
			if (session->disconnect)
				break;
			goto retry_alloc_buf;
		}

		session->outbuf->app.size =
					stream_read(session->stream_tx, &session->outbuf->app);
		if (!session->outbuf->app.size)
		{
			vsfip_buffer_release(session->outbuf);
			continue;
		}

		session->caller_txpt.state = 0;
		vsfsm_pt_entry(pt);
		err = vsfip_tcp_send(&session->caller_txpt, evt, session->so,
						&session->so->remote_sockaddr, session->outbuf, false);
		if (err > 0) return err; else if (err < 0)
		{
			session->disconnect = true;
		}
	}

	// close tcp socket
	session->caller_txpt.state = 0;
	vsfsm_pt_entry(pt);
	err = vsfip_tcp_close(&session->caller_txpt, evt, session->so);
	if (err > 0) return err;

	// close socket no matter if tcp closed OK or not
	vsfip_close(session->so);
	session->connected = false;

	vsfsm_pt_end(pt);
	return VSFERR_NONE;
}
Exemple #3
0
static vsf_err_t vsfip_telnetd_thread(struct vsfsm_pt_t *pt, vsfsm_evt_t evt)
{
	struct vsfip_telnetd_t *telnetd = (struct vsfip_telnetd_t *)pt->user_data;
	vsf_err_t err = VSFERR_NONE;
	int i;

	vsfsm_pt_begin(pt);

	telnetd->caller_pt.sm = pt->sm;
	telnetd->so = vsfip_socket(AF_INET, IPPROTO_TCP);
	if (NULL == telnetd->so)
	{
		return VSFERR_FAIL;
	}

	if ((vsfip_bind(telnetd->so, telnetd->port) != 0) ||
		(vsfip_listen(telnetd->so, telnetd->session_num) != 0))
	{
		err = VSFERR_FAIL;
		goto fail_socket_connect;
	}

	while (1)
	{
		telnetd->caller_pt.state = 0;
		vsfsm_pt_entry(pt);
		err = vsfip_tcp_accept(&telnetd->caller_pt, evt, telnetd->so,
								&telnetd->cur_session);
		if (err > 0) return err; else if (err < 0)
		{
			continue;
		}

		// get session
		for (i = 0; i < telnetd->session_num; i++)
		{
			if (!telnetd->sessions[i].connected)
			{
				struct vsfip_telnetd_session_t *session = &telnetd->sessions[i];

				session->connected = true;
				session->disconnect = false;
				session->so = telnetd->cur_session;

				session->stream_rx->callback_tx.param = session;
				session->stream_rx->callback_tx.on_inout =
											vsfip_telnetd_session_stream_on_out;
				session->stream_tx->callback_rx.param = session;
				session->stream_tx->callback_rx.on_inout =
											vsfip_telnetd_session_stream_on_in;
				stream_connect_tx(session->stream_rx);
				stream_connect_rx(session->stream_tx);

				vsfsm_sem_init(&session->stream_tx_sem, 0,
											VSFIP_TELNETD_EVT_STREAM_IN);
				vsfsm_sem_init(&session->stream_rx_sem, 0,
												VSFIP_TELNETD_EVT_STREAM_OUT);

				session->txpt.thread = vsfip_telnetd_session_tx_thread;
				session->txpt.user_data = session;
				session->rxpt.thread = vsfip_telnetd_session_rx_thread;
				session->rxpt.user_data = session;
				vsfsm_pt_init(&session->txsm, &session->txpt);
				vsfsm_pt_init(&session->rxsm, &session->rxpt);
				break;
			}
		}
		if (i == telnetd->session_num)
		{
			telnetd->caller_pt.state = 0;
			vsfsm_pt_entry(pt);
			err = vsfip_tcp_close(&telnetd->caller_pt, evt,
										telnetd->cur_session);
			if (err > 0) return err;
			vsfip_close(telnetd->cur_session);
		}
	}

fail_socket_connect:
	vsfip_close(telnetd->so);
	telnetd->so = NULL;

	vsfsm_pt_end(pt);
	return VSFERR_NONE;
}
Exemple #4
0
static struct vsfsm_state_t *
vsfip_dhcpc_evt_handler(struct vsfsm_t *sm, vsfsm_evt_t evt)
{
	struct vsfip_dhcpc_t *dhcpc = (struct vsfip_dhcpc_t *)sm->user_data;
	struct vsfip_netif_t *netif = dhcpc->netif;

	switch (evt)
	{
	case VSFSM_EVT_INIT:
		dhcpc->ready = true;
		dhcpc->retry = 0;

	retry:
		dhcpc->xid = vsfip_dhcpc.xid++;
		dhcpc->so = vsfip_socket(AF_INET, IPPROTO_UDP);
		if (NULL == dhcpc->so)
		{
			goto cleanup;
		}
		vsfip_socket_cb(dhcpc->so, dhcpc, vsfip_dhcpc_input, NULL);
		if (vsfip_bind(dhcpc->so, DHCP_CLIENT_PORT))
		{
			goto cleanup;
		}
		vsfip_listen(dhcpc->so, 0);

		// if address already allocated, do resume, send request again
		if (dhcpc->ipaddr.size != 0)
		{
			goto dhcp_request;
		}

		// discover
		memset(&netif->ipaddr, 0, sizeof(netif->ipaddr));
		dhcpc->ipaddr.size = 0;
		if (vsfip_dhcpc_init_msg(dhcpc, (uint8_t)DHCPOP_DISCOVER) < 0)
		{
			goto cleanup;
		}
		vsfip_dhcp_end_opt(dhcpc->outbuffer, &dhcpc->optlen);
		dhcpc->sockaddr.sin_addr.addr.s_addr = 0xFFFFFFFF;
		vsfip_udp_async_send(dhcpc->so, &dhcpc->sockaddr, dhcpc->outbuffer);
		dhcpc->so->remote_sockaddr.sin_addr.addr.s_addr = VSFIP_IPADDR_ANY;

		dhcpc->to = vsftimer_create(sm, 5000, 1, VSFIP_DHCP_EVT_TIMEROUT);
		break;
	case VSFIP_DHCP_EVT_SEND_REQUEST:
	dhcp_request:
		vsftimer_free(dhcpc->to);
		if (vsfip_dhcpc_init_msg(dhcpc, (uint8_t)DHCPOP_REQUEST) < 0)
		{
			goto cleanup;
		}
		vsfip_dhcp_append_opt(dhcpc->outbuffer, &dhcpc->optlen,
								DHCPOPT_REQIP, dhcpc->ipaddr.size,
								dhcpc->ipaddr.addr.s_addr_buf);
		vsfip_dhcp_end_opt(dhcpc->outbuffer, &dhcpc->optlen);
		dhcpc->sockaddr.sin_addr.addr.s_addr = 0xFFFFFFFF;
		vsfip_udp_async_send(dhcpc->so, &dhcpc->sockaddr, dhcpc->outbuffer);
		dhcpc->so->remote_sockaddr.sin_addr.addr.s_addr = VSFIP_IPADDR_ANY;

		dhcpc->to = vsftimer_create(sm, 2000, 1, VSFIP_DHCP_EVT_TIMEROUT);
		break;
	case VSFIP_DHCP_EVT_READY:
		vsftimer_free(dhcpc->to);
		// update netif->ipaddr
		dhcpc->ready = 1;
		netif->ipaddr = dhcpc->ipaddr;
		netif->gateway = dhcpc->gw;
		netif->netmask = dhcpc->netmask;
		netif->dns[0] = dhcpc->dns[0];
		netif->dns[1] = dhcpc->dns[1];

		// timer out for resume
//		vsftimer_create(sm, 2000, 1, VSFIP_DHCP_EVT_TIMEROUT);
		goto cleanup;
		break;
	case VSFIP_DHCP_EVT_TIMEROUT:
		// maybe need to resume, set the ready to false
		dhcpc->ready = false;
	cleanup:
		if (dhcpc->so != NULL)
		{
			vsfip_close(dhcpc->so);
			dhcpc->so = NULL;
		}
		if (!dhcpc->ready && (++dhcpc->retry < VSFIP_DHCPC_RETRY_CNT))
		{
			goto retry;
		}

		// notify callder
		if (dhcpc->update_sem.evt != VSFSM_EVT_NONE)
		{
			vsfsm_sem_post(&dhcpc->update_sem);
		}
		break;
	}

	return NULL;
}