CURLMOPT_SOCKETFUNCTION(3)

πŸ’… CURLMOPT_SOCKETFUNCTION(3) πŸ’…

okay so bestie, welcome to the CURLMOPT_SOCKETFUNCTION(3) page β€” it's a libcurl library functions manual situation, and we're about to make your socket-watching era iconic ✨

πŸŽ€ NAME πŸŽ€

CURLMOPT_SOCKETFUNCTION β€” the callback that gets told what to wait for πŸ‘€

🌸 SYNOPSIS 🌸

#include <curl/curl.h>

int socket_callback(CURL *easy,      /* easy handle */
                    curl_socket_t s, /* socket */
                    int what,        /* describes the socket */
                    void *clientp,   /* private callback pointer */
                    void *socketp);  /* private socket pointer */

CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_SOCKETFUNCTION, socket_callback);

πŸ¦‹ DESCRIPTION πŸ¦‹

So you pass in a pointer to your callback function, and it has to match that prototype up there ⬆️ β€” no freestyling the signature, ok?

When curl_multi_socket_action(3) gets called, it uses this callback to keep your app in the loop about updates in the socket (file descriptor) status β€” and it does that by making none, one, or multiple calls to socket_callback 😌. Your callback gets status updates covering what's changed since the last time it was called. And if you set that callback pointer to NULL, no callback happens at all. peace out ✌️

Then libcurl is like "okay bestie, you're on socket duty now" β€” it expects the application to monitor the sockets for whatever specific activities, and tell libcurl again when something happens on one of them. You tell libcurl by calling curl_multi_socket_action(3). periodt 🫢

Heads up: this callback may get invoked at any time when interacting with libcurl πŸ‘‘. It may even happen after all transfers are done, and it's likely to happen during a call to curl_multi_cleanup(3) when cached connections are shut down. so don't be surprised, it's giving normal πŸ’€

✨ CALLBACK ARGUMENTS ✨

  • easy β€” identifies the specific transfer that this update is related to. But since this callback manages a whole multi handle, your app should not make assumptions about which particular handle gets passed here 😭. It might even be an internal easy handle that your application didn't add itself. main character energy from a handle you've never met fr fr.
  • s β€” the specific socket this function invocation concerns. If the what argument is not CURL_POLL_REMOVE, then it holds info about what activity on this socket the application is supposed to monitor πŸ‘€. And subsequent calls to this callback might update the what bits for a socket that's already being monitored. lowkey convenient.
  • return value β€” the socket callback should return 0 on success, and -1 on error πŸ’€. And if this callback returns error, all transfers currently in progress in this multi handle are aborted and made to fail. so like... no pressure but also all the pressure 🫠
  • clientp β€” set with CURLMOPT_SOCKETDATA(3).
  • socketp β€” set with curl_multi_assign(3) or NULL.

The what parameter informs the callback on the status of the given socket 🌈. It can hold one of these values:

  • CURL_POLL_IN β€” wait for incoming data. For the socket to become readable πŸ“₯
  • CURL_POLL_OUT β€” wait for outgoing data. For the socket to become writable πŸ“€
  • CURL_POLL_INOUT β€” wait for incoming and outgoing data. For the socket to become readable or writable πŸ”
  • CURL_POLL_REMOVE β€” the specified socket/file descriptor is no longer used by libcurl for any active transfer. It might soon be added again πŸ‘‹ (it's giving "not goodbye, just see you later")

πŸ’– DEFAULT πŸ’–

NULL (no callback) β€” so like, nothing happens unless you ask πŸŽ€

🌈 PROTOCOLS 🌈

This functionality affects all supported protocols β€” every single one, no cap πŸ‘‘

πŸ“ EXAMPLE πŸ“

struct priv {
  void *ours;
};

static int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp)
{
  struct priv *p = cbp;
  printf("our ptr: %p\n", p->ours);

  if(what == CURL_POLL_REMOVE) {
    /* remove the socket from our collection */
  }
  if(what & CURL_POLL_IN) {
    /* wait for read on this socket */
  }
  if(what & CURL_POLL_OUT) {
    /* wait for write on this socket */
  }

  return 0;
}

int main(void)
{
  struct priv setup;
  CURLM *multi = curl_multi_init();
  /* ... use socket callback and custom pointer */
  curl_multi_setopt(multi, CURLMOPT_SOCKETFUNCTION, sock_cb);
  curl_multi_setopt(multi, CURLMOPT_SOCKETDATA, &setup);
}

⭐ AVAILABILITY ⭐

Added in curl 7.15.4 β€” she's been around a minute, an OG 🫢

πŸ”₯ RETURN VALUE πŸ”₯

Returns CURLM_OK. that's it, that's the whole vibe πŸ’…

🧚 SEE ALSO 🧚


okay that's the whole page bestie, go monitor some sockets πŸ’œ

this has been libcurl, dated 2026-10-12 β€” catch you in the next manpage, mwah πŸŽ€βœ¨

πŸ“¦ where this page comes from