|
@@ -26,7 +26,13 @@ int udp_sock;
|
|
int udp_init(unsigned long ip, unsigned short port)
|
|
int udp_init(unsigned long ip, unsigned short port)
|
|
{
|
|
{
|
|
struct sockaddr_in* addr;
|
|
struct sockaddr_in* addr;
|
|
- int optval;
|
|
|
|
|
|
+ int optval, optvallen;
|
|
|
|
+ int ioptval, ioptvallen;
|
|
|
|
+ int foptval, foptvallen;
|
|
|
|
+ int voptval, voptvallen;
|
|
|
|
+ int i;
|
|
|
|
+ int phase=0;
|
|
|
|
+
|
|
|
|
|
|
addr=(struct sockaddr_in*)malloc(sizeof(struct sockaddr));
|
|
addr=(struct sockaddr_in*)malloc(sizeof(struct sockaddr));
|
|
if (addr==0){
|
|
if (addr==0){
|
|
@@ -51,6 +57,68 @@ int udp_init(unsigned long ip, unsigned short port)
|
|
goto error;
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /* jku: try to increase buffer size as much as we can */
|
|
|
|
+ ioptvallen=sizeof(ioptval);
|
|
|
|
+ if (getsockopt( udp_sock, SOL_SOCKET, SO_RCVBUF, (void*) &ioptval,
|
|
|
|
+ &ioptvallen) == -1 )
|
|
|
|
+ {
|
|
|
|
+ LOG(L_ERR, "ERROR: udp_init: getsockopt: %s\n", strerror(errno));
|
|
|
|
+ goto error;
|
|
|
|
+ }
|
|
|
|
+ if ( ioptval==0 )
|
|
|
|
+ {
|
|
|
|
+ LOG(L_DBG, "DEBUG: udp_init: SO_RCVBUF initialy set to 0; resetting to %d\n",
|
|
|
|
+ BUFFER_INCREMENT );
|
|
|
|
+ ioptval=BUFFER_INCREMENT;
|
|
|
|
+ } else LOG(L_INFO, "INFO: udp_init: SO_RCVBUF is initially %d\n", ioptval );
|
|
|
|
+ for (optval=ioptval; optval < MAX_RECV_BUFFER_SIZE ; ) {
|
|
|
|
+ /* increase size; double in initial phase, add linearly later */
|
|
|
|
+ if (phase==0) optval <<= 1; else optval+=BUFFER_INCREMENT;
|
|
|
|
+ LOG(L_DBG, "DEBUG: udp_init: trying SO_RCVBUF: %d\n", optval );
|
|
|
|
+ if (setsockopt( udp_sock, SOL_SOCKET, SO_RCVBUF,
|
|
|
|
+ (void*)&optval, sizeof(optval)) ==-1)
|
|
|
|
+ {
|
|
|
|
+ LOG(L_DBG, "DEBUG: udp_init: SOL_SOCKET failed for %d, phase %d: %s\n",
|
|
|
|
+ optval, phase, strerror(errno) );
|
|
|
|
+ /* if setting buffer size failed and still in the aggressive
|
|
|
|
+ phase, try less agressively; otherwise give up
|
|
|
|
+ */
|
|
|
|
+ if (phase==0) { phase=1; optval >>=1 ; continue; }
|
|
|
|
+ else break;
|
|
|
|
+ }
|
|
|
|
+ /* verify if change has taken effect */
|
|
|
|
+ voptvallen=sizeof(voptval);
|
|
|
|
+ if (getsockopt( udp_sock, SOL_SOCKET, SO_RCVBUF, (void*) &voptval,
|
|
|
|
+ &voptvallen) == -1 )
|
|
|
|
+ {
|
|
|
|
+ LOG(L_ERR, "ERROR: udp_init: getsockopt: %s\n", strerror(errno));
|
|
|
|
+ goto error;
|
|
|
|
+ } else {
|
|
|
|
+ LOG(L_DBG, "DEBUG: setting SO_RCVBUF; set=%d,verify=%d\n",
|
|
|
|
+ optval, voptval);
|
|
|
|
+ if (voptval<optval) {
|
|
|
|
+ LOG(L_DBG, "DEBUG: setting SO_RCVBUF has no effect\n");
|
|
|
|
+ /* if setting buffer size failed and still in the aggressive
|
|
|
|
+ phase, try less agressively; otherwise give up
|
|
|
|
+ */
|
|
|
|
+ if (phase==0) { phase=1; optval >>=1 ; continue; }
|
|
|
|
+ else break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ } /* for ... */
|
|
|
|
+ foptvallen=sizeof(foptval);
|
|
|
|
+ if (getsockopt( udp_sock, SOL_SOCKET, SO_RCVBUF, (void*) &foptval,
|
|
|
|
+ &foptvallen) == -1 )
|
|
|
|
+ {
|
|
|
|
+ LOG(L_ERR, "ERROR: udp_init: getsockopt: %s\n", strerror(errno));
|
|
|
|
+ goto error;
|
|
|
|
+ }
|
|
|
|
+ LOG(L_INFO, "INFO: udp_init: SO_RCVBUF is finally %d\n", foptval );
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /* EoJKU */
|
|
|
|
+
|
|
if (bind(udp_sock, (struct sockaddr*) addr, sizeof(struct sockaddr))==-1){
|
|
if (bind(udp_sock, (struct sockaddr*) addr, sizeof(struct sockaddr))==-1){
|
|
LOG(L_ERR, "ERROR: udp_init: bind: %s\n", strerror(errno));
|
|
LOG(L_ERR, "ERROR: udp_init: bind: %s\n", strerror(errno));
|
|
goto error;
|
|
goto error;
|