mirror of
https://github.com/soypat/lneto.git
synced 2026-08-29 19:09:07 +00:00
receive HTTP request success; still working on response
This commit is contained in:
+26
-17
@@ -61,6 +61,7 @@ func main() {
|
|||||||
fmt.Println("hosting server at ", addrPort.String(), "over tap interface of mtu:", mtu, "prefix:", ippfx, "gateway:", net.HardwareAddr(gatewayMAC[:]).String())
|
fmt.Println("hosting server at ", addrPort.String(), "over tap interface of mtu:", mtu, "prefix:", ippfx, "gateway:", net.HardwareAddr(gatewayMAC[:]).String())
|
||||||
buf := make([]byte, mtu)
|
buf := make([]byte, mtu)
|
||||||
var hdr httpraw.Header
|
var hdr httpraw.Header
|
||||||
|
hdr.Reset(make([]byte, 0, 1024))
|
||||||
for {
|
for {
|
||||||
nread, err := tap.Read(buf[:])
|
nread, err := tap.Read(buf[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -74,6 +75,7 @@ func main() {
|
|||||||
slogger.error("recv", slog.String("err", err.Error()), slog.Int("plen", nread))
|
slogger.error("recv", slog.String("err", err.Error()), slog.Int("plen", nread))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
doHTTP(handler, &hdr)
|
||||||
nw, err := lStack.HandleEth(buf[:])
|
nw, err := lStack.HandleEth(buf[:])
|
||||||
debugEthPacket(nil, "OUT", buf[:nw])
|
debugEthPacket(nil, "OUT", buf[:nw])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -87,29 +89,36 @@ func main() {
|
|||||||
slogger.info("write", slog.Int("plen", nw))
|
slogger.info("write", slog.Int("plen", nw))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if handler.State() == tcp.StateEstablished {
|
|
||||||
data := handler.BufferedInput()
|
|
||||||
if data > 0 {
|
|
||||||
n, err := handler.Read(buf[:])
|
|
||||||
if err != nil {
|
|
||||||
slogger.error("tcp-read", slog.String("err", err.Error()))
|
|
||||||
} else {
|
|
||||||
hdr.Reset(buf[:n])
|
|
||||||
err = hdr.Parse(false)
|
|
||||||
if err != nil {
|
|
||||||
slogger.error("http-parse", slog.String("err", err.Error()))
|
|
||||||
} else {
|
|
||||||
fmt.Println(hdr.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if nread == 0 && nw == 0 {
|
if nread == 0 && nw == 0 {
|
||||||
time.Sleep(5 * time.Millisecond)
|
time.Sleep(5 * time.Millisecond)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func doHTTP(conn *internet.TCPConn, hdr *httpraw.Header) error {
|
||||||
|
const asRequest = false
|
||||||
|
if conn.State() != tcp.StateEstablished || conn.BufferedInput() == 0 {
|
||||||
|
return nil // No data yet.
|
||||||
|
}
|
||||||
|
fmt.Println("state is established; check request and send response")
|
||||||
|
_, err := hdr.ReadFromLimited(conn, hdr.Free())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
needMore, err := hdr.TryParse(asRequest)
|
||||||
|
if err != nil {
|
||||||
|
if !needMore {
|
||||||
|
fmt.Println("IT's SO GOVER")
|
||||||
|
conn.Close()
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// HTTP parsed succesfully!
|
||||||
|
fmt.Println("GOT HTTP:\n", hdr.String())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func NewEthernetTCPStack(ourMAC, gwMAC [6]byte, ip netip.AddrPort, mtu uint16, slogger logger) (*LinkStack, *internet.TCPConn, error) {
|
func NewEthernetTCPStack(ourMAC, gwMAC [6]byte, ip netip.AddrPort, mtu uint16, slogger logger) (*LinkStack, *internet.TCPConn, error) {
|
||||||
var err error
|
var err error
|
||||||
lStack := LinkStack{
|
lStack := LinkStack{
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
"github.com/soypat/lneto/http/httpraw"
|
"github.com/soypat/lneto/http/httpraw"
|
||||||
)
|
)
|
||||||
@@ -17,27 +19,51 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func run() error {
|
func run() error {
|
||||||
|
// Prepare GET request.
|
||||||
|
var hdr httpraw.Header
|
||||||
|
hdr.SetMethod("GET")
|
||||||
|
hdr.SetRequestURI("/")
|
||||||
|
hdr.SetProtocol("HTTP/1.1")
|
||||||
|
req, err := hdr.AppendRequest(nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Println("dialing...")
|
fmt.Println("dialing...")
|
||||||
conn, err := net.DialTCP("tcp4", &net.TCPAddr{IP: []byte{192, 168, 10, 1}, Port: 1337}, &net.TCPAddr{IP: []byte{192, 168, 10, 2}, Port: 80})
|
conn, err := net.DialTCP("tcp4", &net.TCPAddr{IP: []byte{192, 168, 10, 1}, Port: 1337}, &net.TCPAddr{IP: []byte{192, 168, 10, 2}, Port: 80})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
go func() {
|
||||||
|
c := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
||||||
|
s := <-c
|
||||||
|
fmt.Println("terminating connection on signal", s.String())
|
||||||
|
conn.Close()
|
||||||
|
os.Exit(0)
|
||||||
|
}()
|
||||||
fmt.Println("reading...")
|
fmt.Println("reading...")
|
||||||
var hdr httpraw.Header
|
conn.Write(req)
|
||||||
for {
|
|
||||||
|
hdr.Reset(nil)
|
||||||
|
var needMore bool = true
|
||||||
|
for needMore {
|
||||||
_, err = hdr.ReadFromLimited(conn, 1024)
|
_, err = hdr.ReadFromLimited(conn, 1024)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
break
|
||||||
}
|
}
|
||||||
const asRequest = false
|
const asResponse = true
|
||||||
var ok bool
|
needMore, err = hdr.TryParse(asResponse)
|
||||||
ok, err = hdr.TryParse(asRequest)
|
if needMore {
|
||||||
if ok {
|
|
||||||
break
|
break
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return err
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
fmt.Println("got HTTP:\n", hdr.String())
|
fmt.Println("got HTTP:\n", hdr.String())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-9
@@ -24,6 +24,7 @@ const (
|
|||||||
flagConnClose
|
flagConnClose
|
||||||
flagNoHTTP11
|
flagNoHTTP11
|
||||||
flagMangledBuffer // set when header fields appended to buffer via Add,Set calls
|
flagMangledBuffer // set when header fields appended to buffer via Add,Set calls
|
||||||
|
flagReaderEOF
|
||||||
)
|
)
|
||||||
|
|
||||||
func (f flags) hasAny(checkThese flags) bool {
|
func (f flags) hasAny(checkThese flags) bool {
|
||||||
@@ -77,20 +78,21 @@ func (h *Header) Parse(asResponse bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TryParse begins parsing or resumes parsing from a failed previous attempt from any of the Parse* methods.
|
// TryParse begins parsing or resumes parsing from a failed previous attempt from any of the Parse* methods.
|
||||||
// It fails if HTTP data is incomplete. It panics if called after header parsing completed succesfully.
|
// As long as needMoreData returns true future calls to TryParse may succeed and the header is not done parsing.
|
||||||
// As long as ok returns true future calls to TryParse may succeed.
|
|
||||||
//
|
//
|
||||||
// ok, err := h.TryParse()
|
// needMoreData := true
|
||||||
// for ; ok; ok, err = h.TryParse() {
|
// var err error
|
||||||
// _, err = h.ReadFrom(r, 256)
|
// for needMoreData {
|
||||||
// if err != nil && err != io.EOF {
|
// _, err = h.ReadFrom(r, 1024)
|
||||||
// return err
|
// if err != nil {
|
||||||
|
// break
|
||||||
// }
|
// }
|
||||||
|
// needMoreData, err = h.TryParse()
|
||||||
// }
|
// }
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
// return err
|
// return err
|
||||||
// }
|
// }
|
||||||
func (h *Header) TryParse(asResponse bool) (ok bool, err error) {
|
func (h *Header) TryParse(asResponse bool) (needMoreData bool, err error) {
|
||||||
if h.flags.hasAny(flagDoneParsingHeader) {
|
if h.flags.hasAny(flagDoneParsingHeader) {
|
||||||
return false, errors.New("TryParse called after header parsed")
|
return false, errors.New("TryParse called after header parsed")
|
||||||
} else if h.flags.hasAny(flagMangledBuffer) {
|
} else if h.flags.hasAny(flagMangledBuffer) {
|
||||||
@@ -103,11 +105,12 @@ func (h *Header) TryParse(asResponse bool) (ok bool, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = h.parseNextHeaders()
|
err = h.parseNextHeaders()
|
||||||
return err == nil || err == errNeedMore, err
|
return err == errNeedMore, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadFromLimited reads at most maxBytesToRead from reader and appends them to underlying buffer.
|
// ReadFromLimited reads at most maxBytesToRead from reader and appends them to underlying buffer.
|
||||||
// Used to accumulate HTTP header for later parsing with [Header.TryParse].
|
// Used to accumulate HTTP header for later parsing with [Header.TryParse].
|
||||||
|
// If read is successful (read length>0) and reader returns [io.EOF] then ReadFromLimited will return a nil error.
|
||||||
func (h *Header) ReadFromLimited(r io.Reader, maxBytesToRead int) (int, error) {
|
func (h *Header) ReadFromLimited(r io.Reader, maxBytesToRead int) (int, error) {
|
||||||
if maxBytesToRead <= 0 {
|
if maxBytesToRead <= 0 {
|
||||||
return 0, errSmallBuffer
|
return 0, errSmallBuffer
|
||||||
@@ -124,6 +127,12 @@ func (h *Header) ReadFromLimited(r io.Reader, maxBytesToRead int) (int, error) {
|
|||||||
blen := len(h.hbuf.buf)
|
blen := len(h.hbuf.buf)
|
||||||
b := h.hbuf.buf[blen:min(blen+maxBytesToRead, cap(h.hbuf.buf))]
|
b := h.hbuf.buf[blen:min(blen+maxBytesToRead, cap(h.hbuf.buf))]
|
||||||
n, err := r.Read(b)
|
n, err := r.Read(b)
|
||||||
|
if err != nil && err == io.EOF {
|
||||||
|
h.flags |= flagReaderEOF
|
||||||
|
if n > 0 {
|
||||||
|
err = nil // Nil-out error if read was succesful so as to not spook readers.
|
||||||
|
}
|
||||||
|
}
|
||||||
h.hbuf.buf = h.hbuf.buf[:blen+n]
|
h.hbuf.buf = h.hbuf.buf[:blen+n]
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
@@ -150,6 +159,11 @@ func (h *Header) Free() int {
|
|||||||
return h.hbuf.free()
|
return h.hbuf.free()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Capacity returns the total capacity of the underlying buffer.
|
||||||
|
func (h *Header) Capacity() int {
|
||||||
|
return cap(h.hbuf.buf)
|
||||||
|
}
|
||||||
|
|
||||||
// ForEach iterates over header key-value field tuples.
|
// ForEach iterates over header key-value field tuples.
|
||||||
func (h *Header) ForEach(cb func(key, value []byte) error) error {
|
func (h *Header) ForEach(cb func(key, value []byte) error) error {
|
||||||
return h.hbuf.forEach(cb)
|
return h.hbuf.forEach(cb)
|
||||||
|
|||||||
+36
-20
@@ -56,7 +56,7 @@ func (h *HTTPTapClient) ensureMTU() (err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var info TapInfo
|
var info tapInfo
|
||||||
err = json.NewDecoder(resp.Body).Decode(&info)
|
err = json.NewDecoder(resp.Body).Decode(&info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -85,40 +85,56 @@ type HTTPTapClient struct {
|
|||||||
buf []byte
|
buf []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HTTPTapClient) ReadDiscard() {
|
func (h *HTTPTapClient) ReadDiscard() error {
|
||||||
var data [2048]byte
|
for {
|
||||||
var n int = -1
|
d, _ := h.ReadBytes() // Empty remote data.
|
||||||
for n != 0 {
|
if len(d) == 0 {
|
||||||
n, _ = h.Read(data[:]) // Empty remote data.
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HTTPTapClient) ReadBytes() (data []byte, err error) {
|
||||||
|
err = h.ensureMTU()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resp, err := h.c.Get(h.recvurl)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if resp.StatusCode != 200 {
|
||||||
|
return nil, errors.New(resp.Status + " for " + h.recvurl)
|
||||||
|
}
|
||||||
|
buf := h.buf
|
||||||
|
err = json.NewDecoder(resp.Body).Decode(&buf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return buf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HTTPTapClient) Read(b []byte) (int, error) {
|
func (h *HTTPTapClient) Read(b []byte) (int, error) {
|
||||||
err := h.ensureMTU()
|
err := h.ensureMTU()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
|
} else if len(b) < h.MTU() {
|
||||||
|
return 0, errors.New("buffer must have at least MTU size")
|
||||||
}
|
}
|
||||||
resp, err := h.c.Get(h.recvurl)
|
data, err := h.ReadBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
} else if resp.StatusCode != 200 {
|
|
||||||
return 0, errors.New(resp.Status + " for " + h.recvurl)
|
|
||||||
}
|
}
|
||||||
var data []byte
|
n := copy(b, data)
|
||||||
err = json.NewDecoder(resp.Body).Decode(&data)
|
return n, nil
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
} else if len(b) < len(data) {
|
|
||||||
return 0, fmt.Errorf("got too large packet %d for buffer %d", len(data), len(b))
|
|
||||||
}
|
|
||||||
copy(b, data)
|
|
||||||
return len(data), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HTTPTapClient) Write(b []byte) (int, error) {
|
func (h *HTTPTapClient) Write(b []byte) (int, error) {
|
||||||
err := h.ensureMTU()
|
err := h.ensureMTU()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
|
} else if len(b) > h.MTU() {
|
||||||
|
return 0, errors.New("buffer larger than MTU")
|
||||||
}
|
}
|
||||||
data, _ := json.Marshal(b)
|
data, _ := json.Marshal(b)
|
||||||
resp, err := h.c.Post(h.sendurl, "application/json", bytes.NewReader(data))
|
resp, err := h.c.Post(h.sendurl, "application/json", bytes.NewReader(data))
|
||||||
@@ -140,7 +156,7 @@ type HTTPTapServer struct {
|
|||||||
tapfailed bool
|
tapfailed bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type TapInfo struct {
|
type tapInfo struct {
|
||||||
MTU int
|
MTU int
|
||||||
IPPrefix string
|
IPPrefix string
|
||||||
HardwareAddr string
|
HardwareAddr string
|
||||||
@@ -185,7 +201,7 @@ func NewHTTPTapServer(iface string, ip netip.Prefix, mtu, queueOut, queueIn int)
|
|||||||
})
|
})
|
||||||
ipstr := ip.String()
|
ipstr := ip.String()
|
||||||
sv.HandleFunc("/info", func(w http.ResponseWriter, r *http.Request) {
|
sv.HandleFunc("/info", func(w http.ResponseWriter, r *http.Request) {
|
||||||
info := TapInfo{
|
info := tapInfo{
|
||||||
MTU: mtu,
|
MTU: mtu,
|
||||||
IPPrefix: ipstr,
|
IPPrefix: ipstr,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user