... | ... |
@@ -26,7 +26,13 @@ int udp_sock; |
26 | 26 |
int udp_init(unsigned long ip, unsigned short port) |
27 | 27 |
{ |
28 | 28 |
struct sockaddr_in* addr; |
29 |
- int optval; |
|
29 |
+ int optval, optvallen; |
|
30 |
+ int ioptval, ioptvallen; |
|
31 |
+ int foptval, foptvallen; |
|
32 |
+ int voptval, voptvallen; |
|
33 |
+ int i; |
|
34 |
+ int phase=0; |
|
35 |
+ |
|
30 | 36 |
|
31 | 37 |
addr=(struct sockaddr_in*)malloc(sizeof(struct sockaddr)); |
32 | 38 |
if (addr==0){ |
... | ... |
@@ -51,6 +57,68 @@ int udp_init(unsigned long ip, unsigned short port) |
51 | 57 |
goto error; |
52 | 58 |
} |
53 | 59 |
|
60 |
+ /* jku: try to increase buffer size as much as we can */ |
|
61 |
+ ioptvallen=sizeof(ioptval); |
|
62 |
+ if (getsockopt( udp_sock, SOL_SOCKET, SO_RCVBUF, (void*) &ioptval, |
|
63 |
+ &ioptvallen) == -1 ) |
|
64 |
+ { |
|
65 |
+ LOG(L_ERR, "ERROR: udp_init: getsockopt: %s\n", strerror(errno)); |
|
66 |
+ goto error; |
|
67 |
+ } |
|
68 |
+ if ( ioptval==0 ) |
|
69 |
+ { |
|
70 |
+ LOG(L_DBG, "DEBUG: udp_init: SO_RCVBUF initialy set to 0; resetting to %d\n", |
|
71 |
+ BUFFER_INCREMENT ); |
|
72 |
+ ioptval=BUFFER_INCREMENT; |
|
73 |
+ } else LOG(L_INFO, "INFO: udp_init: SO_RCVBUF is initially %d\n", ioptval ); |
|
74 |
+ for (optval=ioptval; optval < MAX_RECV_BUFFER_SIZE ; ) { |
|
75 |
+ /* increase size; double in initial phase, add linearly later */ |
|
76 |
+ if (phase==0) optval <<= 1; else optval+=BUFFER_INCREMENT; |
|
77 |
+ LOG(L_DBG, "DEBUG: udp_init: trying SO_RCVBUF: %d\n", optval ); |
|
78 |
+ if (setsockopt( udp_sock, SOL_SOCKET, SO_RCVBUF, |
|
79 |
+ (void*)&optval, sizeof(optval)) ==-1) |
|
80 |
+ { |
|
81 |
+ LOG(L_DBG, "DEBUG: udp_init: SOL_SOCKET failed for %d, phase %d: %s\n", |
|
82 |
+ optval, phase, strerror(errno) ); |
|
83 |
+ /* if setting buffer size failed and still in the aggressive |
|
84 |
+ phase, try less agressively; otherwise give up |
|
85 |
+ */ |
|
86 |
+ if (phase==0) { phase=1; optval >>=1 ; continue; } |
|
87 |
+ else break; |
|
88 |
+ } |
|
89 |
+ /* verify if change has taken effect */ |
|
90 |
+ voptvallen=sizeof(voptval); |
|
91 |
+ if (getsockopt( udp_sock, SOL_SOCKET, SO_RCVBUF, (void*) &voptval, |
|
92 |
+ &voptvallen) == -1 ) |
|
93 |
+ { |
|
94 |
+ LOG(L_ERR, "ERROR: udp_init: getsockopt: %s\n", strerror(errno)); |
|
95 |
+ goto error; |
|
96 |
+ } else { |
|
97 |
+ LOG(L_DBG, "DEBUG: setting SO_RCVBUF; set=%d,verify=%d\n", |
|
98 |
+ optval, voptval); |
|
99 |
+ if (voptval<optval) { |
|
100 |
+ LOG(L_DBG, "DEBUG: setting SO_RCVBUF has no effect\n"); |
|
101 |
+ /* if setting buffer size failed and still in the aggressive |
|
102 |
+ phase, try less agressively; otherwise give up |
|
103 |
+ */ |
|
104 |
+ if (phase==0) { phase=1; optval >>=1 ; continue; } |
|
105 |
+ else break; |
|
106 |
+ } |
|
107 |
+ } |
|
108 |
+ |
|
109 |
+ } /* for ... */ |
|
110 |
+ foptvallen=sizeof(foptval); |
|
111 |
+ if (getsockopt( udp_sock, SOL_SOCKET, SO_RCVBUF, (void*) &foptval, |
|
112 |
+ &foptvallen) == -1 ) |
|
113 |
+ { |
|
114 |
+ LOG(L_ERR, "ERROR: udp_init: getsockopt: %s\n", strerror(errno)); |
|
115 |
+ goto error; |
|
116 |
+ } |
|
117 |
+ LOG(L_INFO, "INFO: udp_init: SO_RCVBUF is finally %d\n", foptval ); |
|
118 |
+ |
|
119 |
+ |
|
120 |
+ /* EoJKU */ |
|
121 |
+ |
|
54 | 122 |
if (bind(udp_sock, (struct sockaddr*) addr, sizeof(struct sockaddr))==-1){ |
55 | 123 |
LOG(L_ERR, "ERROR: udp_init: bind: %s\n", strerror(errno)); |
56 | 124 |
goto error; |