#Only one usage of each socket address (protocol/network address/port) is normally permitted

108 messages · Page 1 of 1 (latest)

hollow storm
#

I've tried everything I can find during research, but still cannot find the solution to this issue.

It works fine for about 15.000 solves, then it stops completely and starts with this error.

heavy mist
#

which error?

hollow storm
#

I've been on this for days now, and cannot find the solution to it

heavy mist
#

what prints it? which function errors and return this as err ?

hollow storm
#

As said it works fine for the first 15000 solves, then it stops.

heavy mist
#

probably you’re leaking connections

hollow storm
#

Also tried with fastHTTP, still the same issue

hollow storm
#

I have looked everywhere for it aswell

#

Here it stops

heavy mist
#

that's a different error... a timeout

forest spindle
#

You've sort of posted three different errors now ("only one usage of each socket address", "failed to solve captcha" and a timeout)

hollow storm
#

Yes, but the failed to solve cap issue never appears until the issue arrives.

#

The timeout is nothing, ignore that.

heavy mist
#

who/what prints "failed to solve" as it's not in the txt you provided

forest spindle
#

Figuring out what function is returning each error would help with figuring out what's going on. Though "failure to solve" sounds like it's coming from the API, with them saying "whoops, oh well, we can't do it with this one"
That "only one usage" one seems to be Windows-specific and sounds like it could be due to a connection leak, as Moorea said.

hollow storm
# forest spindle Figuring out what function is returning each error would help with figuring out ...
func SolveCaptcha() (string, error) {
    apikey := captcha_api_key
    api := nextcaptcha.NewNextCaptchaAPI(apikey, "0", "https://github.com/", false)
    result, err := api.RecaptchaV2Enterprise("https://xxx/", "xxx", nextcaptcha.RecaptchaV2EnterpriseOptions{})

    if err != nil {
        ui.PrintData(fmt.Sprint(err))
        return "", err
    }

    if result["solution"] == nil {
        return "", errors.New("Failed to solve cap!")
    }

    //ui.PrintData(fmt.Sprint(result["solution"].(map[string]interface{})["gRecaptchaResponse"].(string)))
    return result["solution"].(map[string]interface{})["gRecaptchaResponse"].(string), nil

}```
#

That's this part

#

If solution is empty, it prints that error.

heavy mist
#

instead of

   if result["solution"] == nil {
        return "", errors.New("Failed to solve cap!")
    }

you should dump the full reply

hollow storm
#

But it still does not explain the socket issue

#

Which is causing this entire pool of errors

heavy mist
#

which happens first? and which lines prints it? consider using a logger that prints file+line

forest spindle
#

Well. Uhh. Maybe the API response has more information if solution is missing? So, as Moorea said, dump the whole thing.
I can't seem to find public documentation on the API though.

hollow storm
#

It's just pain that I have to spend $15 every time I want to debug this issue

forest spindle
heavy mist
#

maybe TIME_WAIT* but from the sent code cursory, it does use a single shared http client so ... it should be doing connection reuse

forest spindle
#

Windows does only have somewhere around 15k ports in the ephemeral port range, so, a connection leak sounds very likely.

heavy mist
#

unless you are making many api object

#

and/or go routines

#

make sure you're calling NewApiClient only exactly once

hollow storm
#

I am doing several reqs besides this one, but it seems only this one is reacting to that error

#

It works fine with lower threads somehow

heavy mist
#

well... there you go

forest spindle
#

It could just be that whatever is eating up connections is doing it more slowly on a lower thread count. Lowering the amount of threads to anything but 1 doesn't tend to really mitigate issues.
And you should still check netstat -a to see if you're leaking connections. Having 5k connections idling after a while is probably a sign that something's off.

hollow storm
#

Oh yes, there was tons of spammed connections after doing netstat -a
So i'm guessing something is leaking connections

heavy mist
#

how do you make the go routines, is it bounded... you should share the http client

forest spindle
#

I mean, you do have MaxIdleConns: 10000 set on your API client.

hollow storm
heavy mist
forest spindle
#

Reducing it to something reasonable could still help. Though idk, I don't think it should really matter if the client is only connecting to one host, it should just reuse that one.
Still, though, those high timeouts and everything sound bad.
Running this when an API client is discarded might help.
https://pkg.go.dev/net/http#Transport.CloseIdleConnections

noble craneBOT
#
func (t *Transport) CloseIdleConnections()```
CloseIdleConnections closes any connections which were previously connected from previous requests but are now sitting idle in a "keep-alive" state. It does not interrupt any connections currently in use.
forest spindle
#

Assuming the clients are created and discarded regularly.

hollow storm
#

I'll try something else, and I will let you know.

heavy mist
#

...

#

make sure you're calling NewApiClient only exactly once

how do you make the go routines, is it bounded... you should share the http client
calling CloseIdleConnections but making new transports/clients won't help

forest spindle
#

It'll close the connections immediately instead of having them stick around until the time.AfterFunc that'll close it after the timeout runs, would it not?

heavy mist
#

you do want to get connection pooling/reuse and for that you need to NOT make a new client for each request

forest spindle
#

Well, yeah, fixing the strange design choices would be better.

heavy mist
#

so sure, calling CloseIdleConnections (assuming there is a "end") would help a little bit but that's still not how you're supposed to use the http client

hollow storm
#

We never had this issue in Python

#

Well, that didnt solve anything.

heavy mist
#

"that" being ?

hollow storm
#

I tried implementing backoff

func (c *ApiClient) postJSON(path string, data interface{}) (map[string]interface{}, error) {
    body, err := json.Marshal(data)
    if err != nil {
        return nil, err
    }

    req, err := http.NewRequest(http.MethodPost, HOST+path, bytes.NewBuffer(body))
    if err != nil {
        return nil, err
    }

    req.Header.Set("Content-Type", "application/json")

    var resp *http.Response
    operation := func() error {
        var err error
        resp, err = c.httpClient.Do(req)
        if err != nil {
            return err
        }
        return nil
    }

    err = backoff.Retry(operation, backoff.NewExponentialBackOff())
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        body, _ := ioutil.ReadAll(resp.Body)
        if c.openLog {
            log.Printf("Error: %d %s", resp.StatusCode, string(body))
        }
        return nil, errors.New(string(body))
    }

    var result map[string]interface{}
    if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
        return nil, err
    }

    return result, nil
}
#

Which infact did nothing

forest spindle
#

Doesn't really help if there's no ephemeral port to bind to.

hollow storm
heavy mist
#

it did nothing because

make sure you're calling NewApiClient only exactly once

how do you make the go routines, is it bounded... you should share the http client

hollow storm
#

I'm not the developer here, just trying to solve the issue since he is sleeping

hollow storm
#

wait, maybe not

#

nvm, I am calling it once

heavy mist
#

how about you add a print in NewApiClient()

hollow storm
#

That was a commented function

forest spindle
#

If that "one" call is done once per gothread, then it's going to get called more than once.

hollow storm
#

I've already wasted $100 debugging this ffs, and we have been at this issue for maybe 2 weeks now.

forest spindle
#

Well, as Moorea said, add a print to the start of NewApiClient to see if it really is only called once.

hollow storm
#

Its only being called once

heavy mist
#

I doubt it with your symptoms, did you really add the print? and you don't need to run more than 10 calls to debug

hollow storm
#

I added the print statement, and it looks like it's fine?

#

It's printing once after being called if i'm correct

#

Let me try something else

heavy mist
#

define "fine"? after each call or once total (for say 10 threads or whichever threads/go routine number you use)

hollow storm
#

Yes, I ran 10 threads. Which did 10 solves,

log.Printf("NewApiClient function called %d times.", newApiClientCallCount)```

Was printed 10 times.
heavy mist
#

so that's why...

hollow storm
#

Hm?

#

It did 10 solves as supposed to, and it printed 10 times?

forest spindle
#

So, if you do 20 solves, does it print 20 times?

heavy mist
#

and as I said what feels like a dozen times already, it should be 1 - when your developper wakes up, tell him to

share the http client

forest spindle
#

So, each new solve incurs a NewApiClient call 🙃

hollow storm
hollow storm
#

I have the full source code

forest spindle
#

If every single connection creates a new API client with a new http.Client, each configured to keep a connection alive for 90 seconds, and you create 15k connections within those 90 seconds, then those connections will be dutifully kept alive for 90 seconds and you'll run out of ports to bind to.

#

Just have one API client instance, period (as Moorea's been saying). Maybe one per worker thread or something. But one per connection and with each configured to hold on, for a long time, to resources it's not going to be around to use for very long is silly.

heavy mist
#

it's wasteful for both you (the client, churning new expensive to establish connections, and running out) and for the server you are calling repeatedly (though I guess if they are charging you for each, maybe they don't care)

hollow storm
#

Well, in that case I will try to get ahold of my dev in the morning. It seems to be too much for me to solve alone

#

Thank you both so much for the help eitherway

heavy mist
#

you could try to get chatgpt / copilot to fix it for you but basically it's making the http client a singleton (or even use the default one)

hollow storm
#

I did that too, it's not much help. AI is really shit

heavy mist
#

good 🙂 some basic human skills still needed 🙂

cursive fog
#

Hey!

#
func (ofSession Session) doFastHttpRequest(uri string, userId string, cookie string) (error, *fasthttp.Response) {

    req := fasthttp.AcquireRequest()
    req.SetRequestURI(uri)
    sign, time := header.GetSignAndTime(uri, userId)

    if userId == "0" {
        userId = "none"
    }

    req = ofSession.SetFastHeaders(req, sign, time, cookie, false, userId)

    res := fasthttp.AcquireResponse()

    if err := ofSession.fastClient.Do(req, res); err != nil {
        ui.PrintData(fmt.Sprint(err))
        fasthttp.ReleaseResponse(res)
        ui.AddInteger("errors")
        return errors.New("NIGGA"), nil
    }

    fasthttp.ReleaseRequest(req)

    return nil, res
}

func (ofSession Session) doFastHttpRequestPost(uri string, userId string, payload interface{}) (error, *fasthttp.Response) {

    payloadBytes, err := json.Marshal(payload)
    if err != nil {
        return err, nil
    }

    req := fasthttp.AcquireRequest()
    req.Header.SetMethod("POST")
    req.SetBody(payloadBytes)
    req.Header.SetContentType("application/json")
    req.SetRequestURI(uri)
    sign, time := header.GetSignAndTime(uri, userId)

    if userId == "0" {
        userId = "none"
    }

    req = ofSession.SetFastHeaders(req, sign, time, ofSession.cookieToUse, true, userId)

    res := fasthttp.AcquireResponse()

    if err := ofSession.fastClient.Do(req, res); err != nil {
        fasthttp.ReleaseResponse(res)
        ui.AddInteger("errors")
        return errors.New("NIGGA"), nil
    }

    fasthttp.ReleaseRequest(req)

    return nil, res
}
#

this is the part where we are facing that error

#

"ui.PrintData(fmt.Sprint(err))"

#

ofSession.fastClient = fasthttp.Client{MaxConnsPerHost: 100000000, Dial: fasthttpproxy.FasthttpHTTPDialerTimeout(ofSession.proxyUrl, timer.Second*60)}
ofSession.XHash = ofSession.GetXHash()

hollow storm
#

@heavy mist Here he is

heavy mist
#

you don’t need to use fasthttp, stick to stdlib and just make sure you have a single httpclient shared across requests

cursive fog
#

alr then

heavy mist
#

done? works now?