From b917920aa5c230c77f2c484171c4869e43fedd1f Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Wed, 26 Feb 2020 08:38:23 +0000 Subject: [PATCH] added 2 more parameters to sys::write() adding a tcp proxy script --- hawk/lib/mod-sys.c | 15 ++- hawk/scripts/tcp-proxy.awk | 267 +++++++++++++++++++++++++++++++++++++ 2 files changed, 280 insertions(+), 2 deletions(-) create mode 100644 hawk/scripts/tcp-proxy.awk diff --git a/hawk/lib/mod-sys.c b/hawk/lib/mod-sys.c index 56b604ac..5f6a0a74 100644 --- a/hawk/lib/mod-sys.c +++ b/hawk/lib/mod-sys.c @@ -713,13 +713,24 @@ static int fnc_write (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) { hawk_bch_t* dptr; hawk_oow_t dlen; + hawk_ooi_t startpos = 0, maxlen = HAWK_TYPE_MAX(hawk_ooi_t); hawk_val_t* a1; + if (hawk_rtx_getnargs(rtx) >= 3 && hawk_rtx_valtoint(rtx, hawk_rtx_getarg(rtx, 2), &startpos) <= -1 || startpos < 0) startpos = 0; + else if (startpos > 1) startpos--; /* this position is 1-based */ + + if (hawk_rtx_getnargs(rtx) >= 4 && hawk_rtx_valtoint(rtx, hawk_rtx_getarg(rtx, 3), &maxlen) <= -1) maxlen = HAWK_TYPE_MAX(hawk_ooi_t); + else if (maxlen < 0) maxlen = 0; + a1 = hawk_rtx_getarg(rtx, 1); dptr = hawk_rtx_getvalbcstr(rtx, a1, &dlen); if (dptr) { - rx = write(sys_node->ctx.u.file.fd, dptr, dlen); + if (dlen > maxlen) dlen = maxlen; + if (startpos >= dlen) startpos = dlen; + dlen -= startpos; + + rx = write(sys_node->ctx.u.file.fd, &dptr[startpos], dlen); if (rx <= -1) rx = set_error_on_sys_list_with_errno(rtx, sys_list, HAWK_T("unable to write")); hawk_rtx_freevalbcstr (rtx, a1, dptr); } @@ -4280,7 +4291,7 @@ static fnctab_t fnctab[] = { HAWK_T("unsetenv"), { { 1, 1, HAWK_NULL }, fnc_unsetenv, 0 } }, { HAWK_T("wait"), { { 1, 3, HAWK_T("vrv") }, fnc_wait, 0 } }, { HAWK_T("waitonmux"), { { 2, 2, HAWK_T("vv") }, fnc_waitonmux, 0 } }, - { HAWK_T("write"), { { 2, 2, HAWK_NULL }, fnc_write, 0 } }, + { HAWK_T("write"), { { 2, 4, HAWK_NULL }, fnc_write, 0 } }, { HAWK_T("writelog"), { { 2, 2, HAWK_NULL }, fnc_writelog, 0 } } }; diff --git a/hawk/scripts/tcp-proxy.awk b/hawk/scripts/tcp-proxy.awk new file mode 100644 index 00000000..9691beac --- /dev/null +++ b/hawk/scripts/tcp-proxy.awk @@ -0,0 +1,267 @@ +@pragma entry main +@pragma implicit off + +function break_bridge_by_local_fd (&localtab, &remotetab, fd, mx) +{ + @local r; + r = localtab[fd]; + sys::delfrommux (mx, fd); + sys::delfrommux (mx, r); + sys::close (fd); + sys::close (r); + delete localtab[fd]; + delete localtab[fd,"pending"]; + delete remotetab[r]; + delete remotetab[r,"connecting"]; + delete remotetab[r,"pending"]; +} + +function break_bridge_by_remote_fd (localtab, remotetab, fd, mx) +{ + @local l; + l = remotetab[fd]; + sys::delfrommux (mx, l); + sys::delfrommux (mx, fd); + sys::close (l); + sys::close (fd); + delete localtab[l]; + delete localtab[l,"pending"]; + delete remotetab[fd]; + delete remotetab[fd,"connecting"]; + delete remotetab[fd,"pending"]; +} + +function bridge_remote_to_local (localtab, remotetab, fd, mx) +{ + @local len, buf; + + len = sys::read(fd, buf, 8096); + if (len <= 0) + { + print "closing read error ", fd; + break_bridge_by_remote_fd (localtab, remotetab, fd, mx); + } + else + { + do + { + @local x; + + x = sys::write(remotetab[fd], buf); + if (x == sys::RC_EAGAIN) + { + remotetab[fd,"pending"] = remotetab[fd,"pending"] %% buf; + break; + } + else if (x <= -1) + { + break_bridge_by_remote_fd (localtab, remotetab, fd, mx); + break; + } + + len -= x; + if (len <= 0) break; + + buf = substr(buf, x + 1); + } + while (1); + } +} + +function bridge_local_to_remote (localtab, remotetab, fd, mx) +{ + @local len, buf; + + len = sys::read(fd, buf, 8096); + if (len <= 0) + { + print "closing read error ", fd; + break_bridge_by_local_fd (localtab, remotetab, fd, mx); + } + else + { +printf ("ABOUT TO WRITE TO REMOTE........\n"); + do + { + @local x; + + x = sys::write(localtab[fd], buf); + if (x == sys::RC_EAGAIN) + { + localtab[fd,"pending"] = localtab[fd,"pending"] %% buf; + ## TODO: MOD mux for writing.. + break; + } + else if (x <= -1) + { + break_bridge_by_local_fd (localtab, remotetab, fd, mx); + break; + } + + len -= x; + if (len <= 0) break; + + buf = substr(buf, x + 1); + } + while (1); + } +} + +function serve_connections (mx, ss, remoteaddr) +{ + @local localtab, remotetab + + while (1) + { + @local x, i; + + if ((x = sys::waitonmux(mx, 3.10)) <= -1) + { + print "Error: problem while waiting on multiplexer -", sys::errmsg(); + break; + } + + if (x == 0) continue; ## timed out + + + for (i = 0; i < x; i++) + { + @local fd, evmask; + + if (sys::getmuxevt(mx, i, fd, evmask) <= -1) continue; + + if (fd == ss) + { + ## server socket event + @local l, r; + + l = sys::accept(ss, sys::SOCK_CLOEXEC | sys::SOCK_NONBLOCK); + if (l <= -1) + { + print "Error: failed to accept connection -", sys::errmsg(); + } + else + { + r = sys::socket(sys::AF_INET6, sys::SOCK_STREAM | sys::SOCK_CLOEXEC | sys::SOCK_NONBLOCK, 0); + if (r <= -1) + { + print "Error: unable to create remote socket for local socket", l, "-", sys::errmsg(); + sys::close(l); + } + else + { + @local x; + x = sys::connect(r, remoteaddr); + if ((x <= -1 && x != sys::RC_EINPROG) || sys::addtomux(mx, r, sys::MUX_EVT_OUT) <= -1) + { +print "Unable to conneect to remote...", sys::errmsg(); + sys::close (r); + sys::close (l); + } + else + { + localtab[l] = r; + remotetab[r] = l; + remotetab[r,"connecting"] = 1; +printf ("NEW SESSION %d %d\n", l, r); + } + } + } + } + else + { + ## event on a client socket + if (fd in remotetab) + { + if (evmask & (sys::MUX_EVT_HUP | sys::MUX_EVT_ERR)) + { + print "closing HUP ERR", fd; + break_bridge_by_remote_fd (localtab, remotetab, fd, mx); + } + else + { + if (evmask & sys::MUX_EVT_OUT) + { + if ((fd,"connecting") in remotetab) + { + ## remote connected + sys::addtomux (mx, remotetab[fd], sys::MUX_EVT_IN); + sys::modinmux (mx, fd, sys::MUX_EVT_IN); + delete remotetab[fd,"connecting"]; + } + } + + if (evmask & sys::MUX_EVT_IN) + { + bridge_remote_to_local (localtab, remotetab, fd, mx); + } + } + } + + if (fd in localtab) + { + if (evmask & (sys::MUX_EVT_HUP | sys::MUX_EVT_ERR)) + { + print "closing HUP ERR local", fd; + break_bridge_by_local_fd (localtab, remotetab, fd, mx); + } + else if (evmask & sys::MUX_EVT_IN) + { + print "event on " fd; + bridge_local_to_remote (localtab, remotetab, fd, mx); + } + } + } + } + } + + return 0; +} + +function main (localaddr, remoteaddr, c) +{ + @local ss, mx; + + if (ARGC != 3) + { + printf ("Usage: %s local-address remote-address\n", ARGV[0]); ## TODO: add SCRIPTNAME to hawk interpreter + return -1; + } + + mx = sys::openmux(); + if (mx <= -1) + { + print "Error: unable to create multiplexer -", sys::errmsg(); + return -1; + } + + ss = sys::socket(sys::AF_INET6, sys::SOCK_STREAM | sys::SOCK_CLOEXEC | sys::SOCK_NONBLOCK, 0); + if (ss <= -1) + { + print "Error: unable to create socket -", sys::errmsg(); + return -1; + } + + sys::setsockopt(ss, sys::SOL_SOCKET, sys::SO_REUSEADDR, 1); + sys::setsockopt(ss, sys::SOL_SOCKET, sys::SO_REUSEPORT, 1); + + if (sys::bind(ss, localaddr) <= -1 || sys::listen(ss, 0) <= -1) + { + print "Error: socket error -", sys::errmsg(); + sys::close (ss); + return -1; + } + + if (sys::addtomux(mx, ss, sys::MUX_EVT_IN) <= -1) + { + print "Error: unable to add server socket to multiplexer -", sys::errmsg(); + sys::close (ss); + return -1; + } + + serve_connections (mx, ss, remoteaddr); + + sys::delfrommux (mx, ss); + sys::close (ss); + sys::close (mx); +}