aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/proto.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/dccp/proto.c')
-rw-r--r--net/dccp/proto.c65
1 files changed, 7 insertions, 58 deletions
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 66c43fce17a6..877c1e0e3c48 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -182,8 +182,7 @@ int dccp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
182 return -EMSGSIZE; 182 return -EMSGSIZE;
183 183
184 lock_sock(sk); 184 lock_sock(sk);
185 185 timeo = sock_sndtimeo(sk, noblock);
186 timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
187 186
188 /* 187 /*
189 * We have to use sk_stream_wait_connect here to set sk_write_pending, 188 * We have to use sk_stream_wait_connect here to set sk_write_pending,
@@ -192,77 +191,27 @@ int dccp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
192 /* Wait for a connection to finish. */ 191 /* Wait for a connection to finish. */
193 if ((1 << sk->sk_state) & ~(DCCPF_OPEN | DCCPF_PARTOPEN | DCCPF_CLOSING)) 192 if ((1 << sk->sk_state) & ~(DCCPF_OPEN | DCCPF_PARTOPEN | DCCPF_CLOSING))
194 if ((rc = sk_stream_wait_connect(sk, &timeo)) != 0) 193 if ((rc = sk_stream_wait_connect(sk, &timeo)) != 0)
195 goto out_err; 194 goto out_release;
196 195
197 size = sk->sk_prot->max_header + len; 196 size = sk->sk_prot->max_header + len;
198 release_sock(sk); 197 release_sock(sk);
199 skb = sock_alloc_send_skb(sk, size, noblock, &rc); 198 skb = sock_alloc_send_skb(sk, size, noblock, &rc);
200 lock_sock(sk); 199 lock_sock(sk);
201
202 if (skb == NULL) 200 if (skb == NULL)
203 goto out_release; 201 goto out_release;
204 202
205 skb_reserve(skb, sk->sk_prot->max_header); 203 skb_reserve(skb, sk->sk_prot->max_header);
206 rc = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); 204 rc = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
207 if (rc == 0) { 205 if (rc != 0)
208 struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); 206 goto out_discard;
209 const struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts;
210 long delay;
211
212 /*
213 * XXX: This is just to match the Waikato tree CA interaction
214 * points, after the CCID3 code is stable and I have a better
215 * understanding of behaviour I'll change this to look more like
216 * TCP.
217 */
218 while (1) {
219 rc = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk,
220 skb, len, &delay);
221 if (rc == 0)
222 break;
223 if (rc != -EAGAIN)
224 goto out_discard;
225 if (delay > timeo)
226 goto out_discard;
227 release_sock(sk);
228 delay = schedule_timeout(delay);
229 lock_sock(sk);
230 timeo -= delay;
231 if (signal_pending(current))
232 goto out_interrupted;
233 rc = -EPIPE;
234 if (!(sk->sk_state == DCCP_PARTOPEN || sk->sk_state == DCCP_OPEN))
235 goto out_discard;
236 }
237 207
238 if (sk->sk_state == DCCP_PARTOPEN) { 208 rc = dccp_write_xmit(sk, skb, len);
239 /* See 8.1.5. Handshake Completion */
240 inet_csk_schedule_ack(sk);
241 inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, inet_csk(sk)->icsk_rto, TCP_RTO_MAX);
242 dcb->dccpd_type = DCCP_PKT_DATAACK;
243 /* FIXME: we really should have a dccps_ack_pending or use icsk */
244 } else if (inet_csk_ack_scheduled(sk) ||
245 (dp->dccps_options.dccpo_send_ack_vector &&
246 ap->dccpap_buf_ackno != DCCP_MAX_SEQNO + 1 &&
247 ap->dccpap_ack_seqno == DCCP_MAX_SEQNO + 1))
248 dcb->dccpd_type = DCCP_PKT_DATAACK;
249 else
250 dcb->dccpd_type = DCCP_PKT_DATA;
251 dccp_transmit_skb(sk, skb);
252 ccid_hc_tx_packet_sent(dp->dccps_hc_tx_ccid, sk, 0, len);
253 } else {
254out_discard:
255 kfree_skb(skb);
256 }
257out_release: 209out_release:
258 release_sock(sk); 210 release_sock(sk);
259 return rc ? : len; 211 return rc ? : len;
260out_err: 212out_discard:
261 rc = sk_stream_error(sk, flags, rc); 213 kfree_skb(skb);
262 goto out_release; 214 goto out_release;
263out_interrupted:
264 rc = sock_intr_errno(timeo);
265 goto out_discard;
266} 215}
267 216
268EXPORT_SYMBOL(dccp_sendmsg); 217EXPORT_SYMBOL(dccp_sendmsg);