diff options
Diffstat (limited to 'net/dccp/output.c')
-rw-r--r-- | net/dccp/output.c | 61 |
1 files changed, 59 insertions, 2 deletions
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 */ |