PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0
Showing posts with label tcpserver. Show all posts
Showing posts with label tcpserver. Show all posts

Friday, June 24, 2022

[FIXED] What does tcp proxy session details include?

 June 24, 2022     proxy, reverse-proxy, tcpserver     No comments   

Issue

Suppose TCP proxy has forwarded request back to the backend server. When it receives reply from the backend server, how does it knows which client to reply. What exact session information does a proxy stores?

Can anyone please throw some light on this


Solution

It depends on the protocol, it depends on the proxy, and it depends on whether transparency is a goal. Addressing all of these points exhaustively would take forever, so let's consider a simplistic case.

A network connection in software is usually represented by some sort of handle (whether that's a file descriptor or some other resource). In a C program on a POSIX system, we could simply keep two file descriptors associated with each other:

struct proxy_session {
    int client_fd;
    int server_fd;
}

This is the bare-minimum requirement.

When a client connects, we allocate one of these structures. There may be a protocol that lets us know what backend we should use, or we may be doing load balancing and picking backends ourselves.

Once we've picked a backend (either by virtue of having parsed the protocol or through having made some form routing decision), we initiate a connection to it. Simplistically, a proxy (as an intermediary) simply forwards packets between a client and a server.

We can use any number of interfaces for tying these two things together. On Linux, for example, epoll(2) allows us to associate a pointer to events on a file descriptor. We can provide it a pointer to our proxy_session structure for both the client and server side. When data comes in either of those file descriptors, we know where to map it.

Lacking such an interface, we necessarily have a means for differentiating connection handles (whether they're file descriptors, pointers, or some other representation). We could then use a structure like a hash table to look up the destination for a handle. The solution is found simply by being able to differentiate connections to each other, and holding some state that "glues" two connections together.



Answered By - dho
Answer Checked By - Pedro (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Thursday, April 21, 2022

[FIXED] How to manage connections returned by Accept() in golang?

 April 21, 2022     connection, go, tcp, tcpserver     No comments   

Issue

For a tcp server, we ofter Listen() and Accept().

func main() {
    ln, err := net.Listen("tcp", ":6000")
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }

    for {
        conn, err := ln.Accept()
        if err != nil {
            fmt.Println(err)
            continue
        }

        go handleConnection(conn)
    }
}

But there're 2 ways to handling the connection returned by Accept:

1

func handleConnection(c net.Conn) {
    buf := make([]byte, 4096)

    for {
        n, err := c.Read(buf)
        if err != nil || n == 0 {
            c.Close()
            break
        }
        n, err = c.Write(buf[0:n])
        if err != nil {
            c.Close()
            break
        }
    }
    fmt.Printf("Connection from %v closed.\n", c.RemoteAddr())
}

2

func handleConnection(c net.Conn) {
    defer c.Close()
    buf := make([]byte, 4096)   

    n, err := c.Read(buf)
    if err != nil || n == 0 {
        c.Close()
        break
    }
    n, err = c.Write(buf[0:n])
    if err != nil {
        c.Close()
        break
    }
    fmt.Printf("Connection from %v closed.\n", c.RemoteAddr())
}

Are these 2 approaches correct? It seems approach 1 reuses the connections. But how to indicate the client the EOF?


Solution

This answer assumes that the goal of the program is to echo data back to the client. This answer includes information in comments by torek and limon.

The documentation for Read says

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

The second program may not read all of the data because Read can return available data instead of waiting for more. The second program may not write all of the data because read can return data and an error.

Let's focus on the first program because it's more correct. The program can make multiple Read and Write calls on a connection, but that's not reusing the connection.

It's better to defer c.Close() at the beginning of the function than to sprinkle calls to c.Close() throughout the function. The defer ensures that the connection is closed no matter how the function exits.

func handleConnection(c net.Conn) {
    defer c.Close()
    buf := make([]byte, 4096)

    for {
        n, err := c.Read(buf)
        if err != nil || n == 0 {
            break
        }
        n, err = c.Write(buf[0:n])
        if err != nil {
            break
        }
    }
    fmt.Printf("Connection from %v closed.\n", c.RemoteAddr())
}

Read can return some data and and error. Handle any data returned before processing the error:

func handleConnection(c net.Conn) {
    defer c.Close()
    buf := make([]byte, 4096)

    for {
        n, er := c.Read(buf)
        if n > 0 {
            _, ew := c.Write(buf[:n])
            if ew != nil {
                break
            }
        }
        if er != nil {
            break
        }
    }
    fmt.Printf("Connection from %v closed.\n", c.RemoteAddr())
}

Use io.Copy instead of writing the copy logic in the application. The io.Copy function gets all of the details right. Also, io.Copy can use some lower level optimizations for copying data from one connection to another.

func handleConnection(c net.Conn) {
    defer c.Close()
    io.Copy(c, c)
    fmt.Printf("Connection from %v closed.\n", c.RemoteAddr())
}


Answered By - Zombo
Answer Checked By - Mildred Charles (PHPFixing Admin)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Older Posts Home
View mobile version

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
All Comments
Atom
All Comments

Copyright © PHPFixing