urbit/vere/ames.c

432 lines
10 KiB
C
Raw Normal View History

2013-09-29 00:21:18 +04:00
/* v/http.c
**
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <setjmp.h>
#include <gmp.h>
#include <stdint.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <uv.h>
#include <errno.h>
#include <curses.h>
#include <termios.h>
#include <term.h>
#include "all.h"
#include "vere/vere.h"
2013-09-29 00:21:18 +04:00
/* _ames_alloc(): libuv buffer allocator.
*/
2014-08-21 02:09:51 +04:00
static void
_ames_alloc(uv_handle_t* had_u,
size_t len_i,
uv_buf_t* buf
)
2013-09-29 00:21:18 +04:00
{
2014-04-02 04:47:01 +04:00
void* ptr_v = c3_malloc(len_i);
2014-08-21 02:09:51 +04:00
*buf = uv_buf_init(ptr_v, len_i);
2013-10-05 02:33:26 +04:00
}
/* _ames_free(): contrasting free.
*/
static void
_ames_free(void* ptr_v)
{
// uL(fprintf(uH, "free %p\n", ptr_v));
free(ptr_v);
2013-09-29 00:21:18 +04:00
}
/* _ames_czar(): quasi-static route to emperor.
*/
static c3_w
2017-12-14 02:13:44 +03:00
_ames_czar(c3_y imp_y, c3_s* por_s, c3_c* bos_c)
2013-09-29 00:21:18 +04:00
{
2014-09-11 04:01:32 +04:00
u3_ames* sam_u = &u3_Host.sam_u;
2013-09-29 00:21:18 +04:00
if ( c3n == u3_Host.ops_u.net ) {
2013-09-29 00:21:18 +04:00
*por_s = 31337 + imp_y;
return 0x7f000001;
}
2013-09-29 00:21:18 +04:00
else {
2016-10-25 17:51:10 +03:00
time_t now = time(0);
2013-09-29 00:21:18 +04:00
*por_s = 13337 + imp_y;
if ( 0xffffffff == sam_u->imp_w[imp_y]
&& (now - sam_u -> imp_t[imp_y]) < 300 ) {
2013-09-29 00:21:18 +04:00
return 0;
}
else if ( 0 == sam_u->imp_w[imp_y]
2016-10-25 17:51:10 +03:00
|| (now - sam_u->imp_t[imp_y]) > 300 ) { /* 5 minute TTL */
2014-11-06 06:10:22 +03:00
u3_noun nam = u3dc("scot", 'p', imp_y);
2014-11-06 03:20:01 +03:00
c3_c* nam_c = u3r_string(nam);
2017-12-14 02:13:44 +03:00
c3_c dns_c[256];
2013-09-29 00:21:18 +04:00
2017-12-14 02:13:44 +03:00
snprintf(dns_c, 256, "%s.%s", nam_c + 1, bos_c);
2013-09-29 00:21:18 +04:00
// uL(fprintf(uH, "czar %s, dns %s\n", nam_c, dns_c));
2015-05-18 23:14:27 +03:00
2013-09-29 00:21:18 +04:00
free(nam_c);
2014-09-11 04:01:32 +04:00
u3z(nam);
2013-09-29 00:21:18 +04:00
{
struct addrinfo* air_u;
if ( 0 != getaddrinfo(dns_c, 0, 0, &air_u) ) {
uL(fprintf(uH, "ames: czar at %s: not found (a)\n", dns_c));
if ( sam_u->imp_w[imp_y] == 0
|| sam_u->imp_w[imp_y] == 0xffffffff ) {
sam_u->imp_w[imp_y] = 0xffffffff;
} /* else keep existing ip for 5 more minutes */
sam_u->imp_t[imp_y] = now;
2013-09-29 00:21:18 +04:00
return 0;
}
{
struct addrinfo* rai_u = air_u;
while ( 1 ) {
if ( !rai_u ) {
uL(fprintf(uH, "ames: czar at %s: not found (b)\n", dns_c));
if ( sam_u->imp_w[imp_y] == 0
|| sam_u->imp_w[imp_y] == 0xffffffff ) {
sam_u->imp_w[imp_y] = 0xffffffff;
} /* else keep existing ip for 5 more minutes */
sam_u->imp_t[imp_y] = now;
2013-09-29 00:21:18 +04:00
return 0;
}
if ( (AF_INET == rai_u->ai_family) ) {
struct sockaddr_in* add_u = (struct sockaddr_in *)rai_u->ai_addr;
2016-11-01 00:08:36 +03:00
c3_w old_w = sam_u->imp_w[imp_y];
2013-09-29 00:21:18 +04:00
sam_u->imp_w[imp_y] = ntohl(add_u->sin_addr.s_addr);
2016-10-25 17:51:10 +03:00
sam_u->imp_t[imp_y] = now;
2013-09-29 00:21:18 +04:00
#if 1
if ( sam_u->imp_w[imp_y] != old_w
&& sam_u->imp_w[imp_y] != 0xffffffff ) {
2014-11-06 03:20:01 +03:00
u3_noun wad = u3i_words(1, &sam_u->imp_w[imp_y]);
2014-11-06 06:10:22 +03:00
u3_noun nam = u3dc("scot", c3__if, wad);
2014-11-06 03:20:01 +03:00
c3_c* nam_c = u3r_string(nam);
2013-09-29 00:21:18 +04:00
uL(fprintf(uH, "ames: czar %s: ip %s\n", dns_c, nam_c));
2014-09-11 04:01:32 +04:00
free(nam_c); u3z(nam);
2013-09-29 00:21:18 +04:00
}
#endif
break;
}
rai_u = rai_u->ai_next;
2013-09-29 00:21:18 +04:00
}
}
freeaddrinfo(air_u);
}
}
return sam_u->imp_w[imp_y];
}
}
/* _ames_lane_ipv4(): IPv4 address/ from lane.
*/
2014-11-06 06:10:22 +03:00
u3_noun
2014-09-11 04:01:32 +04:00
_ames_lane_ip(u3_noun lan, c3_s* por_s, c3_w* pip_w)
2013-09-29 00:21:18 +04:00
{
2014-09-11 04:01:32 +04:00
switch ( u3h(lan) ) {
2013-09-29 00:21:18 +04:00
case c3__if: {
2014-09-11 04:01:32 +04:00
*por_s= (c3_s) u3h(u3t(u3t(lan)));
2014-11-06 03:20:01 +03:00
*pip_w = u3r_word(0, u3t(u3t(u3t(lan))));
2013-09-29 00:21:18 +04:00
2014-11-05 04:18:47 +03:00
return c3y;
2013-09-29 00:21:18 +04:00
} break;
case c3__is: {
2014-09-11 04:01:32 +04:00
u3_noun pq_lan = u3h(u3t(u3t(lan)));
2013-09-29 00:21:18 +04:00
2014-11-05 04:18:47 +03:00
if ( u3_nul == pq_lan ) return c3n;
2014-09-11 04:01:32 +04:00
else return _ames_lane_ip(u3t(pq_lan), por_s, pip_w);
2013-09-29 00:21:18 +04:00
} break;
case c3__ix: {
2014-09-11 04:01:32 +04:00
*por_s = (c3_s) u3h(u3t(u3t(lan)));
2014-11-06 03:20:01 +03:00
*pip_w = u3r_word(0, u3t(u3t(u3t(lan))));
2013-09-29 00:21:18 +04:00
2014-11-05 04:18:47 +03:00
return c3y;
2013-09-29 00:21:18 +04:00
} break;
}
2014-11-05 04:18:47 +03:00
return c3n;
2013-09-29 00:21:18 +04:00
}
/* An unusual lameness in libuv.
*/
typedef struct {
uv_udp_send_t snd_u;
c3_y* buf_y;
2014-09-11 04:01:32 +04:00
} _u3_udp_send_t;
2013-09-29 00:21:18 +04:00
/* _ames_send_cb(): send callback.
*/
static void
_ames_send_cb(uv_udp_send_t* req_u, c3_i sas_i)
{
2014-09-11 04:01:32 +04:00
_u3_udp_send_t* ruq_u = (void*)req_u;
2013-09-29 00:21:18 +04:00
2014-06-30 03:58:17 +04:00
#if 0
2013-09-29 00:21:18 +04:00
if ( 0 != sas_i ) {
2014-09-11 04:01:32 +04:00
uL(fprintf(uH, "ames: send_cb: %s\n", uv_strerror(uv_last_error(u3L))));
2013-09-29 00:21:18 +04:00
}
2014-06-30 03:58:17 +04:00
#endif
2013-09-29 00:21:18 +04:00
// fprintf(stderr, "ames: tx\r\n");
free(ruq_u->buf_y);
free(ruq_u);
}
void
2014-09-11 04:01:32 +04:00
u3_ames_ef_bake(void)
{
2014-09-11 04:01:32 +04:00
u3_noun pax = u3nq(u3_blip, c3__newt, u3k(u3A->sen), u3_nul);
2014-11-06 03:20:01 +03:00
u3v_plan(pax, u3nc(c3__barn, u3_nul));
}
2014-09-11 04:01:32 +04:00
/* u3_ames_ef_send(): send packet to network (v4).
2013-09-29 00:21:18 +04:00
*/
void
2014-09-11 04:01:32 +04:00
u3_ames_ef_send(u3_noun lan, u3_noun pac)
2013-09-29 00:21:18 +04:00
{
2014-09-11 04:01:32 +04:00
u3_ames* sam_u = &u3_Host.sam_u;
2013-09-29 00:21:18 +04:00
c3_s por_s;
c3_w pip_w;
2014-09-11 04:01:32 +04:00
if ( u3_Host.ops_u.fuz_w && ((rand() % 100) < u3_Host.ops_u.fuz_w) ) {
u3z(pac);
2013-09-29 00:21:18 +04:00
return;
}
2014-11-05 04:18:47 +03:00
if ( c3y == _ames_lane_ip(lan, &por_s, &pip_w) ) {
2014-11-06 03:20:01 +03:00
c3_w len_w = u3r_met(3, pac);
2014-04-02 04:47:01 +04:00
c3_y* buf_y = c3_malloc(len_w);
2013-09-29 00:21:18 +04:00
2014-11-06 03:20:01 +03:00
u3r_bytes(0, len_w, buf_y, pac);
2013-09-29 00:21:18 +04:00
if ( 0 == pip_w ) {
pip_w = 0x7f000001;
2014-09-11 04:01:32 +04:00
por_s = u3_Host.sam_u.por_s;
2013-09-29 00:21:18 +04:00
}
{
struct sockaddr_in add_u;
if ( (0 == (pip_w >> 16)) && (1 == (pip_w >> 8)) ) {
c3_y imp_y = (pip_w & 0xff);
2017-12-14 02:13:44 +03:00
pip_w = _ames_czar(imp_y, &por_s, u3_Host.ops_u.dns_c);
2013-09-29 00:21:18 +04:00
}
if ( 0 != pip_w ) {
uv_buf_t buf_u = uv_buf_init((c3_c*)buf_y, len_w);
2014-09-11 04:01:32 +04:00
_u3_udp_send_t* ruq_u = c3_malloc(sizeof(_u3_udp_send_t));
2013-09-29 00:21:18 +04:00
ruq_u->buf_y = buf_y;
memset(&add_u, 0, sizeof(add_u));
add_u.sin_family = AF_INET;
add_u.sin_addr.s_addr = htonl(pip_w);
add_u.sin_port = htons(por_s);
2014-08-21 02:09:51 +04:00
int ret;
if ( 0 != (ret = uv_udp_send(&ruq_u->snd_u,
&sam_u->wax_u,
&buf_u, 1,
(const struct sockaddr*) & add_u, // IS THIS RIGHT ?!?!?
_ames_send_cb)) ) {
uL(fprintf(uH, "ames: send: %s\n", uv_strerror(ret)));
2013-09-29 00:21:18 +04:00
}
// fprintf(stderr, "ames: send\r\n");
}
2013-09-29 00:21:18 +04:00
}
}
2014-09-11 04:01:32 +04:00
u3z(lan); u3z(pac);
2013-09-29 00:21:18 +04:00
}
/* _ames_time_cb(): timer callback.
*/
static void
2014-08-21 02:09:51 +04:00
_ames_time_cb(uv_timer_t* tim_uo)
2013-09-29 00:21:18 +04:00
{
2014-09-11 04:01:32 +04:00
u3_ames* sam_u = &u3_Host.sam_u;
u3_lo_open();
2014-04-23 21:02:36 +04:00
sam_u->law_w = time(0);
2013-09-29 00:21:18 +04:00
{
2014-11-06 03:20:01 +03:00
u3v_plan
2014-09-11 04:01:32 +04:00
(u3nt(u3_blip, c3__ames, u3_nul),
u3nc(c3__wake, u3_nul));
2013-09-29 00:21:18 +04:00
}
2014-11-05 04:18:47 +03:00
u3_lo_shut(c3n);
2013-09-29 00:21:18 +04:00
}
/* _ames_recv_cb(): receive callback.
*/
static void
_ames_recv_cb(uv_udp_t* wax_u,
ssize_t nrd_i,
2014-08-21 02:09:51 +04:00
const uv_buf_t * buf_u,
const struct sockaddr* adr_u,
2013-09-29 00:21:18 +04:00
unsigned flg_i)
{
2013-10-05 02:33:26 +04:00
// uL(fprintf(uH, "ames: rx %p\r\n", buf_u.base));
2013-09-29 00:21:18 +04:00
if ( 0 == nrd_i ) {
2014-08-21 02:09:51 +04:00
_ames_free(buf_u->base);
2013-09-29 00:21:18 +04:00
}
else {
2014-09-11 04:01:32 +04:00
u3_lo_open();
2013-09-29 00:21:18 +04:00
{
2014-11-06 03:20:01 +03:00
u3_noun msg = u3i_bytes((c3_w)nrd_i, (c3_y*)buf_u->base);
2015-11-07 01:08:58 +03:00
// fprintf(stderr, "ames: plan\r\n");
#if 0
u3z(msg);
#else
struct sockaddr_in* add_u = (struct sockaddr_in *)adr_u;
2013-09-29 00:21:18 +04:00
c3_s por_s = ntohs(add_u->sin_port);
c3_w pip_w = ntohl(add_u->sin_addr.s_addr);
2014-11-06 03:20:01 +03:00
u3v_plan
2014-09-11 04:01:32 +04:00
(u3nt(u3_blip, c3__ames, u3_nul),
u3nt(c3__hear,
2014-11-06 03:20:01 +03:00
u3nq(c3__if, u3k(u3A->now), por_s, u3i_words(1, &pip_w)),
2014-06-04 01:01:40 +04:00
msg));
2015-11-07 01:08:58 +03:00
#endif
2013-09-29 00:21:18 +04:00
}
2014-08-21 02:09:51 +04:00
_ames_free(buf_u->base);
2014-11-05 04:18:47 +03:00
u3_lo_shut(c3y);
2013-09-29 00:21:18 +04:00
}
}
2014-09-11 04:01:32 +04:00
/* u3_ames_io_init(): initialize ames I/O.
2013-09-29 00:21:18 +04:00
*/
void
2014-09-11 04:01:32 +04:00
u3_ames_io_init()
2013-09-29 00:21:18 +04:00
{
2014-09-11 04:01:32 +04:00
u3_ames* sam_u = &u3_Host.sam_u;
2013-09-29 00:21:18 +04:00
c3_s por_s;
2014-09-11 04:01:32 +04:00
por_s = u3_Host.ops_u.por_s;
if ( 0 != u3_Host.ops_u.imp_c ) {
2014-11-06 03:20:01 +03:00
u3_noun imp = u3i_string(u3_Host.ops_u.imp_c);
2014-11-06 06:10:22 +03:00
u3_noun num = u3dc("slaw", 'p', imp);
2013-09-29 00:21:18 +04:00
c3_y num_y;
2014-11-05 04:18:47 +03:00
if ( c3n == u3du(num) ) {
2014-09-11 04:01:32 +04:00
uL(fprintf(uH, "malformed emperor: %s\n", u3_Host.ops_u.imp_c));
2013-09-29 00:21:18 +04:00
exit(1);
}
2014-11-06 03:20:01 +03:00
num_y = u3r_byte(0, u3t(num));
2017-12-14 02:13:44 +03:00
_ames_czar(num_y, &por_s, u3_Host.ops_u.dns_c);
if ( c3y == u3_Host.ops_u.net ) {
uL(fprintf(uH, "ames: czar: %s on %d\n", u3_Host.ops_u.imp_c, por_s));
}
else {
2017-11-30 04:26:01 +03:00
uL(fprintf(uH, "ames: czar: %s on %d (localhost only)\n",
u3_Host.ops_u.imp_c, por_s));
}
2014-09-11 04:01:32 +04:00
u3z(num);
}
2013-09-29 00:21:18 +04:00
2014-08-21 02:09:51 +04:00
int ret;
2014-09-11 04:01:32 +04:00
if ( 0 != (ret = uv_udp_init(u3L, &u3_Host.sam_u.wax_u)) ) {
2014-08-21 02:09:51 +04:00
uL(fprintf(uH, "ames: init: %s\n", uv_strerror(ret)));
2013-09-29 00:21:18 +04:00
c3_assert(0);
}
// Bind and stuff.
{
struct sockaddr_in add_u;
c3_i add_i = sizeof(add_u);
memset(&add_u, 0, sizeof(add_u));
add_u.sin_family = AF_INET;
add_u.sin_addr.s_addr = htonl(INADDR_ANY);
2014-02-04 01:55:19 +04:00
add_u.sin_port = htons(por_s);
2013-09-29 00:21:18 +04:00
2014-08-21 02:09:51 +04:00
int ret;
2014-10-10 05:27:02 +04:00
if ( (ret = uv_udp_bind(&sam_u->wax_u,
(const struct sockaddr*) & add_u, 0)) != 0 ) {
uL(fprintf(uH, "ames: bind: %s\n",
2014-08-21 02:09:51 +04:00
uv_strerror(ret)));
if (UV_EADDRINUSE == ret){
2014-10-10 05:27:02 +04:00
uL(fprintf(uH,
" ...perhaps you've got two copies of vere running?\n"));
}
exit(1);
2013-09-29 00:21:18 +04:00
}
uv_udp_getsockname(&sam_u->wax_u, (struct sockaddr *)&add_u, &add_i);
c3_assert(add_u.sin_port);
2014-01-17 12:12:05 +04:00
sam_u->por_s = ntohs(add_u.sin_port);
2013-09-29 00:21:18 +04:00
}
// Timer too.
{
2014-09-11 04:01:32 +04:00
uv_timer_init(u3L, &sam_u->tim_u);
2013-09-29 00:21:18 +04:00
}
}
2014-09-11 04:01:32 +04:00
/* u3_ames_io_talk(): start receiving ames traffic.
2014-01-17 12:12:05 +04:00
*/
void
2014-09-11 04:01:32 +04:00
u3_ames_io_talk()
2014-01-17 12:12:05 +04:00
{
2014-09-11 04:01:32 +04:00
u3_ames* sam_u = &u3_Host.sam_u;
2014-01-17 12:12:05 +04:00
uL(fprintf(uH, "ames: on localhost, UDP %d.\n", sam_u->por_s));
uv_udp_recv_start(&sam_u->wax_u, _ames_alloc, _ames_recv_cb);
}
2014-09-11 04:01:32 +04:00
/* u3_ames_io_exit(): terminate ames I/O.
2013-09-29 00:21:18 +04:00
*/
void
2014-09-11 04:01:32 +04:00
u3_ames_io_exit()
2013-09-29 00:21:18 +04:00
{
2014-09-11 04:01:32 +04:00
u3_ames* sam_u = &u3_Host.sam_u;
2013-09-29 00:21:18 +04:00
2015-02-23 03:11:46 +03:00
uv_close(&sam_u->had_u, 0);
2013-09-29 00:21:18 +04:00
}
2014-09-11 04:01:32 +04:00
/* u3_ames_io_poll(): update ames IO state.
2013-09-29 00:21:18 +04:00
*/
void
2014-09-11 04:01:32 +04:00
u3_ames_io_poll()
2013-09-29 00:21:18 +04:00
{
2014-09-11 04:01:32 +04:00
u3_ames* sam_u = &u3_Host.sam_u;
2014-11-06 03:20:01 +03:00
u3_noun wen = u3v_keep(u3nt(u3_blip, c3__ames, u3_nul));
2014-09-11 04:01:32 +04:00
if ( (u3_nul != wen) &&
2014-11-05 04:18:47 +03:00
(c3y == u3du(wen)) &&
(c3y == u3ud(u3t(wen))) )
2013-09-29 00:21:18 +04:00
{
2014-09-11 04:01:32 +04:00
c3_d gap_d = u3_time_gap_ms(u3k(u3A->now), u3k(u3t(wen)));
2014-04-23 21:02:36 +04:00
c3_w lem_w = (time(0) - sam_u->law_w);
c3_w lef_w = (lem_w > 32) ? 0 : (32 - lem_w);
gap_d = c3_min(gap_d, (c3_d)(1000 * lef_w));
2013-09-29 00:21:18 +04:00
2014-11-05 04:18:47 +03:00
if ( c3y == sam_u->alm ) {
2013-09-29 00:21:18 +04:00
uv_timer_stop(&sam_u->tim_u);
}
2014-11-05 04:18:47 +03:00
else sam_u->alm = c3y;
2013-09-29 00:21:18 +04:00
uv_timer_start(&sam_u->tim_u, _ames_time_cb, gap_d, 0);
}
else {
2014-11-05 04:18:47 +03:00
if ( c3y == sam_u->alm ) {
2013-09-29 00:21:18 +04:00
uv_timer_stop(&sam_u->tim_u);
}
2014-11-05 04:18:47 +03:00
sam_u->alm = c3n;
2013-09-29 00:21:18 +04:00
}
2014-09-11 04:01:32 +04:00
u3z(wen);
2013-09-29 00:21:18 +04:00
}