diff options
-rw-r--r-- | net/dccp/ccids/ccid3.c | 2 | ||||
-rw-r--r-- | net/dccp/dccp.h | 3 | ||||
-rw-r--r-- | net/dccp/output.c | 61 | ||||
-rw-r--r-- | net/dccp/proto.c | 2 |
4 files changed, 62 insertions, 6 deletions
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index cf93b019ecbe..9866dc175258 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c | |||
@@ -985,7 +985,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, | |||
985 | ccid3_pr_debug("send_packet delay=%ld\n", delay); | 985 | ccid3_pr_debug("send_packet delay=%ld\n", delay); |
986 | delay /= -1000; | 986 | delay /= -1000; |
987 | /* divide by -1000 is to convert to ms and get sign right */ | 987 | /* divide by -1000 is to convert to ms and get sign right */ |
988 | rc = delay > 0 ? -EAGAIN : 0; | 988 | rc = delay > 0 ? delay : 0; |
989 | break; | 989 | break; |
990 | default: | 990 | default: |
991 | printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", | 991 | printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", |
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index c6ba07ea1a9f..6ba21509e797 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h | |||
@@ -126,8 +126,7 @@ extern void dccp_send_delayed_ack(struct sock *sk); | |||
126 | extern void dccp_send_sync(struct sock *sk, const u64 seq, | 126 | extern void dccp_send_sync(struct sock *sk, const u64 seq, |
127 | const enum dccp_pkt_type pkt_type); | 127 | const enum dccp_pkt_type pkt_type); |
128 | 128 | ||
129 | extern int dccp_write_xmit(struct sock *sk, struct sk_buff *skb, | 129 | extern int dccp_write_xmit(struct sock *sk, struct sk_buff *skb, long *timeo); |
130 | const int len); | ||
131 | 130 | ||
132 | extern void dccp_init_xmit_timers(struct sock *sk); | 131 | extern void dccp_init_xmit_timers(struct sock *sk); |
133 | static inline void dccp_clear_xmit_timers(struct sock *sk) | 132 | static inline void dccp_clear_xmit_timers(struct sock *sk) |
diff --git a/net/dccp/output.c b/net/dccp/output.c index f96dedd3ad5e..116f6db5678d 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c | |||
@@ -150,14 +150,71 @@ unsigned int dccp_sync_mss(struct sock *sk, u32 pmtu) | |||
150 | return mss_now; | 150 | return mss_now; |
151 | } | 151 | } |
152 | 152 | ||
153 | int dccp_write_xmit(struct sock *sk, struct sk_buff *skb, const int len) | 153 | /** |
154 | * dccp_wait_for_ccid - Wait for ccid to tell us we can send a packet | ||
155 | * @sk: socket to wait for | ||
156 | * @timeo: for how long | ||
157 | */ | ||
158 | static int dccp_wait_for_ccid(struct sock *sk, struct sk_buff *skb, | ||
159 | long *timeo) | ||
160 | { | ||
161 | struct dccp_sock *dp = dccp_sk(sk); | ||
162 | DEFINE_WAIT(wait); | ||
163 | long delay; | ||
164 | int rc; | ||
165 | |||
166 | while (1) { | ||
167 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | ||
168 | |||
169 | if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) | ||
170 | goto do_error; | ||
171 | if (!*timeo) | ||
172 | goto do_nonblock; | ||
173 | if (signal_pending(current)) | ||
174 | goto do_interrupted; | ||
175 | |||
176 | rc = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb, | ||
177 | skb->len); | ||
178 | if (rc <= 0) | ||
179 | break; | ||
180 | delay = msecs_to_jiffies(rc); | ||
181 | if (delay > *timeo || delay < 0) | ||
182 | goto do_nonblock; | ||
183 | |||
184 | sk->sk_write_pending++; | ||
185 | release_sock(sk); | ||
186 | *timeo -= schedule_timeout(delay); | ||
187 | lock_sock(sk); | ||
188 | sk->sk_write_pending--; | ||
189 | } | ||
190 | out: | ||
191 | finish_wait(sk->sk_sleep, &wait); | ||
192 | return rc; | ||
193 | |||
194 | do_error: | ||
195 | rc = -EPIPE; | ||
196 | goto out; | ||
197 | do_nonblock: | ||
198 | rc = -EAGAIN; | ||
199 | goto out; | ||
200 | do_interrupted: | ||
201 | rc = sock_intr_errno(*timeo); | ||
202 | goto out; | ||
203 | } | ||
204 | |||
205 | int dccp_write_xmit(struct sock *sk, struct sk_buff *skb, long *timeo) | ||
154 | { | 206 | { |
155 | const struct dccp_sock *dp = dccp_sk(sk); | 207 | const struct dccp_sock *dp = dccp_sk(sk); |
156 | int err = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb, len); | 208 | int err = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb, |
209 | skb->len); | ||
210 | |||
211 | if (err > 0) | ||
212 | err = dccp_wait_for_ccid(sk, skb, timeo); | ||
157 | 213 | ||
158 | if (err == 0) { | 214 | if (err == 0) { |
159 | const struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts; | 215 | const struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts; |
160 | struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); | 216 | struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); |
217 | const int len = skb->len; | ||
161 | 218 | ||
162 | if (sk->sk_state == DCCP_PARTOPEN) { | 219 | if (sk->sk_state == DCCP_PARTOPEN) { |
163 | /* See 8.1.5. Handshake Completion */ | 220 | /* See 8.1.5. Handshake Completion */ |
diff --git a/net/dccp/proto.c b/net/dccp/proto.c index f97e92ea34f3..f4da6561e40c 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c | |||
@@ -261,7 +261,7 @@ int dccp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
261 | if (rc != 0) | 261 | if (rc != 0) |
262 | goto out_discard; | 262 | goto out_discard; |
263 | 263 | ||
264 | rc = dccp_write_xmit(sk, skb, len); | 264 | rc = dccp_write_xmit(sk, skb, &timeo); |
265 | /* | 265 | /* |
266 | * XXX we don't use sk_write_queue, so just discard the packet. | 266 | * XXX we don't use sk_write_queue, so just discard the packet. |
267 | * Current plan however is to _use_ sk_write_queue with | 267 | * Current plan however is to _use_ sk_write_queue with |