Wrapping to enable TCP keep-alives in ffmpeg

The excellent ffmpeg tool is very good at retrieving RTMP TCP video streams. However, if the stream stops (i.e. the camera is turned off), ffmpeg politely waits forever. This is the default for something listening to a TCP stream. If the other end did not explicitly close the connection, infinite patience will be deployed.

It is possible to send "keep alive" packets to check if the other end is still there, but Linux does not do this by default. When it does, its default waiting time is two hours of idleness before starting to investigate.

For a project involving fetching a stream from a camera which was likely to get unplugged frequently, a much faster recovery was needed. So, again, LD_PRELOAD to the rescue. The result is recorded here without any recommendation that one should be mad enough to use it for anything.

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <stdlib.h>

#include <errno.h>

#define __USE_GNU
#include <dlfcn.h>

int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen){
  static int (*connect_real)(int, const struct sockaddr*,socklen_t)=NULL;
  unsigned char *c;
  int rtn,data,old_errno;

  if (!connect_real) connect_real=dlsym(RTLD_NEXT,"connect");

  rtn=connect_real(sockfd,serv_addr,addrlen);

  if (((rtn==0)||(errno=EINPROGRESS))&&(serv_addr->sa_family==AF_INET)){
    old_errno=errno;
    data=1;
    if (!setsockopt(sockfd,SOL_SOCKET,SO_KEEPALIVE,&data,sizeof(data))){
      data=40; /* Worry after 40 seconds */
      setsockopt(sockfd,IPPROTO_TCP,TCP_KEEPIDLE,&data,sizeof(data));
      data=4; /* Send four probes */
      setsockopt(sockfd,IPPROTO_TCP,TCP_KEEPCNT,&data,sizeof(data));
      data=6; /* 6s between each probe */
      setsockopt(sockfd,IPPROTO_TCP,TCP_KEEPINTVL,&data,sizeof(data));
    }
    errno=old_errno;
  }
  
  return rtn;
}

To use, compile with

$ gcc -o keep_alive.so -shared keep_alive.c -ldl

and use with

$ LD_PRELOAD=`pwd`/keep_alive.so ffmpeg [...]

Don't do this. Fix the source instead. But if you must consider the dangerously unsupported (by both me and the authors of whatever program you are trying to modify), you may find the above amusing. The idea is that setsockopt is called only if connect is called on an IPV4 socket, and that all errors from setsockopt are discarded, as whatever called connect would not be expecting them.